electron removed

This commit is contained in:
kitbyte
2025-03-21 23:35:16 +02:00
parent 8e33e58939
commit 4049ade4b1
54 changed files with 3635 additions and 828 deletions
+49
View File
@@ -0,0 +1,49 @@
<Grid x:Class="WeModPatcher.View.Controls.PopupHost"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WeModPatcher.View.Controls"
mc:Ignorable="d"
Visibility="Collapsed">
<Border x:Name="Splash" Background="Black" CornerRadius="7"
Opacity="0.45"
MouseLeftButtonDown="HidePopup"/>
<Border Background="{DynamicResource Background}" d:Margin="0"
Margin="0 40 0 40" x:Name="PopupPresenter" Width="Auto" Height="Auto"
BorderBrush="{DynamicResource Border}" BorderThickness="1" MinWidth="300"
VerticalAlignment="Center" HorizontalAlignment="Center" CornerRadius="4" Padding="15 10 10 15">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Button BorderThickness="0" BorderBrush="Transparent"
Tag="{StaticResource CloseIcon}"
Width="25" Height="25" Padding="8" Background="Transparent"
HorizontalAlignment="Right" VerticalAlignment="Top" Click="HidePopup"
x:Name="cancel">
<Button.Style>
<Style BasedOn="{StaticResource IconButton}" TargetType="Button">
<Setter Property="Foreground" Value="{DynamicResource MutedForeground}"/>
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Foreground" Value="{DynamicResource Foreground}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
<TextBlock x:Name="Title" Text="This is title" Foreground="{DynamicResource Foreground}"
HorizontalAlignment="Left" FontWeight="Bold" FontSize="16"
VerticalAlignment="Bottom"/>
<ContentPresenter x:Name="Presenter" Margin="0 20 0 0"
Content="{Binding PopupContent}" Grid.Row="2"/>
</Grid>
</Border>
</Grid>
@@ -0,0 +1,100 @@
using System;
using System.Threading;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media.Animation;
namespace WeModPatcher.View.Controls
{
public partial class PopupHost : Grid
{
internal Action Closed;
public static readonly DependencyProperty PopupContentProperty =
DependencyProperty.Register("PopupContent", typeof(object), typeof(PopupHost), new PropertyMetadata(null));
internal readonly SemaphoreSlim OpenedSemaphore = new SemaphoreSlim(1, 1);
private DoubleAnimation OpeningAnimation;
private DoubleAnimation ClosingAnimation;
public bool IsOpen
{
get => this.Visibility == Visibility.Visible;
set
{
if (value)
{
if(OpenedSemaphore.CurrentCount == 0)
return;
Visibility = Visibility.Visible;
cancel.Focus();
PopupPresenter.BeginAnimation(OpacityProperty, OpeningAnimation);
OpenedSemaphore.Wait();
}
else
{
PopupPresenter.BeginAnimation(OpacityProperty, ClosingAnimation);
}
}
}
public object PopupContent
{
get => GetValue(PopupContentProperty);
set => SetValue(PopupContentProperty, value);
}
private void HidePopup(object sender, EventArgs e)
{
if (OpenedSemaphore.CurrentCount == 1)
return;
IsOpen = false;
}
private void OnClosing(object sender, EventArgs e)
{
if (PopupContent == null)
return;
Visibility = Visibility.Collapsed;
Closed?.Invoke();
PopupContent = null;
Closed = null;
OpenedSemaphore.Release();
}
public PopupHost()
{
InitializeComponent();
PreviewKeyDown += (sender, e) =>
{
if (e.Key != Key.Escape)
return;
HidePopup(null, null);
e.Handled = true;
};
OpeningAnimation = new DoubleAnimation(0, 1, new Duration(TimeSpan.FromSeconds(0.4)))
{
EasingFunction = App.Current.FindResource("BaseAnimationFunction") as IEasingFunction
};
OpeningAnimation.Freeze();
ClosingAnimation = new DoubleAnimation(1, 0, new Duration(TimeSpan.FromSeconds(0.2)));
ClosingAnimation.Completed += OnClosing;
ClosingAnimation.Freeze();
this.Splash.DataContext = this;
this.PopupPresenter.DataContext = this;
}
}
}
+15
View File
@@ -0,0 +1,15 @@
namespace WeModPatcher.View.MainWindow
{
public enum ELogType
{
Info,
Warn,
Error,
Success
}
public class LogEntry
{
public ELogType LogType { get; set; }
public string Message { get; set; }
}
}
@@ -0,0 +1,186 @@
<Window x:Class="WeModPatcher.View.MainWindow.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WeModPatcher.View.MainWindow"
xmlns:controls="clr-namespace:WeModPatcher.View.Controls"
mc:Ignorable="d"
d:DataContext="{d:DesignInstance local:MainWindowVm}"
Title="WeMod Patcher"
Height="510" MaxHeight="510"
Width="780" MaxWidth="780"
Opacity="0.97"
Background="Transparent"
WindowStyle="None"
FontFamily="{StaticResource Inter}"
AllowsTransparency="True">
<Border CornerRadius="7" Background="{DynamicResource Background}"
BorderBrush="{DynamicResource Border}"
BorderThickness="1" Margin="10">
<Border.Effect>
<DropShadowEffect BlurRadius="15" Direction="-90"
RenderingBias="Quality" ShadowDepth="2"/>
</Border.Effect>
<Grid>
<Grid Background="Transparent" VerticalAlignment="Top"
MouseLeftButtonDown="OnDragMove" Height="55">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center" Margin="25 0 0 0">
<Viewbox VerticalAlignment="Center" Width="32" Height="32">
<Path
Fill="White" Data="{StaticResource Logo}"/>
</Viewbox>
<TextBlock Foreground="{DynamicResource Foreground}"
FontWeight="SemiBold" Opacity="0.9"
VerticalAlignment="Center"
FontSize="18" Margin="10 0 0 0">
<Bold>
WeMod Patcher
</Bold>
</TextBlock>
</StackPanel>
<StackPanel HorizontalAlignment="Right" Orientation="Horizontal">
<Button
Margin="9 0 15 0"
Tag="{StaticResource CloseIcon}"
Width="25" Height="25" Padding="6.5"
HorizontalAlignment="Right"
Click="OnClosing"
VerticalAlignment="Center">
<Button.Resources>
<CornerRadius x:Key="CornerRadius">5 5 5 5</CornerRadius>
</Button.Resources>
<Button.Style>
<Style BasedOn="{StaticResource IconButton}" TargetType="Button">
<Style.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter Property="Background" Value="{DynamicResource Secondary}"/>
<Setter Property="Foreground" Value="{DynamicResource Destructive}"/>
</Trigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
</StackPanel>
<Border Background="{DynamicResource Border}" Height="1" VerticalAlignment="Bottom"></Border>
</Grid>
<Grid Margin="0 55 0 0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition/>
<RowDefinition Height="50"/>
</Grid.RowDefinitions>
<TextBox Style="{StaticResource TitledTextBox}"
Uid="Folder path" Margin="10" IsReadOnly="True"
Cursor="Hand"
Text="{Binding WeModPath}"
VerticalAlignment="Center" Tag="Folder not found">
<TextBox.InputBindings>
<MouseBinding Gesture="LeftClick" Command="{Binding SetFolderPathCommand}" />
</TextBox.InputBindings>
</TextBox>
<Border Grid.Row="1" BorderBrush="{DynamicResource Border}" BorderThickness="1"
Margin="10 0 10 10"
CornerRadius="5">
<ListBox ItemsSource="{Binding LogList}" SelectionMode="Single"
BorderBrush="Transparent" BorderThickness="0"
Background="Transparent"
Padding="6"
ScrollViewer.VerticalScrollBarVisibility="Hidden"
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
ScrollViewer.CanContentScroll="False">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="FocusVisualStyle" Value="{x:Null}"/>
<Setter Property="Margin" Value="0 0 0 5"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListBoxItem">
<Border x:Name="Card" HorizontalAlignment="Left"
Background="#08fc81"
BorderBrush="{DynamicResource Border}"
Padding="5 3 5 3" CornerRadius="3">
<TextBox Text="{Binding Message}"
Cursor="IBeam" FontSize="13"
Background="Transparent" TextWrapping="Wrap"
BorderThickness="0"
IsReadOnly="True"/>
</Border>
<ControlTemplate.Triggers>
<DataTrigger Binding="{Binding LogType}" Value="Error">
<Setter TargetName="Card" Property="Background" Value="#f04343"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LogType}" Value="Info">
<Setter TargetName="Card" Property="Background" Value="#FFF"></Setter>
</DataTrigger>
<DataTrigger Binding="{Binding LogType}" Value="Warn">
<Setter TargetName="Card" Property="Background" Value="#facc15"></Setter>
</DataTrigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</Border>
<Grid Grid.Row="2" HorizontalAlignment="Right" Margin="10 0 10 10">
<Grid.Style>
<Style TargetType="{x:Type Grid}">
<Style.Triggers>
<DataTrigger Binding="{Binding IsPatchEnabled}" Value="False">
<Setter Property="Cursor" Value="No"/>
</DataTrigger>
</Style.Triggers>
</Style>
</Grid.Style>
<Button Style="{StaticResource ColoredButton}"
IsEnabled="{Binding IsPatchEnabled}"
FontWeight="Bold" FontSize="16" Width="200"
Command="{Binding ApplyPatchCommand}">Patch</Button>
</Grid>
<Button Grid.Row="2"
Margin="10 0 10 10" HorizontalAlignment="Right"
Command="{Binding RestoreBackupCommand }"
FontWeight="Bold" FontSize="16" Width="200"
Style="{StaticResource ColoredButton}"
Visibility="{Binding AlreadyPatched, Converter={StaticResource ToVisibilityConverter}}"
Content="Restore"/>
<DockPanel Grid.Row="2" Margin="10 0 10 10">
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
Cursor="Hand"
MouseDown="OpenSourceClicked"
Background="Transparent">
<Viewbox VerticalAlignment="Center" Width="32" Height="32">
<Path
Fill="White" Data="{StaticResource GitHub}"/>
</Viewbox>
<Grid>
<TextBlock Margin="8 0 0 0" FontSize="10" Foreground="{DynamicResource AccentForeground}">
<Hyperlink Foreground="{DynamicResource AccentForeground}">Source code </Hyperlink>
<LineBreak/>
<Run>Made with ❤️ by k1tbyte</Run>
<LineBreak/>
<Run Foreground="{DynamicResource MutedForeground}">Put a star if you found this helpful ;)</Run>
</TextBlock>
</Grid>
</StackPanel>
</DockPanel>
</Grid>
<controls:PopupHost x:Name="PopupHost"/>
</Grid>
</Border>
</Window>
@@ -0,0 +1,49 @@
using System;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
namespace WeModPatcher.View.MainWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public static MainWindow Instance;
public MainWindow()
{
InitializeComponent();
this.DataContext = new MainWindowVm();
Instance = this;
}
public void OpenPopup(object content, string title = null)
{
this.PopupHost.PopupContent = content;
PopupHost.Title.Text = title;
PopupHost.IsOpen = true;
}
private void OnDragMove(object sender, MouseButtonEventArgs e)
{
this.DragMove();
}
private void OnClosing(object sender, RoutedEventArgs e)
{
Application.Current.Shutdown();
}
public void ClosePopup()
{
PopupHost.IsOpen = false;
}
private void OpenSourceClicked(object sender, MouseButtonEventArgs e)
{
System.Diagnostics.Process.Start(Constants.RepositoryUrl);
}
}
}
@@ -0,0 +1,206 @@
using System;
using System.Collections.ObjectModel;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Threading;
using AsarSharp;
using WeModPatcher.ReactiveCore;
using WeModPatcher.Utils;
using WeModPatcher.View.Popups;
using Application = System.Windows.Application;
namespace WeModPatcher.View.MainWindow
{
public class MainWindowVm : ObservableObject
{
public ObservableCollection<LogEntry> LogList { get; } = new ObservableCollection<LogEntry>();
private string _weModPath;
public string WeModPath
{
get => _weModPath;
set
{
SetProperty(ref _weModPath, value);
if (value == null) return;
Log($"WeMod directory found at '{_weModPath}'", ELogType.Success);
if (File.Exists(Path.Combine(_weModPath, "resources", "app.asar.backup")))
{
Log("WeMod already patched. If you want to patch again, please restore the backup first.", ELogType.Warn);
IsPatchEnabled = false;
AlreadyPatched = true;
return;
}
Log("Ready for patching.", ELogType.Info);
IsPatchEnabled = true;
}
}
private bool _isPatchEnabled = false;
public bool IsPatchEnabled
{
get => _isPatchEnabled;
set => SetProperty(ref _isPatchEnabled, value);
}
private bool _alreadyPatched = false;
public bool AlreadyPatched
{
get => _alreadyPatched;
set => SetProperty(ref _alreadyPatched, value);
}
public RelayCommand SetFolderPathCommand { get; }
public RelayCommand ApplyPatchCommand { get; }
public RelayCommand RestoreBackupCommand { get; }
private bool CheckWeModPath(string root)
{
try
{
return File.Exists(Path.Combine(root, "WeMod.exe")) &&
File.Exists(Path.Combine(root, "resources", "app.asar"));
}
catch
{
return false;
}
}
public string FindWeModDirectory()
{
string localAppDataPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
string defaultDir = Path.Combine(localAppDataPath, "WeMod");
if (!Directory.Exists(defaultDir))
{
return null;
}
var appFolders = Directory.EnumerateDirectories(defaultDir)
.Select(folderPath => new DirectoryInfo(folderPath))
.Where(dirInfo => Regex.IsMatch(dirInfo.Name, @"^app-\w+"))
.Select(dirInfo => new
{
Name = dirInfo.Name,
Path = dirInfo.FullName,
LastModified = dirInfo.LastWriteTime
})
.OrderByDescending(item => item.LastModified)
.ToList();
return (
from folder
in appFolders
where CheckWeModPath(folder.Path)
select folder.Path
).FirstOrDefault();
}
private void OnFolderPathSelection(object obj)
{
using (var dialog = new FolderBrowserDialog())
{
dialog.SelectedPath = Environment.GetEnvironmentVariable("LOCALAPPDATA");
dialog.Description = "Select the WeMod directory";
dialog.ShowNewFolderButton = false;
if (dialog.ShowDialog() != DialogResult.OK) return;
string selectedPath = dialog.SelectedPath;
string fileName = Path.GetFileName(selectedPath);
if (CheckWeModPath(selectedPath))
{
WeModPath = selectedPath;
return;
}
LogList.Add(new LogEntry
{
LogType = ELogType.Error,
Message = $"The selected folder '{fileName}' is not a valid WeMod directory."
});
}
}
private void OnBackupRestoring(object param)
{
var backupPath = Path.Combine(WeModPath, "resources", "app.asar.backup");
if (!File.Exists(backupPath))
{
Log("Backup not found. Please dont delete it manually", ELogType.Error);
return;
}
try
{
using (File.Open(backupPath, FileMode.Open, FileAccess.ReadWrite, FileShare.None))
{
}
}
catch
{
Log("Backup file is locked. Please close the WeMod and try again.", ELogType.Error);
return;
}
File.Copy(backupPath, Path.Combine(WeModPath, "resources", "app.asar"), true);
Log("Backup restored successfully.", ELogType.Success);
AlreadyPatched = false;
IsPatchEnabled = true;
}
private void OnPatching(object param)
{
if (WeModPath == null)
{
Log("Can't be done. Please specify the directory first.", ELogType.Warn);
return;
}
MainWindow.Instance.OpenPopup(new PatchVectorsPopup(async config =>
{
MainWindow.Instance.ClosePopup();
IsPatchEnabled = false;
await Task.Run(() => new Patcher(WeModPath, Log, config).Patch());
IsPatchEnabled = true;
}), "What are we gonna patch?");
}
private void Log(string message, ELogType logType)
{
Application.Current.Dispatcher.Invoke(() =>
{
message = $"[{logType.ToString().ToUpper()}] {message}";
LogList.Add(new LogEntry
{
LogType = logType,
Message = message
});
});
}
public MainWindowVm()
{
SetFolderPathCommand = new RelayCommand(OnFolderPathSelection);
ApplyPatchCommand = new RelayCommand(OnPatching);
RestoreBackupCommand = new RelayCommand(OnBackupRestoring);
WeModPath = FindWeModDirectory();
if (WeModPath == null)
{
Log("WeMod directory not found.", ELogType.Error);
return;
}
}
}
}
@@ -0,0 +1,31 @@
<UserControl x:Class="WeModPatcher.View.Popups.PatchVectorsPopup"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:WeModPatcher.View.Popups"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300"
Foreground="{DynamicResource MutedForeground}"
FontWeight="Medium"
FontSize="13">
<Grid Margin="0 0 5 0">
<Grid.RowDefinitions>
<RowDefinition Height="27"/>
<RowDefinition Height="27"/>
<RowDefinition Height="27"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" VerticalAlignment="Center" Text="Activate WeMod Pro"/>
<CheckBox Grid.Row="0" x:Name="ActivateProBox" HorizontalAlignment="Right" VerticalAlignment="Center" IsChecked="True"/>
<TextBlock Grid.Row="1" VerticalAlignment="Center" Text="Disable telemetry"/>
<CheckBox Grid.Row="1" x:Name="DisableTelemetryBox" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBlock Grid.Row="2" VerticalAlignment="Center" Text="Disable updates"/>
<CheckBox Grid.Row="2" x:Name="DisableUpdateBox" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<Button Grid.Row="3" Padding="0 5 0 5" Margin="0 15 0 0" Content="Continue"
Click="ButtonBase_OnClick"/>
</Grid>
</UserControl>
@@ -0,0 +1,40 @@
using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using WeModPatcher.Models;
namespace WeModPatcher.View.Popups
{
public partial class PatchVectorsPopup : UserControl
{
private readonly Action<HashSet<EPatchType>> _onApply;
public PatchVectorsPopup(Action<HashSet<EPatchType>> onApply)
{
_onApply = onApply;
InitializeComponent();
}
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
if(ActivateProBox.IsChecked != true && DisableUpdateBox.IsChecked != true && DisableTelemetryBox.IsChecked != true)
{
return;
}
var result = new HashSet<EPatchType>();
if (ActivateProBox.IsChecked == true)
{
result.Add(EPatchType.ActivatePro);
}
if (DisableUpdateBox.IsChecked == true)
{
result.Add(EPatchType.DisableUpdates);
}
_onApply(result);
}
}
}