namespace ServiceLib.ViewModels; public partial class RoutingSettingViewModel : MyReactiveObject { public Interaction ShowYesNoInteraction { get; } = new(); #region Reactive public BulkObservableCollection RoutingItems { get; } = []; [Reactive] public partial RoutingItemModel SelectedSource { get; set; } public IList SelectedSources { get; set; } [Reactive] public partial string DomainStrategy { get; set; } [Reactive] public partial string DomainStrategy4Singbox { get; set; } public ReactiveCommand RoutingAdvancedAddCmd { get; } public ReactiveCommand RoutingAdvancedRemoveCmd { get; } public ReactiveCommand RoutingAdvancedSetDefaultCmd { get; } public ReactiveCommand RoutingAdvancedImportRulesCmd { get; } public bool IsModified { get; set; } #endregion Reactive public RoutingSettingViewModel() { _config = AppManager.Instance.Config; var canEditRemove = this.WhenAnyValue( x => x.SelectedSource, selectedSource => selectedSource != null && !selectedSource.Remarks.IsNullOrEmpty()); RoutingAdvancedAddCmd = ReactiveCommand.CreateFromTask(async () => { await RoutingAdvancedEditAsync(true); }); RoutingAdvancedRemoveCmd = ReactiveCommand.CreateFromTask(async () => { await RoutingAdvancedRemoveAsync(); }, canEditRemove); RoutingAdvancedSetDefaultCmd = ReactiveCommand.CreateFromTask(async () => { await RoutingAdvancedSetDefault(); }, canEditRemove); RoutingAdvancedImportRulesCmd = ReactiveCommand.CreateFromTask(async () => { await RoutingAdvancedImportRules(); }); _ = Init(); // Auto-save DomainStrategy when changed this.WhenAnyValue( x => x.DomainStrategy, x => x.DomainStrategy4Singbox) .Skip(1) .DistinctUntilChanged() .Subscribe(x => { IsModified = true; _ = SaveSettingsAsync(); }); } private async Task Init() { SelectedSource = new(); DomainStrategy = _config.RoutingBasicItem.DomainStrategy; DomainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox; await ConfigHandler.InitBuiltinRouting(_config); await RefreshRoutingItems(); } #region Refresh Save public async Task RefreshRoutingItems() { RoutingItems.Clear(); var models = new List(); var routings = await AppManager.Instance.RoutingItems(); foreach (var item in routings) { var it = new RoutingItemModel() { IsActive = item.IsActive, RuleNum = item.RuleNum, Id = item.Id, Remarks = item.Remarks, Url = item.Url, CustomIcon = item.CustomIcon, CustomRulesetPath4Singbox = item.CustomRulesetPath4Singbox, Sort = item.Sort, }; models.Add(it); } RoutingItems.AddRange(models); } /// /// Save DomainStrategy settings /// public async Task SaveSettingsAsync() { _config.RoutingBasicItem.DomainStrategy = DomainStrategy; _config.RoutingBasicItem.DomainStrategy4Singbox = DomainStrategy4Singbox; await ConfigHandler.SaveConfig(_config); } #endregion Refresh Save public async Task RoutingAdvancedEditAsync(bool blNew) { RoutingItem item; if (blNew) { item = new(); } else { item = await AppManager.Instance.GetRoutingItem(SelectedSource?.Id); if (item is null) { return; } } var routingRuleSettingViewModel = new RoutingRuleSettingViewModel(item); if (await AppManager.Instance.WindowDialog.ShowDialogAsync(routingRuleSettingViewModel) == true) { await RefreshRoutingItems(); IsModified = true; } } public async Task RoutingAdvancedRemoveAsync() { if (SelectedSource is null || SelectedSource.Remarks.IsNullOrEmpty()) { NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules); return; } if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false) { return; } foreach (var it in SelectedSources ?? [SelectedSource]) { var item = await AppManager.Instance.GetRoutingItem(it?.Id); if (item != null) { await ConfigHandler.RemoveRoutingItem(item); } } await RefreshRoutingItems(); IsModified = true; } public async Task RoutingAdvancedSetDefault() { var item = await AppManager.Instance.GetRoutingItem(SelectedSource?.Id); if (item is null) { NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules); return; } if (await ConfigHandler.SetDefaultRouting(_config, item) == 0) { await RefreshRoutingItems(); IsModified = true; } } private async Task RoutingAdvancedImportRules() { if (await ConfigHandler.InitRouting(_config, true) == 0) { await RefreshRoutingItems(); IsModified = true; } } }