Compare commits

...

4 commits

Author SHA1 Message Date
nayeko
dbd3ca44c2
Fix Package AppImage script (#6794)
Some checks are pending
release Linux / build (Release) (push) Waiting to run
release macOS / build (Release) (push) Waiting to run
release Windows desktop (Avalonia UI) / build (Release) (push) Waiting to run
release Windows / build (Release) (push) Waiting to run
Co-authored-by: nayeko <nayeko@users.noreply.github.com>
2025-02-25 10:06:33 +08:00
dependabot[bot]
ae495dde54
Bump actions/upload-artifact from 4.6.0 to 4.6.1 (#6797)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4.6.0 to 4.6.1.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v4.6.0...v4.6.1)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-02-25 09:46:08 +08:00
2dust
4ae25b2f34 Improved global hotkey setting 2025-02-24 19:53:38 +08:00
2dust
cdfb621c59 Update MsgView.axaml 2025-02-24 19:07:05 +08:00
10 changed files with 153 additions and 149 deletions

View file

@ -42,7 +42,7 @@ jobs:
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64 dotnet publish ./AmazTool/AmazTool.csproj -c Release -r linux-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0 uses: actions/upload-artifact@v4.6.1
with: with:
name: v2rayN-linux name: v2rayN-linux
path: | path: |
@ -68,9 +68,8 @@ jobs:
- name: Package AppImage - name: Package AppImage
if: github.event.inputs.release_tag != '' if: github.event.inputs.release_tag != ''
run: | run: |
chmod 755 package-appimage.sh chmod a+x package-appimage.sh
./package-appimage.sh $OutputArch $OutputPath64 ${{ github.event.inputs.release_tag }} ./package-appimage.sh
./package-appimage.sh $OutputArchArm $OutputPathArm64 ${{ github.event.inputs.release_tag }}
- name: Upload AppImage to release - name: Upload AppImage to release
uses: svenstaro/upload-release-action@v2 uses: svenstaro/upload-release-action@v2

View file

@ -42,7 +42,7 @@ jobs:
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64 dotnet publish ./AmazTool/AmazTool.csproj -c Release -r osx-arm64 --self-contained=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0 uses: actions/upload-artifact@v4.6.1
with: with:
name: v2rayN-macos name: v2rayN-macos
path: | path: |

View file

@ -42,7 +42,7 @@ jobs:
dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64 dotnet publish ./AmazTool/AmazTool.csproj -c Release -r win-arm64 --self-contained=true -p:EnableWindowsTargeting=true -p:PublishTrimmed=true -o $OutputPathArm64
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0 uses: actions/upload-artifact@v4.6.1
with: with:
name: v2rayN-windows-desktop name: v2rayN-windows-desktop
path: | path: |

View file

@ -46,7 +46,7 @@ jobs:
- name: Upload build artifacts - name: Upload build artifacts
uses: actions/upload-artifact@v4.6.0 uses: actions/upload-artifact@v4.6.1
with: with:
name: v2rayN-windows name: v2rayN-windows
path: | path: |

View file

@ -1,71 +1,14 @@
#!/bin/bash #!/bin/bash
Arch="$1" sudo apt update -y
OutputPath="$2"
Version="$3"
FileName="v2rayN-${Arch}.zip"
wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/$FileName"
7z x $FileName -aoa
cp -rf v2rayN-${Arch}/* $OutputPath
PackagePath="v2rayN-Package-${Arch}"
mkdir -p "${PackagePath}/AppDir/opt"
cp -rf $OutputPath "${PackagePath}/AppDir/opt/v2rayN"
echo "When this file exists, app will not store configs under this folder" >"${PackagePath}/AppDir/opt/v2rayN/NotStoreConfigHere.txt"
if [ $Arch = "linux-64" ]; then
Arch2="x86_64"
Arch3="amd64"
else
Arch2="aarch64"
Arch3="arm64"
fi
echo $Arch2
# basic
cat >"${PackagePath}/AppDir/AppRun" <<-EOF
#!/bin/sh
HERE="\$(dirname "\$(readlink -f "\${0}")")"
export PATH="\${HERE}"/opt/v2rayN/:"\${PATH}"
export LD_LIBRARY_PATH="\${HERE}"/opt/v2rayN/:"\${LD_LIBRARY_PATH}"
exec "\${HERE}/opt/v2rayN/v2rayN" \$@
EOF
cat >"${PackagePath}/AppDir/v2rayN.desktop" <<-EOF
[Desktop Entry]
Name=v2rayN
Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
Exec=v2rayN
Icon=v2rayN
Terminal=false
Type=Application
Categories=Network;
EOF
sudo cp "${PackagePath}/AppDir/opt/v2rayN/v2rayN.png" "${PackagePath}/AppDir/v2rayN.png"
sudo dpkg --add-architecture ${Arch3}
mkdir deb_folder
cd deb_folder
apt download libicu74:${Arch3}
apt download libfontconfig1:${Arch3} || true
apt download libfontconfig:${Arch3} || true
mkdir ../output_folder
for deb in *.deb; do
dpkg-deb -x "$deb" ../output_folder/
done
cd ..
find output_folder -type f -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
find output_folder -type l -name "*.so*" -exec cp {} ${PackagePath}/AppDir/opt/v2rayN/ \;
rm -rf deb_folder output_folder
sudo chmod 0755 "${PackagePath}/AppDir/opt/v2rayN/v2rayN"
sudo chmod 0755 "${PackagePath}/AppDir/AppRun"
# desktop && PATH
wget "https://github.com/AppImage/appimagetool/releases/download/continuous/appimagetool-x86_64.AppImage"
chmod a+x appimagetool-x86_64.AppImage
sudo apt install -y libfuse2 sudo apt install -y libfuse2
sudo ./appimagetool-x86_64.AppImage "${PackagePath}/AppDir" wget -O pkg2appimage https://github.com/AppImageCommunity/pkg2appimage/releases/download/continuous/pkg2appimage-1eceb30-x86_64.AppImage
sudo mv "v2rayN-${Arch2}.AppImage" "v2rayN-${Arch}.AppImage" chmod a+x pkg2appimage
export AppImageOutputArch=$OutputArch
export OutputPath=$OutputPath64
./pkg2appimage ./pkg2appimage.yml
mv out/*.AppImage v2rayN-${AppImageOutputArch}.AppImage
export AppImageOutputArch=$OutputArchArm
export OutputPath=$OutputPathArm64
./pkg2appimage ./pkg2appimage.yml
mv out/*.AppImage v2rayN-${AppImageOutputArch}.AppImage

37
pkg2appimage.yml Normal file
View file

@ -0,0 +1,37 @@
app: v2rayN
binpatch: true
ingredients:
script:
- export FileName="v2rayN-${AppImageOutputArch}.zip"
- wget -nv -O $FileName "https://github.com/2dust/v2rayN-core-bin/raw/refs/heads/master/${FileName}"
- 7z x $FileName -aoa
- cp -rf v2rayN-${AppImageOutputArch}/* $OutputPath
script:
- mkdir -p usr/bin usr/lib
- cp -rf $OutputPath usr/lib/v2rayN
- echo "When this file exists, app will not store configs under this folder" > usr/lib/v2rayN/NotStoreConfigHere.txt
- ln -sf usr/lib/v2rayN/v2rayN usr/bin/v2rayN
- chmod a+x usr/lib/v2rayN/v2rayN
- find usr -type f -exec sh -c 'file "{}" | grep -qi "executable" && chmod +x "{}"' \;
- install -Dm644 usr/lib/v2rayN/v2rayN.png v2rayN.png
- install -Dm644 usr/lib/v2rayN/v2rayN.png usr/share/pixmaps/v2rayN.png
- cat > v2rayN.desktop <<EOF
- [Desktop Entry]
- Name=v2rayN
- Comment=A GUI client for Windows and Linux, support Xray core and sing-box-core and others
- Exec=v2rayN
- Icon=v2rayN
- Terminal=false
- Type=Application
- Categories=Network;
- EOF
- install -Dm644 v2rayN.desktop usr/share/applications/v2rayN.desktop
- cat > AppRun <<\EOF
- #!/bin/sh
- HERE="$(dirname "$(readlink -f "${0}")")"
- cd ${HERE}/usr/lib/v2rayN
- exec ${HERE}/usr/lib/v2rayN/v2rayN $@
- EOF
- chmod a+x AppRun

View file

@ -10,8 +10,8 @@
mc:Ignorable="d"> mc:Ignorable="d">
<DockPanel Margin="2"> <DockPanel Margin="2">
<WrapPanel <WrapPanel
VerticalAlignment="Center"
Margin="{StaticResource Margin4}" Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
DockPanel.Dock="Top" DockPanel.Dock="Top"
Orientation="Horizontal"> Orientation="Horizontal">
@ -37,6 +37,8 @@
</Button> </Button>
<Button <Button
x:Name="btnClear" x:Name="btnClear"
Width="{StaticResource IconButtonWidth}"
Height="{StaticResource IconButtonHeight}"
Margin="{StaticResource MarginLr8}" Margin="{StaticResource MarginLr8}"
Classes="Success" Classes="Success"
Click="menuMsgViewClear_Click" Click="menuMsgViewClear_Click"

View file

@ -11,15 +11,8 @@ namespace v2rayN.Handler
{ {
private static readonly Lazy<HotkeyHandler> _instance = new(() => new()); private static readonly Lazy<HotkeyHandler> _instance = new(() => new());
public static HotkeyHandler Instance = _instance.Value; public static HotkeyHandler Instance = _instance.Value;
private const int WmHotkey = 0x0312; private const int WmHotkey = 0x0312;
private readonly Dictionary<int, List<EGlobalHotkey>> _hotkeyTriggerDic = new();
private Config _config
{
get => AppHandler.Instance.Config;
}
private Dictionary<int, List<EGlobalHotkey>> _hotkeyTriggerDic;
public bool IsPause { get; set; } = false; public bool IsPause { get; set; } = false;
@ -29,7 +22,6 @@ namespace v2rayN.Handler
public HotkeyHandler() public HotkeyHandler()
{ {
_hotkeyTriggerDic = new();
ComponentDispatcher.ThreadPreprocessMessage += OnThreadPreProcessMessage; ComponentDispatcher.ThreadPreprocessMessage += OnThreadPreProcessMessage;
Init(); Init();
} }
@ -37,20 +29,31 @@ namespace v2rayN.Handler
private void Init() private void Init()
{ {
_hotkeyTriggerDic.Clear(); _hotkeyTriggerDic.Clear();
if (_config.GlobalHotkeys == null) if (AppHandler.Instance.Config.GlobalHotkeys == null)
{
return; return;
foreach (var item in _config.GlobalHotkeys) }
foreach (var item in AppHandler.Instance.Config.GlobalHotkeys)
{ {
if (item.KeyCode != null && (Key)item.KeyCode != Key.None) if (item.KeyCode != null && (Key)item.KeyCode != Key.None)
{ {
int key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode); var key = KeyInterop.VirtualKeyFromKey((Key)item.KeyCode);
KeyModifiers modifiers = KeyModifiers.None; var modifiers = KeyModifiers.None;
if (item.Control) if (item.Control)
{
modifiers |= KeyModifiers.Ctrl; modifiers |= KeyModifiers.Ctrl;
}
if (item.Shift) if (item.Shift)
{
modifiers |= KeyModifiers.Shift; modifiers |= KeyModifiers.Shift;
}
if (item.Alt) if (item.Alt)
{
modifiers |= KeyModifiers.Alt; modifiers |= KeyModifiers.Alt;
}
key = (key << 16) | (int)modifiers; key = (key << 16) | (int)modifiers;
if (!_hotkeyTriggerDic.ContainsKey(key)) if (!_hotkeyTriggerDic.ContainsKey(key))
{ {
@ -59,19 +62,21 @@ namespace v2rayN.Handler
else else
{ {
if (!_hotkeyTriggerDic[key].Contains(item.EGlobalHotkey)) if (!_hotkeyTriggerDic[key].Contains(item.EGlobalHotkey))
{
_hotkeyTriggerDic[key].Add(item.EGlobalHotkey); _hotkeyTriggerDic[key].Add(item.EGlobalHotkey);
} }
} }
} }
} }
}
public void Load() public void Load()
{ {
foreach (var _hotkeyCode in _hotkeyTriggerDic.Keys) foreach (var _hotkeyCode in _hotkeyTriggerDic.Keys)
{ {
var hotkeyInfo = GetHotkeyInfo(_hotkeyCode); var hotkeyInfo = GetHotkeyInfo(_hotkeyCode);
bool isSuccess = false; var isSuccess = false;
string msg; var msg = string.Empty;
Application.Current?.Dispatcher.Invoke(() => Application.Current?.Dispatcher.Invoke(() =>
{ {
@ -106,29 +111,38 @@ namespace v2rayN.Handler
Load(); Load();
} }
private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeycode) private (int fsModifiers, int vKey, string hotkeyStr, List<string> Names) GetHotkeyInfo(int hotkeyCode)
{ {
var _fsModifiers = hotkeycode & 0xffff; var fsModifiers = hotkeyCode & 0xffff;
var _vkey = (hotkeycode >> 16) & 0xffff; var vKey = (hotkeyCode >> 16) & 0xffff;
var _hotkeyStr = new StringBuilder(); var hotkeyStr = new StringBuilder();
var _names = new List<string>(); var names = new List<string>();
var mdif = (KeyModifiers)_fsModifiers; var modify = (KeyModifiers)fsModifiers;
var key = KeyInterop.KeyFromVirtualKey(_vkey); var key = KeyInterop.KeyFromVirtualKey(vKey);
if ((mdif & KeyModifiers.Ctrl) == KeyModifiers.Ctrl) if ((modify & KeyModifiers.Ctrl) == KeyModifiers.Ctrl)
_hotkeyStr.Append($"{KeyModifiers.Ctrl}+");
if ((mdif & KeyModifiers.Alt) == KeyModifiers.Alt)
_hotkeyStr.Append($"{KeyModifiers.Alt}+");
if ((mdif & KeyModifiers.Shift) == KeyModifiers.Shift)
_hotkeyStr.Append($"{KeyModifiers.Shift}+");
_hotkeyStr.Append(key.ToString());
foreach (var name in _hotkeyTriggerDic[hotkeycode])
{ {
_names.Add(name.ToString()); hotkeyStr.Append($"{KeyModifiers.Ctrl}+");
} }
return (_fsModifiers, _vkey, _hotkeyStr.ToString(), _names); if ((modify & KeyModifiers.Alt) == KeyModifiers.Alt)
{
hotkeyStr.Append($"{KeyModifiers.Alt}+");
}
if ((modify & KeyModifiers.Shift) == KeyModifiers.Shift)
{
hotkeyStr.Append($"{KeyModifiers.Shift}+");
}
hotkeyStr.Append(key.ToString());
foreach (var name in _hotkeyTriggerDic[hotkeyCode])
{
names.Add(name.ToString());
}
return (fsModifiers, vKey, hotkeyStr.ToString(), names);
} }
private void OnThreadPreProcessMessage(ref MSG msg, ref bool handled) private void OnThreadPreProcessMessage(ref MSG msg, ref bool handled)
@ -138,21 +152,18 @@ namespace v2rayN.Handler
return; return;
} }
handled = true; handled = true;
var _hotKeyCode = (int)msg.lParam; var hotKeyCode = (int)msg.lParam;
if (IsPause) if (IsPause)
{ {
Application.Current?.Dispatcher.Invoke(() => Application.Current?.Dispatcher.Invoke(() =>
{ {
UIElement? element = Keyboard.FocusedElement as UIElement; if (Keyboard.FocusedElement is UIElement element)
if (element != null)
{ {
var _keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, var keyEventArgs = new KeyEventArgs(Keyboard.PrimaryDevice, PresentationSource.FromVisual(element), 0, KeyInterop.KeyFromVirtualKey(GetHotkeyInfo(hotKeyCode).vKey))
PresentationSource.FromVisual(element), 0,
KeyInterop.KeyFromVirtualKey(GetHotkeyInfo(_hotKeyCode).vKey))
{ {
RoutedEvent = UIElement.KeyDownEvent RoutedEvent = UIElement.KeyDownEvent
}; };
element.RaiseEvent(_keyEventArgs); element.RaiseEvent(keyEventArgs);
} }
}); });
} }

View file

@ -1,18 +1,17 @@
<reactiveui:ReactiveWindow <reactiveui:ReactiveWindow
x:Class="v2rayN.Views.GlobalHotkeySettingWindow" x:Class="v2rayN.Views.GlobalHotkeySettingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:reactiveui="http://reactiveui.net"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:materialDesign="http://materialdesigninxaml.net/winfx/xaml/themes"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:reactiveui="http://reactiveui.net"
xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib" xmlns:resx="clr-namespace:ServiceLib.Resx;assembly=ServiceLib"
xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib" xmlns:vms="clr-namespace:ServiceLib.ViewModels;assembly=ServiceLib"
Title="{x:Static resx:ResUI.menuSetting}" Title="{x:Static resx:ResUI.menuSetting}"
Width="700" Width="700"
Height="500" Height="500"
x:TypeArguments="vms:SubEditViewModel" x:TypeArguments="vms:SubEditViewModel"
KeyDown="GlobalHotkeySettingWindow_KeyDown"
ShowInTaskbar="False" ShowInTaskbar="False"
Style="{StaticResource WindowGlobal}" Style="{StaticResource WindowGlobal}"
WindowStartupLocation="CenterScreen" WindowStartupLocation="CenterScreen"

View file

@ -8,8 +8,8 @@ namespace v2rayN.Views
{ {
public partial class GlobalHotkeySettingWindow public partial class GlobalHotkeySettingWindow
{ {
private static Config _config = default!; private static Config? _config;
private Dictionary<object, KeyEventItem> _TextBoxKeyEventItem = default!; private Dictionary<object, KeyEventItem> _textBoxKeyEventItem = new();
public GlobalHotkeySettingWindow() public GlobalHotkeySettingWindow()
{ {
@ -17,7 +17,7 @@ namespace v2rayN.Views
this.Owner = Application.Current.MainWindow; this.Owner = Application.Current.MainWindow;
_config = AppHandler.Instance.Config; _config = AppHandler.Instance.Config;
_config.GlobalHotkeys ??= new List<KeyEventItem>(); _config.GlobalHotkeys ??= new();
btnReset.Click += btnReset_Click; btnReset.Click += btnReset_Click;
btnSave.Click += btnSave_ClickAsync; btnSave.Click += btnSave_ClickAsync;
@ -36,7 +36,7 @@ namespace v2rayN.Views
private void InitData() private void InitData()
{ {
_TextBoxKeyEventItem = new() _textBoxKeyEventItem = new()
{ {
{ txtGlobalHotkey0,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.ShowForm) }, { txtGlobalHotkey0,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.ShowForm) },
{ txtGlobalHotkey1,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyClear) }, { txtGlobalHotkey1,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyClear) },
@ -44,24 +44,32 @@ namespace v2rayN.Views
{ txtGlobalHotkey3,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyUnchanged)}, { txtGlobalHotkey3,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyUnchanged)},
{ txtGlobalHotkey4,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyPac)} { txtGlobalHotkey4,GetKeyEventItemByEGlobalHotkey(_config.GlobalHotkeys,EGlobalHotkey.SystemProxyPac)}
}; };
BindingData(); BindingData();
} }
private void TxtGlobalHotkey_PreviewKeyDown(object sender, KeyEventArgs e) private void TxtGlobalHotkey_PreviewKeyDown(object? sender, KeyEventArgs e)
{ {
e.Handled = true; e.Handled = true;
var _ModifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, if (sender is null)
Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin}; {
_TextBoxKeyEventItem[sender].KeyCode = (int)(e.Key == Key.System ? (_ModifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (_ModifierKeys.Contains(e.Key) ? Key.None : e.Key)); return;
_TextBoxKeyEventItem[sender].Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
_TextBoxKeyEventItem[sender].Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
_TextBoxKeyEventItem[sender].Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
(sender as TextBox)!.Text = KeyEventItemToString(_TextBoxKeyEventItem[sender]);
} }
private KeyEventItem GetKeyEventItemByEGlobalHotkey(List<KeyEventItem> KEList, EGlobalHotkey eg) var item = _textBoxKeyEventItem[sender];
var modifierKeys = new Key[] { Key.LeftCtrl, Key.RightCtrl, Key.LeftShift, Key.RightShift, Key.LeftAlt, Key.RightAlt, Key.LWin, Key.RWin };
item.KeyCode = (int)(e.Key == Key.System ? (modifierKeys.Contains(e.SystemKey) ? Key.None : e.SystemKey) : (modifierKeys.Contains(e.Key) ? Key.None : e.Key));
item.Alt = (Keyboard.Modifiers & ModifierKeys.Alt) == ModifierKeys.Alt;
item.Control = (Keyboard.Modifiers & ModifierKeys.Control) == ModifierKeys.Control;
item.Shift = (Keyboard.Modifiers & ModifierKeys.Shift) == ModifierKeys.Shift;
(sender as TextBox)!.Text = KeyEventItemToString(item);
}
private KeyEventItem GetKeyEventItemByEGlobalHotkey(List<KeyEventItem> lstKey, EGlobalHotkey eg)
{ {
return JsonUtils.DeepCopy(KEList.Find((it) => it.EGlobalHotkey == eg) ?? new() return JsonUtils.DeepCopy(lstKey.Find((it) => it.EGlobalHotkey == eg) ?? new()
{ {
EGlobalHotkey = eg, EGlobalHotkey = eg,
Control = false, Control = false,
@ -76,20 +84,31 @@ namespace v2rayN.Views
var res = new StringBuilder(); var res = new StringBuilder();
if (item.Control) if (item.Control)
{
res.Append($"{ModifierKeys.Control}+"); res.Append($"{ModifierKeys.Control}+");
}
if (item.Shift) if (item.Shift)
{
res.Append($"{ModifierKeys.Shift}+"); res.Append($"{ModifierKeys.Shift}+");
}
if (item.Alt) if (item.Alt)
{
res.Append($"{ModifierKeys.Alt}+"); res.Append($"{ModifierKeys.Alt}+");
}
if (item.KeyCode != null && (Key)item.KeyCode != Key.None) if (item.KeyCode != null && (Key)item.KeyCode != Key.None)
{
res.Append($"{(Key)item.KeyCode}"); res.Append($"{(Key)item.KeyCode}");
}
return res.ToString(); return res.ToString();
} }
private void BindingData() private void BindingData()
{ {
foreach (var item in _TextBoxKeyEventItem) foreach (var item in _textBoxKeyEventItem)
{ {
if (item.Value.KeyCode != null && (Key)item.Value.KeyCode != Key.None) if (item.Value.KeyCode != null && (Key)item.Value.KeyCode != Key.None)
{ {
@ -104,7 +123,7 @@ namespace v2rayN.Views
private async void btnSave_ClickAsync(object sender, RoutedEventArgs e) private async void btnSave_ClickAsync(object sender, RoutedEventArgs e)
{ {
_config.GlobalHotkeys = _TextBoxKeyEventItem.Values.ToList(); _config.GlobalHotkeys = _textBoxKeyEventItem.Values.ToList();
if (await ConfigHandler.SaveConfig(_config) == 0) if (await ConfigHandler.SaveConfig(_config) == 0)
{ {
@ -119,22 +138,16 @@ namespace v2rayN.Views
private void btnReset_Click(object sender, RoutedEventArgs e) private void btnReset_Click(object sender, RoutedEventArgs e)
{ {
foreach (var k in _TextBoxKeyEventItem.Keys) foreach (var k in _textBoxKeyEventItem.Keys)
{ {
_TextBoxKeyEventItem[k].Alt = false; var item = _textBoxKeyEventItem[k];
_TextBoxKeyEventItem[k].Control = false;
_TextBoxKeyEventItem[k].Shift = false; item.Alt = false;
_TextBoxKeyEventItem[k].KeyCode = (int)Key.None; item.Control = false;
item.Shift = false;
item.KeyCode = (int)Key.None;
} }
BindingData(); BindingData();
} }
private void GlobalHotkeySettingWindow_KeyDown(object sender, KeyEventArgs e)
{
if (e.Key == Key.Escape)
{
this.Close();
}
}
} }
} }