From d61246de6ac100779c8de8411f781bc1c280db3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=AE=E3=83=A3=E3=83=83=E3=83=97?= Date: Mon, 21 Jul 2025 08:56:27 +0200 Subject: [PATCH 1/5] enhance: Add "Move to New Window" and "Copy to New Window" options Enhanced the user interface by adding new menu items for "Move to New Window" and "Copy to New Window" in various language files. Implemented the corresponding functionality in `Launcher.cs` to allow users to move or copy tabs to new windows. --- src/Resources/Locales/de_DE.axaml | 2 ++ src/Resources/Locales/en_US.axaml | 2 ++ src/Resources/Locales/es_ES.axaml | 2 ++ src/Resources/Locales/fr_FR.axaml | 2 ++ src/Resources/Locales/it_IT.axaml | 2 ++ src/Resources/Locales/ja_JP.axaml | 2 ++ src/Resources/Locales/pt_BR.axaml | 2 ++ src/Resources/Locales/ru_RU.axaml | 2 ++ src/Resources/Locales/ta_IN.axaml | 2 ++ src/Resources/Locales/uk_UA.axaml | 2 ++ src/Resources/Locales/zh_CN.axaml | 2 ++ src/Resources/Locales/zh_TW.axaml | 2 ++ src/ViewModels/Launcher.cs | 32 +++++++++++++++++++++++++++++++ 13 files changed, 56 insertions(+) diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml index bb78b8e7c..bfee0947e 100644 --- a/src/Resources/Locales/de_DE.axaml +++ b/src/Resources/Locales/de_DE.axaml @@ -503,6 +503,8 @@ Andere Tabs schließen Rechte Tabs schließen Kopiere Repository-Pfad + In neues Fenster verschieben + In neues Fenster kopieren Repositories Einfügen Vor {0} Tagen diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml index 655f6e976..20d0d810e 100644 --- a/src/Resources/Locales/en_US.axaml +++ b/src/Resources/Locales/en_US.axaml @@ -500,6 +500,8 @@ Close Other Tabs Close Tabs to the Right Copy Repository Path + Move into New Window + Copy into New Window Repositories Paste {0} days ago diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml index 4ef06eae9..5c22f0da8 100644 --- a/src/Resources/Locales/es_ES.axaml +++ b/src/Resources/Locales/es_ES.axaml @@ -503,6 +503,8 @@ Cerrar Otras Pestañas Cerrar Pestañas a la Derecha Copiar Ruta del Repositorio + Mover a Nueva Ventana + Copiar a Nueva Ventana Repositorios Pegar Hace {0} días diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml index 919dfeac8..332422747 100644 --- a/src/Resources/Locales/fr_FR.axaml +++ b/src/Resources/Locales/fr_FR.axaml @@ -411,6 +411,8 @@ Fermer les autres onglets Fermer les onglets à droite Copier le chemin vers le dépôt + Déplacer vers une nouvelle fenêtre + Copier vers une nouvelle fenêtre Dépôts Coller il y a {0} jours diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml index c12e3e53c..abcd13fbf 100644 --- a/src/Resources/Locales/it_IT.axaml +++ b/src/Resources/Locales/it_IT.axaml @@ -431,6 +431,8 @@ Chiudi Altri Tab Chiudi i Tab a Destra Copia Percorso Repository + Sposta in Nuova Finestra + Copia in Nuova Finestra Repository Incolla {0} giorni fa diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml index 32c41f216..d65ab3710 100644 --- a/src/Resources/Locales/ja_JP.axaml +++ b/src/Resources/Locales/ja_JP.axaml @@ -410,6 +410,8 @@ 他のタブを閉じる 右のタブを閉じる リポジトリパスをコピー + 新しいウィンドウに移動 + 新しいウィンドウにコピー リポジトリ 貼り付け {0} 日前 diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml index 3fbac432f..331fb195e 100644 --- a/src/Resources/Locales/pt_BR.axaml +++ b/src/Resources/Locales/pt_BR.axaml @@ -373,6 +373,8 @@ Fechar Outras Abas Fechar Abas à Direita Copiar Caminho do Repositório + Mover para Nova Janela + Copiar para Nova Janela Repositórios Colar {0} dias atrás diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml index 413b99e32..7aeddf5f7 100644 --- a/src/Resources/Locales/ru_RU.axaml +++ b/src/Resources/Locales/ru_RU.axaml @@ -503,6 +503,8 @@ Закрыть другие вкладки Закрыть вкладки справа Копировать путь репозитория + Переместить в новое окно + Копировать в новое окно Репозитории Вставить {0} дней назад diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml index 3a0c8e532..3947c4f55 100644 --- a/src/Resources/Locales/ta_IN.axaml +++ b/src/Resources/Locales/ta_IN.axaml @@ -410,6 +410,8 @@ பிற தாவல்களை மூடு வலதுபுறத்தில் உள்ள தாவல்களை மூடு களஞ்சிய பாதை நகலெடு + புதிய சாளரத்திற்கு நகர்த்து + புதிய சாளரத்திற்கு நகலெடு களஞ்சியங்கள் ஒட்டு {0} நாட்களுக்கு முன்பு diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml index 46e42fcda..2b6c9c1b8 100644 --- a/src/Resources/Locales/uk_UA.axaml +++ b/src/Resources/Locales/uk_UA.axaml @@ -415,6 +415,8 @@ Закрити інші вкладки Закрити вкладки праворуч Копіювати шлях до сховища + Перемістити в нове вікно + Копіювати в нове вікно Сховища Вставити {0} днів тому diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml index 711ab12f3..afc34083a 100644 --- a/src/Resources/Locales/zh_CN.axaml +++ b/src/Resources/Locales/zh_CN.axaml @@ -504,6 +504,8 @@ 关闭其他标签页 关闭右侧标签页 复制仓库路径 + 移动到新窗口 + 复制到新窗口 新标签页 粘贴 {0}天前 diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml index 61956e97f..ec3cdb254 100644 --- a/src/Resources/Locales/zh_TW.axaml +++ b/src/Resources/Locales/zh_TW.axaml @@ -504,6 +504,8 @@ 關閉其他分頁 關閉右側分頁 複製存放庫路徑 + 移動到新視窗 + 複製到新視窗 新分頁 貼上 {0} 天前 diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index b079ccf61..dd0ef284b 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -495,6 +495,24 @@ public ContextMenu CreateContextForPageTab(LauncherPage page) if (page.Node.IsRepository) { + var moveToNewWindow = new MenuItem(); + moveToNewWindow.Header = App.Text("PageTabBar.Tab.MoveToNewWindow"); + moveToNewWindow.Click += (_, e) => + { + MoveToNewWindow(page); + e.Handled = true; + }; + menu.Items.Add(moveToNewWindow); + + var copyToNewWindow = new MenuItem(); + copyToNewWindow.Header = App.Text("PageTabBar.Tab.CopyToNewWindow"); + copyToNewWindow.Click += (_, e) => + { + CopyToNewWindow(page); + e.Handled = true; + }; + menu.Items.Add(copyToNewWindow); + var bookmark = new MenuItem(); bookmark.Header = App.Text("PageTabBar.Tab.Bookmark"); bookmark.Icon = App.CreateMenuIcon("Icons.Bookmark"); @@ -534,6 +552,20 @@ public ContextMenu CreateContextForPageTab(LauncherPage page) return menu; } + public void MoveToNewWindow(LauncherPage page) + { + CloseTab(page); + + var newWindow = new Views.Launcher() { DataContext = new Launcher(page.Node.Id) }; + newWindow.Show(); + } + + public void CopyToNewWindow(LauncherPage page) + { + var newWindow = new Views.Launcher() { DataContext = new Launcher(page.Node.Id) }; + newWindow.Show(); + } + private string GetRepositoryGitDir(string repo) { var fullpath = Path.Combine(repo, ".git"); From c2d339acb9246c2902d36b4378c9825dc0f08335 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=AE=E3=83=A3=E3=83=83=E3=83=97?= Date: Mon, 21 Jul 2025 10:34:22 +0200 Subject: [PATCH 2/5] refactor: Add secondary window support in Launcher class - Introduced `IsSecondaryWindow` property and `OnRequestClose` event in the `Launcher` view model. - Updated the constructor to accept a boolean for secondary window status. - Modified `Quit` method to handle close requests for secondary windows. - Refactored `MoveToNewWindow` and `CopyToNewWindow` methods to streamline window creation. - Added `RegisterOnRequestClose` method in the `Launcher` view to manage close requests. - Updated `using` directives in `Launcher.axaml.cs` to include `Avalonia.Threading`. --- src/ViewModels/Launcher.cs | 29 ++++++++++++++++++++++------- src/Views/Launcher.axaml.cs | 7 +++++++ 2 files changed, 29 insertions(+), 7 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index dd0ef284b..7693a3dc1 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -50,7 +50,15 @@ public IDisposable Switcher private set => SetProperty(ref _switcher, value); } - public Launcher(string startupRepo) + public bool IsSecondaryWindow + { + get => _isSecondaryWindow; + set => SetProperty(ref _isSecondaryWindow, value); + } + + public event Action OnRequestClose; + + public Launcher(string startupRepo, bool isSecondaryWindow = false) { _ignoreIndexChange = true; @@ -116,6 +124,8 @@ public Launcher(string startupRepo) if (string.IsNullOrEmpty(_title)) UpdateTitle(); + + IsSecondaryWindow = isSecondaryWindow; } public void Quit() @@ -273,7 +283,10 @@ public void CloseTab(LauncherPage page) } else { - App.Quit(0); + if (IsSecondaryWindow) + OnRequestClose?.Invoke(); + else + App.Quit(0); } return; @@ -554,15 +567,16 @@ public ContextMenu CreateContextForPageTab(LauncherPage page) public void MoveToNewWindow(LauncherPage page) { + NewWindow(page); CloseTab(page); - - var newWindow = new Views.Launcher() { DataContext = new Launcher(page.Node.Id) }; - newWindow.Show(); } - public void CopyToNewWindow(LauncherPage page) + public void CopyToNewWindow(LauncherPage page) => NewWindow(page); + + private void NewWindow(LauncherPage page) { - var newWindow = new Views.Launcher() { DataContext = new Launcher(page.Node.Id) }; + var newWindow = new Views.Launcher() { DataContext = new Launcher(page.Node.Id, true) }; + newWindow.RegisterOnRequestClose(); newWindow.Show(); } @@ -643,5 +657,6 @@ private void UpdateTitle() private bool _ignoreIndexChange = false; private string _title = string.Empty; private IDisposable _switcher = null; + private bool _isSecondaryWindow = false; } } diff --git a/src/Views/Launcher.axaml.cs b/src/Views/Launcher.axaml.cs index 4c8a4f9a1..8786a16ac 100644 --- a/src/Views/Launcher.axaml.cs +++ b/src/Views/Launcher.axaml.cs @@ -5,6 +5,7 @@ using Avalonia.Input; using Avalonia.Interactivity; using Avalonia.Platform; +using Avalonia.Threading; using Avalonia.VisualTree; namespace SourceGit.Views @@ -85,6 +86,12 @@ public Launcher() WindowStartupLocation = WindowStartupLocation.CenterScreen; } + public void RegisterOnRequestClose() + { + if (DataContext is ViewModels.Launcher vm) + vm.OnRequestClose += () => Dispatcher.UIThread.Post(Close); + } + public void BringToTop() { if (WindowState == WindowState.Minimized) From ee36ed10318c5670511dff6b1db62cb0e718f922 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=AE=E3=83=A3=E3=83=83=E3=83=97?= Date: Mon, 21 Jul 2025 10:44:08 +0200 Subject: [PATCH 3/5] refactor: Copilot review [nitpick] The nested if-else structure could be simplified for better readability. Consider early return pattern: 'if (IsSecondaryWindow) { OnRequestClose?.Invoke(); return; }' --- src/ViewModels/Launcher.cs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index 7693a3dc1..e9bad5ac2 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -284,9 +284,13 @@ public void CloseTab(LauncherPage page) else { if (IsSecondaryWindow) + { OnRequestClose?.Invoke(); - else - App.Quit(0); + + return; + } + + App.Quit(0); } return; From 4beba0899fd32c338a6cdff9c9a5e08e3271a913 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E3=82=AE=E3=83=A3=E3=83=83=E3=83=97?= Date: Mon, 21 Jul 2025 10:48:05 +0200 Subject: [PATCH 4/5] fix: Format Check workflow failure --- src/ViewModels/Launcher.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ViewModels/Launcher.cs b/src/ViewModels/Launcher.cs index e9bad5ac2..c7dcd6667 100644 --- a/src/ViewModels/Launcher.cs +++ b/src/ViewModels/Launcher.cs @@ -289,7 +289,7 @@ public void CloseTab(LauncherPage page) return; } - + App.Quit(0); } From 05dba3261478b96ea70e51ac65ff93db4278e440 Mon Sep 17 00:00:00 2001 From: leo Date: Mon, 21 Jul 2025 16:44:00 +0800 Subject: [PATCH 5/5] fix: try to fix the issue that getting askpass for every action even when it's not necessary (#1577) Signed-off-by: leo --- build/resources/_common/applications/sourcegit.desktop | 2 +- build/resources/_common/sourcegit | 4 ++++ build/resources/appimage/sourcegit | 4 ++++ build/resources/rpm/SPECS/build.spec | 3 ++- build/scripts/package.linux.sh | 6 ++++-- src/Commands/Command.cs | 2 +- 6 files changed, 16 insertions(+), 5 deletions(-) create mode 100644 build/resources/_common/sourcegit create mode 100644 build/resources/appimage/sourcegit diff --git a/build/resources/_common/applications/sourcegit.desktop b/build/resources/_common/applications/sourcegit.desktop index bcf9c813c..42b1bcf5e 100644 --- a/build/resources/_common/applications/sourcegit.desktop +++ b/build/resources/_common/applications/sourcegit.desktop @@ -1,7 +1,7 @@ [Desktop Entry] Name=SourceGit Comment=Open-source & Free Git GUI Client -Exec=/opt/sourcegit/sourcegit +Exec=/usr/bin/sourcegit Icon=/usr/share/icons/sourcegit.png Terminal=false Type=Application diff --git a/build/resources/_common/sourcegit b/build/resources/_common/sourcegit new file mode 100644 index 000000000..0ff93d3a9 --- /dev/null +++ b/build/resources/_common/sourcegit @@ -0,0 +1,4 @@ +#!/bin/bash + +eval `ssh-agent -s` +/opt/sourcegit/sourcegit $@ diff --git a/build/resources/appimage/sourcegit b/build/resources/appimage/sourcegit new file mode 100644 index 000000000..b0f9ee31c --- /dev/null +++ b/build/resources/appimage/sourcegit @@ -0,0 +1,4 @@ +#!/bin/bash + +eval `ssh-agent -s` +"$APPDIR/opt/sourcegit/sourcegit" $@ diff --git a/build/resources/rpm/SPECS/build.spec b/build/resources/rpm/SPECS/build.spec index 2a684837a..0deab37a6 100644 --- a/build/resources/rpm/SPECS/build.spec +++ b/build/resources/rpm/SPECS/build.spec @@ -21,11 +21,12 @@ mkdir -p %{buildroot}/%{_bindir} mkdir -p %{buildroot}/usr/share/applications mkdir -p %{buildroot}/usr/share/icons cp -f ../../../SourceGit/* %{buildroot}/opt/sourcegit/ -ln -rsf %{buildroot}/opt/sourcegit/sourcegit %{buildroot}/%{_bindir} +cp -f ../../_common/sourcegit %{buildroot}/%{_bindir} cp -r ../../_common/applications %{buildroot}/%{_datadir} cp -r ../../_common/icons %{buildroot}/%{_datadir} chmod 755 -R %{buildroot}/opt/sourcegit chmod 755 %{buildroot}/%{_datadir}/applications/sourcegit.desktop +chmod 755 %{buildroot}/%{_bindir}/sourcegit %files %dir /opt/sourcegit/ diff --git a/build/scripts/package.linux.sh b/build/scripts/package.linux.sh index 1b4adbdcb..d1a4fdeba 100755 --- a/build/scripts/package.linux.sh +++ b/build/scripts/package.linux.sh @@ -42,7 +42,8 @@ desktop-file-install resources/_common/applications/sourcegit.desktop --dir Sour --set-icon com.sourcegit_scm.SourceGit --set-key=Exec --set-value=AppRun mv SourceGit.AppDir/usr/share/applications/{sourcegit,com.sourcegit_scm.SourceGit}.desktop cp resources/appimage/sourcegit.png SourceGit.AppDir/com.sourcegit_scm.SourceGit.png -ln -rsf SourceGit.AppDir/opt/sourcegit/sourcegit SourceGit.AppDir/AppRun +cp -f resources/appimage/sourcegit SourceGit.AppDir/AppRun +chmod 755 SourceGit.AppDir/AppRun ln -rsf SourceGit.AppDir/usr/share/applications/com.sourcegit_scm.SourceGit.desktop SourceGit.AppDir cp resources/appimage/sourcegit.appdata.xml SourceGit.AppDir/usr/share/metainfo/com.sourcegit_scm.SourceGit.appdata.xml @@ -53,9 +54,10 @@ mkdir -p resources/deb/usr/bin mkdir -p resources/deb/usr/share/applications mkdir -p resources/deb/usr/share/icons cp -f SourceGit/* resources/deb/opt/sourcegit -ln -rsf resources/deb/opt/sourcegit/sourcegit resources/deb/usr/bin +cp -f resources/_common/sourcegit resources/deb/usr/bin/ cp -r resources/_common/applications resources/deb/usr/share cp -r resources/_common/icons resources/deb/usr/share +chmod 755 resources/deb/usr/bin/sourcegit # Calculate installed size in KB installed_size=$(du -sk resources/deb | cut -f1) # Update the control file diff --git a/src/Commands/Command.cs b/src/Commands/Command.cs index 11a25b369..666926cc5 100644 --- a/src/Commands/Command.cs +++ b/src/Commands/Command.cs @@ -172,7 +172,7 @@ private ProcessStartInfo CreateGitStartInfo(bool redirect) // If an SSH private key was provided, sets the environment. if (!start.Environment.ContainsKey("GIT_SSH_COMMAND") && !string.IsNullOrEmpty(SSHKey)) - start.Environment.Add("GIT_SSH_COMMAND", $"ssh -i '{SSHKey}'"); + start.Environment.Add("GIT_SSH_COMMAND", $"ssh -o AddKeysToAgent=yes -i {SSHKey.Quoted()}"); // Force using en_US.UTF-8 locale if (OperatingSystem.IsLinux())