diff --git a/src/Models/AvatarManager.cs b/src/Models/AvatarManager.cs
index a9ef3eb4..2edcb619 100644
--- a/src/Models/AvatarManager.cs
+++ b/src/Models/AvatarManager.cs
@@ -17,7 +17,7 @@ namespace SourceGit.Models
{
public interface IAvatarHost
{
- void OnAvatarResourceChanged(string email);
+ void OnAvatarResourceChanged(string email, Bitmap image);
}
public partial class AvatarManager
@@ -119,7 +119,7 @@ namespace SourceGit.Models
Dispatcher.UIThread.InvokeAsync(() =>
{
_resources[email] = img;
- NotifyResourceChanged(email);
+ NotifyResourceChanged(email, img);
});
}
@@ -151,7 +151,7 @@ namespace SourceGit.Models
if (File.Exists(localFile))
File.Delete(localFile);
- NotifyResourceChanged(email);
+ NotifyResourceChanged(email, null);
}
else
{
@@ -186,6 +186,37 @@ namespace SourceGit.Models
return null;
}
+ public void SetFromLocal(string email, string file)
+ {
+ try
+ {
+ Bitmap image = null;
+
+ using (var stream = File.OpenRead(file))
+ {
+ image = Bitmap.DecodeToWidth(stream, 128);
+ }
+
+ if (image == null)
+ return;
+
+ if (_resources.ContainsKey(email))
+ _resources[email] = image;
+ else
+ _resources.Add(email, image);
+
+ _requesting.Remove(email);
+
+ var store = Path.Combine(_storePath, GetEmailHash(email));
+ File.Copy(file, store, true);
+ NotifyResourceChanged(email, image);
+ }
+ catch
+ {
+ // ignore
+ }
+ }
+
private void LoadDefaultAvatar(string key, string img)
{
var icon = AssetLoader.Open(new Uri($"avares://SourceGit/Resources/Images/{img}", UriKind.RelativeOrAbsolute));
@@ -203,12 +234,10 @@ namespace SourceGit.Models
return builder.ToString();
}
- private void NotifyResourceChanged(string email)
+ private void NotifyResourceChanged(string email, Bitmap image)
{
foreach (var avatar in _avatars)
- {
- avatar.OnAvatarResourceChanged(email);
- }
+ avatar.OnAvatarResourceChanged(email, image);
}
}
}
diff --git a/src/Resources/Locales/de_DE.axaml b/src/Resources/Locales/de_DE.axaml
index 3c900d42..b7874216 100644
--- a/src/Resources/Locales/de_DE.axaml
+++ b/src/Resources/Locales/de_DE.axaml
@@ -39,6 +39,7 @@
ALS UNVERÄNDERT ANGENOMMENE DATEIEN
KEINE ALS UNVERÄNDERT ANGENOMMENEN DATEIEN
ENTFERNEN
+ Aktualisieren
BINÄRE DATEI NICHT UNTERSTÜTZT!!!
Bisect
Abbrechen
@@ -550,7 +551,6 @@
Lokale Änderungen stashen & wieder anwenden
Auf:
Rebase:
- Aktualisieren
Remote hinzufügen
Remote bearbeiten
Name:
diff --git a/src/Resources/Locales/en_US.axaml b/src/Resources/Locales/en_US.axaml
index 4834aef9..765b6f8c 100644
--- a/src/Resources/Locales/en_US.axaml
+++ b/src/Resources/Locales/en_US.axaml
@@ -35,6 +35,8 @@
FILES ASSUME UNCHANGED
NO FILES ASSUMED AS UNCHANGED
REMOVE
+ Load Image...
+ Refresh
BINARY FILE NOT SUPPORTED!!!
Bisect
Abort
@@ -561,7 +563,6 @@
Stash & reapply local changes
On:
Rebase:
- Refresh
Add Remote
Edit Remote
Name:
diff --git a/src/Resources/Locales/es_ES.axaml b/src/Resources/Locales/es_ES.axaml
index 36c60346..c1687f9c 100644
--- a/src/Resources/Locales/es_ES.axaml
+++ b/src/Resources/Locales/es_ES.axaml
@@ -39,6 +39,7 @@
ARCHIVOS ASUMIDOS COMO SIN CAMBIOS
NO HAY ARCHIVOS ASUMIDOS COMO SIN CAMBIOS
REMOVER
+ Refrescar
¡ARCHIVO BINARIO NO SOPORTADO!
Bisect
Abortar
@@ -565,7 +566,6 @@
Stash & reaplicar cambios locales
En:
Rebase:
- Refrescar
Añadir Remoto
Editar Remoto
Nombre:
diff --git a/src/Resources/Locales/fr_FR.axaml b/src/Resources/Locales/fr_FR.axaml
index 25e6ca3e..24dd365e 100644
--- a/src/Resources/Locales/fr_FR.axaml
+++ b/src/Resources/Locales/fr_FR.axaml
@@ -39,6 +39,7 @@
FICHIERS PRÉSUMÉS INCHANGÉS
PAS DE FICHIERS PRÉSUMÉS INCHANGÉS
SUPPRIMER
+ Rafraîchir
FICHIER BINAIRE NON SUPPORTÉ !!!
Blâme
LE BLÂME SUR CE FICHIER N'EST PAS SUPPORTÉ!!!
@@ -532,7 +533,6 @@
Stash & réappliquer changements locaux
Sur :
Rebase :
- Rafraîchir
Ajouter dépôt distant
Modifier dépôt distant
Nom :
diff --git a/src/Resources/Locales/it_IT.axaml b/src/Resources/Locales/it_IT.axaml
index 22c4e8fe..1484201c 100644
--- a/src/Resources/Locales/it_IT.axaml
+++ b/src/Resources/Locales/it_IT.axaml
@@ -39,6 +39,7 @@
FILE ASSUNTI COME INVARIATI
NESSUN FILE ASSUNTO COME INVARIATO
RIMUOVI
+ Aggiorna
FILE BINARIO NON SUPPORTATO!!!
Biseca
Annulla
@@ -553,7 +554,6 @@
Stasha e Riapplica modifiche locali
Su:
Riallinea:
- Aggiorna
Aggiungi Remoto
Modifica Remoto
Nome:
diff --git a/src/Resources/Locales/ja_JP.axaml b/src/Resources/Locales/ja_JP.axaml
index 945cf2d9..db395d86 100644
--- a/src/Resources/Locales/ja_JP.axaml
+++ b/src/Resources/Locales/ja_JP.axaml
@@ -39,6 +39,7 @@
変更されていないとみなされるファイル
変更されていないとみなされるファイルはありません
削除
+ 更新
バイナリファイルはサポートされていません!!!
Blame
BLAMEではこのファイルはサポートされていません!!!
@@ -531,7 +532,6 @@
ローカルの変更をスタッシュして再適用
On:
リベース:
- 更新
リモートを追加
リモートを編集
名前:
diff --git a/src/Resources/Locales/pt_BR.axaml b/src/Resources/Locales/pt_BR.axaml
index a75d6777..2d34f612 100644
--- a/src/Resources/Locales/pt_BR.axaml
+++ b/src/Resources/Locales/pt_BR.axaml
@@ -33,6 +33,7 @@
ARQUIVOS CONSIDERADOS SEM ALTERAÇÕES
NENHUM ARQUIVO CONSIDERADO SEM ALTERAÇÕES
REMOVER
+ Atualizar
ARQUIVO BINÁRIO NÃO SUPORTADO!!!
Blame
BLAME NESTE ARQUIVO NÃO É SUPORTADO!!!
@@ -488,7 +489,6 @@
Guardar & reaplicar alterações locais
Em:
Rebase:
- Atualizar
Adicionar Remoto
Editar Remoto
Nome:
diff --git a/src/Resources/Locales/ru_RU.axaml b/src/Resources/Locales/ru_RU.axaml
index 0a6ccba4..537a3deb 100644
--- a/src/Resources/Locales/ru_RU.axaml
+++ b/src/Resources/Locales/ru_RU.axaml
@@ -39,6 +39,7 @@
НЕОТСЛЕЖИВАЕМЫЕ ФАЙЛЫ
СПИСОК ПУСТ
УДАЛИТЬ
+ Обновить
ДВОИЧНЫЙ ФАЙЛ НЕ ПОДДЕРЖИВАЕТСЯ!!!
Раздвоить
О
@@ -564,7 +565,6 @@
Отложить и применить повторно локальные изменения
На:
Переместить:
- Обновить
Добавить внешний репозиторий
Редактировать внешний репозиторий
Имя:
diff --git a/src/Resources/Locales/ta_IN.axaml b/src/Resources/Locales/ta_IN.axaml
index e66af3ff..7f3542c3 100644
--- a/src/Resources/Locales/ta_IN.axaml
+++ b/src/Resources/Locales/ta_IN.axaml
@@ -39,6 +39,7 @@
கோப்புகள் மாற்றப்படவில்லை எனக் கருதப்படுகிறது
எந்த கோப்புகளும் மாற்றப்படவில்லை எனக் கருதப்படுகிறது
நீக்கு
+ புதுப்பி
இருமம் கோப்பு ஆதரிக்கப்படவில்லை!!!
குற்றச்சாட்டு
இந்த கோப்பில் குற்றம் சாட்ட ஆதரிக்கப்படவில்லை!!!
@@ -531,7 +532,6 @@
உள்ளக மாற்றங்களை பதுக்கிவை & மீண்டும் இடு
மேல்:
மறுதளம்:
- புதுப்பி
தொலையைச் சேர்
தொலையைத் திருத்து
பெயர்:
diff --git a/src/Resources/Locales/uk_UA.axaml b/src/Resources/Locales/uk_UA.axaml
index 2e7b399b..62842054 100644
--- a/src/Resources/Locales/uk_UA.axaml
+++ b/src/Resources/Locales/uk_UA.axaml
@@ -39,6 +39,7 @@
ФАЙЛИ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
НЕМАЄ ФАЙЛІВ, ЩО ВВАЖАЮТЬСЯ НЕЗМІНЕНИМИ
ВИДАЛИТИ
+ Оновити
БІНАРНИЙ ФАЙЛ НЕ ПІДТРИМУЄТЬСЯ!!!
Автор рядка
ПОШУК АВТОРА РЯДКА ДЛЯ ЦЬОГО ФАЙЛУ НЕ ПІДТРИМУЄТЬСЯ!!!
@@ -536,7 +537,6 @@
Сховати та застосувати локальні зміни
На:
Перебазувати:
- Оновити
Додати віддалене сховище
Редагувати віддалене сховище
Назва:
diff --git a/src/Resources/Locales/zh_CN.axaml b/src/Resources/Locales/zh_CN.axaml
index 77a55f75..c2a44bbf 100644
--- a/src/Resources/Locales/zh_CN.axaml
+++ b/src/Resources/Locales/zh_CN.axaml
@@ -39,6 +39,8 @@
不跟踪更改的文件
没有不跟踪更改的文件
移除
+ 加载本地图片
+ 重新加载
二进制文件不支持该操作!!!
二分定位(bisect)
终止
@@ -565,7 +567,6 @@
自动贮藏并恢复本地变更
目标提交 :
分支 :
- 重新加载
添加远程仓库
编辑远程仓库
远程名 :
diff --git a/src/Resources/Locales/zh_TW.axaml b/src/Resources/Locales/zh_TW.axaml
index aef769de..a4e6074b 100644
--- a/src/Resources/Locales/zh_TW.axaml
+++ b/src/Resources/Locales/zh_TW.axaml
@@ -39,6 +39,8 @@
不追蹤變更的檔案
沒有不追蹤變更的檔案
移除
+ 載入本機圖片...
+ 重新載入
二進位檔案不支援該操作!
二分搜尋 (bisect)
中止
@@ -565,7 +567,6 @@
自動擱置變更並復原本機變更
目標提交:
分支:
- 重新載入
新增遠端存放庫
編輯遠端存放庫
遠端名稱:
diff --git a/src/Views/Avatar.cs b/src/Views/Avatar.cs
index 5dacac69..d8d8c564 100644
--- a/src/Views/Avatar.cs
+++ b/src/Views/Avatar.cs
@@ -1,5 +1,6 @@
using System;
using System.Globalization;
+using System.IO;
using System.Security.Cryptography;
using System.Text;
@@ -8,6 +9,7 @@ using Avalonia.Controls;
using Avalonia.Interactivity;
using Avalonia.Media;
using Avalonia.Media.Imaging;
+using Avalonia.Platform.Storage;
namespace SourceGit.Views
{
@@ -24,16 +26,6 @@ namespace SourceGit.Views
public Avatar()
{
- var refetch = new MenuItem() { Header = App.Text("RefetchAvatar") };
- refetch.Click += (_, _) =>
- {
- if (User != null)
- Models.AvatarManager.Instance.Request(User.Email, true);
- };
-
- ContextMenu = new ContextMenu();
- ContextMenu.Items.Add(refetch);
-
RenderOptions.SetBitmapInterpolationMode(this, BitmapInterpolationMode.HighQuality);
}
@@ -102,11 +94,11 @@ namespace SourceGit.Views
clip.Dispose();
}
- public void OnAvatarResourceChanged(string email)
+ public void OnAvatarResourceChanged(string email, Bitmap image)
{
if (User.Email.Equals(email, StringComparison.Ordinal))
{
- _img = Models.AvatarManager.Instance.Request(User.Email, false);
+ _img = image;
InvalidateVisual();
}
}
@@ -115,11 +107,13 @@ namespace SourceGit.Views
{
base.OnLoaded(e);
Models.AvatarManager.Instance.Subscribe(this);
+ ContextRequested += OnContextRequested;
}
protected override void OnUnloaded(RoutedEventArgs e)
{
base.OnUnloaded(e);
+ ContextRequested -= OnContextRequested;
Models.AvatarManager.Instance.Unsubscribe(this);
}
@@ -138,6 +132,94 @@ namespace SourceGit.Views
}
}
+ private void OnContextRequested(object sender, ContextRequestedEventArgs e)
+ {
+ var toplevel = TopLevel.GetTopLevel(this);
+ if (toplevel == null)
+ {
+ e.Handled = true;
+ return;
+ }
+
+ var refetch = new MenuItem();
+ refetch.Icon = App.CreateMenuIcon("Icons.Loading");
+ refetch.Header = App.Text("Avatar.Refetch");
+ refetch.Click += (_, ev) =>
+ {
+ if (User != null)
+ Models.AvatarManager.Instance.Request(User.Email, true);
+
+ ev.Handled = true;
+ };
+
+ var load = new MenuItem();
+ load.Icon = App.CreateMenuIcon("Icons.Folder.Open");
+ load.Header = App.Text("Avatar.Load");
+ load.Click += async (_, ev) =>
+ {
+ var options = new FilePickerOpenOptions()
+ {
+ FileTypeFilter = [new FilePickerFileType("PNG") { Patterns = ["*.png"] }],
+ AllowMultiple = false,
+ };
+
+ var selected = await toplevel.StorageProvider.OpenFilePickerAsync(options);
+ if (selected.Count == 1)
+ {
+ var localFile = selected[0].Path.LocalPath;
+ Models.AvatarManager.Instance.SetFromLocal(User.Email, localFile);
+ }
+
+ ev.Handled = true;
+ };
+
+ var saveAs = new MenuItem();
+ saveAs.Icon = App.CreateMenuIcon("Icons.Save");
+ saveAs.Header = App.Text("SaveAs");
+ saveAs.Click += async (_, ev) =>
+ {
+ var options = new FilePickerSaveOptions();
+ options.Title = App.Text("SaveAs");
+ options.DefaultExtension = ".png";
+ options.FileTypeChoices = [new FilePickerFileType("PNG") { Patterns = ["*.png"] }];
+
+ var storageFile = await toplevel.StorageProvider.SaveFilePickerAsync(options);
+ if (storageFile != null)
+ {
+ var saveTo = storageFile.Path.LocalPath;
+ using (var writer = File.OpenWrite(saveTo))
+ {
+ if (_img != null)
+ {
+ _img.Save(writer);
+ }
+ else
+ {
+ var pixelSize = new PixelSize((int)Bounds.Width, (int)Bounds.Height);
+ var dpi = new Vector(96, 96);
+
+ using (var rt = new RenderTargetBitmap(pixelSize, dpi))
+ using (var ctx = rt.CreateDrawingContext())
+ {
+ this.Render(ctx);
+ rt.Save(writer);
+ }
+ }
+ }
+ }
+
+ ev.Handled = true;
+ };
+
+ var menu = new ContextMenu();
+ menu.Items.Add(refetch);
+ menu.Items.Add(load);
+ menu.Items.Add(new MenuItem() { Header = "-" });
+ menu.Items.Add(saveAs);
+
+ menu.Open(this);
+ }
+
private Bitmap _img = null;
}
}