Files
clashN/clashN/clashN/ViewModels/ProfilesViewModel.cs
2023-04-13 20:34:18 +08:00

385 lines
12 KiB
C#

using ClashN.Handler;
using ClashN.Mode;
using ClashN.Resx;
using ClashN.Views;
using DynamicData;
using DynamicData.Binding;
using MaterialDesignThemes.Wpf;
using ReactiveUI;
using ReactiveUI.Fody.Helpers;
using Splat;
using System.IO;
using System.Reactive;
using System.Windows.Forms;
using Application = System.Windows.Application;
namespace ClashN.ViewModels
{
public class ProfilesViewModel : ReactiveObject
{
private static Config _config;
private NoticeHandler? _noticeHandler;
private IObservableCollection<ProfileItemModel> _profileItems = new ObservableCollectionExtended<ProfileItemModel>();
public IObservableCollection<ProfileItemModel> ProfileItems => _profileItems;
public ReactiveCommand<Unit, Unit> EditLocalFileCmd { get; }
public ReactiveCommand<Unit, Unit> EditProfileCmd { get; }
public ReactiveCommand<Unit, Unit> AddProfileCmd { get; }
public ReactiveCommand<Unit, Unit> AddProfileViaScanCmd { get; }
public ReactiveCommand<Unit, Unit> AddProfileViaClipboardCmd { get; }
public ReactiveCommand<Unit, Unit> ExportProfileCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateSelectedCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateViaProxyCmd { get; }
public ReactiveCommand<Unit, Unit> SubUpdateSelectedViaProxyCmd { get; }
public ReactiveCommand<Unit, Unit> RemoveProfileCmd { get; }
public ReactiveCommand<Unit, Unit> CloneProfileCmd { get; }
public ReactiveCommand<Unit, Unit> SetDefaultProfileCmd { get; }
public ReactiveCommand<Unit, Unit> ClearStatisticCmd { get; }
public ReactiveCommand<Unit, Unit> ProfileReloadCmd { get; }
public ReactiveCommand<Unit, Unit> ProfileQrcodeCmd { get; }
[Reactive]
public ProfileItemModel SelectedSource { get; set; }
public ProfilesViewModel()
{
_noticeHandler = Locator.Current.GetService<NoticeHandler>();
_config = LazyConfig.Instance.Config;
SelectedSource = new();
RefreshProfiles();
var canEditRemove = this.WhenAnyValue(
x => x.SelectedSource,
selectedSource => selectedSource != null && !string.IsNullOrEmpty(selectedSource.indexId));
//Profile
EditLocalFileCmd = ReactiveCommand.Create(() =>
{
EditLocalFile();
}, canEditRemove);
EditProfileCmd = ReactiveCommand.Create(() =>
{
EditProfile(false);
}, canEditRemove);
AddProfileCmd = ReactiveCommand.Create(() =>
{
EditProfile(true);
});
AddProfileViaScanCmd = ReactiveCommand.CreateFromTask(() =>
{
return ScanScreenTaskAsync();
});
AddProfileViaClipboardCmd = ReactiveCommand.Create(() =>
{
AddProfilesViaClipboard(false);
});
ExportProfileCmd = ReactiveCommand.Create(() =>
{
ExportProfile2Clipboard();
}, canEditRemove);
//Subscription
SubUpdateCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(false, false);
});
SubUpdateSelectedCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(false, true);
}, canEditRemove);
SubUpdateViaProxyCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(true, false);
});
SubUpdateSelectedViaProxyCmd = ReactiveCommand.Create(() =>
{
UpdateSubscriptionProcess(true, true);
}, canEditRemove);
//Profile other
RemoveProfileCmd = ReactiveCommand.Create(() =>
{
RemoveProfile();
}, canEditRemove);
CloneProfileCmd = ReactiveCommand.Create(() =>
{
CloneProfile();
}, canEditRemove);
SetDefaultProfileCmd = ReactiveCommand.Create(() =>
{
SetDefaultProfile();
}, canEditRemove);
ClearStatisticCmd = ReactiveCommand.Create(() =>
{
ConfigProc.ClearAllServerStatistics(ref _config);
RefreshProfiles();
});
ProfileReloadCmd = ReactiveCommand.Create(() =>
{
RefreshProfiles();
});
ProfileQrcodeCmd = ReactiveCommand.Create(() =>
{
ProfileQrcode();
}, canEditRemove);
}
private void EditLocalFile()
{
var address = SelectedSource.address;
if (string.IsNullOrEmpty(address))
{
_noticeHandler?.Enqueue(ResUI.FillProfileAddressCustom);
return;
}
address = Path.Combine(Utils.GetConfigPath(), address);
if (File.Exists(address))
{
Utils.ProcessStart(address);
}
else
{
_noticeHandler?.Enqueue(ResUI.FailedReadConfiguration);
}
}
public void EditProfile(bool blNew)
{
ProfileItem item;
if (blNew)
{
item = new()
{
coreType = CoreKind.ClashMeta
};
}
else
{
item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
return;
}
}
PorfileEditWindow dialog = new PorfileEditWindow(item)
{
Owner = App.Current.MainWindow,
};
if (dialog.ShowDialog() == true)
{
RefreshProfiles();
}
}
public async Task ScanScreenTaskAsync()
{
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(false);
string result = await Task.Run(() =>
{
return Utils.ScanScreen();
});
Locator.Current.GetService<MainWindowViewModel>()?.ShowHideWindow(true);
if (string.IsNullOrEmpty(result))
{
_noticeHandler?.Enqueue(ResUI.NoValidQRcodeFound);
}
else
{
int ret = ConfigProc.AddBatchProfiles(ref _config, result, "", "");
if (ret == 0)
{
RefreshProfiles();
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedProfileViaScan);
}
}
}
public void AddProfilesViaClipboard(bool bClear)
{
string? clipboardData = Utils.GetClipboardData();
if (string.IsNullOrEmpty(clipboardData))
{
return;
}
int ret = ConfigProc.AddBatchProfiles(ref _config, clipboardData, "", "");
if (ret == 0)
{
if (bClear)
{
Utils.SetClipboardData(String.Empty);
}
RefreshProfiles();
_noticeHandler?.Enqueue(ResUI.SuccessfullyImportedProfileViaClipboard);
}
}
public void ExportProfile2Clipboard()
{
var item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
return;
}
var content = ConfigProc.GetProfileContent(item);
if (string.IsNullOrEmpty(content))
{
content = item.url;
}
Utils.SetClipboardData(content);
_noticeHandler?.Enqueue(ResUI.BatchExportSuccessfully);
}
public void UpdateSubscriptionProcess(bool blProxy, bool blSelected)
{
List<ProfileItem> profileItems = null;
if (blSelected)
{
var item = _config.GetProfileItem(SelectedSource.indexId);
profileItems = new List<ProfileItem>() { item };
}
void _updateUI(bool success, string msg)
{
_noticeHandler?.SendMessage(msg);
if (success)
{
RefreshProfiles();
}
};
(new UpdateHandle()).UpdateSubscriptionProcess(_config, blProxy, profileItems, _updateUI);
}
public void RemoveProfile()
{
var item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
return;
}
if (UI.ShowYesNo(ResUI.RemoveProfile) == DialogResult.No)
{
return;
}
ConfigProc.RemoveProfile(_config, new List<ProfileItem>() { item });
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshProfiles();
Locator.Current.GetService<MainWindowViewModel>()?.LoadCore();
}
private void CloneProfile()
{
var item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
return;
}
if (ConfigProc.CopyProfile(ref _config, new List<ProfileItem>() { item }) == 0)
{
_noticeHandler?.Enqueue(ResUI.OperationSuccess);
RefreshProfiles();
}
}
public void SetDefaultProfile()
{
if (string.IsNullOrEmpty(SelectedSource?.indexId))
{
return;
}
if (SelectedSource?.indexId == _config.IndexId)
{
return;
}
var item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
_noticeHandler?.Enqueue(ResUI.PleaseSelectProfile);
return;
}
if (ConfigProc.SetDefaultProfile(ref _config, item) == 0)
{
_noticeHandler?.SendMessage(ResUI.OperationSuccess);
RefreshProfiles();
Locator.Current.GetService<MainWindowViewModel>()?.LoadCore();
}
}
public void RefreshProfiles()
{
ConfigProc.SetDefaultProfile(_config, _config.ProfileItems);
var lstModel = new List<ProfileItemModel>();
foreach (var item in _config.ProfileItems.OrderBy(it => it.sort))
{
var model = Utils.FromJson<ProfileItemModel>(Utils.ToJson(item));
model.IsActive = _config.IsActiveNode(item);
lstModel.Add(model);
}
Application.Current.Dispatcher.Invoke((Action)(() =>
{
_profileItems.Clear();
_profileItems.AddRange(lstModel);
}));
}
public void MoveProfile(int startIndex, ProfileItemModel targetItem)
{
var targetIndex = _profileItems.IndexOf(targetItem);
if (startIndex >= 0 && targetIndex >= 0 && startIndex != targetIndex)
{
if (ConfigProc.MoveProfile(ref _config, startIndex, MovementTarget.Position, targetIndex) == 0)
{
RefreshProfiles();
}
}
}
public async void ProfileQrcode()
{
var item = _config.GetProfileItem(SelectedSource.indexId);
if (item is null)
{
return;
}
if (string.IsNullOrEmpty(item.url))
{
return;
}
var img = QRCodeHelper.GetQRCode(item.url);
var dialog = new ProfileQrcodeView()
{
imgQrcode = { Source = img },
txtContent = { Text = item.url },
};
await DialogHost.Show(dialog, "RootDialog");
}
}
}