Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 1 addition & 6 deletions src/Views/CommitBaseInfo.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,7 @@
<StackPanel Grid.Row="0" Grid.Column="1" Orientation="Horizontal" Height="24">
<TextBlock Text="{Binding SHA}" Margin="12,0,4,0" FontFamily="{DynamicResource Fonts.Monospace}" VerticalAlignment="Center"/>

<Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnCopyCommitSHA" ToolTip.Tip="{DynamicResource Text.Copy}">
<Grid>
<Path Width="12" Height="12" Data="{StaticResource Icons.Copy}" IsVisible="{Binding #ThisControl.IsSHACopied, Mode=OneWay, Converter={x:Static BoolConverters.Not}}"/>
<Path Width="14" Height="14" Margin="0,2,0,0" Data="{StaticResource Icons.Check}" Fill="Green" IsVisible="{Binding #ThisControl.IsSHACopied, Mode=OneWay}"/>
</Grid>
</Button>
<v:CopyButton Width="24" Cursor="Hand" CopyText="{Binding SHA}" ToolTip.Tip="{DynamicResource Text.Copy}"/>

<Button Classes="icon_button" Width="24" Cursor="Hand" Click="OnOpenContainsIn" IsVisible="{Binding #ThisControl.SupportsContainsIn}" ToolTip.Tip="{DynamicResource Text.CommitDetail.Info.ContainsIn}">
<Path Width="14" Height="14" Margin="0,1,0,0" Data="{StaticResource Icons.Milestone}"/>
Expand Down
63 changes: 0 additions & 63 deletions src/Views/CommitBaseInfo.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Avalonia.Controls;
using Avalonia.Input;
using Avalonia.Interactivity;
using Avalonia.Threading;

namespace SourceGit.Views
{
Expand Down Expand Up @@ -47,17 +46,6 @@ public List<Models.CommitLink> WebLinks
set => SetAndRaise(WebLinksProperty, ref _webLinks, value);
}

public static readonly DirectProperty<CommitBaseInfo, bool> IsSHACopiedProperty =
AvaloniaProperty.RegisterDirect<CommitBaseInfo, bool>(
nameof(IsSHACopied),
static o => o.IsSHACopied);

public bool IsSHACopied
{
get => _isSHACopied;
private set => SetAndRaise(IsSHACopiedProperty, ref _isSHACopied, value);
}

public static readonly DirectProperty<CommitBaseInfo, bool> SupportsContainsInProperty =
AvaloniaProperty.RegisterDirect<CommitBaseInfo, bool>(
nameof(SupportsContainsIn),
Expand All @@ -80,45 +68,6 @@ protected override void OnDataContextChanged(EventArgs e)
SupportsContainsIn = DataContext is ViewModels.CommitDetail;
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);

if (change.Property == ContentProperty)
{
IsSHACopied = false;
_iconResetTimer?.Stop();
}
}

protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);

_iconResetTimer = new DispatcherTimer();
_iconResetTimer.Interval = TimeSpan.FromSeconds(1);
_iconResetTimer.Tag = this;
_iconResetTimer.Tick += static (o, _) =>
{
if (o is DispatcherTimer { Tag: CommitBaseInfo view } timer)
{
if (view.IsSHACopied)
view.IsSHACopied = false;

timer.IsEnabled = false;
}
};
_iconResetTimer.IsEnabled = false;
}

protected override void OnUnloaded(RoutedEventArgs e)
{
_iconResetTimer.Tag = null;
_iconResetTimer.IsEnabled = false;

base.OnUnloaded(e);
}

private void OnDateTimeContextMenuRequested(object sender, ContextRequestedEventArgs e)
{
if (sender is DateTimePresenter presenter)
Expand All @@ -139,16 +88,6 @@ private void OnDateTimeContextMenuRequested(object sender, ContextRequestedEvent
}
}

private async void OnCopyCommitSHA(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: Models.Commit commit })
await this.CopyTextAsync(commit.SHA);

IsSHACopied = true;
_iconResetTimer?.Start();
e.Handled = true;
}

private void OnOpenWebLink(object sender, RoutedEventArgs e)
{
if (DataContext is ViewModels.CommitDetail detail && sender is Control control)
Expand Down Expand Up @@ -323,7 +262,5 @@ sender is CommitRefsPresenter presenter &&
private Models.CommitSignInfo _signInfo = null;
private bool _supportsContainsIn = false;
private List<Models.CommitLink> _webLinks = null;
private bool _isSHACopied = false;
private DispatcherTimer _iconResetTimer = null;
}
}
125 changes: 125 additions & 0 deletions src/Views/CopyButton.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,125 @@
using System;

using Avalonia;
using Avalonia.Controls;
using Avalonia.Controls.Shapes;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Threading;

namespace SourceGit.Views
{
public class CopyButton : Button
{
protected override Type StyleKeyOverride => typeof(Button);

public static readonly DirectProperty<CopyButton, string> CopyTextProperty =
AvaloniaProperty.RegisterDirect<CopyButton, string>(
nameof(CopyText),
static o => o.CopyText,
static (o, v) => o.CopyText = v);

public string CopyText
{
get => _copyText;
set => SetAndRaise(CopyTextProperty, ref _copyText, value);
}

public static readonly DirectProperty<CopyButton, bool> IsCopiedProperty =
AvaloniaProperty.RegisterDirect<CopyButton, bool>(
nameof(IsCopied),
static o => o.IsCopied);

public bool IsCopied
{
get => _isCopied;
private set => SetAndRaise(IsCopiedProperty, ref _isCopied, value);
}

public CopyButton()
{
Classes.Add("icon_button");

_copyIcon = new Path() { Width = 12, Height = 12 };
_checkIcon = new Path()
{
Width = 14,
Height = 14,
Margin = new Thickness(0, 2, 0, 0),
Fill = Brushes.Green,
IsVisible = false,
};

var grid = new Grid();
grid.Children.Add(_copyIcon);
grid.Children.Add(_checkIcon);
Content = grid;
}

protected override void OnLoaded(RoutedEventArgs e)
{
base.OnLoaded(e);

if (this.FindResource("Icons.Copy") is Geometry copyGeo)
_copyIcon.Data = copyGeo;
if (this.FindResource("Icons.Check") is Geometry checkGeo)
_checkIcon.Data = checkGeo;

_resetTimer = new DispatcherTimer();
_resetTimer.Interval = TimeSpan.FromSeconds(1);
_resetTimer.Tag = this;
_resetTimer.Tick += static (o, _) =>
{
if (o is DispatcherTimer { Tag: CopyButton btn } timer)
{
btn.IsCopied = false;
timer.IsEnabled = false;
}
};
_resetTimer.IsEnabled = false;
}

protected override void OnUnloaded(RoutedEventArgs e)
{
_resetTimer.Tag = null;
_resetTimer.IsEnabled = false;
base.OnUnloaded(e);
}

protected override void OnPropertyChanged(AvaloniaPropertyChangedEventArgs change)
{
base.OnPropertyChanged(change);

if (change.Property == IsCopiedProperty)
{
_copyIcon.IsVisible = !_isCopied;
_checkIcon.IsVisible = _isCopied;
}
else if (change.Property == CopyTextProperty)
{
// Reset the copied state when CopyText changes (e.g. switching to a different commit)
IsCopied = false;
_resetTimer?.Stop();
}
}

protected override async void OnClick()
{
base.OnClick();

var text = CopyText;
if (string.IsNullOrEmpty(text))
return;

await this.CopyTextAsync(text);
IsCopied = true;
_resetTimer?.Start();
}

private readonly Path _copyIcon;
private readonly Path _checkIcon;
private string _copyText = string.Empty;
private bool _isCopied = false;
private DispatcherTimer _resetTimer = null;
}
}
4 changes: 1 addition & 3 deletions src/Views/LauncherPage.axaml
Original file line number Diff line number Diff line change
Expand Up @@ -166,9 +166,7 @@
<Path Grid.Column="0" Width="14" Height="14" Data="{StaticResource Icons.Info}" Fill="Green" IsVisible="{Binding !IsError}"/>
<TextBlock Grid.Column="1" Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Error}" IsVisible="{Binding IsError}"/>
<TextBlock Grid.Column="1" Margin="8,0,0,0" FontWeight="Bold" FontSize="14" Text="{DynamicResource Text.Launcher.Info}" IsVisible="{Binding !IsError}"/>
<Button Grid.Column="2" Classes="icon_button" Width="16" Height="16" Click="OnCopyNotification">
<Path Width="12" Height="12" Data="{StaticResource Icons.Copy}"/>
</Button>
<v:CopyButton Grid.Column="2" Width="16" Height="16" CopyText="{Binding Message}"/>
<Button Grid.Column="3" Classes="icon_button" Width="16" Height="16" Margin="8,0,0,0" Click="OnDismissNotification">
<Path Width="10" Height="10" Data="{StaticResource Icons.Close}"/>
</Button>
Expand Down
8 changes: 0 additions & 8 deletions src/Views/LauncherPage.axaml.cs
Original file line number Diff line number Diff line change
Expand Up @@ -72,14 +72,6 @@ private void OnMaskClicked(object sender, PointerPressedEventArgs e)
OnPopupCancel(sender, e);
}

private async void OnCopyNotification(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: Models.Notification notice })
await this.CopyTextAsync(notice.Message);

e.Handled = true;
}

private void OnDismissNotification(object sender, RoutedEventArgs e)
{
if (sender is Button { DataContext: Models.Notification notice } &&
Expand Down