Refactor code to decouple view and viewmodel

pull/5550/head
2dust 2024-08-11 15:45:55 +08:00
parent 3dd75b17cf
commit 9e9808e489
13 changed files with 360 additions and 285 deletions

View File

@ -9,6 +9,7 @@
ProfilesFocus,
ShareSub,
ShareServer,
ShowHideWindow,
SubEditWindow,
RoutingRuleSettingWindow,
RoutingRuleDetailsWindow,
@ -19,5 +20,14 @@
OptionSettingWindow,
GlobalHotkeySettingWindow,
SubSettingWindow,
DispatcherSpeedTest,
DispatcherRefreshConnections,
DispatcherRefreshProxyGroups,
DispatcherProxiesDelayTest,
DispatcherStatistics,
DispatcherServerAvailability,
DispatcherReload,
DispatcherRefreshServersBiz,
}
}

View File

@ -72,7 +72,7 @@ namespace v2rayN.Handler
bool isSuccess = false;
string msg;
Application.Current.Dispatcher.Invoke(() =>
Application.Current?.Dispatcher.Invoke(() =>
{
isSuccess = RegisterHotKey(IntPtr.Zero, _hotkeyCode, hotkeyInfo.fsModifiers, hotkeyInfo.vKey);
});
@ -96,7 +96,7 @@ namespace v2rayN.Handler
{
foreach (var hotkey in _hotkeyTriggerDic.Keys)
{
Application.Current.Dispatcher.Invoke(() =>
Application.Current?.Dispatcher.Invoke(() =>
{
UnregisterHotKey(IntPtr.Zero, hotkey);
});
@ -137,7 +137,7 @@ namespace v2rayN.Handler
var _hotKeyCode = (int)msg.lParam;
if (IsPause)
{
Application.Current.Dispatcher.Invoke(() =>
Application.Current?.Dispatcher.Invoke(() =>
{
UIElement? element = Keyboard.FocusedElement as UIElement;
if (element != null)

View File

@ -14,14 +14,14 @@ namespace v2rayN.Handler
private CoreHandler _coreHandler;
private List<ServerTestItem> _selecteds;
private ESpeedActionType _actionType;
private Action<string, string, string> _updateFunc;
private Action<SpeedTestResult> _updateFunc;
public SpeedtestHandler(Config config)
{
_config = config;
}
public SpeedtestHandler(Config config, CoreHandler coreHandler, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<string, string, string> update)
public SpeedtestHandler(Config config, CoreHandler coreHandler, List<ProfileItem> selecteds, ESpeedActionType actionType, Action<SpeedTestResult> update)
{
_config = config;
_coreHandler = coreHandler;
@ -408,7 +408,7 @@ namespace v2rayN.Handler
private void UpdateFunc(string indexId, string delay, string speed = "")
{
_updateFunc(indexId, delay, speed);
_updateFunc(new() { IndexId = indexId, Delay = delay, Speed = speed });
}
}
}

View File

@ -0,0 +1,12 @@
namespace v2rayN.Models
{
[Serializable]
public class SpeedTestResult
{
public string? IndexId { get; set; }
public string? Delay { get; set; }
public string? Speed { get; set; }
}
}

View File

@ -4,7 +4,6 @@ using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using System.Reactive;
using System.Reactive.Linq;
using System.Windows;
using v2rayN.Base;
using v2rayN.Enums;
using v2rayN.Handler;
@ -30,9 +29,10 @@ namespace v2rayN.ViewModels
[Reactive]
public bool AutoRefresh { get; set; }
public ClashConnectionsViewModel()
public ClashConnectionsViewModel(Func<EViewAction, object?, bool>? updateView)
{
_config = LazyConfig.Instance.GetConfig();
_updateView = updateView;
SortingSelected = _config.clashUIItem.connectionsSorting;
AutoRefresh = _config.clashUIItem.connectionsAutoRefresh;
@ -110,14 +110,11 @@ namespace v2rayN.ViewModels
return;
}
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
RefreshConnections(it?.connections);
}));
_updateView?.Invoke(EViewAction.DispatcherRefreshConnections, it?.connections);
});
}
private void RefreshConnections(List<ConnectionItem>? connections)
public void RefreshConnections(List<ConnectionItem>? connections)
{
_connectionItems.Clear();

View File

@ -5,7 +5,6 @@ using ReactiveUI.Fody.Helpers;
using Splat;
using System.Reactive;
using System.Reactive.Linq;
using System.Windows;
using v2rayN.Base;
using v2rayN.Enums;
using v2rayN.Handler;
@ -48,10 +47,11 @@ namespace v2rayN.ViewModels
[Reactive]
public bool AutoRefresh { get; set; }
public ClashProxiesViewModel()
public ClashProxiesViewModel(Func<EViewAction, object?, bool>? updateView)
{
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.GetConfig();
_updateView = updateView;
SelectedGroup = new();
SelectedDetail = new();
@ -149,20 +149,6 @@ namespace v2rayN.ViewModels
ProxiesDelayTest();
}
public void ProxiesClear()
{
proxies = null;
providers = null;
ClashApiHandler.Instance.SetProxies(proxies);
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
_proxyGroups.Clear();
_proxyDetails.Clear();
}));
}
public void ProxiesDelayTest()
{
ProxiesDelayTest(true);
@ -197,15 +183,12 @@ namespace v2rayN.ViewModels
}
if (refreshUI)
{
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
RefreshProxyGroups();
}));
_updateView?.Invoke(EViewAction.DispatcherRefreshProxyGroups, null);
}
});
}
private void RefreshProxyGroups()
public void RefreshProxyGroups()
{
var selectedName = SelectedGroup?.name;
_proxyGroups.Clear();
@ -425,34 +408,37 @@ namespace v2rayN.ViewModels
{
return;
}
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
//UpdateHandler(false, $"{item.name}={result}");
var detail = _proxyDetails.Where(it => it.name == item.name).FirstOrDefault();
if (detail != null)
{
var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result);
if (dicResult != null && dicResult.ContainsKey("delay"))
{
detail.delay = Convert.ToInt32(dicResult["delay"].ToString());
detail.delayName = $"{detail.delay}ms";
}
else if (dicResult != null && dicResult.ContainsKey("message"))
{
detail.delay = delayTimeout;
detail.delayName = $"{dicResult["message"]}";
}
else
{
detail.delay = delayTimeout;
detail.delayName = String.Empty;
}
_proxyDetails.Replace(detail, JsonUtils.DeepCopy(detail));
}
}));
_updateView?.Invoke(EViewAction.DispatcherProxiesDelayTest, new SpeedTestResult() { IndexId = item.name, Delay = result });
});
}
public void ProxiesDelayTestResult(SpeedTestResult result)
{
//UpdateHandler(false, $"{item.name}={result}");
var detail = _proxyDetails.Where(it => it.name == result.IndexId).FirstOrDefault();
if (detail != null)
{
var dicResult = JsonUtils.Deserialize<Dictionary<string, object>>(result.Delay);
if (dicResult != null && dicResult.ContainsKey("delay"))
{
detail.delay = Convert.ToInt32(dicResult["delay"].ToString());
detail.delayName = $"{detail.delay}ms";
}
else if (dicResult != null && dicResult.ContainsKey("message"))
{
detail.delay = delayTimeout;
detail.delayName = $"{dicResult["message"]}";
}
else
{
detail.delay = delayTimeout;
detail.delayName = String.Empty;
}
_proxyDetails.Replace(detail, JsonUtils.DeepCopy(detail));
}
}
#endregion proxy function
#region task

View File

@ -25,8 +25,6 @@ namespace v2rayN.ViewModels
private CoreHandler _coreHandler;
private bool _showInTaskbar;
#endregion private prop
#region ObservableCollection
@ -175,7 +173,7 @@ namespace v2rayN.ViewModels
_updateView = updateView;
ThreadPool.RegisterWaitForSingleObject(App.ProgramStarted, OnProgramStarted, null, -1, false);
MessageBus.Current.Listen<string>(Global.CommandRefreshProfiles).Subscribe(x => RefreshServersBiz());
MessageBus.Current.Listen<string>(Global.CommandRefreshProfiles).Subscribe(x => _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null));
SelectedRouting = new();
SelectedServer = new();
@ -352,7 +350,7 @@ namespace v2rayN.ViewModels
NotifyLeftClickCmd = ReactiveCommand.Create(() =>
{
ShowHideWindow(null);
_updateView?.Invoke(EViewAction.ShowHideWindow, null);
});
//System proxy
@ -377,8 +375,7 @@ namespace v2rayN.ViewModels
AutoHideStartup();
_showInTaskbar = true;
_config.uiItem.showInTaskbar = _showInTaskbar;
_config.uiItem.showInTaskbar = true;
}
private void Init()
@ -405,10 +402,7 @@ namespace v2rayN.ViewModels
private void OnProgramStarted(object state, bool timeout)
{
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
ShowHideWindow(true);
}));
_updateView?.Invoke(EViewAction.ShowHideWindow, true);
}
#endregion Init
@ -417,7 +411,7 @@ namespace v2rayN.ViewModels
private void UpdateHandler(bool notify, string msg)
{
if (!_showInTaskbar)
if (!_config.uiItem.showInTaskbar)
{
return;
}
@ -443,24 +437,25 @@ namespace v2rayN.ViewModels
}
private void UpdateStatisticsHandler(ServerSpeedItem update)
{
if (!_config.uiItem.showInTaskbar)
{
return;
}
_updateView?.Invoke(EViewAction.DispatcherStatistics, update);
}
public void SetStatisticsResult(ServerSpeedItem update)
{
try
{
if (!_showInTaskbar)
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.proxyUp), Utils.HumanFy(update.proxyDown));
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.directUp), Utils.HumanFy(update.directDown));
if ((update.proxyUp + update.proxyDown) > 0 && DateTime.Now.Second % 3 == 0)
{
return;
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
}
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
SpeedProxyDisplay = string.Format(ResUI.SpeedDisplayText, Global.ProxyTag, Utils.HumanFy(update.proxyUp), Utils.HumanFy(update.proxyDown));
SpeedDirectDisplay = string.Format(ResUI.SpeedDisplayText, Global.DirectTag, Utils.HumanFy(update.directUp), Utils.HumanFy(update.directDown));
if ((update.proxyUp + update.proxyDown) > 0 && DateTime.Now.Second % 3 == 0)
{
Locator.Current.GetService<ProfilesViewModel>()?.UpdateStatistics(update);
}
}));
}
catch (Exception ex)
{
@ -473,7 +468,7 @@ namespace v2rayN.ViewModels
switch (e)
{
case EGlobalHotkey.ShowForm:
ShowHideWindow(null);
_updateView?.Invoke(EViewAction.ShowHideWindow, null);
break;
case EGlobalHotkey.SystemProxyClear:
@ -535,25 +530,22 @@ namespace v2rayN.ViewModels
MessageBus.Current.SendMessage("", Global.CommandRefreshProfiles);
}
private void RefreshServersBiz()
public void RefreshServersBiz()
{
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
RefreshServersMenu();
RefreshServersMenu();
//display running server
var running = ConfigHandler.GetDefaultServer(_config);
if (running != null)
{
RunningServerDisplay =
RunningServerToolTipText = running.GetSummary();
}
else
{
RunningServerDisplay =
RunningServerToolTipText = ResUI.CheckServerSettings;
}
}));
//display running server
var running = ConfigHandler.GetDefaultServer(_config);
if (running != null)
{
RunningServerDisplay =
RunningServerToolTipText = running.GetSummary();
}
else
{
RunningServerDisplay =
RunningServerToolTipText = ResUI.CheckServerSettings;
}
}
private void RefreshServersMenu()
@ -633,7 +625,7 @@ namespace v2rayN.ViewModels
public async Task ScanScreenTaskAsync()
{
ShowHideWindow(false);
_updateView?.Invoke(EViewAction.ShowHideWindow, false);
var dpiXY = QRCodeHelper.GetDpiXY(Application.Current.MainWindow);
string result = await Task.Run(() =>
@ -641,7 +633,7 @@ namespace v2rayN.ViewModels
return QRCodeHelper.ScanScreen(dpiXY.Item1, dpiXY.Item2);
});
ShowHideWindow(true);
_updateView?.Invoke(EViewAction.ShowHideWindow, true);
if (Utils.IsNullOrEmpty(result))
{
@ -710,17 +702,20 @@ namespace v2rayN.ViewModels
(new UpdateHandle()).RunAvailabilityCheck((bool success, string msg) =>
{
_noticeHandler?.SendMessage(msg, true);
Application.Current?.Dispatcher.Invoke((Action)(() =>
if (!_config.uiItem.showInTaskbar)
{
if (!_showInTaskbar)
{
return;
}
RunningInfoDisplay = msg;
}));
return;
}
_updateView?.Invoke(EViewAction.DispatcherServerAvailability, msg);
});
}
public void TestServerAvailabilityResult(string msg)
{
RunningInfoDisplay = msg;
}
#endregion Add Servers
#region Subscription
@ -854,29 +849,28 @@ namespace v2rayN.ViewModels
{
TestServerAvailability();
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
BlReloadEnabled = true;
ShowClashUI = _config.IsRunningCore(ECoreType.clash);
if (ShowClashUI)
{
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
}
else { TabMainSelectedIndex = 0; }
}));
_updateView?.Invoke(EViewAction.DispatcherReload, null);
});
}
public void ReloadResult()
{
ChangeSystemProxyStatus(_config.systemProxyItem.sysProxyType, false);
BlReloadEnabled = true;
ShowClashUI = _config.IsRunningCore(ECoreType.clash);
if (ShowClashUI)
{
Locator.Current.GetService<ClashProxiesViewModel>()?.ProxiesReload();
}
else { TabMainSelectedIndex = 0; }
}
private async Task LoadCore()
{
await Task.Run(() =>
{
var node = ConfigHandler.GetDefaultServer(_config);
_coreHandler.LoadCore(node);
//ConfigHandler.SaveConfig(_config, false);
ChangeSystemProxyStatus(_config.systemProxyItem.sysProxyType, false);
});
}
@ -911,21 +905,18 @@ namespace v2rayN.ViewModels
SysProxyHandle.UpdateSysProxy(_config, _config.tunModeItem.enableTun ? true : false);
_noticeHandler?.SendMessage($"{ResUI.TipChangeSystemProxy} - {_config.systemProxyItem.sysProxyType.ToString()}", true);
Application.Current?.Dispatcher.Invoke((Action)(() =>
BlSystemProxyClear = (type == ESysProxyType.ForcedClear);
BlSystemProxySet = (type == ESysProxyType.ForcedChange);
BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
BlSystemProxyPac = (type == ESysProxyType.Pac);
InboundDisplayStaus();
if (blChange)
{
BlSystemProxyClear = (type == ESysProxyType.ForcedClear);
BlSystemProxySet = (type == ESysProxyType.ForcedChange);
BlSystemProxyNothing = (type == ESysProxyType.Unchanged);
BlSystemProxyPac = (type == ESysProxyType.Pac);
InboundDisplayStaus();
if (blChange)
{
NotifyIcon = MainFormHandler.Instance.GetNotifyIcon(_config);
AppIcon = MainFormHandler.Instance.GetAppIcon(_config);
}
}));
NotifyIcon = MainFormHandler.Instance.GetNotifyIcon(_config);
AppIcon = MainFormHandler.Instance.GetAppIcon(_config);
}
}
private void RefreshRoutingsMenu()
@ -1013,27 +1004,6 @@ namespace v2rayN.ViewModels
#region UI
public void ShowHideWindow(bool? blShow)
{
var bl = blShow ?? !_showInTaskbar;
if (bl)
{
Application.Current.MainWindow.Show();
if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
{
Application.Current.MainWindow.WindowState = WindowState.Normal;
}
Application.Current.MainWindow.Activate();
Application.Current.MainWindow.Focus();
}
else
{
Application.Current.MainWindow.Hide();
}
_showInTaskbar = bl;
_config.uiItem.showInTaskbar = _showInTaskbar;
}
public void InboundDisplayStaus()
{
StringBuilder sb = new();
@ -1078,10 +1048,7 @@ namespace v2rayN.ViewModels
.Delay(TimeSpan.FromSeconds(1))
.Subscribe(x =>
{
Application.Current?.Dispatcher.Invoke(() =>
{
ShowHideWindow(false);
});
_updateView?.Invoke(EViewAction.ShowHideWindow, false);
});
}
}

View File

@ -6,7 +6,6 @@ using Splat;
using System.Reactive;
using System.Reactive.Linq;
using System.Text;
using System.Windows;
using v2rayN.Base;
using v2rayN.Enums;
using v2rayN.Handler;
@ -106,7 +105,7 @@ namespace v2rayN.ViewModels
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_updateView = updateView;
MessageBus.Current.Listen<string>(Global.CommandRefreshProfiles).Subscribe(x => RefreshServersBiz());
MessageBus.Current.Listen<string>(Global.CommandRefreshProfiles).Subscribe(x => _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null));
SelectedProfile = new();
SelectedSub = new();
@ -246,34 +245,31 @@ namespace v2rayN.ViewModels
Locator.Current.GetService<MainWindowViewModel>()?.Reload();
}
private void UpdateSpeedtestHandler(string indexId, string delay, string speed)
private void UpdateSpeedtestHandler(SpeedTestResult result)
{
Application.Current?.Dispatcher.Invoke((Action)(() =>
{
SetTestResult(indexId, delay, speed);
}));
_updateView?.Invoke(EViewAction.DispatcherSpeedTest, result);
}
private void SetTestResult(string indexId, string delay, string speed)
public void SetSpeedTestResult(SpeedTestResult result)
{
if (Utils.IsNullOrEmpty(indexId))
if (Utils.IsNullOrEmpty(result.IndexId))
{
_noticeHandler?.SendMessage(delay, true);
_noticeHandler?.Enqueue(delay);
_noticeHandler?.SendMessage(result.Delay, true);
_noticeHandler?.Enqueue(result.Delay);
return;
}
var item = _profileItems.Where(it => it.indexId == indexId).FirstOrDefault();
var item = _profileItems.Where(it => it.indexId == result.IndexId).FirstOrDefault();
if (item != null)
{
if (!Utils.IsNullOrEmpty(delay))
if (!Utils.IsNullOrEmpty(result.Delay))
{
int.TryParse(delay, out int temp);
int.TryParse(result.Delay, out int temp);
item.delay = temp;
item.delayVal = $"{delay} {Global.DelayUnit}";
item.delayVal = $"{result.Delay} {Global.DelayUnit}";
}
if (!Utils.IsNullOrEmpty(speed))
if (!Utils.IsNullOrEmpty(result.Speed))
{
item.speedVal = $"{speed} {Global.SpeedUnit}";
item.speedVal = $"{result.Speed} {Global.SpeedUnit}";
}
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
}
@ -283,28 +279,25 @@ namespace v2rayN.ViewModels
{
try
{
Application.Current?.Dispatcher.Invoke((Action)(() =>
var item = _profileItems.Where(it => it.indexId == update.indexId).FirstOrDefault();
if (item != null)
{
var item = _profileItems.Where(it => it.indexId == update.indexId).FirstOrDefault();
if (item != null)
{
item.todayDown = Utils.HumanFy(update.todayDown);
item.todayUp = Utils.HumanFy(update.todayUp);
item.totalDown = Utils.HumanFy(update.totalDown);
item.totalUp = Utils.HumanFy(update.totalUp);
item.todayDown = Utils.HumanFy(update.todayDown);
item.todayUp = Utils.HumanFy(update.todayUp);
item.totalDown = Utils.HumanFy(update.totalDown);
item.totalUp = Utils.HumanFy(update.totalUp);
if (SelectedProfile?.indexId == item.indexId)
{
var temp = JsonUtils.DeepCopy(item);
_profileItems.Replace(item, temp);
SelectedProfile = temp;
}
else
{
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
}
if (SelectedProfile?.indexId == item.indexId)
{
var temp = JsonUtils.DeepCopy(item);
_profileItems.Replace(item, temp);
SelectedProfile = temp;
}
}));
else
{
_profileItems.Replace(item, JsonUtils.DeepCopy(item));
}
}
}
catch
{
@ -346,7 +339,7 @@ namespace v2rayN.ViewModels
MessageBus.Current.SendMessage("", Global.CommandRefreshProfiles);
}
private void RefreshServersBiz()
public void RefreshServersBiz()
{
var lstModel = LazyConfig.Instance.ProfileItems(_config.subIndexId, _serverFilter);
@ -381,25 +374,22 @@ namespace v2rayN.ViewModels
totalDown = t22 == null ? "" : Utils.HumanFy(t22.totalDown),
totalUp = t22 == null ? "" : Utils.HumanFy(t22.totalUp)
}).OrderBy(t => t.sort).ToList();
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel));
_lstProfile = JsonUtils.Deserialize<List<ProfileItem>>(JsonUtils.Serialize(lstModel)) ?? [];
Application.Current?.Dispatcher.Invoke((Action)(() =>
_profileItems.Clear();
_profileItems.AddRange(lstModel);
if (lstModel.Count > 0)
{
_profileItems.Clear();
_profileItems.AddRange(lstModel);
if (lstModel.Count > 0)
var selected = lstModel.FirstOrDefault(t => t.indexId == _config.indexId);
if (selected != null)
{
var selected = lstModel.FirstOrDefault(t => t.indexId == _config.indexId);
if (selected != null)
{
SelectedProfile = selected;
}
else
{
SelectedProfile = lstModel[0];
}
SelectedProfile = selected;
}
}));
else
{
SelectedProfile = lstModel[0];
}
}
}
public void RefreshSubscriptions()

View File

@ -8,7 +8,6 @@ using v2rayN.Enums;
using v2rayN.Handler;
using v2rayN.Models;
using v2rayN.Resx;
using Application = System.Windows.Application;
namespace v2rayN.ViewModels
{
@ -76,9 +75,9 @@ namespace v2rayN.ViewModels
{
ImportRulesFromClipboard();
});
ImportRulesFromUrlCmd = ReactiveCommand.CreateFromTask(() =>
ImportRulesFromUrlCmd = ReactiveCommand.Create(() =>
{
return ImportRulesFromUrl();
ImportRulesFromUrl();
});
RuleRemoveCmd = ReactiveCommand.Create(() =>
@ -292,7 +291,7 @@ namespace v2rayN.ViewModels
}
}
private async Task ImportRulesFromUrl()
private void ImportRulesFromUrl()
{
var url = SelectedRouting.url;
if (Utils.IsNullOrEmpty(url))
@ -302,13 +301,10 @@ namespace v2rayN.ViewModels
}
DownloadHandle downloadHandle = new DownloadHandle();
var result = await downloadHandle.TryDownloadString(url, true, "");
var result = downloadHandle.TryDownloadString(url, true, "").Result;
if (AddBatchRoutingRules(SelectedRouting, result) == 0)
{
Application.Current.Dispatcher.Invoke((Action)(() =>
{
RefreshRulesItems();
}));
RefreshRulesItems();
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
}
}

View File

@ -1,5 +1,9 @@
using ReactiveUI;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Threading;
using v2rayN.Enums;
using v2rayN.Models;
using v2rayN.ViewModels;
namespace v2rayN.Views
@ -12,7 +16,7 @@ namespace v2rayN.Views
public ClashConnectionsView()
{
InitializeComponent();
ViewModel = new ClashConnectionsViewModel();
ViewModel = new ClashConnectionsViewModel(UpdateViewHandler);
this.WhenActivated(disposables =>
{
@ -28,6 +32,22 @@ namespace v2rayN.Views
});
}
private bool UpdateViewHandler(EViewAction action, object? obj)
{
switch (action)
{
case EViewAction.DispatcherRefreshConnections:
if (obj is null) return false;
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.RefreshConnections((List<ConnectionItem>?)obj);
}), DispatcherPriority.Normal);
break;
}
return true;
}
private void btnClose_Click(object sender, System.Windows.RoutedEventArgs e)
{
ViewModel?.ClashConnectionClose(false);

View File

@ -1,7 +1,11 @@
using ReactiveUI;
using Splat;
using System.Reactive.Disposables;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using v2rayN.Enums;
using v2rayN.Models;
using v2rayN.ViewModels;
namespace v2rayN.Views
@ -14,7 +18,7 @@ namespace v2rayN.Views
public ClashProxiesView()
{
InitializeComponent();
ViewModel = new ClashProxiesViewModel();
ViewModel = new ClashProxiesViewModel(UpdateViewHandler);
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(ClashProxiesViewModel));
lstProxyDetails.PreviewMouseDoubleClick += lstProxyDetails_PreviewMouseDoubleClick;
@ -38,6 +42,30 @@ namespace v2rayN.Views
});
}
private bool UpdateViewHandler(EViewAction action, object? obj)
{
switch (action)
{
case EViewAction.DispatcherRefreshProxyGroups:
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.RefreshProxyGroups();
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherProxiesDelayTest:
if (obj is null) return false;
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.ProxiesDelayTestResult((SpeedTestResult)obj);
}), DispatcherPriority.Normal);
break;
}
return true;
}
private void ProxiesView_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)

View File

@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Threading;
using v2rayN.Enums;
using v2rayN.Handler;
using v2rayN.Models;
@ -184,35 +185,67 @@ namespace v2rayN.Views
private bool UpdateViewHandler(EViewAction action, object? obj)
{
if (action == EViewAction.AddServerWindow)
switch (action)
{
if (obj is null) return false;
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
}
else if (action == EViewAction.AddServer2Window)
{
if (obj is null) return false;
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
}
else if (action == EViewAction.DNSSettingWindow)
{
return (new DNSSettingWindow().ShowDialog() ?? false);
}
else if (action == EViewAction.RoutingSettingWindow)
{
return (new RoutingSettingWindow().ShowDialog() ?? false);
}
else if (action == EViewAction.OptionSettingWindow)
{
return (new OptionSettingWindow().ShowDialog() ?? false);
}
else if (action == EViewAction.GlobalHotkeySettingWindow)
{
return (new GlobalHotkeySettingWindow().ShowDialog() ?? false);
}
else if (action == EViewAction.SubSettingWindow)
{
return (new SubSettingWindow().ShowDialog() ?? false);
case EViewAction.AddServerWindow:
if (obj is null) return false;
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
case EViewAction.AddServer2Window:
if (obj is null) return false;
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
case EViewAction.DNSSettingWindow:
return (new DNSSettingWindow().ShowDialog() ?? false);
case EViewAction.RoutingSettingWindow:
return (new RoutingSettingWindow().ShowDialog() ?? false);
case EViewAction.OptionSettingWindow:
return (new OptionSettingWindow().ShowDialog() ?? false);
case EViewAction.GlobalHotkeySettingWindow:
return (new GlobalHotkeySettingWindow().ShowDialog() ?? false);
case EViewAction.SubSettingWindow:
return (new SubSettingWindow().ShowDialog() ?? false);
case EViewAction.ShowHideWindow:
Application.Current?.Dispatcher.Invoke((() =>
{
ShowHideWindow((bool?)obj);
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherStatistics:
if (obj is null) return false;
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.SetStatisticsResult((ServerSpeedItem)obj);
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherServerAvailability:
if (obj is null) return false;
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.TestServerAvailabilityResult((string)obj);
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherReload:
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.ReloadResult();
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherRefreshServersBiz:
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.RefreshServersBiz();
}), DispatcherPriority.Normal);
break;
}
return true;
@ -223,7 +256,7 @@ namespace v2rayN.Views
private void MainWindow_Closing(object? sender, CancelEventArgs e)
{
e.Cancel = true;
ViewModel?.ShowHideWindow(false);
ShowHideWindow(false);
}
private void menuExit_Click(object sender, RoutedEventArgs e)
@ -269,7 +302,7 @@ namespace v2rayN.Views
private void menuClose_Click(object sender, RoutedEventArgs e)
{
StorageUI();
ViewModel?.ShowHideWindow(false);
ShowHideWindow(false);
}
private void menuPromotion_Click(object sender, RoutedEventArgs e)
@ -291,6 +324,26 @@ namespace v2rayN.Views
#region UI
public void ShowHideWindow(bool? blShow)
{
var bl = blShow ?? !_config.uiItem.showInTaskbar;
if (bl)
{
Application.Current.MainWindow.Show();
if (Application.Current.MainWindow.WindowState == WindowState.Minimized)
{
Application.Current.MainWindow.WindowState = WindowState.Normal;
}
Application.Current.MainWindow.Activate();
Application.Current.MainWindow.Focus();
}
else
{
Application.Current.MainWindow.Hide();
}
_config.uiItem.showInTaskbar = bl;
}
private void RestoreUI()
{
if (_config.uiItem.mainWidth > 0 && _config.uiItem.mainHeight > 0)

View File

@ -7,6 +7,7 @@ using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using v2rayN.Base;
using v2rayN.Enums;
using v2rayN.Handler;
@ -89,6 +90,7 @@ namespace v2rayN.Views
});
RestoreUI();
ViewModel?.RefreshServers();
}
#region Event
@ -100,36 +102,50 @@ namespace v2rayN.Views
private bool UpdateViewHandler(EViewAction action, object? obj)
{
if (action == EViewAction.ProfilesFocus)
switch (action)
{
lstProfiles.Focus();
}
else if (action == EViewAction.ShowYesNo)
{
if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)
{
return false;
}
}
else if (action == EViewAction.AddServerWindow)
{
if (obj is null) return false;
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
}
else if (action == EViewAction.AddServer2Window)
{
if (obj is null) return false;
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
}
else if (action == EViewAction.ShareServer)
{
if (obj is null) return false;
ShareServer((string)obj);
}
else if (action == EViewAction.SubEditWindow)
{
if (obj is null) return false;
return (new SubEditWindow((SubItem)obj)).ShowDialog() ?? false;
case EViewAction.ProfilesFocus:
lstProfiles.Focus();
break;
case EViewAction.ShowYesNo:
if (UI.ShowYesNo(ResUI.RemoveServer) == MessageBoxResult.No)
{
return false;
}
break;
case EViewAction.AddServerWindow:
if (obj is null) return false;
return (new AddServerWindow((ProfileItem)obj)).ShowDialog() ?? false;
case EViewAction.AddServer2Window:
if (obj is null) return false;
return (new AddServer2Window((ProfileItem)obj)).ShowDialog() ?? false;
case EViewAction.ShareServer:
if (obj is null) return false;
ShareServer((string)obj);
break;
case EViewAction.SubEditWindow:
if (obj is null) return false;
return (new SubEditWindow((SubItem)obj)).ShowDialog() ?? false;
case EViewAction.DispatcherSpeedTest:
if (obj is null) return false;
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.SetSpeedTestResult((SpeedTestResult)obj);
}), DispatcherPriority.Normal);
break;
case EViewAction.DispatcherRefreshServersBiz:
Application.Current?.Dispatcher.Invoke((() =>
{
ViewModel?.RefreshServersBiz();
}), DispatcherPriority.Normal);
break;
}
return true;