mirror of
https://github.com/2dust/v2rayN.git
synced 2026-08-16 12:12:07 +03:00
@@ -134,4 +134,25 @@ public static class Extension
|
||||
.Replace("\r", replacement)
|
||||
.Replace("\n", replacement);
|
||||
}
|
||||
|
||||
public static async Task<TOutput> HandleSafe<TInput, TOutput>(
|
||||
this Interaction<TInput, TOutput> interaction,
|
||||
TInput input,
|
||||
TOutput defaultValue = default!)
|
||||
{
|
||||
try
|
||||
{
|
||||
return await interaction.Handle(input);
|
||||
}
|
||||
catch (UnhandledInteractionException<TInput, TOutput> ex)
|
||||
{
|
||||
Logging.SaveLog($"Unhandled interaction exception for input: {input}", ex);
|
||||
return defaultValue;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.SaveLog($"Exception occurred while handling interaction for input: {input}", ex);
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@ public partial class AddServer2ViewModel : MyReactiveObject, ICloseable
|
||||
|
||||
BrowseServerCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var fileName = await BrowseConfigFileInteraction.Handle(RxVoid.Default);
|
||||
var fileName = await BrowseConfigFileInteraction.HandleSafe(RxVoid.Default);
|
||||
if (fileName.IsNullOrEmpty())
|
||||
{
|
||||
return;
|
||||
|
||||
@@ -85,8 +85,6 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
#endregion Menu
|
||||
|
||||
private readonly SynchronizationContext _uiContext = SynchronizationContext.Current;
|
||||
|
||||
#region Init
|
||||
|
||||
public MainWindowViewModel()
|
||||
@@ -302,7 +300,7 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
.ObserveOn(RxSchedulers.MainThreadScheduler)
|
||||
.Subscribe(async blShow =>
|
||||
{
|
||||
await ShowHideWindowInteraction.Handle(blShow);
|
||||
await ShowHideWindowInteraction.HandleSafe(blShow);
|
||||
});
|
||||
|
||||
StatusBarViewModel.SetDefaultServerRequested
|
||||
@@ -413,14 +411,25 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
private async Task RefreshServersDispatcherAsync()
|
||||
{
|
||||
//await Observable.Start(async () => await RefreshServers(), RxSchedulers.MainThreadScheduler);
|
||||
_uiContext?.Post(_ => _ = RefreshServers(), null);
|
||||
await Signal.FromAsync(async () =>
|
||||
{
|
||||
await RefreshServers();
|
||||
return RxVoid.Default;
|
||||
})
|
||||
.SubscribeOn(RxSchedulers.MainThreadScheduler)
|
||||
.ToTask();
|
||||
}
|
||||
|
||||
private async Task RefreshSubscriptions()
|
||||
{
|
||||
//await Observable.Start(async () => await ProfilesViewModel.RefreshSubscriptions(), RxSchedulers.MainThreadScheduler);
|
||||
|
||||
_uiContext?.Post(_ => _ = ProfilesViewModel.RefreshSubscriptions(), null);
|
||||
await Signal.FromAsync(async () =>
|
||||
{
|
||||
await ProfilesViewModel.RefreshSubscriptions();
|
||||
return RxVoid.Default;
|
||||
})
|
||||
.SubscribeOn(RxSchedulers.MainThreadScheduler)
|
||||
.ToTask();
|
||||
}
|
||||
|
||||
#endregion Servers && Groups
|
||||
@@ -467,7 +476,7 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
var stringData = clipboardData;
|
||||
if (clipboardData == null)
|
||||
{
|
||||
var result = await ReadTextFromClipboardInteraction.Handle(RxVoid.Default);
|
||||
var result = await ReadTextFromClipboardInteraction.HandleSafe(RxVoid.Default);
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
|
||||
@@ -490,7 +499,7 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
public async Task AddServerViaScanAsync()
|
||||
{
|
||||
var result = await ScanScreenInteraction.Handle(RxVoid.Default);
|
||||
var result = await ScanScreenInteraction.HandleSafe(RxVoid.Default);
|
||||
await ScanScreenResult(result);
|
||||
}
|
||||
|
||||
@@ -502,7 +511,7 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
|
||||
public async Task AddServerViaImageAsync()
|
||||
{
|
||||
var imageFileName = await BrowseImageFileInteraction.Handle(RxVoid.Default);
|
||||
var imageFileName = await BrowseImageFileInteraction.HandleSafe(RxVoid.Default);
|
||||
await AddScanResultAsync(imageFileName);
|
||||
}
|
||||
|
||||
@@ -691,10 +700,12 @@ public partial class MainWindowViewModel : MyReactiveObject
|
||||
//{
|
||||
// await ClashProxiesViewModel.ProxiesReload();
|
||||
//}, RxSchedulers.MainThreadScheduler);
|
||||
RxSchedulers.MainThreadScheduler.Schedule(async () =>
|
||||
{
|
||||
await ClashProxiesViewModel.ProxiesReload();
|
||||
});
|
||||
await Signal.FromAsync(async () =>
|
||||
{
|
||||
await ClashProxiesViewModel.ProxiesReload();
|
||||
return RxVoid.Default;
|
||||
}).SubscribeOn(RxSchedulers.MainThreadScheduler)
|
||||
.ToTask();
|
||||
}
|
||||
|
||||
ReloadResult(showClashUI);
|
||||
|
||||
@@ -74,7 +74,7 @@ public partial class MsgViewModel : MyReactiveObject
|
||||
{
|
||||
try
|
||||
{
|
||||
await DispatcherShowMsgInteraction.Handle(sb.ToString());
|
||||
await DispatcherShowMsgInteraction.HandleSafe(sb.ToString());
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
|
||||
@@ -138,13 +138,7 @@ public partial class ProfilesSelectViewModel : MyReactiveObject, ICloseable
|
||||
|
||||
await RefreshServers();
|
||||
|
||||
try
|
||||
{
|
||||
await ProfilesFocusInteraction.Handle(RxVoid.Default);
|
||||
}
|
||||
catch (UnhandledInteractionException<RxVoid, RxVoid>)
|
||||
{
|
||||
}
|
||||
await ProfilesFocusInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
|
||||
private async Task ServerFilterChanged(bool c)
|
||||
|
||||
@@ -345,13 +345,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
|
||||
await RefreshServers();
|
||||
|
||||
try
|
||||
{
|
||||
await ProfilesFocusInteraction.Handle(RxVoid.Default);
|
||||
}
|
||||
catch (UnhandledInteractionException<RxVoid, RxVoid>)
|
||||
{
|
||||
}
|
||||
await ProfilesFocusInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
|
||||
private async Task ServerFilterChanged(bool c)
|
||||
@@ -395,13 +389,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
SelectedProfile = selected ?? lstModel.First();
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
await DispatcherRefreshServersBizInteraction.Handle(RxVoid.Default);
|
||||
}
|
||||
catch (UnhandledInteractionException<RxVoid, RxVoid>)
|
||||
{
|
||||
}
|
||||
await DispatcherRefreshServersBizInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
|
||||
public async Task RefreshSubscriptions()
|
||||
@@ -419,7 +407,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
|
||||
public async Task AdjustMainLvColWidth()
|
||||
{
|
||||
await AdjustMainLvColWidthInteraction.Handle(RxVoid.Default);
|
||||
await AdjustMainLvColWidthInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
|
||||
private async Task<List<ProfileItemModel>?> GetProfileItemsEx(string subid, string filter)
|
||||
@@ -535,7 +523,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -556,7 +544,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
|
||||
private async Task RemoveDuplicateServer()
|
||||
{
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -631,7 +619,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
return;
|
||||
}
|
||||
|
||||
await ShareServerInteraction.Handle(url);
|
||||
await ShareServerInteraction.HandleSafe(url);
|
||||
}
|
||||
|
||||
private async Task GenGroupAllServer()
|
||||
@@ -799,13 +787,13 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
}
|
||||
else
|
||||
{
|
||||
await SetClipboardDataInteraction.Handle((string)result.Data);
|
||||
await SetClipboardDataInteraction.HandleSafe((string)result.Data);
|
||||
NoticeManager.Instance.SendMessage(ResUI.OperationSuccess);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
await SaveFileDialogInteraction.Handle(item);
|
||||
await SaveFileDialogInteraction.HandleSafe(item);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -854,11 +842,11 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
{
|
||||
if (blEncode)
|
||||
{
|
||||
await SetClipboardDataInteraction.Handle(Utils.Base64Encode(sb.ToString()));
|
||||
await SetClipboardDataInteraction.HandleSafe(Utils.Base64Encode(sb.ToString()));
|
||||
}
|
||||
else
|
||||
{
|
||||
await SetClipboardDataInteraction.Handle(sb.ToString());
|
||||
await SetClipboardDataInteraction.HandleSafe(sb.ToString());
|
||||
}
|
||||
NoticeManager.Instance.SendMessage(ResUI.BatchExportURLSuccessfully);
|
||||
}
|
||||
@@ -881,7 +869,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
|
||||
if (!result.IsNullOrEmpty())
|
||||
{
|
||||
await SetClipboardDataInteraction.Handle(result);
|
||||
await SetClipboardDataInteraction.HandleSafe(result);
|
||||
NoticeManager.Instance.SendMessage(ResUI.BatchExportURLSuccessfully);
|
||||
}
|
||||
else
|
||||
@@ -925,7 +913,7 @@ public partial class ProfilesViewModel : MyReactiveObject
|
||||
return;
|
||||
}
|
||||
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||
});
|
||||
ImportRulesFromFileCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
var fileName = await BrowseRulesFileInteraction.Handle(RxVoid.Default);
|
||||
var fileName = await BrowseRulesFileInteraction.HandleSafe(RxVoid.Default);
|
||||
await ImportRulesFromFileAsync(fileName);
|
||||
});
|
||||
ImportRulesFromClipboardCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
@@ -156,7 +156,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||
NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);
|
||||
return;
|
||||
}
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -199,7 +199,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||
DefaultIgnoreCondition = JsonIgnoreCondition.WhenWritingNull,
|
||||
PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
|
||||
};
|
||||
await SetClipboardDataInteraction.Handle(JsonUtils.Serialize(lst, options));
|
||||
await SetClipboardDataInteraction.HandleSafe(JsonUtils.Serialize(lst, options));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -277,7 +277,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||
var stringData = clipboardData;
|
||||
if (clipboardData == null)
|
||||
{
|
||||
var result = await ReadTextFromClipboardInteraction.Handle(RxVoid.Default);
|
||||
var result = await ReadTextFromClipboardInteraction.HandleSafe(RxVoid.Default);
|
||||
if (result.IsNullOrEmpty())
|
||||
{
|
||||
NoticeManager.Instance.Enqueue(ResUI.OperationFailed);
|
||||
@@ -315,7 +315,7 @@ public partial class RoutingRuleSettingViewModel : MyReactiveObject, ICloseable
|
||||
private async Task<int> AddBatchRoutingRulesAsync(RoutingItem routingItem, string? clipboardData)
|
||||
{
|
||||
var blReplace = false;
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.AddBatchRoutingRulesYesNo) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.AddBatchRoutingRulesYesNo) == false)
|
||||
{
|
||||
blReplace = true;
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public partial class RoutingSettingViewModel : MyReactiveObject
|
||||
NoticeManager.Instance.Enqueue(ResUI.PleaseSelectRules);
|
||||
return;
|
||||
}
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -243,7 +243,7 @@ public partial class StatusBarViewModel : MyReactiveObject
|
||||
sb.AppendLine($"{cmd} HTTPS_PROXY={Global.HttpProtocol}{address}");
|
||||
sb.AppendLine($"{cmd} ALL_PROXY={Global.Socks5Protocol}{address}");
|
||||
|
||||
await SetClipboardDataInteraction.Handle(sb.ToString());
|
||||
await SetClipboardDataInteraction.HandleSafe(sb.ToString());
|
||||
}
|
||||
|
||||
private async Task AddServerViaClipboard()
|
||||
@@ -389,14 +389,7 @@ public partial class StatusBarViewModel : MyReactiveObject
|
||||
|
||||
if (blChange)
|
||||
{
|
||||
try
|
||||
{
|
||||
await DispatcherRefreshIconInteraction.Handle(RxVoid.Default);
|
||||
}
|
||||
catch (UnhandledInteractionException<RxVoid, RxVoid>)
|
||||
{
|
||||
// Ignore
|
||||
}
|
||||
await DispatcherRefreshIconInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -432,7 +425,7 @@ public partial class StatusBarViewModel : MyReactiveObject
|
||||
{
|
||||
NoticeManager.Instance.SendMessageEx(ResUI.TipChangeRouting);
|
||||
ReloadRequested.Publish();
|
||||
await DispatcherRefreshIconInteraction.Handle(RxVoid.Default);
|
||||
await DispatcherRefreshIconInteraction.HandleSafe(RxVoid.Default);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -469,7 +462,7 @@ public partial class StatusBarViewModel : MyReactiveObject
|
||||
}
|
||||
else
|
||||
{
|
||||
var password = await PasswordInputInteraction.Handle(RxVoid.Default);
|
||||
var password = await PasswordInputInteraction.HandleSafe(RxVoid.Default);
|
||||
if (password.IsNullOrEmpty())
|
||||
{
|
||||
_config.TunModeItem.EnableTun = false;
|
||||
|
||||
@@ -40,7 +40,7 @@ public partial class SubSettingViewModel : MyReactiveObject
|
||||
}, canEditRemove);
|
||||
SubShareCmd = ReactiveCommand.CreateFromTask(async () =>
|
||||
{
|
||||
await ShareSubInteraction.Handle(SelectedSource?.Url);
|
||||
await ShareSubInteraction.HandleSafe(SelectedSource?.Url);
|
||||
}, canEditRemove);
|
||||
|
||||
_ = Init();
|
||||
@@ -84,7 +84,7 @@ public partial class SubSettingViewModel : MyReactiveObject
|
||||
|
||||
private async Task DeleteSubAsync()
|
||||
{
|
||||
if (await ShowYesNoInteraction.Handle(ResUI.RemoveServer) == false)
|
||||
if (await ShowYesNoInteraction.HandleSafe(ResUI.RemoveServer) == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user