code_review: PR #1890

- Re-design LFS Locks window
- Unlocking multiple files is only used in `LFS Locks` window. Remove it from `ViewModels.Repository`
- Use `App.AskConfirmAsync` instead of show confirm window manually
- Add missing translation for Chinese

Signed-off-by: leo <longshuang@msn.cn>
This commit is contained in:
leo
2025-11-03 10:57:25 +08:00
parent bdeac3e530
commit 0f56df35bc
8 changed files with 53 additions and 79 deletions

View File

@@ -94,19 +94,16 @@ namespace SourceGit.Commands
return await ExecAsync().ConfigureAwait(false);
}
public async Task<bool> UnlockAsync(string remote, List<string> files, bool force)
public async Task<bool> UnlockMultipleAsync(string remote, List<string> files, bool force)
{
var builder = new StringBuilder();
builder
.Append("lfs unlock --remote=")
.Append(remote)
.Append(force ? " -f " : " ");
.Append(force ? " -f" : " ");
foreach (string file in files)
{
builder.Append(file.Quoted());
builder.Append(" ");
}
builder.Append(' ').Append(file.Quoted());
Args = builder.ToString();
return await ExecAsync().ConfigureAwait(false);

View File

@@ -441,10 +441,10 @@
<x:String x:Key="Text.GitLFS.Locks.Empty" xml:space="preserve">No Locked Files</x:String>
<x:String x:Key="Text.GitLFS.Locks.Lock" xml:space="preserve">Lock</x:String>
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">Show only my locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAll.Confirm" xml:space="preserve">Are you sure you want to unlock all your locked files?</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks" xml:space="preserve">Unlock all of my locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS Locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">Unlock</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks" xml:space="preserve">Unlock all of my locks</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks.Confirm" xml:space="preserve">Are you sure you want to unlock all your locked files?</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">Force Unlock</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">Prune</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">Run `git lfs prune` to delete old LFS files from local storage</x:String>

View File

@@ -447,6 +447,8 @@
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">仅显示被我锁定的文件</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS对象锁状态</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解锁</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks" xml:space="preserve">解锁所有被我锁定的文件</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks.Confirm" xml:space="preserve">确定要解锁所有被您锁定的文件吗?</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">强制解锁</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">精简本地LFS对象存储</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">运行`git lfs prune`命令从本地存储中精简当前版本不需要的LFS对象</x:String>

View File

@@ -447,6 +447,8 @@
<x:String x:Key="Text.GitLFS.Locks.OnlyMine" xml:space="preserve">僅顯示被我鎖定的檔案</x:String>
<x:String x:Key="Text.GitLFS.Locks.Title" xml:space="preserve">LFS 物件鎖</x:String>
<x:String x:Key="Text.GitLFS.Locks.Unlock" xml:space="preserve">解鎖</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks" xml:space="preserve">解鎖所有由我鎖定的檔案</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockAllMyLocks.Confirm" xml:space="preserve">您確定要解鎖所有由您自己鎖定的檔案嗎?</x:String>
<x:String x:Key="Text.GitLFS.Locks.UnlockForce" xml:space="preserve">強制解鎖</x:String>
<x:String x:Key="Text.GitLFS.Prune" xml:space="preserve">清理 (prune)</x:String>
<x:String x:Key="Text.GitLFS.Prune.Tips" xml:space="preserve">執行 `git lfs prune` 以從本機中清理目前版本不需要的 LFS 物件</x:String>

View File

@@ -3,7 +3,6 @@ using System.Collections.Generic;
using System.Threading.Tasks;
using Avalonia.Threading;
using CommunityToolkit.Mvvm.ComponentModel;
using SourceGit.Models;
namespace SourceGit.ViewModels
{
@@ -73,29 +72,29 @@ namespace SourceGit.ViewModels
IsLoading = false;
}
public async Task UnlockAllMyLocksAsync(bool force = false)
public async Task UnlockAllMyLocksAsync()
{
if (_isLoading)
if (_isLoading || string.IsNullOrEmpty(_userName))
return;
IsLoading = true;
List<string> myLocks = [];
foreach (LFSLock lfsLock in _cachedLocks)
var locks = new List<string>();
foreach (var lfsLock in _cachedLocks)
{
if (lfsLock.Owner.Name.Equals(_userName, StringComparison.Ordinal))
{
myLocks.Add(lfsLock.Path);
}
locks.Add(lfsLock.Path);
}
bool succ = await _repo.UnlockLFSFilesAsync(_remote, myLocks, force, false);
var log = _repo.CreateLog("Unlock LFS Locks");
var succ = await new Commands.LFS(_repo.FullPath).Use(log).UnlockMultipleAsync(_remote, locks, true);
if (succ)
{
_cachedLocks.RemoveAll(lfsLock => lfsLock.Owner.Name.Equals(_userName, StringComparison.Ordinal));
UpdateVisibleLocks();
}
log.Complete();
IsLoading = false;
}

View File

@@ -738,20 +738,6 @@ namespace SourceGit.ViewModels
return succ;
}
public async Task<bool> UnlockLFSFilesAsync(string remote, List<string> paths, bool force, bool notify)
{
CommandLog log = CreateLog("Unlock LFS File");
bool succ = await new Commands.LFS(FullPath)
.Use(log)
.UnlockAsync(remote, paths, force);
if (succ && notify)
App.SendNotification(FullPath, $"Unlocked {paths.Count} files successfully!");
log.Complete();
return succ;
}
public CommandLog CreateLog(string name)
{
var log = new CommandLog(name);

View File

@@ -14,7 +14,7 @@
Title="{DynamicResource Text.GitLFS.Locks.Title}"
Width="600" Height="400"
WindowStartupLocation="CenterOwner">
<Grid RowDefinitions="Auto,Auto,*">
<Grid RowDefinitions="Auto,*,40">
<!-- TitleBar -->
<Grid Grid.Row="0" Height="28" IsVisible="{Binding !#ThisControl.UseSystemWindowFrame}">
<Border Background="{DynamicResource Brush.TitleBar}"
@@ -37,39 +37,9 @@
IsVisible="{OnPlatform True, macOS=False}"/>
</Grid>
<!-- Filter and Unlock All -->
<StackPanel Grid.Row="1"
HorizontalAlignment="Left"
Orientation="Horizontal">
<CheckBox Margin="8,0,4,0"
Content="{DynamicResource Text.GitLFS.Locks.OnlyMine}"
IsChecked="{Binding ShowOnlyMyLocks, Mode=TwoWay}"
VerticalAlignment="Center">
<CheckBox.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</CheckBox.IsEnabled>
</CheckBox>
<Button Margin="4,0,4,0"
Content="{DynamicResource Text.GitLFS.Locks.UnlockAllMyLocks}"
Click="OnUnlockAllMyLocksButtonClicked">
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</Button.IsEnabled>
</Button>
</StackPanel>
<!-- Locked Files -->
<Grid Grid.Row="2">
<ListBox Margin="8,0,8,8"
<Grid Grid.Row="1">
<ListBox Margin="8,8,8,0"
Background="{DynamicResource Brush.Contents}"
ItemsSource="{Binding VisibleLocks}"
SelectionMode="Single"
@@ -130,5 +100,32 @@
HorizontalAlignment="Center" VerticalAlignment="Center"
IsVisible="{Binding IsLoading}"/>
</Grid>
<!-- Filter and Unlock All -->
<Grid Grid.Row="2" ColumnDefinitions="*,Auto" Margin="8,6">
<CheckBox Grid.Column="0"
Content="{DynamicResource Text.GitLFS.Locks.OnlyMine}"
IsChecked="{Binding ShowOnlyMyLocks, Mode=TwoWay}"
VerticalAlignment="Center">
<CheckBox.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</CheckBox.IsEnabled>
</CheckBox>
<Button Grid.Column="1"
Classes="flat primary"
Content="{DynamicResource Text.GitLFS.Locks.UnlockAllMyLocks}"
Click="OnUnlockAllMyLocksButtonClicked">
<Button.IsEnabled>
<MultiBinding Converter="{x:Static BoolConverters.And}">
<Binding Path="HasValidUserName" />
<Binding Path="!IsLoading" />
</MultiBinding>
</Button.IsEnabled>
</Button>
</Grid>
</Grid>
</v:ChromelessWindow>

View File

@@ -29,23 +29,14 @@ namespace SourceGit.Views
private async void OnUnlockAllMyLocksButtonClicked(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.LFSLocks vm)
{
Confirm dialog = new()
{
Message =
{
Text = App.Text("GitLFS.Locks.UnlockAll.Confirm")
}
};
if (DataContext is not ViewModels.LFSLocks vm)
return;
bool result = await dialog.ShowDialog<bool>(this);
if (result)
{
await vm.UnlockAllMyLocksAsync(true);
}
}
var shouldContinue = await App.AskConfirmAsync(App.Text("GitLFS.Locks.UnlockAllMyLocks.Confirm"));
if (!shouldContinue)
return;
await vm.UnlockAllMyLocksAsync();
e.Handled = true;
}
}