Centralize config access in database handlers

Remove Config parameters from ConfigDbHandler methods and use the current configuration where needed. Update desktop, WebAPI, and test callers.
This commit is contained in:
2dust
2026-11-15 15:18:32 +08:00
parent a6624e0370
commit 254b39bc45
24 changed files with 262 additions and 279 deletions
@@ -32,7 +32,7 @@ public class ConfigHandlerCustomSubscriptionTests
oldProfile.IsSub = true; oldProfile.IsSub = true;
await SQLiteHelper.Instance.InsertAsync(oldProfile); await SQLiteHelper.Instance.InsertAsync(oldProfile);
var count = await ConfigDbHandler.AddBatchServers(config, FullXrayConfigs, subId, true); var count = await ConfigDbHandler.AddBatchServers( FullXrayConfigs, subId, true);
var profiles = await ConfigDbQuery.ProfileItems(subId) ?? []; var profiles = await ConfigDbQuery.ProfileItems(subId) ?? [];
await count.Should().BeEqualTo(2); await count.Should().BeEqualTo(2);
@@ -66,7 +66,7 @@ public class ConfigHandlerCustomSubscriptionTests
await SQLiteHelper.Instance.InsertAsync(existing); await SQLiteHelper.Instance.InsertAsync(existing);
var invalidSubscription = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("not a valid profile")); var invalidSubscription = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes("not a valid profile"));
var count = await ConfigDbHandler.AddBatchServers(config, invalidSubscription, subId, true); var count = await ConfigDbHandler.AddBatchServers( invalidSubscription, subId, true);
var profiles = await ConfigDbQuery.ProfileItems(subId) ?? []; var profiles = await ConfigDbQuery.ProfileItems(subId) ?? [];
await (count < 1).Should().BeTrue(); await (count < 1).Should().BeTrue();
@@ -46,7 +46,7 @@ public class CoreConfigContextBuilder
SimpleDnsItem = config.SimpleDNSItem, SimpleDnsItem = config.SimpleDNSItem,
ProtectDomainList = [], ProtectDomainList = [],
RawDnsItem = await ConfigDbQuery.GetDNSItem(coreType), RawDnsItem = await ConfigDbQuery.GetDNSItem(coreType),
RoutingItem = await ConfigDbHandler.GetDefaultRouting(config), RoutingItem = await ConfigDbHandler.GetDefaultRouting(),
IsWindows = Utils.IsWindows(), IsWindows = Utils.IsWindows(),
IsMacOS = Utils.IsMacOS(), IsMacOS = Utils.IsMacOS(),
IsLinux = Utils.IsLinux(), IsLinux = Utils.IsLinux(),
File diff suppressed because it is too large Load Diff
@@ -106,7 +106,7 @@ public class SubscriptionHandler(
await updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgStartParsingSubscription}"); await updateFunc?.Invoke(false, $"{hashCode}{ResUI.MsgStartParsingSubscription}");
// Add servers to configuration // Add servers to configuration
var ret = await ConfigDbHandler.AddBatchServers(_config, result, id, true); var ret = await ConfigDbHandler.AddBatchServers(result, id, true);
if (ret <= 0) if (ret <= 0)
{ {
Logging.SaveLog("FailedImportSubscription"); Logging.SaveLog("FailedImportSubscription");
+1 -1
View File
@@ -113,7 +113,7 @@ public class TaskManager
}); });
await handler.UpdateProcess(item.Id); await handler.UpdateProcess(item.Id);
item.UpdateTime = updateTime; item.UpdateTime = updateTime;
await ConfigDbHandler.AddSubItem(_config, item); await ConfigDbHandler.AddSubItem(item);
await Task.Delay(1000); await Task.Delay(1000);
} }
} }
@@ -245,7 +245,7 @@ public partial class AddGroupServerViewModel : MyReactiveObject, ICloseable
SelectedSource.SetProtocolExtra(protocolExtra); SelectedSource.SetProtocolExtra(protocolExtra);
if (await ConfigDbHandler.AddServerCommon(_config, SelectedSource) == 0) if (await ConfigDbHandler.AddServerCommon(SelectedSource) == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -71,7 +71,7 @@ public partial class AddServer2ViewModel : MyReactiveObject, ICloseable
IsSingboxEndpoint = IsSingboxEndpoint ? true : null, IsSingboxEndpoint = IsSingboxEndpoint ? true : null,
}); });
if (await ConfigDbHandler.EditCustomServer(_config, SelectedSource) == 0) if (await ConfigDbHandler.EditCustomServer(SelectedSource) == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -92,7 +92,7 @@ public partial class AddServer2ViewModel : MyReactiveObject, ICloseable
var item = await ConfigDbQuery.GetProfileItem(SelectedSource.IndexId); var item = await ConfigDbQuery.GetProfileItem(SelectedSource.IndexId);
item ??= SelectedSource; item ??= SelectedSource;
item.Address = fileName; item.Address = fileName;
var result = item.ConfigType == EConfigType.Outbound ? await ConfigDbHandler.AddCustomOutboundServer(_config, item, false) : await ConfigDbHandler.AddCustomServer(_config, item, false); var result = item.ConfigType == EConfigType.Outbound ? await ConfigDbHandler.AddCustomOutboundServer(item, false) : await ConfigDbHandler.AddCustomServer(item, false);
if (result == 0) if (result == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer); NoticeManager.Instance.Enqueue(ResUI.SuccessfullyImportedCustomServer);
@@ -1,5 +1,3 @@
namespace ServiceLib.ViewModels; namespace ServiceLib.ViewModels;
public partial class AddServerViewModel : MyReactiveObject, ICloseable public partial class AddServerViewModel : MyReactiveObject, ICloseable
@@ -594,7 +592,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
}); });
SelectedSource.SetTransportExtra(transport); SelectedSource.SetTransportExtra(transport);
if (await ConfigDbHandler.AddServer(_config, SelectedSource) == 0) if (await ConfigDbHandler.AddServer(SelectedSource) == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -625,6 +623,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
XdriveS3PathStyle = true; XdriveS3PathStyle = true;
break; break;
case "Google Drive": case "Google Drive":
XdriveService = "google-drive"; XdriveService = "google-drive";
SelectedSource.StreamSecurity = Global.StreamSecurity; SelectedSource.StreamSecurity = Global.StreamSecurity;
@@ -649,6 +648,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
} }
break; break;
case "AWS S3 (Global)": case "AWS S3 (Global)":
XdriveService = "s3"; XdriveService = "s3";
if (XdriveS3Region.IsNullOrEmpty()) if (XdriveS3Region.IsNullOrEmpty())
@@ -658,6 +658,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
XdriveS3PathStyle = false; XdriveS3PathStyle = false;
break; break;
case "Yandex Cloud S3": case "Yandex Cloud S3":
XdriveService = "s3"; XdriveService = "s3";
if (XdriveS3Region.IsNullOrEmpty()) if (XdriveS3Region.IsNullOrEmpty())
@@ -667,6 +668,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
XdriveS3PathStyle = true; XdriveS3PathStyle = true;
break; break;
case "ArvanCloud S3": case "ArvanCloud S3":
XdriveService = "s3"; XdriveService = "s3";
if (XdriveS3Region.IsNullOrEmpty()) if (XdriveS3Region.IsNullOrEmpty())
@@ -676,6 +678,7 @@ public partial class AddServerViewModel : MyReactiveObject, ICloseable
XdriveS3PathStyle = true; XdriveS3PathStyle = true;
break; break;
case "Custom S3": case "Custom S3":
XdriveService = "s3"; XdriveService = "s3";
break; break;
@@ -207,7 +207,7 @@ public partial class DNSSettingViewModel : MyReactiveObject, ICloseable
item1.UseSystemHosts = UseSystemHostsCompatible; item1.UseSystemHosts = UseSystemHostsCompatible;
item1.NormalDNS = NormalDNSCompatible; item1.NormalDNS = NormalDNSCompatible;
item1.TunDNS = TunDNSCompatible; item1.TunDNS = TunDNSCompatible;
await ConfigDbHandler.SaveDNSItems(_config, item1); await ConfigDbHandler.SaveDNSItems(item1);
var item2 = await ConfigDbQuery.GetDNSItem(ECoreType.sing_box); var item2 = await ConfigDbQuery.GetDNSItem(ECoreType.sing_box);
item2.Enabled = SBCustomDNSEnableCompatible; item2.Enabled = SBCustomDNSEnableCompatible;
@@ -215,7 +215,7 @@ public partial class DNSSettingViewModel : MyReactiveObject, ICloseable
item2.DomainDNSAddress = DomainDNSAddress2Compatible; item2.DomainDNSAddress = DomainDNSAddress2Compatible;
item2.NormalDNS = JsonUtils.Serialize(JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible)); item2.NormalDNS = JsonUtils.Serialize(JsonUtils.Deserialize<Dns4Sbox>(NormalDNS2Compatible));
item2.TunDNS = JsonUtils.Serialize(JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible)); item2.TunDNS = JsonUtils.Serialize(JsonUtils.Deserialize<Dns4Sbox>(TunDNS2Compatible));
await ConfigDbHandler.SaveDNSItems(_config, item2); await ConfigDbHandler.SaveDNSItems(item2);
await ConfigTextHandler.SaveConfig(); await ConfigTextHandler.SaveConfig();
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -104,7 +104,7 @@ public partial class FullConfigTemplateViewModel : MyReactiveObject, ICloseable
item.AddProxyOnly = AddProxyOnly4Ray; item.AddProxyOnly = AddProxyOnly4Ray;
item.ProxyDetour = ProxyDetour4Ray; item.ProxyDetour = ProxyDetour4Ray;
await ConfigDbHandler.SaveFullConfigTemplate(_config, item); await ConfigDbHandler.SaveFullConfigTemplate(item);
return true; return true;
} }
@@ -122,7 +122,7 @@ public partial class FullConfigTemplateViewModel : MyReactiveObject, ICloseable
item.AddProxyOnly = AddProxyOnly4Singbox; item.AddProxyOnly = AddProxyOnly4Singbox;
item.ProxyDetour = ProxyDetour4Singbox; item.ProxyDetour = ProxyDetour4Singbox;
await ConfigDbHandler.SaveFullConfigTemplate(_config, item); await ConfigDbHandler.SaveFullConfigTemplate(item);
return true; return true;
} }
} }
@@ -331,8 +331,8 @@ public partial class MainWindowViewModel : MyReactiveObject
} }
//await ConfigHandler.InitBuiltinRouting(_config); //await ConfigHandler.InitBuiltinRouting(_config);
await ConfigDbHandler.InitBuiltinDNS(_config); await ConfigDbHandler.InitBuiltinDNS();
await ConfigDbHandler.InitBuiltinFullConfigTemplate(_config); await ConfigDbHandler.InitBuiltinFullConfigTemplate();
await ProfileExManager.Instance.Init(); await ProfileExManager.Instance.Init();
await CoreManager.Instance.Init(_config, UpdateHandler); await CoreManager.Instance.Init(_config, UpdateHandler);
await CertPemManager.Instance.Init(_config); await CertPemManager.Instance.Init(_config);
@@ -499,7 +499,7 @@ public partial class MainWindowViewModel : MyReactiveObject
} }
stringData = result; stringData = result;
} }
var ret = await ConfigDbHandler.AddBatchServers(_config, stringData, _config.SubIndexId, false); var ret = await ConfigDbHandler.AddBatchServers(stringData, _config.SubIndexId, false);
if (ret > 0) if (ret > 0)
{ {
await RefreshSubscriptions(); await RefreshSubscriptions();
@@ -549,7 +549,7 @@ public partial class MainWindowViewModel : MyReactiveObject
} }
else else
{ {
var ret = await ConfigDbHandler.AddBatchServers(_config, result, _config.SubIndexId, false); var ret = await ConfigDbHandler.AddBatchServers(result, _config.SubIndexId, false);
if (ret > 0) if (ret > 0)
{ {
await RefreshSubscriptions(); await RefreshSubscriptions();
@@ -610,7 +610,7 @@ public partial class MainWindowViewModel : MyReactiveObject
var ret = await AppManager.Instance.WindowDialog.ShowDialogAsync(routingSettingViewModel); var ret = await AppManager.Instance.WindowDialog.ShowDialogAsync(routingSettingViewModel);
if (ret == true) if (ret == true)
{ {
await ConfigDbHandler.InitBuiltinRouting(_config); await ConfigDbHandler.InitBuiltinRouting();
RxSchedulers.MainThreadScheduler.Schedule(async () => RxSchedulers.MainThreadScheduler.Schedule(async () =>
{ {
await StatusBarViewModel.RefreshRoutingsMenu(); await StatusBarViewModel.RefreshRoutingsMenu();
@@ -788,8 +788,8 @@ public partial class MainWindowViewModel : MyReactiveObject
public async Task ApplyRegionalPreset(EPresetType type) public async Task ApplyRegionalPreset(EPresetType type)
{ {
await ConfigDbHandler.ApplyRegionalPreset(_config, type); await ConfigDbHandler.ApplyRegionalPreset(type);
await ConfigDbHandler.InitRouting(_config); await ConfigDbHandler.InitRouting();
RxSchedulers.MainThreadScheduler.Schedule(async () => RxSchedulers.MainThreadScheduler.Schedule(async () =>
{ {
await StatusBarViewModel.RefreshRoutingsMenu(); await StatusBarViewModel.RefreshRoutingsMenu();
@@ -514,7 +514,7 @@ public partial class ProfilesViewModel : MyReactiveObject
} }
var exists = lstSelected.Exists(t => t.IndexId == _config.IndexId); var exists = lstSelected.Exists(t => t.IndexId == _config.IndexId);
await ConfigDbHandler.RemoveServers(_config, lstSelected); await ConfigDbHandler.RemoveServers(lstSelected);
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
if (lstSelected.Count == ProfileItems.Count) if (lstSelected.Count == ProfileItems.Count)
{ {
@@ -534,7 +534,7 @@ public partial class ProfilesViewModel : MyReactiveObject
return; return;
} }
var tuple = await ConfigDbHandler.DedupServerList(_config, _config.SubIndexId); var tuple = await ConfigDbHandler.DedupServerList(_config.SubIndexId);
if (tuple.Item1 > 0 || tuple.Item2 > 0) if (tuple.Item1 > 0 || tuple.Item2 > 0)
{ {
await RefreshServers(); await RefreshServers();
@@ -550,7 +550,7 @@ public partial class ProfilesViewModel : MyReactiveObject
{ {
return; return;
} }
if (await ConfigDbHandler.CopyServer(_config, lstSelected) == 0) if (await ConfigDbHandler.CopyServer(lstSelected) == 0)
{ {
await RefreshServers(); await RefreshServers();
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
@@ -609,7 +609,7 @@ public partial class ProfilesViewModel : MyReactiveObject
private async Task GenGroupAllServer() private async Task GenGroupAllServer()
{ {
var ret = await ConfigDbHandler.AddGroupAllServer(_config, SelectedSub); var ret = await ConfigDbHandler.AddGroupAllServer( SelectedSub);
if (ret.Success != true) if (ret.Success != true)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationFailed); NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
@@ -621,7 +621,7 @@ public partial class ProfilesViewModel : MyReactiveObject
private async Task GenGroupRegionServer() private async Task GenGroupRegionServer()
{ {
var ret = await ConfigDbHandler.AddGroupRegionServer(_config, SelectedSub); var ret = await ConfigDbHandler.AddGroupRegionServer( SelectedSub);
if (ret.Success != true) if (ret.Success != true)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationFailed); NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
@@ -641,7 +641,7 @@ public partial class ProfilesViewModel : MyReactiveObject
_dicHeaderSort.TryAdd(colName, true); _dicHeaderSort.TryAdd(colName, true);
_dicHeaderSort.TryGetValue(colName, out var asc); _dicHeaderSort.TryGetValue(colName, out var asc);
if (await ConfigDbHandler.SortServers(_config, _config.SubIndexId, colName, asc) != 0) if (await ConfigDbHandler.SortServers( _config.SubIndexId, colName, asc) != 0)
{ {
return; return;
} }
@@ -651,7 +651,7 @@ public partial class ProfilesViewModel : MyReactiveObject
public async Task RemoveInvalidServerResult() public async Task RemoveInvalidServerResult()
{ {
var count = await ConfigDbHandler.RemoveInvalidServerResult(_config, _config.SubIndexId); var count = await ConfigDbHandler.RemoveInvalidServerResult( _config.SubIndexId);
await RefreshServers(); await RefreshServers();
NoticeManager.Instance.Enqueue(string.Format(ResUI.RemoveInvalidServerResultTip, count)); NoticeManager.Instance.Enqueue(string.Format(ResUI.RemoveInvalidServerResultTip, count));
} }
@@ -665,7 +665,7 @@ public partial class ProfilesViewModel : MyReactiveObject
return; return;
} }
await ConfigDbHandler.MoveToGroup(_config, lstSelected, SelectedMoveToGroup.Id); await ConfigDbHandler.MoveToGroup( lstSelected, SelectedMoveToGroup.Id);
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
await RefreshServers(); await RefreshServers();
@@ -683,7 +683,7 @@ public partial class ProfilesViewModel : MyReactiveObject
return; return;
} }
if (await ConfigDbHandler.MoveServer(_config, lstProfile, index, eMove) == 0) if (await ConfigDbHandler.MoveServer( lstProfile, index, eMove) == 0)
{ {
await RefreshServers(); await RefreshServers();
} }
@@ -695,7 +695,7 @@ public partial class ProfilesViewModel : MyReactiveObject
if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex) if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex)
{ {
var lstProfile = ProfileItems?.Select(t => t.IndexId).ToList() ?? []; var lstProfile = ProfileItems?.Select(t => t.IndexId).ToList() ?? [];
if (await ConfigDbHandler.MoveServer(_config, lstProfile, startIndex, EMove.Position, targetIndex) == 0) if (await ConfigDbHandler.MoveServer( lstProfile, startIndex, EMove.Position, targetIndex) == 0)
{ {
await RefreshServers(); await RefreshServers();
} }
@@ -718,7 +718,6 @@ public partial class ProfilesViewModel : MyReactiveObject
.ToList(); .ToList();
var result = await ConfigDbHandler.MoveServersTo( var result = await ConfigDbHandler.MoveServersTo(
_config,
orderedProfileIds, orderedProfileIds,
sourceIndices, sourceIndices,
insertIndex); insertIndex);
@@ -921,7 +920,7 @@ public partial class ProfilesViewModel : MyReactiveObject
{ {
return; return;
} }
await ConfigDbHandler.DeleteSubItem(_config, item.Id); await ConfigDbHandler.DeleteSubItem( item.Id);
await RefreshSubscriptions(); await RefreshSubscriptions();
await SubSelectedChangedAsync(); await SubSelectedChangedAsync();
@@ -233,7 +233,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
item.RuleNum = _rules.Count; item.RuleNum = _rules.Count;
item.RuleSet = JsonUtils.Serialize(_rules, false); item.RuleSet = JsonUtils.Serialize(_rules, false);
if (await ConfigDbHandler.SaveRoutingItem(_config, item) == 0) if (await ConfigDbHandler.SaveRoutingItem( item) == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -77,7 +77,7 @@ public partial class RoutingSettingViewModel : MyReactiveObject
DomainStrategy = _config.RoutingBasicItem.DomainStrategy; DomainStrategy = _config.RoutingBasicItem.DomainStrategy;
DomainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox; DomainStrategy4Singbox = _config.RoutingBasicItem.DomainStrategy4Singbox;
await ConfigDbHandler.InitBuiltinRouting(_config); await ConfigDbHandler.InitBuiltinRouting();
await RefreshRoutingItems(); await RefreshRoutingItems();
} }
@@ -174,7 +174,7 @@ public partial class RoutingSettingViewModel : MyReactiveObject
return; return;
} }
if (await ConfigDbHandler.SetDefaultRouting(_config, item) == 0) if (await ConfigDbHandler.SetDefaultRouting( item) == 0)
{ {
await RefreshRoutingItems(); await RefreshRoutingItems();
IsModified = true; IsModified = true;
@@ -183,7 +183,7 @@ public partial class RoutingSettingViewModel : MyReactiveObject
private async Task RoutingAdvancedImportRules() private async Task RoutingAdvancedImportRules()
{ {
if (await ConfigDbHandler.InitRouting(_config, true) == 0) if (await ConfigDbHandler.InitRouting(true) == 0)
{ {
await RefreshRoutingItems(); await RefreshRoutingItems();
IsModified = true; IsModified = true;
@@ -218,7 +218,7 @@ public partial class StatusBarViewModel : MyReactiveObject
private async Task Init() private async Task Init()
{ {
await ConfigDbHandler.InitBuiltinRouting(_config); await ConfigDbHandler.InitBuiltinRouting();
await RefreshRoutingsMenu(); await RefreshRoutingsMenu();
await InboundDisplayStatus(); await InboundDisplayStatus();
// The view refreshes its icon on initialization; interaction handlers are not registered yet. // The view refreshes its icon on initialization; interaction handlers are not registered yet.
@@ -413,7 +413,7 @@ public partial class StatusBarViewModel : MyReactiveObject
return; return;
} }
if (await ConfigDbHandler.SetDefaultRouting(_config, item) == 0) if (await ConfigDbHandler.SetDefaultRouting(item) == 0)
{ {
NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting); NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting);
ReloadRequested.Publish(); ReloadRequested.Publish();
@@ -89,7 +89,7 @@ public partial class SubEditViewModel : MyReactiveObject, ICloseable
SelectedSource.PrevProfile = PrevProfile; SelectedSource.PrevProfile = PrevProfile;
SelectedSource.NextProfile = NextProfile; SelectedSource.NextProfile = NextProfile;
if (await ConfigDbHandler.AddSubItem(_config, SelectedSource) == 0) if (await ConfigDbHandler.AddSubItem( SelectedSource) == 0)
{ {
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
RequestClose?.Invoke(this, EventArgs.Empty); RequestClose?.Invoke(this, EventArgs.Empty);
@@ -92,7 +92,7 @@ public partial class SubSettingViewModel : MyReactiveObject
foreach (var it in SelectedSources ?? [SelectedSource]) foreach (var it in SelectedSources ?? [SelectedSource])
{ {
await ConfigDbHandler.DeleteSubItem(_config, it.Id); await ConfigDbHandler.DeleteSubItem( it.Id);
} }
await RefreshSubItems(); await RefreshSubItems();
NoticeManager.Instance.Enqueue(ResUI.OperationSuccess); NoticeManager.Instance.Enqueue(ResUI.OperationSuccess);
@@ -9,9 +9,8 @@ internal static class BuiltinDnsProfileBootstrap
]; ];
public static async Task EnsureAsync( public static async Task EnsureAsync(
Config config,
Func<Task<IReadOnlyList<DNSItem>>> load, Func<Task<IReadOnlyList<DNSItem>>> load,
Func<Config, DNSItem, Task<int>> save) Func<DNSItem, Task<int>> save)
{ {
var existing = await load(); var existing = await load();
foreach (var (coreType, remarks) in BuiltinProfiles) foreach (var (coreType, remarks) in BuiltinProfiles)
@@ -27,7 +26,7 @@ internal static class BuiltinDnsProfileBootstrap
CoreType = coreType, CoreType = coreType,
Enabled = false, Enabled = false,
}; };
if (await save(config, item) != 0) if (await save(item) != 0)
{ {
throw new IOException($"The built-in {coreType} DNS profile could not be created."); throw new IOException($"The built-in {coreType} DNS profile could not be created.");
} }
@@ -60,7 +60,7 @@ public sealed partial class V2rayRuntime
var count = await _mutations.RunAsync(async () => var count = await _mutations.RunAsync(async () =>
{ {
var imported = await ConfigDbHandler.AddBatchServers(Config, request.Content, groupId, request.IsSubscription); var imported = await ConfigDbHandler.AddBatchServers(request.Content, groupId, request.IsSubscription);
if (imported > 0) if (imported > 0)
{ {
await EnsureConfigSaveSucceededAsync(() => ConfigTextHandler.SaveConfig()); await EnsureConfigSaveSucceededAsync(() => ConfigTextHandler.SaveConfig());
@@ -160,13 +160,13 @@ public sealed partial class V2rayRuntime
try try
{ {
result = await _mutations.RunAsync(() => profile.ConfigType.IsGroupType() result = await _mutations.RunAsync(() => profile.ConfigType.IsGroupType()
? ConfigDbHandler.AddServerCommon(Config, profile) ? ConfigDbHandler.AddServerCommon(profile)
: profile.ConfigType switch : profile.ConfigType switch
{ {
EConfigType.Custom when isNew => ConfigDbHandler.AddCustomServer(Config, profile, blDelete: false), EConfigType.Custom when isNew => ConfigDbHandler.AddCustomServer(profile, blDelete: false),
EConfigType.Outbound when isNew => ConfigDbHandler.AddCustomOutboundServer(Config, profile, blDelete: false, toFile: true), EConfigType.Outbound when isNew => ConfigDbHandler.AddCustomOutboundServer(profile, blDelete: false, toFile: true),
EConfigType.Custom or EConfigType.Outbound => ConfigDbHandler.EditCustomServer(Config, profile), EConfigType.Custom or EConfigType.Outbound => ConfigDbHandler.EditCustomServer(profile),
_ => ConfigDbHandler.AddServer(Config, profile), _ => ConfigDbHandler.AddServer(profile),
}); });
} }
catch (Exception exception) catch (Exception exception)
@@ -263,7 +263,7 @@ public sealed partial class V2rayRuntime
await _mutations.RunAsync(async () => await _mutations.RunAsync(async () =>
{ {
if (await ConfigDbHandler.RemoveServers(Config, selected) != 0) if (await ConfigDbHandler.RemoveServers(selected) != 0)
{ {
throw new IOException("ServiceLib could not remove the selected profiles."); throw new IOException("ServiceLib could not remove the selected profiles.");
} }
@@ -297,7 +297,7 @@ public sealed partial class V2rayRuntime
return OperationView.Fail("profile_not_found", ApiMessageKeys.ProfileNotFound); return OperationView.Fail("profile_not_found", ApiMessageKeys.ProfileNotFound);
} }
if (await _mutations.RunAsync(() => ConfigDbHandler.CopyServer(Config, items)) != 0) if (await _mutations.RunAsync(() => ConfigDbHandler.CopyServer(items)) != 0)
{ {
return OperationView.Fail("profile_copy_failed", ApiMessageKeys.CommonInvalidInput); return OperationView.Fail("profile_copy_failed", ApiMessageKeys.CommonInvalidInput);
} }
@@ -319,7 +319,7 @@ public sealed partial class V2rayRuntime
return OperationView.Fail("profile_not_found", ApiMessageKeys.ProfileNotFound); return OperationView.Fail("profile_not_found", ApiMessageKeys.ProfileNotFound);
} }
if (await _mutations.RunAsync(() => ConfigDbHandler.MoveToGroup(Config, items, request.SubscriptionId ?? string.Empty)) != 0) if (await _mutations.RunAsync(() => ConfigDbHandler.MoveToGroup(items, request.SubscriptionId ?? string.Empty)) != 0)
{ {
return OperationView.Fail("profile_move_failed", ApiMessageKeys.CommonInvalidInput); return OperationView.Fail("profile_move_failed", ApiMessageKeys.CommonInvalidInput);
} }
@@ -338,7 +338,7 @@ public sealed partial class V2rayRuntime
return OperationView.Fail("profile_not_in_group", ApiMessageKeys.ProfileNotInGroup); return OperationView.Fail("profile_not_in_group", ApiMessageKeys.ProfileNotInGroup);
} }
var result = await _mutations.RunAsync(() => ConfigDbHandler.MoveServer(Config, orderedIds, index, request.Direction, request.Position)); var result = await _mutations.RunAsync(() => ConfigDbHandler.MoveServer(orderedIds, index, request.Direction, request.Position));
_events.Publish("profiles-changed", new { subscriptionId = groupId }); _events.Publish("profiles-changed", new { subscriptionId = groupId });
return result == 0 return result == 0
? OperationView.Ok(ApiMessageKeys.ProfileOrderSaved) ? OperationView.Ok(ApiMessageKeys.ProfileOrderSaved)
@@ -353,7 +353,7 @@ public sealed partial class V2rayRuntime
return OperationView.Fail("profile_sort_column_invalid", ApiMessageKeys.CommonInvalidInput); return OperationView.Fail("profile_sort_column_invalid", ApiMessageKeys.CommonInvalidInput);
} }
var result = await _mutations.RunAsync(() => ConfigDbHandler.SortServers(Config, groupId, request.Column, request.Ascending)); var result = await _mutations.RunAsync(() => ConfigDbHandler.SortServers(groupId, request.Column, request.Ascending));
_events.Publish("profiles-changed", new { subscriptionId = groupId }); _events.Publish("profiles-changed", new { subscriptionId = groupId });
return result == 0 return result == 0
? OperationView.Ok(ApiMessageKeys.ProfileOrderSaved) ? OperationView.Ok(ApiMessageKeys.ProfileOrderSaved)
@@ -362,14 +362,14 @@ public sealed partial class V2rayRuntime
public async Task<OperationView> RemoveDuplicateProfilesAsync(string? subscriptionId) public async Task<OperationView> RemoveDuplicateProfilesAsync(string? subscriptionId)
{ {
var result = await _mutations.RunAsync(() => ConfigDbHandler.DedupServerList(Config, subscriptionId ?? Config.SubIndexId ?? string.Empty)); var result = await _mutations.RunAsync(() => ConfigDbHandler.DedupServerList(subscriptionId ?? Config.SubIndexId ?? string.Empty));
_events.Publish("profiles-changed", new { subscriptionId = subscriptionId ?? Config.SubIndexId }); _events.Publish("profiles-changed", new { subscriptionId = subscriptionId ?? Config.SubIndexId });
return OperationView.Ok(ApiMessageKeys.ProfileDeduplicated, new { removed = result.Item1 - result.Item2 }); return OperationView.Ok(ApiMessageKeys.ProfileDeduplicated, new { removed = result.Item1 - result.Item2 });
} }
public async Task<OperationView> RemoveInvalidProfilesAsync(string? subscriptionId) public async Task<OperationView> RemoveInvalidProfilesAsync(string? subscriptionId)
{ {
var count = await _mutations.RunAsync(() => ConfigDbHandler.RemoveInvalidServerResult(Config, subscriptionId ?? Config.SubIndexId ?? string.Empty)); var count = await _mutations.RunAsync(() => ConfigDbHandler.RemoveInvalidServerResult(subscriptionId ?? Config.SubIndexId ?? string.Empty));
_events.Publish("profiles-changed", new { subscriptionId = subscriptionId ?? Config.SubIndexId }); _events.Publish("profiles-changed", new { subscriptionId = subscriptionId ?? Config.SubIndexId });
return count < 0 return count < 0
? OperationView.Ok(ApiMessageKeys.CommonCompleted, new { removed = 0 }) ? OperationView.Ok(ApiMessageKeys.CommonCompleted, new { removed = 0 })
@@ -389,8 +389,8 @@ public sealed partial class V2rayRuntime
} }
var result = await _mutations.RunAsync(() => byRegion var result = await _mutations.RunAsync(() => byRegion
? ConfigDbHandler.AddGroupRegionServer(Config, subscription) ? ConfigDbHandler.AddGroupRegionServer(subscription)
: ConfigDbHandler.AddGroupAllServer(Config, subscription)); : ConfigDbHandler.AddGroupAllServer(subscription));
if (!result.Success) if (!result.Success)
{ {
return OperationView.Fail("profile_group_empty", ApiMessageKeys.ProfileGrouped, result.Data); return OperationView.Fail("profile_group_empty", ApiMessageKeys.ProfileGrouped, result.Data);
@@ -563,7 +563,7 @@ public sealed partial class V2rayRuntime
|| current.DomainDNSAddress != input.DomainDNSAddress || current.DomainDNSAddress != input.DomainDNSAddress
|| current.Remarks != (input.Remarks ?? current.Remarks); || current.Remarks != (input.Remarks ?? current.Remarks);
var item = ApplyDnsProfileInput(current, coreType, input); var item = ApplyDnsProfileInput(current, coreType, input);
return (Result: await ConfigDbHandler.SaveDNSItems(Config, item), Changed: changed); return (Result: await ConfigDbHandler.SaveDNSItems( item), Changed: changed);
}); });
if (result.Result == -2) if (result.Result == -2)
{ {
@@ -696,7 +696,7 @@ public sealed partial class V2rayRuntime
item.RuleNum = parsedRules.Count; item.RuleNum = parsedRules.Count;
} }
var result = parsedRules.Count == 0 var result = parsedRules.Count == 0
? await ConfigDbHandler.SaveRoutingItem(Config, item) ? await ConfigDbHandler.SaveRoutingItem( item)
: await ConfigDbHandler.AddBatchRoutingRules(item, JsonUtils.Serialize(parsedRules, false)); : await ConfigDbHandler.AddBatchRoutingRules(item, JsonUtils.Serialize(parsedRules, false));
return (Result: result, Item: (RoutingItem?)item, Changed: changed); return (Result: result, Item: (RoutingItem?)item, Changed: changed);
}); });
@@ -735,7 +735,7 @@ public sealed partial class V2rayRuntime
var fallback = remaining.FirstOrDefault(); var fallback = remaining.FirstOrDefault();
if (fallback is not null) if (fallback is not null)
{ {
if (await ConfigDbHandler.SetDefaultRouting(Config, fallback) != 0) if (await ConfigDbHandler.SetDefaultRouting( fallback) != 0)
{ {
throw new IOException("ServiceLib could not select the fallback routing profile."); throw new IOException("ServiceLib could not select the fallback routing profile.");
} }
@@ -772,7 +772,7 @@ public sealed partial class V2rayRuntime
return (Result: -2, Changed: false); return (Result: -2, Changed: false);
} }
var changed = !item.IsActive; var changed = !item.IsActive;
return (Result: changed ? await ConfigDbHandler.SetDefaultRouting(Config, item) : 0, Changed: changed); return (Result: changed ? await ConfigDbHandler.SetDefaultRouting( item) : 0, Changed: changed);
}); });
if (result.Result == -2) if (result.Result == -2)
{ {
@@ -993,7 +993,7 @@ public sealed partial class V2rayRuntime
} }
var before = await GetActiveRoutingSignatureAsync(); var before = await GetActiveRoutingSignatureAsync();
var result = await _mutations.RunAsync(() => ConfigDbHandler.InitRouting(Config, true)); var result = await _mutations.RunAsync(() => ConfigDbHandler.InitRouting( true));
if (result != 0) if (result != 0)
{ {
return OperationView.Fail("routing_import_failed", ApiMessageKeys.RoutingSaveFailed); return OperationView.Fail("routing_import_failed", ApiMessageKeys.RoutingSaveFailed);
@@ -1048,7 +1048,7 @@ public sealed partial class V2rayRuntime
return -2; return -2;
} }
var item = ApplyCoreConfigTemplateInput(current, coreType, input); var item = ApplyCoreConfigTemplateInput(current, coreType, input);
return await ConfigDbHandler.SaveFullConfigTemplate(Config, item); return await ConfigDbHandler.SaveFullConfigTemplate( item);
}); });
if (result == -2) if (result == -2)
{ {
@@ -1160,7 +1160,7 @@ public sealed partial class V2rayRuntime
await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>(); await SQLiteHelper.Instance.DeleteAllAsync<DNSItem>();
foreach (var item in stage.DnsItems) foreach (var item in stage.DnsItems)
{ {
if (await ConfigDbHandler.SaveDNSItems(Config, item) != 0) if (await ConfigDbHandler.SaveDNSItems( item) != 0)
{ {
throw new IOException($"The {item.CoreType} DNS profile could not be saved."); throw new IOException($"The {item.CoreType} DNS profile could not be saved.");
} }
@@ -1168,7 +1168,7 @@ public sealed partial class V2rayRuntime
// Default routing uses embedded data only; this call performs no network I/O // Default routing uses embedded data only; this call performs no network I/O
// because the route template source was cleared in the staged plan. // because the route template source was cleared in the staged plan.
if (await ConfigDbHandler.InitRouting(Config, false) != 0) if (await ConfigDbHandler.InitRouting( false) != 0)
{ {
throw new IOException("The built-in routing profiles could not be initialized."); throw new IOException("The built-in routing profiles could not be initialized.");
} }
@@ -1177,7 +1177,7 @@ public sealed partial class V2rayRuntime
{ {
foreach (var item in stage.DnsItems) foreach (var item in stage.DnsItems)
{ {
if (await ConfigDbHandler.SaveDNSItems(Config, item) != 0) if (await ConfigDbHandler.SaveDNSItems( item) != 0)
{ {
throw new IOException($"The {item.CoreType} DNS profile could not be saved."); throw new IOException($"The {item.CoreType} DNS profile could not be saved.");
} }
@@ -1216,7 +1216,7 @@ public sealed partial class V2rayRuntime
var defaultItem = stage.Routing.DefaultRemarks is { } remarks var defaultItem = stage.Routing.DefaultRemarks is { } remarks
? stage.Routing.Items.FirstOrDefault(item => item.Remarks == remarks) ? stage.Routing.Items.FirstOrDefault(item => item.Remarks == remarks)
: null; : null;
if (defaultItem is not null && await ConfigDbHandler.SetDefaultRouting(Config, defaultItem) != 0) if (defaultItem is not null && await ConfigDbHandler.SetDefaultRouting( defaultItem) != 0)
{ {
throw new IOException("The first staged routing profile could not be activated."); throw new IOException("The first staged routing profile could not be activated.");
} }
@@ -1226,7 +1226,7 @@ public sealed partial class V2rayRuntime
{ {
var existingDefault = currentRoutes.FirstOrDefault(item => item.Id == existingDefaultId); var existingDefault = currentRoutes.FirstOrDefault(item => item.Id == existingDefaultId);
if (existingDefault is not null && !existingDefault.IsActive if (existingDefault is not null && !existingDefault.IsActive
&& await ConfigDbHandler.SetDefaultRouting(Config, existingDefault) != 0) && await ConfigDbHandler.SetDefaultRouting( existingDefault) != 0)
{ {
throw new IOException("The migrated default routing profile could not be activated."); throw new IOException("The migrated default routing profile could not be activated.");
} }
+9 -10
View File
@@ -247,17 +247,16 @@ public sealed partial class V2rayRuntime(
} }
await EnsureConfigSaveSucceededAsync(() => ConfigTextHandler.SaveConfig()); await EnsureConfigSaveSucceededAsync(() => ConfigTextHandler.SaveConfig());
}); });
await ConfigDbHandler.InitBuiltinDNS(Config); await ConfigDbHandler.InitBuiltinDNS();
await BuiltinDnsProfileBootstrap.EnsureAsync( await BuiltinDnsProfileBootstrap.EnsureAsync(
Config,
async () => await ConfigDbQuery.DNSItems() ?? [], async () => await ConfigDbQuery.DNSItems() ?? [],
ConfigDbHandler.SaveDNSItems); ConfigDbHandler.SaveDNSItems);
await ConfigDbHandler.InitBuiltinFullConfigTemplate(Config); await ConfigDbHandler.InitBuiltinFullConfigTemplate();
// Keep startup aligned with Desktop's StatusBarViewModel. In particular, // Keep startup aligned with Desktop's StatusBarViewModel. In particular,
// InitBuiltinRouting owns the RoutingIndexId -> IsActive migration and must // InitBuiltinRouting owns the RoutingIndexId -> IsActive migration and must
// run even when a restored Desktop database already has routing rows. // run even when a restored Desktop database already has routing rows.
await ConfigDbHandler.InitBuiltinRouting(Config); await ConfigDbHandler.InitBuiltinRouting();
_ = await ConfigDbHandler.GetDefaultRouting(Config); _ = await ConfigDbHandler.GetDefaultRouting();
var restoredSubscriptions = await ConfigDbQuery.SubItems() ?? []; var restoredSubscriptions = await ConfigDbQuery.SubItems() ?? [];
var normalizedSubIndexId = NormalizeSelectedSubscriptionId( var normalizedSubIndexId = NormalizeSelectedSubscriptionId(
Config.SubIndexId, Config.SubIndexId,
@@ -437,7 +436,7 @@ public sealed partial class V2rayRuntime(
} }
var item = ToSubItem(input, null); var item = ToSubItem(input, null);
var result = await _mutations.RunAsync(() => ConfigDbHandler.AddSubItem(Config, item)); var result = await _mutations.RunAsync(() => ConfigDbHandler.AddSubItem(item));
if (result != 0) if (result != 0)
{ {
return new(false, "subscription_save_failed", ApiMessageKeys.SubscriptionSaveFailed, null); return new(false, "subscription_save_failed", ApiMessageKeys.SubscriptionSaveFailed, null);
@@ -466,7 +465,7 @@ public sealed partial class V2rayRuntime(
var item = ToSubItem(input, existing); var item = ToSubItem(input, existing);
item.Id = id; item.Id = id;
var result = await ConfigDbHandler.AddSubItem(Config, item); var result = await ConfigDbHandler.AddSubItem(item);
if (result != 0) if (result != 0)
{ {
return new SubscriptionMutationResult(false, "subscription_save_failed", ApiMessageKeys.SubscriptionSaveFailed, null); return new SubscriptionMutationResult(false, "subscription_save_failed", ApiMessageKeys.SubscriptionSaveFailed, null);
@@ -496,7 +495,7 @@ public sealed partial class V2rayRuntime(
await _mutations.RunAsync(async () => await _mutations.RunAsync(async () =>
{ {
if (await ConfigDbHandler.DeleteSubItem(Config, id) != 0) if (await ConfigDbHandler.DeleteSubItem(id) != 0)
{ {
throw new IOException("ServiceLib could not delete the subscription."); throw new IOException("ServiceLib could not delete the subscription.");
} }
@@ -1178,7 +1177,7 @@ public sealed partial class V2rayRuntime(
if (item is not null) if (item is not null)
{ {
item.UpdateTime = updateTime; item.UpdateTime = updateTime;
if (await ConfigDbHandler.AddSubItem(Config, item) != 0) if (await ConfigDbHandler.AddSubItem(item) != 0)
{ {
throw new IOException("ServiceLib could not save the subscription timestamp."); throw new IOException("ServiceLib could not save the subscription timestamp.");
} }
@@ -1191,7 +1190,7 @@ public sealed partial class V2rayRuntime(
if (item.Enabled) if (item.Enabled)
{ {
item.UpdateTime = updateTime; item.UpdateTime = updateTime;
if (await ConfigDbHandler.AddSubItem(Config, item) != 0) if (await ConfigDbHandler.AddSubItem(item) != 0)
{ {
throw new IOException("ServiceLib could not save the subscription timestamp."); throw new IOException("ServiceLib could not save the subscription timestamp.");
} }
@@ -57,9 +57,8 @@ public class BuiltinDnsProfileBootstrapTests
var rows = new List<DNSItem>(initial); var rows = new List<DNSItem>(initial);
var savedTypes = new List<ECoreType>(); var savedTypes = new List<ECoreType>();
await BuiltinDnsProfileBootstrap.EnsureAsync( await BuiltinDnsProfileBootstrap.EnsureAsync(
new Config(),
() => Task.FromResult<IReadOnlyList<DNSItem>>(rows.ToArray()), () => Task.FromResult<IReadOnlyList<DNSItem>>(rows.ToArray()),
(_, item) => (item) =>
{ {
rows.Add(item); rows.Add(item);
savedTypes.Add(item.CoreType); savedTypes.Add(item.CoreType);
@@ -24,7 +24,7 @@ public class ParityValidationTests
await code.Should().BeEqualTo("ok"); await code.Should().BeEqualTo("ok");
await profile.IsValid().Should().BeFalse(); await profile.IsValid().Should().BeFalse();
var result = await ConfigDbHandler.AddShadowsocksServer(new Config(), profile, toFile: false); var result = await ConfigDbHandler.AddShadowsocksServer( profile, toFile: false);
await result.Should().BeEqualTo(0); await result.Should().BeEqualTo(0);
await profile.ConfigVersion.Should().BeEqualTo(4); await profile.ConfigVersion.Should().BeEqualTo(4);
@@ -41,7 +41,7 @@ public class ParityValidationTests
await code.Should().BeEqualTo("ok"); await code.Should().BeEqualTo("ok");
await profile.IsValid().Should().BeTrue(); await profile.IsValid().Should().BeTrue();
var result = await ConfigDbHandler.AddShadowsocksServer(new Config(), profile, toFile: false); var result = await ConfigDbHandler.AddShadowsocksServer( profile, toFile: false);
await result.Should().BeEqualTo(0); await result.Should().BeEqualTo(0);
} }
@@ -54,7 +54,7 @@ public class ParityValidationTests
var valid = V2rayRuntime.TryValidateProfile(profile, out _, out _); var valid = V2rayRuntime.TryValidateProfile(profile, out _, out _);
await valid.Should().BeTrue(); await valid.Should().BeTrue();
var result = await ConfigDbHandler.AddShadowsocksServer(new Config(), profile, toFile: false); var result = await ConfigDbHandler.AddShadowsocksServer(profile, toFile: false);
await result.Should().BeEqualTo(-1); await result.Should().BeEqualTo(-1);
} }
+1 -1
View File
@@ -55,7 +55,7 @@ public sealed class WindowsManager
{ {
try try
{ {
var item = await ConfigDbHandler.GetDefaultRouting(config); var item = await ConfigDbHandler.GetDefaultRouting();
if (item == null || item.CustomIcon.IsNullOrEmpty() || !File.Exists(item.CustomIcon)) if (item == null || item.CustomIcon.IsNullOrEmpty() || !File.Exists(item.CustomIcon))
{ {
return null; return null;