Skip to content

Commit e0ccdf4

Browse files
committed
feature: add Move to Workspace context menu entry for repository tab in main tab bar (#1968)
This commit also changes the behavior of opening a repository from CLI. Now, `SourceGit` will always open the last actived workspace first and then open the target repository specified from CLI if it is needed Signed-off-by: leo <[email protected]>
1 parent 5f31883 commit e0ccdf4

File tree

5 files changed

+92
-83
lines changed

5 files changed

+92
-83
lines changed

src/Resources/Locales/en_US.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -551,6 +551,7 @@
551551
<x:String x:Key="Text.PageTabBar.Tab.CloseOther" xml:space="preserve">Close Other Tabs</x:String>
552552
<x:String x:Key="Text.PageTabBar.Tab.CloseRight" xml:space="preserve">Close Tabs to the Right</x:String>
553553
<x:String x:Key="Text.PageTabBar.Tab.CopyPath" xml:space="preserve">Copy Repository Path</x:String>
554+
<x:String x:Key="Text.PageTabBar.Tab.MoveToWorkspace" xml:space="preserve">Move to Workspace</x:String>
554555
<x:String x:Key="Text.PageTabBar.Tab.Refresh" xml:space="preserve">Refresh</x:String>
555556
<x:String x:Key="Text.PageTabBar.Welcome.Title" xml:space="preserve">Repositories</x:String>
556557
<x:String x:Key="Text.Paste" xml:space="preserve">Paste</x:String>

src/Resources/Locales/zh_CN.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@
555555
<x:String x:Key="Text.PageTabBar.Tab.CloseOther" xml:space="preserve">关闭其他标签页</x:String>
556556
<x:String x:Key="Text.PageTabBar.Tab.CloseRight" xml:space="preserve">关闭右侧标签页</x:String>
557557
<x:String x:Key="Text.PageTabBar.Tab.CopyPath" xml:space="preserve">复制仓库路径</x:String>
558+
<x:String x:Key="Text.PageTabBar.Tab.MoveToWorkspace" xml:space="preserve">移至工作区</x:String>
558559
<x:String x:Key="Text.PageTabBar.Tab.Refresh" xml:space="preserve">刷新</x:String>
559560
<x:String x:Key="Text.PageTabBar.Welcome.Title" xml:space="preserve">新标签页</x:String>
560561
<x:String x:Key="Text.Paste" xml:space="preserve">粘贴</x:String>

src/Resources/Locales/zh_TW.axaml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -555,6 +555,7 @@
555555
<x:String x:Key="Text.PageTabBar.Tab.CloseOther" xml:space="preserve">關閉其他分頁</x:String>
556556
<x:String x:Key="Text.PageTabBar.Tab.CloseRight" xml:space="preserve">關閉右側分頁</x:String>
557557
<x:String x:Key="Text.PageTabBar.Tab.CopyPath" xml:space="preserve">複製存放庫路徑</x:String>
558+
<x:String x:Key="Text.PageTabBar.Tab.MoveToWorkspace" xml:space="preserve">移至工作區</x:String>
558559
<x:String x:Key="Text.PageTabBar.Tab.Refresh" xml:space="preserve">重新整理</x:String>
559560
<x:String x:Key="Text.PageTabBar.Welcome.Title" xml:space="preserve">新分頁</x:String>
560561
<x:String x:Key="Text.Paste" xml:space="preserve">貼上</x:String>

src/ViewModels/Launcher.cs

Lines changed: 57 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -35,13 +35,7 @@ public LauncherPage ActivePage
3535
set
3636
{
3737
if (SetProperty(ref _activePage, value))
38-
{
39-
CancelCommandPalette();
40-
UpdateTitle();
41-
42-
if (!_ignoreIndexChange && value is { Data: Repository repo })
43-
_activeWorkspace.ActiveIdx = _activeWorkspace.Repositories.IndexOf(repo.FullPath);
44-
}
38+
PostActivePageChanged(value?.Data as Repository);
4539
}
4640
}
4741

@@ -59,64 +53,43 @@ public Launcher(string startupRepo)
5953
AddNewTab();
6054

6155
var pref = Preferences.Instance;
62-
if (string.IsNullOrEmpty(startupRepo))
63-
{
64-
ActiveWorkspace = pref.GetActiveWorkspace();
56+
ActiveWorkspace = pref.GetActiveWorkspace();
6557

66-
var repos = ActiveWorkspace.Repositories.ToArray();
67-
foreach (var repo in repos)
68-
{
69-
var node = pref.FindNode(repo) ??
70-
new RepositoryNode
71-
{
72-
Id = repo,
73-
Name = Path.GetFileName(repo),
74-
Bookmark = 0,
75-
IsRepository = true,
76-
};
77-
78-
OpenRepositoryInTab(node, null);
79-
}
58+
var repos = ActiveWorkspace.Repositories.ToArray();
59+
foreach (var repo in repos)
60+
{
61+
var node = pref.FindNode(repo) ??
62+
new RepositoryNode
63+
{
64+
Id = repo,
65+
Name = Path.GetFileName(repo),
66+
Bookmark = 0,
67+
IsRepository = true,
68+
};
8069

81-
var activeIdx = ActiveWorkspace.ActiveIdx;
82-
if (activeIdx >= 0 && activeIdx < Pages.Count)
83-
{
84-
ActivePage = Pages[activeIdx];
85-
}
86-
else
87-
{
88-
ActivePage = Pages[0];
89-
ActiveWorkspace.ActiveIdx = 0;
90-
}
70+
OpenRepositoryInTab(node, null);
9171
}
92-
else
93-
{
94-
ActiveWorkspace = new Workspace() { Name = "Unnamed" };
9572

96-
foreach (var w in pref.Workspaces)
97-
w.IsActive = false;
73+
_ignoreIndexChange = false;
9874

75+
if (!string.IsNullOrEmpty(startupRepo))
76+
{
9977
var test = new Commands.QueryRepositoryRootPath(startupRepo).GetResult();
100-
if (!test.IsSuccess || string.IsNullOrEmpty(test.StdOut))
101-
{
102-
Pages[0].Notifications.Add(new Models.Notification
103-
{
104-
IsError = true,
105-
Message = $"Given path: '{startupRepo}' is NOT a valid repository!"
106-
});
107-
}
108-
else
78+
if (test.IsSuccess && !string.IsNullOrEmpty(test.StdOut))
10979
{
11080
var node = pref.FindOrAddNodeByRepositoryPath(test.StdOut.Trim(), null, false);
11181
Welcome.Instance.Refresh();
82+
11283
OpenRepositoryInTab(node, null);
84+
return;
11385
}
11486
}
11587

116-
_ignoreIndexChange = false;
117-
118-
if (string.IsNullOrEmpty(_title))
119-
UpdateTitle();
88+
var activeIdx = ActiveWorkspace.ActiveIdx;
89+
if (activeIdx >= 0 && activeIdx < Pages.Count)
90+
ActivePage = Pages[activeIdx];
91+
else
92+
ActivePage = Pages[0];
12093
}
12194

12295
public void Quit()
@@ -173,18 +146,14 @@ public void SwitchWorkspace(Workspace to)
173146
OpenRepositoryInTab(node, null);
174147
}
175148

149+
_ignoreIndexChange = false;
150+
176151
var activeIdx = to.ActiveIdx;
177152
if (activeIdx >= 0 && activeIdx < Pages.Count)
178-
{
179153
ActivePage = Pages[activeIdx];
180-
}
181154
else
182-
{
183155
ActivePage = Pages[0];
184-
to.ActiveIdx = 0;
185-
}
186156

187-
_ignoreIndexChange = false;
188157
Preferences.Instance.Save();
189158
GC.Collect();
190159
}
@@ -203,17 +172,16 @@ public void MoveTab(LauncherPage from, LauncherPage to)
203172
var fromIdx = Pages.IndexOf(from);
204173
var toIdx = Pages.IndexOf(to);
205174
Pages.Move(fromIdx, toIdx);
206-
ActivePage = from;
207175

208-
ActiveWorkspace.Repositories.Clear();
176+
_activeWorkspace.Repositories.Clear();
209177
foreach (var p in Pages)
210178
{
211179
if (p.Data is Repository r)
212-
ActiveWorkspace.Repositories.Add(r.FullPath);
180+
_activeWorkspace.Repositories.Add(r.FullPath);
213181
}
214-
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(from.Node.Id);
215182

216183
_ignoreIndexChange = false;
184+
ActivePage = from;
217185
}
218186

219187
public void GotoNextTab()
@@ -243,8 +211,8 @@ public void CloseTab(LauncherPage page)
243211
var last = Pages[0];
244212
if (last.Data is Repository repo)
245213
{
246-
ActiveWorkspace.Repositories.Clear();
247-
ActiveWorkspace.ActiveIdx = 0;
214+
_activeWorkspace.Repositories.Clear();
215+
_activeWorkspace.ActiveIdx = 0;
248216

249217
repo.Close();
250218

@@ -253,9 +221,8 @@ public void CloseTab(LauncherPage page)
253221
last.Data = Welcome.Instance;
254222
last.Popup?.Cleanup();
255223
last.Popup = null;
256-
UpdateTitle();
257224

258-
CancelCommandPalette();
225+
PostActivePageChanged(null);
259226
GC.Collect();
260227
}
261228
else
@@ -293,9 +260,9 @@ public void CloseOtherTabs()
293260
}
294261

295262
Pages = new AvaloniaList<LauncherPage> { ActivePage };
296-
ActiveWorkspace.ActiveIdx = 0;
297263
OnPropertyChanged(nameof(Pages));
298264

265+
_activeWorkspace.ActiveIdx = 0;
299266
_ignoreIndexChange = false;
300267
GC.Collect();
301268
}
@@ -345,14 +312,14 @@ public void OpenRepositoryInTab(RepositoryNode node, LauncherPage page)
345312

346313
if (page == null)
347314
{
348-
if (ActivePage == null || ActivePage.Node.IsRepository)
315+
if (_activePage == null || _activePage.Node.IsRepository)
349316
{
350317
page = new LauncherPage(node, repo);
351318
Pages.Add(page);
352319
}
353320
else
354321
{
355-
page = ActivePage;
322+
page = _activePage;
356323
page.Node = node;
357324
page.Data = repo;
358325
}
@@ -363,20 +330,17 @@ public void OpenRepositoryInTab(RepositoryNode node, LauncherPage page)
363330
page.Data = repo;
364331
}
365332

366-
if (page != _activePage)
367-
ActivePage = page;
368-
else
369-
UpdateTitle();
370-
371-
ActiveWorkspace.Repositories.Clear();
333+
_activeWorkspace.Repositories.Clear();
372334
foreach (var p in Pages)
373335
{
374336
if (p.Data is Repository r)
375-
ActiveWorkspace.Repositories.Add(r.FullPath);
337+
_activeWorkspace.Repositories.Add(r.FullPath);
376338
}
377339

378-
if (!_ignoreIndexChange)
379-
ActiveWorkspace.ActiveIdx = ActiveWorkspace.Repositories.IndexOf(node.Id);
340+
if (_activePage == page)
341+
PostActivePageChanged(repo);
342+
else
343+
ActivePage = page;
380344
}
381345

382346
public void OpenCommandPalette(ICommandPalette commandPalette)
@@ -388,9 +352,12 @@ public void OpenCommandPalette(ICommandPalette commandPalette)
388352

389353
public void CancelCommandPalette()
390354
{
391-
_commandPalette?.Dispose();
392-
CommandPalette = null;
393-
GC.Collect();
355+
if (_commandPalette != null)
356+
{
357+
_commandPalette?.Dispose();
358+
CommandPalette = null;
359+
GC.Collect();
360+
}
394361
}
395362

396363
public void DispatchNotification(string pageId, string message, bool isError)
@@ -456,7 +423,7 @@ private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace =
456423
if (page.Data is Repository repo)
457424
{
458425
if (removeFromWorkspace)
459-
ActiveWorkspace.Repositories.Remove(repo.FullPath);
426+
_activeWorkspace.Repositories.Remove(repo.FullPath);
460427

461428
repo.Close();
462429
}
@@ -466,8 +433,11 @@ private void CloseRepositoryInTab(LauncherPage page, bool removeFromWorkspace =
466433
page.Data = null;
467434
}
468435

469-
private void UpdateTitle()
436+
private void PostActivePageChanged(Repository repo)
470437
{
438+
if (_ignoreIndexChange)
439+
return;
440+
471441
var builder = new StringBuilder(512);
472442
if (_activeWorkspace != null)
473443
{
@@ -497,7 +467,11 @@ private void UpdateTitle()
497467
builder.Append("Repositories");
498468
}
499469

470+
CancelCommandPalette();
500471
Title = builder.ToString();
472+
473+
if (repo != null)
474+
_activeWorkspace.ActiveIdx = _activeWorkspace.Repositories.IndexOf(repo.FullPath);
501475
}
502476

503477
private Workspace _activeWorkspace = null;

src/Views/LauncherTabBar.axaml.cs

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -334,6 +334,38 @@ private void OnTabContextRequested(object sender, ContextRequestedEventArgs e)
334334
bookmark.Items.Add(setter);
335335
}
336336
menu.Items.Add(bookmark);
337+
338+
var workspaces = ViewModels.Preferences.Instance.Workspaces;
339+
if (workspaces.Count > 1)
340+
{
341+
var moveTo = new MenuItem();
342+
moveTo.Header = App.Text("PageTabBar.Tab.MoveToWorkspace");
343+
moveTo.Icon = App.CreateMenuIcon("Icons.MoveTo");
344+
345+
foreach (var ws in workspaces)
346+
{
347+
var dupWs = ws;
348+
var isCurrent = dupWs == vm.ActiveWorkspace;
349+
350+
var target = new MenuItem();
351+
target.Header = ws.Name;
352+
target.Icon = App.CreateMenuIcon(isCurrent ? "Icons.Check" : "Icons.Workspace");
353+
target.Click += (_, ev) =>
354+
{
355+
if (!isCurrent)
356+
{
357+
vm.CloseTab(page);
358+
dupWs.Repositories.Add(repo.FullPath);
359+
}
360+
361+
ev.Handled = true;
362+
};
363+
moveTo.Items.Add(target);
364+
}
365+
366+
menu.Items.Add(moveTo);
367+
}
368+
337369
menu.Items.Add(new MenuItem() { Header = "-" });
338370
}
339371

0 commit comments

Comments
 (0)