Fix ViewModel and UI (#10093)

* Fix avalonia ScrollToEnd

* Refactor ViewModel
This commit is contained in:
DHR60
2026-09-04 06:46:41 +00:00
committed by GitHub
parent fe2e219b7a
commit b8e8321603
20 changed files with 130 additions and 189 deletions
@@ -73,18 +73,16 @@ public class BulkObservableCollection<T> : ObservableCollection<T>
public void ReplaceRange(IEnumerable<T>? collection)
{
if (collection == null)
{
return;
}
_suppressNotification = true;
try
{
Items.Clear();
foreach (var item in collection)
if (collection != null)
{
Items.Add(item);
foreach (var item in collection)
{
Items.Add(item);
}
}
}
finally
+5 -1
View File
@@ -12,7 +12,11 @@ public class TaskManager
_config = config;
_updateFunc = updateFunc;
Task.Run(ScheduledTasks);
_ = Task.Factory.StartNew(
ScheduledTasks,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
private async Task ScheduledTasks()
@@ -17,7 +17,11 @@ public class StatisticsSingboxService
_updateFunc = updateFunc;
_exitFlag = false;
_ = Task.Run(Run);
_ = Task.Factory.StartNew(
Run,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
private async Task Init()
@@ -15,7 +15,11 @@ public class StatisticsXrayService
_updateFunc = updateFunc;
_exitFlag = false;
_ = Task.Run(Run);
_ = Task.Factory.StartNew(
Run,
CancellationToken.None,
TaskCreationOptions.LongRunning,
TaskScheduler.Default);
}
public void Close()
@@ -218,8 +218,7 @@ public partial class AddGroupServerViewModel : MyReactiveObject, ICloseable
public async Task UpdatePreviewList()
{
AllProfilePreviewItemsObs.Clear();
AllProfilePreviewItemsObs.AddRange(await GroupProfileManager.GetChildProfileItemsByProtocolExtra(GetUpdatedProtocolExtra()));
AllProfilePreviewItemsObs.ReplaceRange(await GroupProfileManager.GetChildProfileItemsByProtocolExtra(GetUpdatedProtocolExtra()));
}
private async Task SaveServerAsync()
@@ -36,14 +36,10 @@ public partial class CheckUpdateViewModel : MyReactiveObject
EnableCheckPreReleaseUpdate = _config.CheckUpdateItem.CheckPreReleaseUpdate;
EnableUpdateViaProxy = _config.CheckUpdateItem.UpdateViaProxy;
this.WhenAnyValue(
x => x.EnableCheckPreReleaseUpdate,
y => y == true)
.Subscribe(c => _ = OnCheckPreReleaseUpdateChanged());
this.WhenAnyValue(x => x.EnableCheckPreReleaseUpdate)
.SubscribeAsync(async _ => await OnCheckPreReleaseUpdateChanged());
this.WhenAnyValue(
x => x.EnableUpdateViaProxy,
y => y == true)
this.WhenAnyValue(x => x.EnableUpdateViaProxy)
.Subscribe(c => _ = OnUpdateViaProxyChanged());
RefreshCheckUpdateItems();
@@ -57,8 +53,7 @@ public partial class CheckUpdateViewModel : MyReactiveObject
models.Add(GetGeoFileCheckUpdateModel());
CheckUpdateModels.Clear();
CheckUpdateModels.AddRange(models);
CheckUpdateModels.ReplaceRange(models);
}
private CheckUpdateModel GetCheckUpdateModel(ECoreType coreType)
@@ -59,8 +59,6 @@ public partial class ClashConnectionsViewModel : MyReactiveObject
public async Task RefreshConnections(List<ConnectionItem>? connections)
{
ConnectionItems.Clear();
var dtNow = DateTime.Now;
var lstModel = new List<ClashConnectionModel>();
foreach (var item in connections ?? [])
@@ -85,12 +83,8 @@ public partial class ClashConnectionsViewModel : MyReactiveObject
lstModel.Add(model);
}
if (lstModel.Count <= 0)
{
return;
}
ConnectionItems.AddRange(lstModel);
ConnectionItems.ReplaceRange(lstModel);
await Task.CompletedTask;
}
@@ -257,19 +257,19 @@ public partial class MainWindowViewModel : MyReactiveObject
AppEvents.AddServerViaClipboardRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async _ => await AddServerViaClipboardAsync(null));
.SubscribeAsync(async _ => await AddServerViaClipboardAsync(null));
AppEvents.HasUpdateNotified
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async bl => BlNewUpdate = bl);
.Subscribe(bl => BlNewUpdate = bl);
#endregion AppEvents
ProfilesViewModel.RefreshServersRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async _ => await RefreshServers());
.SubscribeAsync(async _ => await RefreshServers());
var vmReloadRequestedList = new List<IObservable<RxVoid>>
{
@@ -282,23 +282,23 @@ public partial class MainWindowViewModel : MyReactiveObject
{
reloadRequested
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async _ => await Reload());
.SubscribeAsync(async _ => await Reload());
}
StatusBarViewModel.AddServerViaScanRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async _ => await AddServerViaScanAsync());
.SubscribeAsync(async _ => await AddServerViaScanAsync());
StatusBarViewModel.AddServerViaClipboardRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async _ => await AddServerViaClipboardAsync(null));
.SubscribeAsync(async _ => await AddServerViaClipboardAsync(null));
StatusBarViewModel.ShowHideWindowRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async blShow =>
.SubscribeAsync(async blShow =>
{
await ShowHideWindowInteraction.HandleSafe(blShow);
});
@@ -306,12 +306,12 @@ public partial class MainWindowViewModel : MyReactiveObject
StatusBarViewModel.SetDefaultServerRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async indexId => await ProfilesViewModel.SetDefaultServer(indexId));
.SubscribeAsync(async indexId => await ProfilesViewModel.SetDefaultServer(indexId));
StatusBarViewModel.SubscriptionsUpdateRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async blProxy => await UpdateSubscriptionProcess("", blProxy));
.SubscribeAsync(async blProxy => await UpdateSubscriptionProcess("", blProxy));
_ = Init();
}
+9 -11
View File
@@ -22,18 +22,16 @@ public partial class MsgViewModel : MyReactiveObject
AutoRefresh = _config.MsgUIItem.AutoRefresh ?? true;
this.WhenAnyValue(
x => x.MsgFilter)
.Subscribe(c => DoMsgFilter());
x => x.MsgFilter)
.Subscribe(c => DoMsgFilter());
this.WhenAnyValue(
x => x.AutoRefresh,
y => y == true)
.Subscribe(c => _config.MsgUIItem.AutoRefresh = AutoRefresh);
this.WhenAnyValue(x => x.AutoRefresh)
.Subscribe(_ => _config.MsgUIItem.AutoRefresh = AutoRefresh);
AppEvents.SendMsgViewRequested
.AsObservable()
//.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(content => _ = AppendQueueMsg(content));
.AsObservable()
//.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(content => _ = AppendQueueMsg(content));
}
public void FlushQueueMsg()
@@ -74,9 +72,9 @@ public partial class MsgViewModel : MyReactiveObject
{
try
{
await DispatcherShowMsgInteraction.HandleSafe(sb.ToString());
await DispatcherShowMsgInteraction.Handle(sb.ToString());
}
catch (Exception)
catch
{
_queueMsg.Enqueue(sb.ToString());
}
@@ -61,24 +61,22 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
SelectFinish();
});
this.WhenAnyValue(
x => x.SelectedSub,
y => y != null && !y.Remarks.IsNullOrEmpty() && _subIndexId != y.Id)
.Subscribe(async c => await SubSelectedChangedAsync(c));
this.WhenAnyValue(x => x.SelectedSub)
.Where(y => y != null && !y.Remarks.IsNullOrEmpty() && _subIndexId != y.Id)
.SubscribeAsync(async _ => await SubSelectedChangedAsync());
this.WhenAnyValue(
x => x.ServerFilter,
y => y != null && _serverFilter != y)
.Subscribe(async c => await ServerFilterChanged(c));
this.WhenAnyValue(x => x.ServerFilter)
.Where(y => y != null && _serverFilter != y)
.SubscribeAsync(async _ => await ServerFilterChanged());
// React to ConfigType filter changes
this.WhenAnyValue(x => x.FilterExclude)
.Skip(1)
.Subscribe(async _ => await RefreshServersBiz());
.SubscribeAsync(async _ => await RefreshServersBiz());
this.WhenAnyValue(x => x.FilterConfigTypes)
.Skip(1)
.Subscribe(async _ => await RefreshServersBiz());
.SubscribeAsync(async _ => await RefreshServersBiz());
#endregion WhenAnyValue && ReactiveCommand
@@ -128,12 +126,8 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
#region Servers && Groups
private async Task SubSelectedChangedAsync(bool c)
private async Task SubSelectedChangedAsync()
{
if (!c)
{
return;
}
_subIndexId = SelectedSub?.Id;
await RefreshServers();
@@ -141,12 +135,8 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
await ProfilesFocusInteraction.HandleSafe(RxVoid.Default);
}
private async Task ServerFilterChanged(bool c)
private async Task ServerFilterChanged()
{
if (!c)
{
return;
}
_serverFilter = ServerFilter;
if (_serverFilter.IsNullOrEmpty())
{
@@ -163,8 +153,7 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
{
var lstModel = await GetProfileItemsEx(_subIndexId, _serverFilter);
ProfileItems.Clear();
ProfileItems.AddRange(lstModel);
ProfileItems.ReplaceRange(lstModel);
if (lstModel.Count > 0)
{
var selected = lstModel.FirstOrDefault(t => t.IndexId == _config.IndexId);
@@ -177,8 +166,7 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
var subItems = await AppManager.Instance.SubItems();
subItems.Insert(0, new SubItem { Remarks = ResUI.AllGroupServers });
SubItems.Clear();
SubItems.AddRange(subItems);
SubItems.ReplaceRange(subItems);
SelectedSub = (_config.SubIndexId.IsNotEmpty()
? subItems.FirstOrDefault(t => t.Id == _config.SubIndexId)
@@ -298,8 +286,7 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
: ProfileItems.OrderByDescending(KeySelector, comparer);
var list = sorted.ToList();
ProfileItems.Clear();
ProfileItems.AddRange(list);
ProfileItems.ReplaceRange(list);
_dicHeaderSort[colName] = !asc;
@@ -103,19 +103,16 @@ public partial class ProfilesViewModel : MyReactiveObject
x => x.SelectedProfile,
selectedSource => selectedSource != null && !selectedSource.IndexId.IsNullOrEmpty());
this.WhenAnyValue(
x => x.SelectedSub,
y => y != null && !y.Remarks.IsNullOrEmpty() && _config.SubIndexId != y.Id)
.Subscribe(async c => await SubSelectedChangedAsync(c));
this.WhenAnyValue(
x => x.SelectedMoveToGroup,
y => y != null && !y.Remarks.IsNullOrEmpty())
.Subscribe(async c => await MoveToGroup(c));
this.WhenAnyValue(x => x.SelectedSub)
.Where(y => y != null && !y.Remarks.IsNullOrEmpty() && _config.SubIndexId != y.Id)
.SubscribeAsync(async _ => await SubSelectedChangedAsync());
this.WhenAnyValue(x => x.SelectedMoveToGroup)
.Where(y => y != null && !y.Remarks.IsNullOrEmpty())
.SubscribeAsync(async _ => await MoveToGroup());
this.WhenAnyValue(
x => x.ServerFilter,
y => y != null && _serverFilter != y)
.Subscribe(async c => await ServerFilterChanged(c));
this.WhenAnyValue(x => x.ServerFilter)
.Where(y => y != null && _serverFilter != y)
.SubscribeAsync(async _ => await ServerFilterChanged());
//servers delete
EditServerCmd = ReactiveCommand.CreateFromTask(async () =>
@@ -249,7 +246,7 @@ public partial class ProfilesViewModel : MyReactiveObject
AppEvents.DispatcherStatisticsRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async result => await UpdateStatistics(result));
.SubscribeAsync(async result => await UpdateStatistics(result));
#endregion AppEvents
@@ -335,12 +332,8 @@ public partial class ProfilesViewModel : MyReactiveObject
#region Servers && Groups
private async Task SubSelectedChangedAsync(bool c)
private async Task SubSelectedChangedAsync()
{
if (!c)
{
return;
}
_config.SubIndexId = SelectedSub?.Id;
await RefreshServers();
@@ -348,12 +341,8 @@ public partial class ProfilesViewModel : MyReactiveObject
await ProfilesFocusInteraction.HandleSafe(RxVoid.Default);
}
private async Task ServerFilterChanged(bool c)
private async Task ServerFilterChanged()
{
if (!c)
{
return;
}
_serverFilter = ServerFilter;
if (_serverFilter.IsNullOrEmpty())
{
@@ -375,8 +364,7 @@ public partial class ProfilesViewModel : MyReactiveObject
var lstModel = await GetProfileItemsEx(_config.SubIndexId, _serverFilter);
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
ProfileItems.Clear();
ProfileItems.AddRange(lstModel ?? []);
ProfileItems.ReplaceRange(lstModel ?? []);
if (lstModel?.Count > 0)
{
ProfileItemModel? selected = null;
@@ -397,8 +385,7 @@ public partial class ProfilesViewModel : MyReactiveObject
var subItems = await AppManager.Instance.SubItems();
subItems.Insert(0, new SubItem { Remarks = ResUI.AllGroupServers });
SubItems.Clear();
SubItems.AddRange(subItems);
SubItems.ReplaceRange(subItems);
SelectedSub = (_config.SubIndexId.IsNotEmpty()
? subItems.FirstOrDefault(t => t.Id == _config.SubIndexId)
@@ -672,13 +659,8 @@ public partial class ProfilesViewModel : MyReactiveObject
}
//move server
private async Task MoveToGroup(bool c)
private async Task MoveToGroup()
{
if (!c)
{
return;
}
var lstSelected = await GetProfileItems(true);
if (lstSelected == null)
{
@@ -901,7 +883,7 @@ public partial class ProfilesViewModel : MyReactiveObject
if (await AppManager.Instance.WindowDialog.ShowDialogAsync(subEditViewModel) == true)
{
await RefreshSubscriptions();
await SubSelectedChangedAsync(true);
await SubSelectedChangedAsync();
}
}
@@ -920,7 +902,7 @@ public partial class ProfilesViewModel : MyReactiveObject
await ConfigHandler.DeleteSubItem(_config, item.Id);
await RefreshSubscriptions();
await SubSelectedChangedAsync(true);
await SubSelectedChangedAsync();
}
#endregion Subscription
@@ -100,8 +100,6 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
public void RefreshRulesItems()
{
RulesItems.Clear();
var models = new List<RulesItemModel>();
foreach (var item in _rules)
{
@@ -120,7 +118,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
};
models.Add(it);
}
RulesItems.AddRange(models);
RulesItems.ReplaceRange(models);
}
public async Task RuleEditAsync(bool blNew)
@@ -61,10 +61,10 @@ public partial class RoutingSettingViewModel : MyReactiveObject
x => x.DomainStrategy4Singbox)
.Skip(1)
.DistinctUntilChanged()
.Subscribe(x =>
.SubscribeAsync(async x =>
{
IsModified = true;
_ = SaveSettingsAsync();
await SaveSettingsAsync();
});
}
@@ -83,7 +83,6 @@ public partial class RoutingSettingViewModel : MyReactiveObject
public async Task RefreshRoutingItems()
{
RoutingItems.Clear();
var models = new List<RoutingItemModel>();
var routings = await AppManager.Instance.RoutingItems();
@@ -102,7 +101,7 @@ public partial class RoutingSettingViewModel : MyReactiveObject
};
models.Add(it);
}
RoutingItems.AddRange(models);
RoutingItems.ReplaceRange(models);
}
/// <summary>
@@ -123,26 +123,21 @@ public partial class StatusBarViewModel : MyReactiveObject
#region WhenAnyValue && ReactiveCommand
this.WhenAnyValue(
x => x.SelectedRouting,
y => y != null && !y.Remarks.IsNullOrEmpty())
.Subscribe(async c => await RoutingSelectedChangedAsync(c));
this.WhenAnyValue(x => x.SelectedRouting)
.Where(y => y != null && !y.Remarks.IsNullOrEmpty())
.SubscribeAsync(async _ => await RoutingSelectedChangedAsync());
this.WhenAnyValue(
x => x.SelectedServer,
y => y != null && !y.Text.IsNullOrEmpty())
.Subscribe(ServerSelectedChanged);
this.WhenAnyValue(x => x.SelectedServer)
.Where(y => y != null && !y.Text.IsNullOrEmpty())
.Subscribe(_ => ServerSelectedChanged());
SystemProxySelected = (int)_config.SystemProxyItem.SysProxyType;
this.WhenAnyValue(
x => x.SystemProxySelected,
y => y >= 0)
.Subscribe(async c => await DoSystemProxySelected(c));
this.WhenAnyValue(x => x.SystemProxySelected)
.Where(y => y >= 0)
.SubscribeAsync(async _ => await DoSystemProxySelected());
this.WhenAnyValue(
x => x.EnableTun,
y => y == true)
.Subscribe(async c => await DoEnableTun(c));
this.WhenAnyValue(x => x.EnableTun)
.SubscribeAsync(async _ => await DoEnableTun());
CopyProxyCmdToClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
{
@@ -207,12 +202,12 @@ public partial class StatusBarViewModel : MyReactiveObject
AppEvents.DispatcherStatisticsRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async result => await UpdateStatistics(result));
.SubscribeAsync(async result => await UpdateStatistics(result));
AppEvents.SysProxyChangeRequested
.AsObservable()
.ObserveOn(RxSchedulers.MainThreadScheduler)
.Subscribe(async result => await SetListenerType(result));
.SubscribeAsync(async result => await SetListenerType(result));
#endregion AppEvents
@@ -300,19 +295,14 @@ public partial class StatusBarViewModel : MyReactiveObject
var models = lstModel.Select(it => new ComboItem { ID = it.IndexId, Text = it.GetSummary() }).ToList();
BlServers = true;
Servers.Clear();
Servers.AddRange(models);
Servers.ReplaceRange(models);
// Update the ItemsSource before SelectedItem so a collection reset does not clear the tray selection.
SelectedServer = models.FirstOrDefault(it => it.ID == _config.IndexId) ?? new();
}
private void ServerSelectedChanged(bool c)
private void ServerSelectedChanged()
{
if (!c)
{
return;
}
if (SelectedServer == null)
{
return;
@@ -402,19 +392,13 @@ public partial class StatusBarViewModel : MyReactiveObject
{
var routings = await AppManager.Instance.RoutingItems();
RoutingItems.Clear();
RoutingItems.AddRange(routings);
RoutingItems.ReplaceRange(routings);
SelectedRouting = routings.FirstOrDefault(t => t.IsActive == true);
}
private async Task RoutingSelectedChangedAsync(bool c)
private async Task RoutingSelectedChangedAsync()
{
if (!c)
{
return;
}
if (SelectedRouting == null)
{
return;
@@ -434,12 +418,8 @@ public partial class StatusBarViewModel : MyReactiveObject
}
}
private async Task DoSystemProxySelected(bool c)
private async Task DoSystemProxySelected()
{
if (!c)
{
return;
}
if (_config.SystemProxyItem.SysProxyType == (ESysProxyType)SystemProxySelected)
{
return;
@@ -447,7 +427,7 @@ public partial class StatusBarViewModel : MyReactiveObject
await SetListenerType((ESysProxyType)SystemProxySelected);
}
private async Task DoEnableTun(bool c)
private async Task DoEnableTun()
{
if (_config.TunModeItem.EnableTun == EnableTun)
{
@@ -55,8 +55,7 @@ public partial class SubSettingViewModel : MyReactiveObject
public async Task RefreshSubItems()
{
SubItems.Clear();
SubItems.AddRange(await AppManager.Instance.SubItems());
SubItems.ReplaceRange(await AppManager.Instance.SubItems());
}
public async Task EditSubAsync(bool blNew)
+1
View File
@@ -22,6 +22,7 @@ global using ReactiveUI;
global using ReactiveUI.Avalonia;
global using ReactiveUI.Primitives;
global using ReactiveUI.Primitives.Disposables;
global using ReactiveUI.Primitives.Extensions;
global using ReactiveUI.SourceGenerators;
global using ServiceLib;
global using ServiceLib.Base;
@@ -35,39 +35,38 @@ public partial class ThemeSettingViewModel : MyReactiveObject
CurrentLanguage = _config.UiItem.CurrentLanguage;
this.WhenAnyValue(x => x.CurrentTheme)
.Subscribe(c =>
.Where(y => y.IsNotEmpty())
.SubscribeAsync(async _ =>
{
if (_config.UiItem.CurrentTheme != CurrentTheme)
{
_config.UiItem.CurrentTheme = CurrentTheme;
ModifyTheme();
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentFontSize,
y => y > 0)
.Subscribe(c =>
this.WhenAnyValue(x => x.CurrentFontSize)
.Where(y => y > 0)
.SubscribeAsync(async _ =>
{
if (_config.UiItem.CurrentFontSize != CurrentFontSize && CurrentFontSize >= Global.MinFontSize)
{
_config.UiItem.CurrentFontSize = CurrentFontSize;
ModifyFontSize();
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
this.WhenAnyValue(x => x.CurrentLanguage)
.Where(y => !y.IsNullOrEmpty())
.SubscribeAsync(async _ =>
{
if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage)
{
_config.UiItem.CurrentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
NoticeManager.Instance.Enqueue(ResUI.NeedRebootTips);
}
});
@@ -50,6 +50,9 @@ public partial class MsgView : ReactiveUserControl<MsgViewModel>
if (togScrollToEnd.IsChecked ?? true)
{
txtMsg.ScrollToEnd();
Dispatcher.UIThread.Invoke(() =>
txtMsg.ScrollTo(txtMsg.LineCount, 0, AvaloniaEdit.Rendering.VisualYPosition.TextBottom, txtMsg.Bounds.Height, 0),
DispatcherPriority.Background);
}
}
+1
View File
@@ -19,6 +19,7 @@ global using ReactiveUI;
global using ReactiveUI.Builder;
global using ReactiveUI.Primitives;
global using ReactiveUI.Primitives.Disposables;
global using ReactiveUI.Primitives.Extensions;
global using ReactiveUI.SourceGenerators;
global using ServiceLib;
global using ServiceLib.Base;
@@ -55,23 +55,21 @@ public partial class ThemeSettingViewModel : MyReactiveObject
CurrentFontSize = _config.UiItem.CurrentFontSize;
CurrentLanguage = _config.UiItem.CurrentLanguage;
this.WhenAnyValue(
x => x.CurrentTheme,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
this.WhenAnyValue(x => x.CurrentTheme)
.Where(y => y != null && !y.IsNullOrEmpty())
.SubscribeAsync(async _ =>
{
if (_config.UiItem.CurrentTheme != CurrentTheme)
{
_config.UiItem.CurrentTheme = CurrentTheme;
ModifyTheme();
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.SelectedSwatch,
y => y != null && !y.Name.IsNullOrEmpty())
.Subscribe(c =>
this.WhenAnyValue(x => x.SelectedSwatch)
.Where(y => y != null && !y.Name.IsNullOrEmpty())
.SubscribeAsync(async _ =>
{
if (SelectedSwatch == null
|| SelectedSwatch.Name.IsNullOrEmpty()
@@ -84,33 +82,31 @@ public partial class ThemeSettingViewModel : MyReactiveObject
{
_config.UiItem.ColorPrimaryName = SelectedSwatch?.Name;
ChangePrimaryColor(SelectedSwatch.ExemplarHue.Color);
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentFontSize,
y => y > 0)
.Subscribe(c =>
this.WhenAnyValue(x => x.CurrentFontSize)
.Where(y => y > 0)
.SubscribeAsync(async _ =>
{
if (_config.UiItem.CurrentFontSize != CurrentFontSize)
{
_config.UiItem.CurrentFontSize = CurrentFontSize;
ModifyFontSize();
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
}
});
this.WhenAnyValue(
x => x.CurrentLanguage,
y => y != null && !y.IsNullOrEmpty())
.Subscribe(c =>
this.WhenAnyValue(x => x.CurrentLanguage)
.Where(y => y != null && !y.IsNullOrEmpty())
.SubscribeAsync(async _ =>
{
if (CurrentLanguage.IsNotEmpty() && _config.UiItem.CurrentLanguage != CurrentLanguage)
{
_config.UiItem.CurrentLanguage = CurrentLanguage;
Thread.CurrentThread.CurrentUICulture = new(CurrentLanguage);
_ = ConfigHandler.SaveConfig(_config);
await ConfigHandler.SaveConfig(_config);
NoticeManager.Instance.Enqueue(ResUI.NeedRebootTips);
}
});