Update On Mon Oct 14 20:35:22 CEST 2024

This commit is contained in:
github-action[bot]
2024-10-14 20:35:22 +02:00
parent 373b4c8443
commit 82266bc767
263 changed files with 3380 additions and 3080 deletions
+1
View File
@@ -793,3 +793,4 @@ Update On Thu Oct 10 20:36:48 CEST 2024
Update On Fri Oct 11 20:34:02 CEST 2024
Update On Sat Oct 12 20:32:54 CEST 2024
Update On Sun Oct 13 20:32:23 CEST 2024
Update On Mon Oct 14 20:35:11 CEST 2024
@@ -0,0 +1,239 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="geofile_import_failed">Nhập thất bại</string>
<string name="toast_profile_updated_complete">Cập nhật thành công</string>
<string name="toast_profile_updated_failed">Cập nhật không thành công</string>
<string name="press_to_import">Chạm để nhập...</string>
<string name="meta_features">Tính năng của Clash Meta</string>
<string name="allow_ipv6">Cho phép Ipv6</string>
<string name="allow_ipv6_summary">Cho phép lưu lượng ipv6 qua hệ thống Vpn</string>
<string name="tun_stack_gvisor">Gvisor</string>
<string name="tun_stack_mixed">Mixed</string>
<string name="tun_stack_mode">Chế độ xếp chồng dữ liệu</string>
<string name="tun_stack_system">Hệ thống</string>
<string name="application_name_alpha">Clash Meta</string>
<string name="application_name_meta">Clash Meta</string>
<string name="clash_meta_core">Clash Meta Core</string>
<string name="clash_meta_for_android">Clash Meta</string>
<string name="clash_meta_wiki">Clash Meta Wiki</string>
<string name="launch_name_alpha">Clash Meta</string>
<string name="launch_name_meta">Clash Meta</string>
<string name="_new">Mới</string>
<string name="about">Thông tin</string>
<string name="accept_http_content">Chỉ chấp nhận http(s)</string>
<string name="access_control_mode">Chế độ kiểm soát truy cập</string>
<string name="access_control_packages">Các gói kiểm soát truy cập</string>
<string name="access_control_packages_summary">Định cấu hình quyền truy cập cho các ứng dụng</string>
<string name="active_unsaved_tips">Hồ sơ cần được lưu trước khi kích hoạt</string>
<string name="allow_all_apps">Cho phép tất cả các ứng dụng</string>
<string name="allow_bypass">Cho phép bỏ qua</string>
<string name="allow_bypass_summary">Cho phép tất cả các ứng dụng bỏ qua kết nối VPN này</string>
<string name="allow_clash_auto_restart">Cho phép Clash tự khởi động lại</string>
<string name="allow_lan">Cho phép mạng LAN</string>
<string name="allow_selected_apps">Cho phép các ứng dụng đã chọn</string>
<string name="always_dark">Luôn tối</string>
<string name="always_light">Luôn sáng</string>
<string name="app">Ứng dụng</string>
<string name="append_system_dns">Nối hệ thống DNS</string>
<string name="application_broken">Ứng dụng bị lỗi</string>
<string name="application_broken_tips">Ứng dụng thiếu các thành phần cần thiết, nguyên nhân thường là do tải xuống apk không đầy đủ.</string>
<string name="application_crashed">Ứng dụng bị dừng</string>
<string name="at_least_15_minutes">Ít nhất 15 phút hoặc để trống</string>
<string name="authentication">Xác thực</string>
<string name="auto_restart">Khởi động lại tự động</string>
<string name="auto_update">Thời gian tự động cập nhật</string>
<string name="auto_update_minutes">Tự động cập nhật (Phút)</string>
<string name="behavior">Điều hướng</string>
<string name="bind_address">Địa chỉ ràng buộc</string>
<string name="block_loopback">Chặn lặp</string>
<string name="block_loopback_summary">Chặn kết nối lặp lại</string>
<string name="browse_configuration_providers">Duyệt qua tệp cấu hình và nhà cung cấp</string>
<string name="browse_files">Duyệt qua tệp</string>
<string name="bypass_private_network">Bỏ qua mạng riêng</string>
<string name="bypass_private_network_summary">Bỏ qua các địa chỉ mạng riêng</string>
<string name="cancel">Huỷ bỏ</string>
<string name="clash_logcat">Nhật ký Clash</string>
<string name="close">Đóng</string>
<string name="compatible">Tương thích</string>
<string name="copied">Đã sao chép</string>
<string name="create_profile">Tạo cấu hình</string>
<string name="dark_mode">Chế độ tối</string>
<string name="debug">Gỡ lỗi</string>
<string name="default_">Mặc định</string>
<string name="default_name_server">Máy chủ định danh mặc định</string>
<string name="delay">Độ trễ</string>
<string name="delay_test">Kiểm tra độ trễ</string>
<string name="delete">Xoá</string>
<string name="delete_all_logs">Xóa tất cả nhật ký</string>
<string name="delete_all_logs_warn">Tất cả nhật ký lịch sử sẽ *MẤT*</string>
<string name="deny_selected_apps">Từ chối các ứng dụng đã chọn</string>
<string name="detail">Chi tiết</string>
<string name="direct_mode">Chế độ trực tiếp</string>
<string name="disabled">Vô hiệu hóa</string>
<string name="dns">DNS</string>
<string name="dns_hijacking">Định tuyến qua DNS</string>
<string name="dns_hijacking_summary">Xử lý tất cả gói DNS</string>
<string name="document">Tài liệu</string>
<string name="domain_fallback">Dự phòng miền</string>
<string name="donate">Quyên góp</string>
<string name="dont_modify">Chưa sửa đổi</string>
<string name="duplicate">Tạo bản sao</string>
<string name="edit">Sửa</string>
<string name="empty">Trống</string>
<string name="empty_name">Tên trống</string>
<string name="enabled">Bật</string>
<string name="enhanced_mode">Chế độ nâng cao</string>
<string name="error">Lỗi</string>
<string name="exit_without_save">Thoát mà không lưu</string>
<string name="exit_without_save_warning">Tất cả thay đổi sẽ *MẤT*</string>
<string name="export">Xuất</string>
<string name="export_to_clipboard">Nhập từ khay nhớ tạm</string>
<string name="external">Bên ngoài</string>
<string name="fakeip">Fake-IP thành ánh xạ miền</string>
<string name="fakeip_filter">Bộ lọc Fake-IP</string>
<string name="fallback">Máy chủ tên dự phòng</string>
<string name="feedback">Phản hồi</string>
<string name="file">Tệp</string>
<string name="file_exported">Tệp đã xuất</string>
<string name="file_name">Tên tệp</string>
<string name="files">Tệp</string>
<string name="filter">Bộ lọc</string>
<string name="follow_system_android_10">Theo hệ thống (Android 10+)</string>
<string name="force_enable">Buộc bật</string>
<string name="format_days_ago">%d ngày trước</string>
<string name="format_elements">%d elements</string>
<string name="format_fetching_configuration">Tìm nạp cấu hình từ \'%s\'</string>
<string name="format_fetching_provider">Nhà cung cấp tìm nạp \'%s\'</string>
<string name="format_hours_ago">%d giờ trước</string>
<string name="format_minutes">%d phút</string>
<string name="format_minutes_ago">%d phút trước</string>
<string name="format_months_ago">%d tháng trước</string>
<string name="format_profile_activated">%s đang sử dụng</string>
<string name="format_provider_type">%1$s(%2$s)</string>
<string name="format_traffic_forwarded">%s được sử dụng</string>
<string name="format_type_unsaved">%s (Chưa lưu)</string>
<string name="format_update_complete">Cập nhật %s thành công</string>
<string name="format_update_failure">Cập nhật %1$s: %2$s</string>
<string name="format_update_provider_failure">Cập nhật %1$s: %2$s</string>
<string name="format_years_ago">%d năm trước</string>
<string name="general">Chung</string>
<string name="geoip_fallback">Dự phòng GeoIP</string>
<string name="geoip_fallback_code">Mã dự phòng GeoIP</string>
<string name="github_issues">Sự cố trên Github</string>
<string name="github_releases">Bản phát hành trên Github</string>
<string name="global_mode">Chế độ toàn cầu</string>
<string name="help">Trợ giúp</string>
<string name="history">Lịch sử</string>
<string name="hosts">Hosts</string>
<string name="http">HTTP</string>
<string name="http_port">Cổng HTTP</string>
<string name="import_">Nhập</string>
<string name="import_from_clipboard">Nhập từ khay nhớ tạm</string>
<string name="import_from_file">Nhập từ tệp</string>
<string name="import_from_url">Nhập từ liên kết URL</string>
<string name="info">Thông tin</string>
<string name="initializing">Khởi tạo</string>
<string name="install_time">Thời gian cài đặt</string>
<string name="interface_">Giao diện</string>
<string name="invalid_file_name">Tên tệp không hợp lệ</string>
<string name="invalid_log_file">Tệp nhật ký không hợp lệ</string>
<string name="invalid_url">Liên kết URL không hợp lệ</string>
<string name="ipcidr_fallback">Dự phòng IPCIDR</string>
<string name="ipv6">IPv6</string>
<string name="key">Khoá</string>
<string name="keyword">Từ khoá</string>
<string name="layout">Bố cục</string>
<string name="listen">Nghe</string>
<string name="loading">Đang tải</string>
<string name="log_level">Mức nhật ký</string>
<string name="logcat">Nhật ký</string>
<string name="logs">Nhật ký</string>
<string name="mapping">IP thực với ánh xạ miền</string>
<string name="mixed_port">Cổng Mixed</string>
<string name="mode">Chế độ</string>
<string name="mode_switch_tips">Chỉ hợp lệ cho phiên hiện tại</string>
<string name="more">Thêm</string>
<string name="multiple">Nhiều</string>
<string name="name">Tên</string>
<string name="name_server">Tên máy chủ</string>
<string name="name_server_policy">Chính sách máy chủ định danh</string>
<string name="network">Mạng</string>
<string name="new_profile">Cấu hình mới</string>
<string name="no_profile_selected">Không có cấu hình</string>
<string name="not_selectable">Không thể chọn</string>
<string name="not_selected">Trống. Nhấn vào để thêm</string>
<string name="ok">OK</string>
<string name="options_unavailable">Tùy chọn không khả dụng cho đến khi Clash ngắt kết nối</string>
<string name="override">Cài đặt thêm</string>
<string name="package_name">Tên gói</string>
<string name="profile">Cấu hình</string>
<string name="profile_name">Tên cấu hình</string>
<string name="profile_process_result">Kết quả xử lý cấu hình</string>
<string name="profile_process_status">Trạng thái xử lý cấu hình</string>
<string name="profile_service_status">Trạng thái dịch vụ cấu hình</string>
<string name="profile_updater">Trình cập nhật cấu hình</string>
<string name="profile_updating">Cập nhật cấu hình</string>
<string name="profile_url">Liên kết URL cấu hình</string>
<string name="profiles">Cấu hình</string>
<string name="properties">Thuộc tính</string>
<string name="provider_files">Tệp nhà cung cấp</string>
<string name="providers">Nhà cung cấp</string>
<string name="proxy">Proxy</string>
<string name="proxy_empty_tips">Không có nhóm nào được hiển thị</string>
<string name="recently">Vừa xong</string>
<string name="redirect_port">Cổng Redirect</string>
<string name="reinstall">Cài đặt lại</string>
<string name="rename">Đổi tên</string>
<string name="reset">Đặt lại</string>
<string name="reset_override_settings">Đặt lại cài đặt ghi đè</string>
<string name="reset_override_settings_message">Tất cả cài đặt ghi đè sẽ bị hủy</string>
<string name="reverse">Đảo ngược</string>
<string name="route_system_traffic">Định tuyến lưu lượng hệ thống</string>
<string name="routing_via_vpn_service">Tự động định tuyến tất cả lưu lượng hệ thống qua VpnService</string>
<string name="rule">Quy tắc</string>
<string name="rule_mode">Chế độ quy tắc</string>
<string name="running">Đang kết nối</string>
<string name="save">Lưu</string>
<string name="script_mode">Chế độ tập lệnh</string>
<string name="search">Tìm kiếm</string>
<string name="select_all">Chọn tất cả</string>
<string name="select_invert">Chọn Đảo ngược</string>
<string name="select_none">Không chọn</string>
<string name="service">Dịch vụ</string>
<string name="settings">Cài đặt</string>
<string name="should_not_be_blank">Không được để trống</string>
<string name="show_traffic">Hiển thị lưu lượng truy cập</string>
<string name="show_traffic_summary">Tự động làm mới lưu lượng truy cập trong thông báo</string>
<string name="sideload_geoip">Sideload GEOIP</string>
<string name="sideload_geoip_summary">Cơ sở dữ liệu GEOIP bên ngoài</string>
<string name="silent">Im lặng</string>
<string name="single">Đơn</string>
<string name="socks_port">Cổng Socks</string>
<string name="sort">Sắp xếp theo</string>
<string name="sources">Nguồn</string>
<string name="stopped">Đã ngắt kết nối</string>
<string name="strategy">Strategy</string>
<string name="system_apps">Ứng dụng hệ thống</string>
<string name="system_proxy">Proxy hệ thống</string>
<string name="system_proxy_summary">Đính kèm proxy,http vào hệ thống Vpn</string>
<string name="tap_to_start">Chạm để kết nối</string>
<string name="tips_help">Clash Meta là một phần mềm miễn phí và chúng tôi KHÔNG cung cấp bất kỳ dịch vụ trả phí nào cho nó</string>
<string name="tips_properties">Chỉ chấp nhận cấu hình Clash bao gồm Proxy và Quy tắc</string>
<string name="tproxy_port">Cổng TProxy</string>
<string name="unable_to_start_vpn">Không thể khởi động thành phần VPN</string>
<string name="unavailable">Không có sẵn</string>
<string name="update">Cập nhật</string>
<string name="update_all">Cập nhật tất cả</string>
<string name="update_failure">Cập nhật thất bại</string>
<string name="update_successfully">Cập nhật thành công</string>
<string name="update_time">Thời gian cập nhật</string>
<string name="url">Liên kết URL</string>
<string name="use_built_in">Sử dụng tích hợp</string>
<string name="use_hosts">Sử dụng Hosts</string>
<string name="value">Giá trị</string>
<string name="verifying">Đang xác minh</string>
<string name="version_updated">Đã cập nhật ứng dụng</string>
<string name="version_updated_tips">Các cài đặt đã được đặt lại và các cấu hình cũ cần được lưu lại.</string>
<string name="vpn_service_options">Tuỳ chọn VpnService</string>
<string name="warning">Cảnh báo</string>
</resources>
@@ -29,7 +29,7 @@
"country-code-emoji": "2.3.0",
"dayjs": "1.11.13",
"framer-motion": "12.0.0-alpha.1",
"i18next": "23.15.2",
"i18next": "23.16.0",
"jotai": "2.10.0",
"json-schema": "0.4.0",
"material-react-table": "3.0.1",
@@ -52,7 +52,7 @@
"@csstools/normalize.css": "12.1.1",
"@emotion/babel-plugin": "11.12.0",
"@emotion/react": "11.13.3",
"@iconify/json": "2.2.259",
"@iconify/json": "2.2.260",
"@monaco-editor/react": "4.6.0",
"@tanstack/react-router": "1.65.0",
"@tanstack/router-devtools": "1.65.0",
+293 -293
View File
File diff suppressed because it is too large Load Diff
@@ -23,6 +23,16 @@ struct dentry;
struct inode;
struct file;
typedef enum rtl8367b_chip_e {
RTL8367B_CHIP_UNKNOWN,
/* Family B */
RTL8367B_CHIP_RTL8367RB,
RTL8367B_CHIP_RTL8367R_VB, /* chip with exception in extif assignment */
/* Family C */
RTL8367B_CHIP_RTL8367RB_VB,
RTL8367B_CHIP_RTL8367S
} rtl8367b_chip_t;
struct rtl8366_mib_counter {
unsigned base;
unsigned offset;
@@ -64,6 +74,7 @@ struct rtl8366_smi {
u8 dbg_vlan_4k_page;
#endif
u32 phy_id;
rtl8367b_chip_t rtl8367b_chip;
struct mii_bus *ext_mbus;
};
@@ -1,5 +1,6 @@
/*
* Platform driver for the Realtek RTL8367R-VB ethernet switches
* Platform driver for Realtek RTL8367B family chips, i.e. RTL8367RB and RTL8367R-VB
* extended with support for RTL8367C family chips, i.e. RTL8367RB-VB and RTL8367S
*
* Copyright (C) 2012 Gabor Juhos <juhosg@openwrt.org>
*
@@ -515,28 +516,19 @@ static int rtl8367b_write_phy_reg(struct rtl8366_smi *smi,
static int rtl8367b_init_regs(struct rtl8366_smi *smi)
{
const struct rtl8367b_initval *initvals;
u32 chip_num;
u32 chip_ver;
int count;
int err;
REG_WR(smi, RTL8367B_RTL_MAGIC_ID_REG, RTL8367B_RTL_MAGIC_ID_VAL);
REG_RD(smi, RTL8367B_CHIP_NUMBER_REG, &chip_num);
REG_RD(smi, RTL8367B_CHIP_VER_REG, &chip_ver);
switch (chip_ver) {
case 0x1000:
case 0x1010:
switch (smi->rtl8367b_chip) {
case RTL8367B_CHIP_RTL8367RB:
case RTL8367B_CHIP_RTL8367R_VB:
initvals = rtl8367b_initvals;
count = ARRAY_SIZE(rtl8367b_initvals);
break;
case 0x0020:
case 0x00A0:
if (chip_num == 0x6367) {
initvals = rtl8367c_initvals;
count = ARRAY_SIZE(rtl8367c_initvals);
} else return -ENODEV;
break
case RTL8367B_CHIP_RTL8367RB_VB:
case RTL8367B_CHIP_RTL8367S:
initvals = rtl8367c_initvals;
count = ARRAY_SIZE(rtl8367c_initvals);
break;
default:
return -ENODEV;
}
@@ -1308,10 +1300,10 @@ static int rtl8367b_detect(struct rtl8366_smi *smi)
const char *chip_name = NULL;
u32 chip_num;
u32 chip_ver;
u32 chip_mode;
int ret;
/* TODO: improve chip detection */
smi->rtl8367b_chip = RTL8367B_CHIP_UNKNOWN;
rtl8366_smi_write_reg(smi, RTL8367B_RTL_MAGIC_ID_REG,
RTL8367B_RTL_MAGIC_ID_VAL);
@@ -1329,41 +1321,41 @@ static int rtl8367b_detect(struct rtl8366_smi *smi)
return ret;
}
ret = rtl8366_smi_read_reg(smi, RTL8367B_CHIP_MODE_REG, &chip_mode);
if (ret) {
dev_err(smi->parent, "unable to read %s register\n",
"chip mode");
return ret;
}
switch (chip_ver) {
case 0x0020:
if (chip_num == 0x6367)
if (chip_num == 0x6367) {
chip_name = "8367RB-VB";
smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB_VB;
}
break;
case 0x00A0:
if (chip_num == 0x6367)
if (chip_num == 0x6367) {
chip_name = "8367S";
smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367S;
}
break;
case 0x1000:
chip_name = "8367RB";
smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367RB;
break;
case 0x1010:
chip_name = "8367R-VB";
smi->rtl8367b_chip = RTL8367B_CHIP_RTL8367R_VB;
}
if (!chip_name) {
dev_err(smi->parent,
"unknown chip num:%04x ver:%04x, mode:%04x\n",
chip_num, chip_ver, chip_mode);
"unknown chip (num:%04x ver:%04x)\n",
chip_num, chip_ver);
return -ENODEV;
}
dev_info(smi->parent, "RTL%s chip found\n", chip_name);
dev_info(smi->parent, "RTL%s chip found (num:%04x ver:%04x)\n", chip_name, chip_num, chip_ver);
/* for the RTL8367R-VB chip, extif1 corresponds to cpu_port 5 */
if (of_property_present(smi->parent->of_node, "realtek,extif2"))
smi->cpu_port = RTL8367B_CPU_PORT_NUM + 2;
else if (of_property_present(smi->parent->of_node, "realtek,extif1") && (chip_ver != 0x1010)) /* for the RTL8367R-VB chip, extif1 corresponds to cpu_port 5 */
else if (of_property_present(smi->parent->of_node, "realtek,extif1") && (smi->rtl8367b_chip != RTL8367B_CHIP_RTL8367R_VB))
smi->cpu_port = RTL8367B_CPU_PORT_NUM + 1;
dev_info(smi->parent, "CPU port: %u\n", smi->cpu_port);
@@ -1,6 +1,8 @@
# Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com>
#
# This is free software, licensed under the Apache License, Version 2.0 .
# Copyright (C) 2021 ImmortalWrt
# <https://immortalwrt.org>
#
# This is free software, licensed under the GNU General Public License v3.
#
include $(TOPDIR)/rules.mk
@@ -9,6 +11,11 @@ LUCI_TITLE:=LuCI Support for FileBrowser
LUCI_DEPENDS:=+filebrowser
LUCI_PKGARCH:=all
PKG_NAME:=luci-app-filebrowser
PKG_VERSION:=snapshot
PKG_RELEASE:=118071b
PKG_LICENSE:=GPLv3
include $(TOPDIR)/feeds/luci/luci.mk
@@ -1,59 +1,19 @@
-- Copyright 2018-2020 Lienol <lawlienol@gmail.com>
-- Improve by xiaozhuai <xiaozhuai7@gmail.com>
module("luci.controller.filebrowser", package.seeall)
local http = require "luci.http"
local api = require "luci.model.cbi.filebrowser.api"
function index()
if not nixio.fs.access("/etc/config/filebrowser") then return end
entry({"admin", "services"}, firstchild(), "Services", 44).dependent = false
entry({"admin", "services", "filebrowser"}, cbi("filebrowser/settings"),
_("File Browser"), 2).dependent = true
entry({"admin", "services", "filebrowser", "check"}, call("action_check")).leaf =
true
entry({"admin", "services", "filebrowser", "download"}, call("action_download")).leaf =
true
entry({"admin", "services", "filebrowser", "status"}, call("act_status")).leaf =
true
entry({"admin", "services", "filebrowser", "get_log"}, call("get_log")).leaf =
true
entry({"admin", "services", "filebrowser", "clear_log"}, call("clear_log")).leaf =
true
end
local function http_write_json(content)
http.prepare_content("application/json")
http.write_json(content or {code = 1})
end
function act_status()
local e = {}
e.status = luci.sys.call("ps -w | grep -v grep | grep 'filebrowser -a' >/dev/null") == 0
http_write_json(e)
end
function action_check()
local json = api.to_check()
http_write_json(json)
end
function action_download()
local json = nil
local task = http.formvalue("task")
if task == "extract" then
json = api.to_extract(http.formvalue("file"))
elseif task == "move" then
json = api.to_move(http.formvalue("file"))
else
json = api.to_download(http.formvalue("url"))
end
http_write_json(json)
end
function get_log()
luci.http.write(luci.sys.exec("[ -f '/var/log/filebrowser.log' ] && cat /var/log/filebrowser.log"))
end
function clear_log() luci.sys.call("echo '' > /var/log/filebrowser.log") end
module("luci.controller.filebrowser", package.seeall)
function index()
if not nixio.fs.access("/etc/config/filebrowser") then
return
end
entry({"admin", "nas"}, firstchild(), _("NAS") , 45).dependent = false
local page
page = entry({"admin", "nas", "filebrowser"}, cbi("filebrowser"), _("文件管理器"), 100)
page.dependent = true
entry({"admin","nas","filebrowser","status"},call("act_status")).leaf=true
end
function act_status()
local e={}
e.running=luci.sys.call("pgrep filebrowser >/dev/null")==0
luci.http.prepare_content("application/json")
luci.http.write_json(e)
end
@@ -0,0 +1,42 @@
m = Map("filebrowser", translate("文件管理器"), translate("FileBrowser是一个基于Go的在线文件管理器,助您方便的管理设备上的文件。"))
m:section(SimpleSection).template = "filebrowser/filebrowser_status"
s = m:section(TypedSection, "filebrowser")
s.addremove = false
s.anonymous = true
enable = s:option(Flag, "enabled", translate("启用"))
enable.rmempty = false
o = s:option(ListValue, "addr_type", translate("监听地址"))
o:value("local", translate("监听本机地址"))
o:value("lan", translate("监听局域网地址"))
o:value("wan", translate("监听全部地址"))
o.default = "lan"
o.rmempty = false
o = s:option(Value, "port", translate("监听端口"))
o.placeholder = 8989
o.default = 8989
o.datatype = "port"
o.rmempty = false
o = s:option(Value, "root_dir", translate("开放目录"))
o.placeholder = "/"
o.default = "/"
o.rmempty = false
o = s:option(Value, "db_dir", translate("数据库目录"))
o.placeholder = "/etc"
o.default = "/etc"
o.rmempty = false
o.description = translate("普通用户请勿随意更改")
o = s:option(Value, "db_name", translate("数据库名"))
o.placeholder = "filebrowser.db"
o.default = "filebrowser.db"
o.rmempty = false
o.description = translate("普通用户请勿随意更改")
return m
@@ -1,338 +0,0 @@
local fs = require "nixio.fs"
local sys = require "luci.sys"
local uci = require"luci.model.uci".cursor()
local util = require "luci.util"
local i18n = require "luci.i18n"
module("luci.model.cbi.filebrowser.api", package.seeall)
local appname = "filebrowser"
local api_url =
"https://api.github.com/repos/filebrowser/filebrowser/releases/latest"
local wget = "/usr/bin/wget"
local wget_args = {
"--no-check-certificate", "--quiet", "--timeout=10", "--tries=2"
}
local command_timeout = 300
local LEDE_BOARD = nil
local DISTRIB_TARGET = nil
function uci_get_type(type, config, default)
value = uci:get_first(appname, type, config, default) or sys.exec(
"echo -n `uci -q get " .. appname .. ".@" .. type .. "[0]." ..
config .. "`")
if (value == nil or value == "") and (default and default ~= "") then
value = default
end
return value
end
local function _unpack(t, i)
i = i or 1
if t[i] ~= nil then return t[i], _unpack(t, i + 1) end
end
local function exec(cmd, args, writer, timeout)
local os = require "os"
local nixio = require "nixio"
local fdi, fdo = nixio.pipe()
local pid = nixio.fork()
if pid > 0 then
fdo:close()
if writer or timeout then
local starttime = os.time()
while true do
if timeout and os.difftime(os.time(), starttime) >= timeout then
nixio.kill(pid, nixio.const.SIGTERM)
return 1
end
if writer then
local buffer = fdi:read(2048)
if buffer and #buffer > 0 then
writer(buffer)
end
end
local wpid, stat, code = nixio.waitpid(pid, "nohang")
if wpid and stat == "exited" then return code end
if not writer and timeout then nixio.nanosleep(1) end
end
else
local wpid, stat, code = nixio.waitpid(pid)
return wpid and stat == "exited" and code
end
elseif pid == 0 then
nixio.dup(fdo, nixio.stdout)
fdi:close()
fdo:close()
nixio.exece(cmd, args, nil)
nixio.stdout:close()
os.exit(1)
end
end
local function compare_versions(ver1, comp, ver2)
local table = table
local av1 = util.split(ver1, "[%.%-]", nil, true)
local av2 = util.split(ver2, "[%.%-]", nil, true)
local max = table.getn(av1)
local n2 = table.getn(av2)
if (max < n2) then max = n2 end
for i = 1, max, 1 do
local s1 = av1[i] or ""
local s2 = av2[i] or ""
if comp == "~=" and (s1 ~= s2) then return true end
if (comp == "<" or comp == "<=") and (s1 < s2) then return true end
if (comp == ">" or comp == ">=") and (s1 > s2) then return true end
if (s1 ~= s2) then return false end
end
return not (comp == "<" or comp == ">")
end
local function auto_get_arch()
local arch = nixio.uname().machine or ""
if fs.access("/usr/lib/os-release") then
LEDE_BOARD = sys.exec(
"echo -n `grep 'LEDE_BOARD' /usr/lib/os-release | awk -F '[\\042\\047]' '{print $2}'`")
end
if fs.access("/etc/openwrt_release") then
DISTRIB_TARGET = sys.exec(
"echo -n `grep 'DISTRIB_TARGET' /etc/openwrt_release | awk -F '[\\042\\047]' '{print $2}'`")
end
if arch == "mips" then
if LEDE_BOARD and LEDE_BOARD ~= "" then
if string.match(LEDE_BOARD, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. LEDE_BOARD ..
"' | grep -oE 'ramips|ar71xx'")
end
elseif DISTRIB_TARGET and DISTRIB_TARGET ~= "" then
if string.match(DISTRIB_TARGET, "ramips") == "ramips" then
arch = "ramips"
else
arch = sys.exec("echo '" .. DISTRIB_TARGET ..
"' | grep -oE 'ramips|ar71xx'")
end
end
end
return util.trim(arch)
end
local function get_file_info(arch)
local file_tree = ""
local sub_version = ""
if arch == "x86_64" then
file_tree = "amd64"
elseif arch == "aarch64" then
file_tree = "arm64"
elseif arch == "ramips" then
file_tree = "mipsle"
elseif arch == "ar71xx" then
file_tree = "mips"
elseif arch:match("^i[%d]86$") then
file_tree = "386"
elseif arch:match("^armv[5-8]") then
file_tree = "armv"
sub_version = arch:match("[5-8]")
if LEDE_BOARD and string.match(LEDE_BOARD, "bcm53xx") == "bcm53xx" then
sub_version = "5"
elseif DISTRIB_TARGET and string.match(DISTRIB_TARGET, "bcm53xx") ==
"bcm53xx" then
sub_version = "5"
end
sub_version = "5"
end
return file_tree, sub_version
end
local function get_api_json(url)
local jsonc = require "luci.jsonc"
local output = {}
-- exec(wget, { "-O-", url, _unpack(wget_args) },
-- function(chunk) output[#output + 1] = chunk end)
-- local json_content = util.trim(table.concat(output))
local json_content = luci.sys.exec(wget ..
" --no-check-certificate --timeout=10 -t 1 -O- " ..
url)
if json_content == "" then return {} end
return jsonc.parse(json_content) or {}
end
function get_version() return uci_get_type("global", "version", "0") end
function to_check(arch)
if not arch or arch == "" then arch = auto_get_arch() end
local file_tree, sub_version = get_file_info(arch)
if file_tree == "" then
return {
code = 1,
error = i18n.translate(
"Can't determine ARCH, or ARCH not supported.")
}
end
local json = get_api_json(api_url)
if json.tag_name == nil then
return {
code = 1,
error = i18n.translate("Get remote version info failed.")
}
end
local remote_version = json.tag_name:match("[^v]+")
local needs_update = compare_versions(get_version(), "<", remote_version)
local html_url, download_url
if needs_update then
html_url = json.html_url
for _, v in ipairs(json.assets) do
if v.name and v.name:match("linux%-" .. file_tree .. sub_version) then
download_url = v.browser_download_url
break
end
end
end
if needs_update and not download_url then
return {
code = 1,
version = remote_version,
html_url = html_url,
error = i18n.translate(
"New version found, but failed to get new version download url.")
}
end
return {
code = 0,
update = needs_update,
version = remote_version,
url = {html = html_url, download = download_url}
}
end
function to_download(url)
if not url or url == "" then
return {code = 1, error = i18n.translate("Download url is required.")}
end
sys.call("/bin/rm -f /tmp/filebrowser_download.*")
local tmp_file = util.trim(util.exec(
"mktemp -u -t filebrowser_download.XXXXXX"))
local result = exec(wget, {"-O", tmp_file, url, _unpack(wget_args)}, nil,
command_timeout) == 0
if not result then
exec("/bin/rm", {"-f", tmp_file})
return {
code = 1,
error = i18n.translatef("File download failed or timed out: %s", url)
}
end
return {code = 0, file = tmp_file}
end
function to_extract(file, subfix)
if not file or file == "" or not fs.access(file) then
return {code = 1, error = i18n.translate("File path required.")}
end
sys.call("/bin/rm -rf /tmp/filebrowser_extract.*")
local tmp_dir = util.trim(util.exec(
"mktemp -d -t filebrowser_extract.XXXXXX"))
local output = {}
exec("/bin/tar", {"-C", tmp_dir, "-zxvf", file},
function(chunk) output[#output + 1] = chunk end)
local files = util.split(table.concat(output))
exec("/bin/rm", {"-f", file})
if not new_file then
for _, f in pairs(files) do
if f:match("filebrowser") then
new_file = tmp_dir .. "/" .. util.trim(f)
break
end
end
end
if not new_file then
exec("/bin/rm", {"-rf", tmp_dir})
return {
code = 1,
error = i18n.translatef("Can't find client in file: %s", file)
}
end
return {code = 0, file = new_file}
end
function to_move(file)
if not file or file == "" or not fs.access(file) then
sys.call("/bin/rm -rf /tmp/filebrowser_extract.*")
return {code = 1, error = i18n.translate("Client file is required.")}
end
local executable_directory =
uci_get_type("global", "executable_directory", "/tmp")
luci.sys.exec("mkdir -p " .. executable_directory)
local client_path = executable_directory .. "/" .. appname
local client_path_bak
if fs.access(client_path) then
client_path_bak = "/tmp/" .. appname .. ".bak"
exec("/bin/mv", {"-f", client_path, client_path_bak})
end
local result = exec("/bin/mv", {"-f", file, client_path}, nil,
command_timeout) == 0
if not result or not fs.access(client_path) then
if client_path_bak then
exec("/bin/mv", {"-f", client_path_bak, client_path})
end
return {
code = 1,
error = i18n.translatef("Can't move new file to path: %s",
client_path)
}
end
exec("/bin/chmod", {"755", client_path})
if client_path_bak then exec("/bin/rm", {"-f", client_path_bak}) end
sys.call("/bin/rm -rf /tmp/filebrowser_extract.*")
return {code = 0}
end
@@ -1,59 +0,0 @@
m = Map("filebrowser", translate("FileBrowser"), translate(
"File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!"))
m:append(Template("filebrowser/status"))
s = m:section(TypedSection, "global", translate("Global Settings"))
s.anonymous = true
s.addremove = false
o = s:option(Flag, "enable", translate("Enable"))
o.rmempty = false
o = s:option(Value, "address", translate("Listen address"))
o.default = "0.0.0.0"
o.rmempty = false
o = s:option(Value, "port", translate("Listen port"))
o.datatype = "port"
o.default = 8088
o.rmempty = false
o = s:option(Value, "database", translate("Database path"))
o.default = "/etc/filebrowser.db"
o.rmempty = false
o = s:option(Value, "username", translate("Initial username"))
o.default = "admin"
o.rmempty = false
o = s:option(Value, "password", translate("Initial password"))
o.default = "admin"
o.rmempty = false
o = s:option(Value, "ssl_cert", translate("SSL cert"))
o.default = ""
o = s:option(Value, "ssl_key", translate("SSL key"))
o.default = ""
o = s:option(Value, "root_path", translate("Root path"), translate(
"Point to a path to access your files in the web interface, default is /root"))
o.default = "/root"
o.rmempty = false
o = s:option(Value, "executable_directory", translate("Executable directory"),
translate(
"The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory<br />For example, /mnt/sda1<br />For example, /tmp"))
o.default = "/tmp"
o.rmempty = false
o = s:option(Button, "_download", translate("Manually download"), translate(
"Make sure you have enough space. <br /><font style='color:red'>Be sure to fill out the executable storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!</font>"))
o.template = "filebrowser/download"
o.inputstyle = "apply"
o.btnclick = "downloadClick(this);"
o.id = "download_btn"
m:append(Template("filebrowser/log"))
return m
@@ -1,169 +0,0 @@
<%
local dsp = require "luci.dispatcher"
-%>
<script type="text/javascript">//<![CDATA[
var msgInfo;
var tokenStr = '<%=token%>';
var clickToDownloadText = '<%:Click to download%>';
var inProgressText = '<%:Downloading...%>';
var downloadInProgressNotice = '<%:Download, are you sure to close?%>';
var downloadSuccessText = '<%:Download successful%>';
var unexpectedErrorText = '<%:Unexpected error%>';
function addPageNotice() {
window.onbeforeunload = function(e) {
e.returnValue = downloadInProgressNotice;
return downloadInProgressNotice;
};
}
function removePageNotice() {
window.onbeforeunload = undefined;
}
function onUpdateSuccess(btn) {
alert(downloadSuccessText);
if (btn) {
btn.value = downloadSuccessText;
btn.placeholder = downloadSuccessText;
btn.disabled = true;
}
window.setTimeout(function () {
window.location.reload();
}, 1000);
}
function onRequestError(btn, errorMessage) {
btn.disabled = false;
btn.value = btn.placeholder;
if (errorMessage) {
alert(errorMessage);
}
}
function doAjaxGet(url, data, onResult) {
new XHR().get(url, data, function(_, json) {
var resultJson = json || {
'code': 1,
'error': unexpectedErrorText
};
if (typeof onResult === 'function') {
onResult(resultJson);
}
})
}
function downloadClick(btn) {
if (msgInfo === undefined) {
checkUpdate(btn);
} else {
doDownload(btn);
}
}
function checkUpdate(btn) {
btn.disabled = true;
btn.value = inProgressText;
addPageNotice();
var ckeckDetailElm = document.getElementById(btn.id + '-detail');
doAjaxGet('<%=dsp.build_url("admin/services/filebrowser/check")%>/', {
token: tokenStr
}, function (json) {
removePageNotice();
if (json.code) {
eval('Info = undefined');
onRequestError(btn, json.error);
} else {
eval('Info = json');
btn.disabled = false;
btn.value = clickToDownloadText;
btn.placeholder = clickToDownloadText;
}
if (ckeckDetailElm) {
var urlNode = '';
if (json.version) {
urlNode = '<em style="color:red;"><%:The latest version:%>' + json.version + '</em>';
if (json.url && json.url.html) {
urlNode = '<a href="' + json.url.html + '" target="_blank">' + urlNode + '</a>';
}
}
ckeckDetailElm.innerHTML = urlNode;
}
msgInfo = json;
});
}
function doDownload(btn) {
btn.disabled = true;
btn.value = '<%:Downloading...%>';
addPageNotice();
var UpdateUrl = '<%=dsp.build_url("admin/services/filebrowser/download")%>';
// Download file
doAjaxGet(UpdateUrl, {
token: tokenStr,
url: msgInfo ? msgInfo.url.download : ''
}, function (json) {
if (json.code) {
removePageNotice();
onRequestError(btn, json.error);
} else {
btn.value = '<%:Unpacking...%>';
// Extract file
doAjaxGet(UpdateUrl, {
token: tokenStr,
task: 'extract',
file: json.file
}, function (json) {
if (json.code) {
removePageNotice();
onRequestError(btn, json.error);
} else {
btn.value = '<%:Moving...%>';
// Move file to target dir
doAjaxGet(UpdateUrl, {
token: tokenStr,
task: 'move',
file: json.file
}, function (json) {
removePageNotice();
if (json.code) {
onRequestError(btn, json.error);
} else {
onUpdateSuccess(btn);
}
})
}
})
}
})
}
//]]></script>
<%+cbi/valueheader%>
<% if self:cfgvalue(section) ~= false then %>
<input class="cbi-button cbi-input-<%=self.inputstyle or "button" %>" type="button"<%=
attr("name", cbid) ..
attr("id", self.id or cbid) ..
attr("value", self.inputtitle or self.title) ..
ifattr(self.btnclick, "onclick", self.btnclick) ..
ifattr(self.placeholder, "placeholder")
%> />
<span id="<%=self.id or cbid%>-detail"></span>
<% else %>
-
<% end %>
<%+cbi/valuefooter%>
@@ -0,0 +1,32 @@
<script type="text/javascript">//<![CDATA[
XHR.poll(1, '<%=url([[admin]], [[nas]], [[filebrowser]], [[status]])%>', null,
function(x, data) {
var tb = document.getElementById('filebrowser_status');
if (data && tb) {
if (data.running) {
var links = '<font color=green>Filebrowser <%:运行中%></font><input class="cbi-button mar-10" type="button" value="<%:打开管理界面%>" onclick="openClient();" />';
tb.innerHTML = links;
} else {
tb.innerHTML = '<font color=red>Filebrowser <%:未运行%></font>';
}
}
}
);
function openClient() {
var curWwwPath = window.document.location.href;
var pathName = window.document.location.pathname;
var pos = curWwwPath.indexOf(pathName);
var localhostPath = curWwwPath.substring(0, pos);
var clientPort = window.document.getElementById("cbid.filebrowser.config.port").value
var url = localhostPath + ":" + clientPort;
window.open(url)
};
//]]>
</script>
<style>.mar-10 {margin-left: 50px; margin-right: 10px;}</style>
<fieldset class="cbi-section">
<p id="filebrowser_status">
<em><%:Collecting data...%></em>
</p>
</fieldset>
@@ -1,31 +0,0 @@
<script type="text/javascript">
//<![CDATA[
function clear_log(btn) {
XHR.get('<%=url([[admin]], [[services]], [[filebrowser]], [[clear_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = "";
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
}
XHR.poll(3, '<%=url([[admin]], [[services]], [[filebrowser]], [[get_log]])%>', null,
function(x, data) {
if(x && x.status == 200) {
var log_textarea = document.getElementById('log_textarea');
log_textarea.innerHTML = x.responseText;
log_textarea.scrollTop = log_textarea.scrollHeight;
}
}
);
//]]>
</script>
<fieldset class="cbi-section" id="_log_fieldset">
<legend>
<%:Logs%>
</legend>
<input class="cbi-button cbi-input-remove" type="button" onclick="clear_log()" value="<%:Clear logs%>" style="margin-left: 10px;">
<textarea id="log_textarea" class="cbi-input-textarea" style="width: calc(100% - 20px); margin: 10px;" data-update="change" rows="5" wrap="off" readonly="readonly"></textarea>
</fieldset>
@@ -1,38 +0,0 @@
<%
local dsp = require "luci.dispatcher"
-%>
<fieldset class="cbi-section">
<legend><%:Running Status%></legend>
<fieldset class="cbi-section">
<div class="cbi-value">
<label class="cbi-value-title"><%:Status%></label>
<div class="cbi-value-field" id="_status"><p><span><%:Collecting data...%></span></p></div>
</div>
</fieldset>
</fieldset>
<script type="text/javascript">//<![CDATA[
var _status = document.getElementById('_status');
XHR.poll(3,'<%=dsp.build_url("admin/services/filebrowser/status")%>', null,
function(x, json) {
if (x && x.status == 200) {
if (_status)
_status.innerHTML = json.status ? '<p><span style="color:green;"><%:RUNNING%></span> <input type="button" class="cbi-button cbi-input-apply" value="<%:Enter interface%>" onclick="openwebui()" /></p>' : '<p><span style="color:red;"><%:NOT RUNNING%></span></p>';
}
});
function openwebui(){
var url = window.location.host;
if (url.indexOf(':')) {
url = url.split(':')[0];
}
ssl_cert = "<%=luci.sys.exec("uci get filebrowser.@global[0].ssl_cert"):gsub("^%s*(.-)%s*$", "%1")%>";
ssl_key = "<%=luci.sys.exec("uci get filebrowser.@global[0].ssl_key"):gsub("^%s*(.-)%s*$", "%1")%>";
port = "<%=luci.sys.exec("uci get filebrowser.@global[0].port"):gsub("^%s*(.-)%s*$", "%1")%>";
protocol = 'http';
if (ssl_cert !== '' && ssl_key !== '') protocol = 'https';
window.open(protocol+'://'+url+':'+port,'target','');
}
//]]></script>
@@ -1,125 +0,0 @@
msgid "File Browser"
msgstr "文件浏览器"
msgid "File explorer is software that creates your own cloud that you can install on a server, point it to a path, and then access your files through a beautiful web interface. You have many features available!"
msgstr "文件浏览器是一种创建你自己的云的软件,你可以在服务器上安装它,将它指向一个路径,然后通过一个漂亮的web界面访问你的文件。您有许多可用的特性!"
msgid "RUNNING"
msgstr "运行中"
msgid "NOT RUNNING"
msgstr "未运行"
msgid "Enter interface"
msgstr "进入界面"
msgid "Global Settings"
msgstr "全局设置"
msgid "Enable"
msgstr "启用"
msgid "Listen address"
msgstr "监听地址"
msgid "Listen port"
msgstr "监听端口"
msgid "Initial username"
msgstr "初始账户"
msgid "Initial password"
msgstr "初始密码"
msgid "SSL cert"
msgstr "SSL 证书"
msgid "SSL key"
msgstr "SSL 私钥"
msgid "Database path"
msgstr "数据库路径"
msgid "Root path"
msgstr "指向路径"
msgid "Point to a path to access your files in the web interface, default is /root"
msgstr "指向一个路径,可在web界面访问你的文件,默认为 /root"
msgid "Executable directory"
msgstr "可执行文件存放目录"
msgid "The file size is large, requiring at least 32M space. It is recommended to insert a usb flash drive or hard disk, or use it in the tmp directory<br />For example, /mnt/sda1<br />For example, /tmp"
msgstr "文件较大,至少需要32M空间。建议插入U盘或硬盘,或放入tmp目录里使用<br />例如:/mnt/sda1<br />例如:/tmp"
msgid "Manually download"
msgstr "手动下载"
msgid "Make sure you have enough space. <br /><font style='color:red'>Be sure to fill out the executable storage directory the first time you run it, and then save the application. Then manually download, otherwise can not use!</font>"
msgstr "请确保具有足够的空间。<br /><font style='color:red'>第一次运行务必填好项目存放目录,然后保存应用。再手动下载,否则无法使用!</font>"
msgid "Logs"
msgstr "日志"
msgid "Clear logs"
msgstr "清空日志"
msgid "It is the latest version"
msgstr "已是最新版本"
msgid "Download successful"
msgstr "下载成功"
msgid "Click to download"
msgstr "点击下载"
msgid "Updating..."
msgstr "更新中"
msgid "Unexpected error"
msgstr "意外错误"
msgid "Download, are you sure to close?"
msgstr "正在下载,你确认要关闭吗?"
msgid "Downloading..."
msgstr "下载中"
msgid "Unpacking..."
msgstr "解压中"
msgid "Moving..."
msgstr "移动中"
msgid "The latest version:"
msgstr "最新版本:"
msgid "Can't determine ARCH, or ARCH not supported."
msgstr "无法确认ARCH架构,或是不支持。"
msgid "Get remote version info failed."
msgstr "获取远程版本信息失败。"
msgid "New version found, but failed to get new version download url."
msgstr "发现新版本,但未能获得新版本的下载地址。"
msgid "Download url is required."
msgstr "请指定下载地址。"
msgid "File download failed or timed out: %s"
msgstr "文件下载失败或超时:%s"
msgid "File path required."
msgstr "请指定文件路径。"
msgid "Can't find client in file: %s"
msgstr "无法在文件中找到客户端:%s"
msgid "Client file is required."
msgstr "请指定客户端文件。"
msgid "The client file is not suitable for current device."
msgstr "客户端文件不适合当前设备。"
msgid "Can't move new file to path: %s"
msgstr "无法移动新文件到:%s"
@@ -1,13 +0,0 @@
config global
option address '0.0.0.0'
option port '8088'
option database '/etc/filebrowser.db'
option username 'admin'
option password 'admin'
option ssl_cert ''
option ssl_key ''
option root_path '/root'
option executable_directory '/tmp'
option enable '0'
@@ -1,48 +0,0 @@
#!/bin/sh /etc/rc.common
# Copyright (C) 2018-2020 Lienol <lawlienol@gmail.com>
# Improve by xiaozhuai <xiaozhuai7@gmail.com>
START=99
LOG_PATH="/var/log/filebrowser.log"
echolog() {
echo -e "$(date "+%Y-%m-%d %H:%M:%S"): $1" >> $LOG_PATH
}
config_t_get() {
local index=0
[ -n "$4" ] && index=$4
local ret=$(uci get filebrowser.@$1[$index].$2 2>/dev/null)
echo ${ret:=$3}
}
start() {
ENABLED=$(config_t_get global enable 0)
[ "$ENABLED" = "0" ] && return
ADDRESS=$(config_t_get global address 0.0.0.0)
PORT=$(config_t_get global port 8088)
DATABASE=$(config_t_get global database /etc/filebrowser.db)
USERNAME=$(config_t_get global username admin)
PASSWORD=$(config_t_get global password admin)
SSL_CERT=$(config_t_get global ssl_cert)
SSL_KEY=$(config_t_get global ssl_key)
ROOT_PATH=$(config_t_get global root_path /root)
executable_directory=$(config_t_get global executable_directory /tmp)
[ ! -f "$executable_directory/filebrowser" ] && echolog "$executable_directory/filebrowser not exists, please download first" && exit
SSL_PARAMS=""
[ -n "$SSL_CERT" ] && [ -n "$SSL_KEY" ] && SSL_PARAMS="-t $SSL_CERT -k $SSL_KEY"
PASSWORD="$($executable_directory/filebrowser hash "$PASSWORD")"
$executable_directory/filebrowser -a $ADDRESS -p $PORT -r $ROOT_PATH -d "$DATABASE" --username $USERNAME --password $PASSWORD $SSL_PARAMS -l $LOG_PATH >/dev/null 2>&1 &
}
stop() {
ps -w | grep -v "grep" | grep "$executable_directory/filebrowser -a" | awk '{print $1}' | xargs kill -9 >/dev/null 2>&1 &
rm -rf $LOG_PATH
}
restart() {
stop
sleep 1
start
}
@@ -1,11 +1,11 @@
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@filebrowser[-1]
add ucitrack filebrowser
set ucitrack.@filebrowser[-1].init=filebrowser
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0
#!/bin/sh
uci -q batch <<-EOF >/dev/null
delete ucitrack.@filebrowser[-1]
add ucitrack filebrowser
set ucitrack.@filebrowser[-1].init=filebrowser
commit ucitrack
EOF
rm -f /tmp/luci-indexcache
exit 0
@@ -1,11 +0,0 @@
{
"luci-app-filebrowser": {
"description": "Grant UCI access for luci-app-filebrowser",
"read": {
"uci": [ "filebrowser" ]
},
"write": {
"uci": [ "filebrowser" ]
}
}
}
@@ -12,7 +12,6 @@ function index()
local page
page = entry({"admin", "services", "gost"}, cbi("gost"), _("Gost"), 100)
page.dependent = true
page.acl_depends = { "luci-app-gost" }
entry({"admin", "services", "gost", "status"},call("act_status")).leaf=true
end
-1
View File
@@ -1 +0,0 @@
zh_Hans
@@ -1,11 +0,0 @@
{
"luci-app-gost": {
"description": "Grant UCI access for luci-app-gost",
"read": {
"uci": [ "gost" ]
},
"write": {
"uci": [ "gost" ]
}
}
}
+1 -1
View File
@@ -34,7 +34,7 @@ require (
github.com/sagernet/sing-shadowsocks v0.2.7
github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-tun v0.4.0-rc.3
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b
github.com/sagernet/sing-vmess v0.1.12
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/utls v1.6.7
+2 -2
View File
@@ -129,8 +129,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.4.0-rc.3 h1:W/Odc87dGXkRhwRo2jhsKYHypNbajIcsGlIzDatmMKA=
github.com/sagernet/sing-tun v0.4.0-rc.3/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM=
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b h1:a2VWOxv7uvIThhJyW6bB+D+bciLSkkqzq4bC4yg3U0g=
github.com/sagernet/sing-tun v0.4.0-rc.3.0.20241014141023-07278fb4705b/go.mod h1:+lQdWhqD4atzrCgRhoyrxBCg1OBru/hAv2BT3kdgmGM=
github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEYAYAPg=
github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
+1 -1
View File
@@ -2,7 +2,7 @@ include $(TOPDIR)/rules.mk
PKG_NAME:=luci-app-ssr-plus
PKG_VERSION:=188
PKG_RELEASE:=7
PKG_RELEASE:=8
PKG_CONFIG_DEPENDS:= \
CONFIG_PACKAGE_$(PKG_NAME)_INCLUDE_NONE_V2RAY \
@@ -109,6 +109,10 @@ o:depends("shunt_dns_mode", "2")
o.rmempty = false
o.default = "0"
o = s:option(Flag, "apple_optimization", translate("Apple domains optimization"), translate("For Apple domains equipped with Chinese mainland CDN, always responsive to Chinese CDN IP addresses"))
o.rmempty = false
o.default = "1"
o = s:option(Flag, "adblock", translate("Enable adblock"))
o.rmempty = false
@@ -927,7 +927,6 @@ if is_finded("xray") then
o:value(v, translate(v))
end
o.rmempty = true
o:depends("xtls", true)
o:depends({type = "v2ray", v2ray_protocol = "vless", transport = "tcp", tls = true})
o:depends({type = "v2ray", v2ray_protocol = "vless", transport = "tcp", reality = true})
@@ -134,7 +134,7 @@ o.description = translate("Custom DNS Server for mosdns")
o = s:option(Flag, "mosdns_ipv6", translate("Disable IPv6 in MOSDNS query mode"))
o:depends("pdnsd_enable", "3")
o.rmempty = false
o.default = "0"
o.default = "1"
if is_finded("chinadns-ng") then
o = s:option(Value, "chinadns_forward", translate("Domestic DNS Server"))
@@ -459,6 +459,12 @@ msgstr "切换检查超时时间(秒)"
msgid "Check Try Count"
msgstr "切换检查重试次数"
msgid "Apple domains optimization"
msgstr "Apple 域名解析优化"
msgid "For Apple domains equipped with Chinese mainland CDN, always responsive to Chinese CDN IP addresses"
msgstr "配备中国大陆 CDN 的 Apple 域名,始终应答中国大陆 CDN 地址"
msgid "Enable adblock"
msgstr "启用广告屏蔽"
@@ -246,6 +246,12 @@ start_dns() {
fi
fi
fi
if [ "$(uci_get_by_type global apple_optimization 1)" == "1" ]; then
echolog "Apple 域名中国大陆 CDN 的 优化规则正在加载。"
cp -f /etc/ssrplus/applechina.conf $TMP_DNSMASQ_PATH/
echolog "Apple 域名中国大陆 CDN 的 优化规则加载完毕。"
fi
}
gen_service_file() { #1-server.type 2-cfgname 3-file_path
@@ -0,0 +1,173 @@
server=/a1.mzstatic.com/114.114.114.114
server=/a2.mzstatic.com/114.114.114.114
server=/a3.mzstatic.com/114.114.114.114
server=/a4.mzstatic.com/114.114.114.114
server=/a5.mzstatic.com/114.114.114.114
server=/adcdownload.apple.com.akadns.net/114.114.114.114
server=/adcdownload.apple.com/114.114.114.114
server=/amp-api-updates.apps.apple.com/114.114.114.114
server=/amp-api.media.apple.com/114.114.114.114
server=/api-p-ap-c.smoot.apple.com/114.114.114.114
server=/api-p-ap-d.smoot.apple.com/114.114.114.114
server=/api-p-ap-e.smoot.apple.com/114.114.114.114
server=/app-site-association.cdn-apple.com/114.114.114.114
server=/appldnld.apple.com/114.114.114.114
server=/appldnld.g.aaplimg.com/114.114.114.114
server=/appleid.cdn-apple.com/114.114.114.114
server=/apps.apple.com/114.114.114.114
server=/apps.mzstatic.com/114.114.114.114
server=/bag-cdn.itunes-apple.com.akadns.net/114.114.114.114
server=/cdn-cn1.apple-mapkit.com/114.114.114.114
server=/cdn-cn2.apple-mapkit.com/114.114.114.114
server=/cdn-cn3.apple-mapkit.com/114.114.114.114
server=/cdn-cn4.apple-mapkit.com/114.114.114.114
server=/cdn.apple-mapkit.com/114.114.114.114
server=/cdn1.apple-mapkit.com/114.114.114.114
server=/cdn2.apple-mapkit.com/114.114.114.114
server=/cdn3.apple-mapkit.com/114.114.114.114
server=/cdn4.apple-mapkit.com/114.114.114.114
server=/cds-cdn.v.aaplimg.com/114.114.114.114
server=/cds.apple.com.akadns.net/114.114.114.114
server=/cds.apple.com/114.114.114.114
server=/cdsassets.apple.com/114.114.114.114
server=/cl1-cdn.origin-apple.com.akadns.net/114.114.114.114
server=/cl1.apple.com/114.114.114.114
server=/cl2-cn.apple.com/114.114.114.114
server=/cl2.apple.com/114.114.114.114
server=/cl3-cdn.origin-apple.com.akadns.net/114.114.114.114
server=/cl3.apple.com/114.114.114.114
server=/cl4-cdn.origin-apple.com.akadns.net/114.114.114.114
server=/cl4-cn.apple.com/114.114.114.114
server=/cl4.apple.com/114.114.114.114
server=/cl5-cdn.origin-apple.com.akadns.net/114.114.114.114
server=/cl5.apple.com/114.114.114.114
server=/clientflow.apple.com.akadns.net/114.114.114.114
server=/clientflow.apple.com/114.114.114.114
server=/cn-smp-paymentservices.apple.com/114.114.114.114
server=/configuration.apple.com.akadns.net/114.114.114.114
server=/configuration.apple.com/114.114.114.114
server=/crl.apple.com/114.114.114.114
server=/cstat.apple.com/114.114.114.114
server=/cstat.cdn-apple.com/114.114.114.114
server=/dd-cdn.origin-apple.com.akadns.net/114.114.114.114
server=/dejavu.apple.com/114.114.114.114
server=/devstreaming-cdn.apple.com/114.114.114.114
server=/download.developer.apple.com/114.114.114.114
server=/experiments.apple.com/114.114.114.114
server=/gs-loc-cn.apple.com/114.114.114.114
server=/gs-loc.apple.com/114.114.114.114
server=/gsp10-ssl-cn.ls.apple.com/114.114.114.114
server=/gsp12-cn.ls.apple.com/114.114.114.114
server=/gsp13-cn.ls.apple.com/114.114.114.114
server=/gsp4-cn.ls.apple.com.edgekey.net.globalredir.akadns.net/114.114.114.114
server=/gsp4-cn.ls.apple.com.edgekey.net/114.114.114.114
server=/gsp4-cn.ls.apple.com/114.114.114.114
server=/gsp5-cn.ls.apple.com/114.114.114.114
server=/gsp85-cn-ssl.ls.apple.com/114.114.114.114
server=/gspe19-2-cn-ssl.ls-apple.com.akadns.net/114.114.114.114
server=/gspe19-2-cn-ssl.ls.apple.com/114.114.114.114
server=/gspe19-cn-ssl.ls.apple.com/114.114.114.114
server=/gspe19-cn.ls-apple.com.akadns.net/114.114.114.114
server=/gspe19-cn.ls.apple.com/114.114.114.114
server=/gspe21-ssl.ls.apple.com/114.114.114.114
server=/gspe21.ls.apple.com/114.114.114.114
server=/gspe35-ssl.ls.apple.com/114.114.114.114
server=/gspe79-cn-ssl.ls.apple.com/114.114.114.114
server=/guzzoni-apple-com.v.aaplimg.com/114.114.114.114
server=/guzzoni.apple.com/114.114.114.114
server=/guzzoni.smoot.apple.com/114.114.114.114
server=/iadsdk.apple.com/114.114.114.114
server=/icloud-cdn.icloud.com.akadns.net/114.114.114.114
server=/icloud.cdn-apple.com/114.114.114.114
server=/images.apple.com.akadns.net/114.114.114.114
server=/images.apple.com.edgekey.net.globalredir.akadns.net/114.114.114.114
server=/images.apple.com/114.114.114.114
server=/init-kt.apple.com/114.114.114.114
server=/init-p01md-lb.push-apple.com.akadns.net/114.114.114.114
server=/init-p01md.apple.com/114.114.114.114
server=/init-p01st-lb.push-apple.com.akadns.net/114.114.114.114
server=/init-p01st.push.apple.com/114.114.114.114
server=/init-s01st-lb.push-apple.com.akadns.net/114.114.114.114
server=/init-s01st.push.apple.com/114.114.114.114
server=/init.ess.apple.com/114.114.114.114
server=/iosapps.itunes.g.aaplimg.com/114.114.114.114
server=/ipcdn.apple.com/114.114.114.114
server=/iphone-ld.apple.com/114.114.114.114
server=/iphone-ld.origin-apple.com.akadns.net/114.114.114.114
server=/is-ssl.mzstatic.com-cn-lb.itunes-apple.com.akadns.net/114.114.114.114
server=/is1-ssl.mzstatic.com/114.114.114.114
server=/is1.mzstatic.com/114.114.114.114
server=/is2-ssl.mzstatic.com/114.114.114.114
server=/is2.mzstatic.com/114.114.114.114
server=/is3-ssl.mzstatic.com/114.114.114.114
server=/is3.mzstatic.com/114.114.114.114
server=/is4-ssl.mzstatic.com/114.114.114.114
server=/is4.mzstatic.com/114.114.114.114
server=/is5-ssl.mzstatic.com/114.114.114.114
server=/is5.mzstatic.com/114.114.114.114
server=/itunes-apple.com.akadns.net/114.114.114.114
server=/itunes.apple.com/114.114.114.114
server=/itunesconnect.apple.com/114.114.114.114
server=/mesu-cdn.apple.com.akadns.net/114.114.114.114
server=/mesu-china.apple.com.akadns.net/114.114.114.114
server=/mesu.apple.com/114.114.114.114
server=/ml.cdn-apple.com/114.114.114.114
server=/music.apple.com/114.114.114.114
server=/ocsp-lb.apple.com.akadns.net/114.114.114.114
server=/ocsp.apple.com/114.114.114.114
server=/ocsp2-lb.apple.com.akadns.net/114.114.114.114
server=/ocsp2.apple.com/114.114.114.114
server=/oscdn.apple.com/114.114.114.114
server=/oscdn.origin-apple.com.akadns.net/114.114.114.114
server=/osxapps.itunes.g.aaplimg.com/114.114.114.114
server=/pancake.apple.com/114.114.114.114
server=/pancake.cdn-apple.com.akadns.net/114.114.114.114
server=/pba0.apple.com/114.114.114.114
server=/probe.siri.apple.com/114.114.114.114
server=/prod-support.apple-support.akadns.net/114.114.114.114
server=/publicassets.cdn-apple.com/114.114.114.114
server=/reserve-prime.apple.com/114.114.114.114
server=/s.mzstatic.com/114.114.114.114
server=/seed-sequoia.siri.apple.com/114.114.114.114
server=/seed-swallow.siri.apple.com/114.114.114.114
server=/seed.siri.apple.com/114.114.114.114
server=/sequoia.apple.com/114.114.114.114
server=/sh-pod2-smp-device.apple.com/114.114.114.114
server=/shazam-insights.cdn-apple.com/114.114.114.114
server=/smp-device-content.apple.com/114.114.114.114
server=/static.gc.apple.com/114.114.114.114
server=/stocks-sparkline-lb.apple.com.akadns.net/114.114.114.114
server=/stocks-sparkline.apple.com/114.114.114.114
server=/store.apple.com.edgekey.net.globalredir.akadns.net/114.114.114.114
server=/store.apple.com.edgekey.net/114.114.114.114
server=/store.apple.com/114.114.114.114
server=/store.storeimages.apple.com.akadns.net/114.114.114.114
server=/store.storeimages.cdn-apple.com/114.114.114.114
server=/support-china.apple-support.akadns.net/114.114.114.114
server=/support.apple.com/114.114.114.114
server=/swallow-apple-com.v.aaplimg.com/114.114.114.114
server=/swallow.apple.com/114.114.114.114
server=/swcatalog-cdn.apple.com.akadns.net/114.114.114.114
server=/swcatalog.apple.com/114.114.114.114
server=/swcdn.apple.com/114.114.114.114
server=/swcdn.g.aaplimg.com/114.114.114.114
server=/swdist.apple.com.akadns.net/114.114.114.114
server=/swdist.apple.com/114.114.114.114
server=/swscan-cdn.apple.com.akadns.net/114.114.114.114
server=/swscan.apple.com/114.114.114.114
server=/sylvan.apple.com/114.114.114.114
server=/tj-pod1-smp-device.apple.com/114.114.114.114
server=/updates-http.cdn-apple.com.akadns.net/114.114.114.114
server=/updates-http.cdn-apple.com/114.114.114.114
server=/updates.cdn-apple.com/114.114.114.114
server=/valid.apple.com/114.114.114.114
server=/valid.origin-apple.com.akadns.net/114.114.114.114
server=/weather-data.apple.com.akadns.net/114.114.114.114
server=/weather-data.apple.com/114.114.114.114
server=/weather-map.apple.com/114.114.114.114
server=/weather-map2.apple.com/114.114.114.114
server=/weatherkit.apple.com/114.114.114.114
server=/www.apple.com.edgekey.net.globalredir.akadns.net/114.114.114.114
server=/www.apple.com.edgekey.net/114.114.114.114
server=/www.apple.com/114.114.114.114
server=/xp.apple.com/114.114.114.114
@@ -362,10 +362,9 @@ local function processData(szType, content)
result.vmess_id = url.user
result.vless_encryption = params.encryption or "none"
result.transport = params.type or "tcp"
result.tls = (params.security == "tls") and "1" or "0"
result.tls = (params.security == "tls" or params.security == "xtls") and "1" or "0"
result.tls_host = params.sni
result.xtls = (params.security == "xtls") and "1" or nil
result.tls_flow = (result.tls == "1" or result.xtls == "1" or result.reality == "1") and params.flow or nil
result.tls_flow = (params.security == "tls" or params.security == "reality") and params.flow or nil
result.fingerprint = params.fp
result.reality = (params.security == "reality") and "1" or "0"
result.reality_publickey = params.pbk and UrlDecode(params.pbk) or nil
+2 -2
View File
@@ -5,12 +5,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=v2ray-core
PKG_VERSION:=5.20.0
PKG_VERSION:=5.21.0
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/v2fly/v2ray-core/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=2de8ac3429705f594ca1a75a2a0fca09820938c94e912370902f87bd72680693
PKG_HASH:=880a929caff7b72ef9d3b9a3262cec0dff6566c2481989822a6b27fdaaeed975
PKG_LICENSE:=MIT
PKG_LICENSE_FILES:=LICENSE
+2 -2
View File
@@ -30,13 +30,13 @@ define Download/geosite
HASH:=f820556ed3aa02eb7eadba7a3743d7e6df8e9234785d0d82d2d1edce20fe4b3c
endef
GEOSITE_IRAN_VER:=202410070035
GEOSITE_IRAN_VER:=202410140035
GEOSITE_IRAN_FILE:=iran.dat.$(GEOSITE_IRAN_VER)
define Download/geosite-ir
URL:=https://github.com/bootmortis/iran-hosted-domains/releases/download/$(GEOSITE_IRAN_VER)/
URL_FILE:=iran.dat
FILE:=$(GEOSITE_IRAN_FILE)
HASH:=be31e14b61dc3e98c9ac518686bc932b45aa04dd2f9491d18456417ba28f3b70
HASH:=97d1efd7ce4e5318f9f44039f5945a6253d5a42f7f3b432d3da124703d4cda28
endef
define Package/v2ray-geodata/template
@@ -36,7 +36,7 @@ namespace ServiceLib.Common
}
};
using var downloader = new Downloader.DownloadService(downloadOpt);
await using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadFileCompleted += (sender, value) =>
{
if (value.Error != null)
@@ -46,12 +46,12 @@ namespace ServiceLib.Common
};
using var cts = new CancellationTokenSource();
using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token).WaitAsync(TimeSpan.FromSeconds(timeout), cts.Token);
using StreamReader reader = new(stream);
downloadOpt = null;
return reader.ReadToEnd();
return await reader.ReadToEndAsync(cts.Token);
}
public async Task DownloadDataAsync4Speed(IWebProxy webProxy, string url, IProgress<string> progress, int timeout)
@@ -72,11 +72,11 @@ namespace ServiceLib.Common
}
};
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
var totalDatetime = DateTime.Now;
var totalSecond = 0;
var hasValue = false;
double maxSpeed = 0;
using var downloader = new Downloader.DownloadService(downloadOpt);
await using var downloader = new Downloader.DownloadService(downloadOpt);
//downloader.DownloadStarted += (sender, value) =>
//{
// if (progress != null)
@@ -86,7 +86,7 @@ namespace ServiceLib.Common
//};
downloader.DownloadProgressChanged += (sender, value) =>
{
TimeSpan ts = (DateTime.Now - totalDatetime);
var ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
hasValue = true;
@@ -112,7 +112,7 @@ namespace ServiceLib.Common
//progress.Report("......");
using var cts = new CancellationTokenSource();
cts.CancelAfter(timeout * 1000);
using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
await using var stream = await downloader.DownloadFileTaskAsync(address: url, cts.Token);
downloadOpt = null;
}
@@ -145,7 +145,7 @@ namespace ServiceLib.Common
var progressPercentage = 0;
var hasValue = false;
using var downloader = new Downloader.DownloadService(downloadOpt);
await using var downloader = new Downloader.DownloadService(downloadOpt);
downloader.DownloadStarted += (sender, value) =>
{
progress?.Report(0);
+12 -12
View File
@@ -23,7 +23,7 @@ namespace ServiceLib.Common
{
try
{
using FileStream fs = File.Create(fileName);
using var fs = File.Create(fileName);
using GZipStream input = new(new MemoryStream(content), CompressionMode.Decompress, false);
input.CopyTo(fs);
}
@@ -38,8 +38,8 @@ namespace ServiceLib.Common
try
{
FileInfo fileInfo = new(fileName);
using FileStream originalFileStream = fileInfo.OpenRead();
using FileStream decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);
using var originalFileStream = fileInfo.OpenRead();
using var decompressedFileStream = File.Create(toName != null ? Path.Combine(toPath, toName) : toPath);
using GZipStream decompressionStream = new(originalFileStream, CompressionMode.Decompress);
decompressionStream.CopyTo(decompressedFileStream);
}
@@ -54,7 +54,7 @@ namespace ServiceLib.Common
return NonExclusiveReadAllText(path, Encoding.Default);
}
public static string NonExclusiveReadAllText(string path, Encoding encoding)
private static string NonExclusiveReadAllText(string path, Encoding encoding)
{
try
{
@@ -73,8 +73,8 @@ namespace ServiceLib.Common
{
try
{
using ZipArchive archive = ZipFile.OpenRead(fileName);
foreach (ZipArchiveEntry entry in archive.Entries)
using var archive = ZipFile.OpenRead(fileName);
foreach (var entry in archive.Entries)
{
if (entry.Length == 0)
{
@@ -110,7 +110,7 @@ namespace ServiceLib.Common
}
try
{
using ZipArchive archive = ZipFile.OpenRead(fileName);
using var archive = ZipFile.OpenRead(fileName);
return archive.Entries.Select(entry => entry.FullName).ToList();
}
catch (Exception ex)
@@ -149,13 +149,13 @@ namespace ServiceLib.Common
throw new DirectoryNotFoundException($"Source directory not found: {dir.FullName}");
// Cache directories before we start copying
DirectoryInfo[] dirs = dir.GetDirectories();
var dirs = dir.GetDirectories();
// Create the destination directory
Directory.CreateDirectory(destinationDir);
// Get the files in the source directory and copy to the destination directory
foreach (FileInfo file in dir.GetFiles())
foreach (var file in dir.GetFiles())
{
if (Utils.IsNotEmpty(ignoredName) && file.Name.Contains(ignoredName))
{
@@ -165,16 +165,16 @@ namespace ServiceLib.Common
{
continue;
}
string targetFilePath = Path.Combine(destinationDir, file.Name);
var targetFilePath = Path.Combine(destinationDir, file.Name);
file.CopyTo(targetFilePath);
}
// If recursive and copying subdirectories, recursively call this method
if (recursive)
{
foreach (DirectoryInfo subDir in dirs)
foreach (var subDir in dirs)
{
string newDestinationDir = Path.Combine(destinationDir, subDir.Name);
var newDestinationDir = Path.Combine(destinationDir, subDir.Name);
CopyDirectory(subDir.FullName, newDestinationDir, true, ignoredName);
}
}
@@ -27,7 +27,7 @@ namespace ServiceLib.Common
try
{
HttpResponseMessage response = await httpClient.GetAsync(url);
var response = await httpClient.GetAsync(url);
return await response.Content.ReadAsStringAsync();
}
catch
@@ -84,8 +84,8 @@ namespace ServiceLib.Common
var total = response.Content.Headers.ContentLength ?? -1L;
var canReportProgress = total != -1 && progress != null;
using var stream = await response.Content.ReadAsStreamAsync(token);
using var file = File.Create(fileName);
await using var stream = await response.Content.ReadAsStreamAsync(token);
await using var file = File.Create(fileName);
var totalRead = 0L;
var buffer = new byte[1024 * 1024];
var progressPercentage = 0;
@@ -98,7 +98,7 @@ namespace ServiceLib.Common
totalRead += read;
if (read == 0) break;
file.Write(buffer, 0, read);
await file.WriteAsync(buffer, 0, read, token);
if (canReportProgress)
{
@@ -133,13 +133,13 @@ namespace ServiceLib.Common
//var total = response.Content.Headers.ContentLength.HasValue ? response.Content.Headers.ContentLength.Value : -1L;
//var canReportProgress = total != -1 && progress != null;
using var stream = await response.Content.ReadAsStreamAsync(token);
await using var stream = await response.Content.ReadAsStreamAsync(token);
var totalRead = 0L;
var buffer = new byte[1024 * 64];
var isMoreToRead = true;
string progressSpeed = string.Empty;
DateTime totalDatetime = DateTime.Now;
int totalSecond = 0;
var progressSpeed = string.Empty;
var totalDatetime = DateTime.Now;
var totalSecond = 0;
do
{
@@ -168,7 +168,7 @@ namespace ServiceLib.Common
totalRead += read;
TimeSpan ts = (DateTime.Now - totalDatetime);
var ts = (DateTime.Now - totalDatetime);
if (progress != null && ts.Seconds > totalSecond)
{
totalSecond = ts.Seconds;
+2 -2
View File
@@ -8,7 +8,7 @@ namespace ServiceLib.Common
* http://stackoverflow.com/questions/6266820/working-example-of-createjobobject-setinformationjobobject-pinvoke-in-net
*/
public class Job : IDisposable
public sealed class Job : IDisposable
{
private IntPtr handle = IntPtr.Zero;
@@ -73,7 +73,7 @@ namespace ServiceLib.Common
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
private void Dispose(bool disposing)
{
if (disposed) return;
disposed = true;
+2 -2
View File
@@ -69,7 +69,7 @@ namespace ServiceLib.Common
/// <returns></returns>
public static string Serialize(object? obj, bool indented = true)
{
string result = string.Empty;
var result = string.Empty;
try
{
if (obj == null)
@@ -112,7 +112,7 @@ namespace ServiceLib.Common
}
try
{
using FileStream file = File.Create(filePath);
using var file = File.Create(filePath);
var options = new JsonSerializerOptions
{
@@ -7,7 +7,7 @@ namespace ServiceLib.Common
public static byte[]? GenQRCode(string? url)
{
using QRCodeGenerator qrGenerator = new();
using QRCodeData qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
using var qrCodeData = qrGenerator.CreateQrCode(url ?? string.Empty, QRCodeGenerator.ECCLevel.Q);
using PngByteQRCode qrCode = new(qrCodeData);
return qrCode.GetGraphic(20);
}
@@ -17,7 +17,7 @@ namespace ServiceLib.Common
private static IOrderedQueryable<T> _OrderBy<T>(IQueryable<T> query, string propertyName, bool isDesc)
{
string methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
var methodname = (isDesc) ? "OrderByDescendingInternal" : "OrderByInternal";
var memberProp = typeof(T).GetProperty(propertyName);
@@ -28,14 +28,14 @@
}
this.version = version.RemovePrefix('v');
string[] parts = this.version.Split('.');
var parts = this.version.Split('.');
if (parts.Length == 2)
{
this.major = int.Parse(parts[0]);
this.minor = int.Parse(parts[1]);
this.patch = 0;
}
else if (parts.Length == 3 || parts.Length == 4)
else if (parts.Length is 3 or 4)
{
this.major = int.Parse(parts[0]);
this.minor = int.Parse(parts[1]);
@@ -11,7 +11,7 @@ namespace ServiceLib.Common
private SQLiteConnection _db;
private SQLiteAsyncConnection _dbAsync;
private static readonly object objLock = new();
public readonly string _configDB = "guiNDB.db";
private readonly string _configDB = "guiNDB.db";
public SQLiteHelper()
{
+7 -33
View File
@@ -25,21 +25,14 @@ namespace ServiceLib.Common
return chars.Contains(s[0]);
}
public static bool IsWhiteSpace(this string value)
private static bool IsWhiteSpace(this string value)
{
foreach (char c in value)
{
if (char.IsWhiteSpace(c)) continue;
return false;
}
return true;
return value.All(char.IsWhiteSpace);
}
public static IEnumerable<string> NonWhiteSpaceLines(this TextReader reader)
{
string? line;
while ((line = reader.ReadLine()) != null)
while (reader.ReadLine() is { } line)
{
if (line.IsWhiteSpace()) continue;
yield return line;
@@ -53,26 +46,12 @@ namespace ServiceLib.Common
public static string RemovePrefix(this string value, char prefix)
{
if (value.StartsWith(prefix))
{
return value.Substring(1);
}
else
{
return value;
}
return value.StartsWith(prefix) ? value[1..] : value;
}
public static string RemovePrefix(this string value, string prefix)
{
if (value.StartsWith(prefix))
{
return value.Substring(prefix.Length);
}
else
{
return value;
}
return value.StartsWith(prefix) ? value[prefix.Length..] : value;
}
public static string UpperFirstChar(this string value)
@@ -82,17 +61,12 @@ namespace ServiceLib.Common
return string.Empty;
}
return char.ToUpper(value[0]) + value.Substring(1);
return char.ToUpper(value[0]) + value[1..];
}
public static string AppendQuotes(this string value)
{
if (string.IsNullOrEmpty(value))
{
return string.Empty;
}
return $"\"{value}\"";
return string.IsNullOrEmpty(value) ? string.Empty : $"\"{value}\"";
}
}
}
+104 -221
View File
@@ -2,7 +2,6 @@
using CliWrap.Buffered;
using System.Collections.Specialized;
using System.Diagnostics;
using System.IO.Compression;
using System.Net;
using System.Net.NetworkInformation;
using System.Net.Sockets;
@@ -11,13 +10,12 @@ using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Security.Principal;
using System.Text;
using System.Text.RegularExpressions;
namespace ServiceLib.Common
{
public class Utils
{
#region Json操作
#region
/// <summary>
/// 获取嵌入文本资源
@@ -26,12 +24,12 @@ namespace ServiceLib.Common
/// <returns></returns>
public static string GetEmbedText(string res)
{
string result = string.Empty;
var result = string.Empty;
try
{
Assembly assembly = Assembly.GetExecutingAssembly();
using Stream? stream = assembly.GetManifestResourceStream(res);
var assembly = Assembly.GetExecutingAssembly();
using var stream = assembly.GetManifestResourceStream(res);
ArgumentNullException.ThrowIfNull(stream);
using StreamReader reader = new(stream);
result = reader.ReadToEnd();
@@ -51,11 +49,10 @@ namespace ServiceLib.Common
{
try
{
if (!File.Exists(res))
if (File.Exists(res))
{
return null;
return File.ReadAllText(res);
}
return File.ReadAllText(res);
}
catch (Exception ex)
{
@@ -64,14 +61,15 @@ namespace ServiceLib.Common
return null;
}
#endregion Json操作
#endregion
#region
/// <summary>
/// List<string>转逗号分隔的字符串
/// 转逗号分隔的字符串
/// </summary>
/// <param name="lst"></param>
/// <param name="wrap"></param>
/// <returns></returns>
public static string List2String(List<string>? lst, bool wrap = false)
{
@@ -93,35 +91,40 @@ namespace ServiceLib.Common
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return string.Empty;
}
return string.Empty;
}
/// <summary>
/// 逗号分隔的字符串,转List<string>
/// 逗号分隔的字符串
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static List<string> String2List(string str)
public static List<string>? String2List(string? str)
{
try
{
if (str == null)
{
return null;
}
str = str.Replace(Environment.NewLine, "");
return new List<string>(str.Split(',', StringSplitOptions.RemoveEmptyEntries));
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return [];
}
return null;
}
/// <summary>
/// 逗号分隔的字符串,先排序后转List<string>
/// 逗号分隔的字符串,先排序后转List
/// </summary>
/// <param name="str"></param>
/// <returns></returns>
public static List<string> String2ListSorted(string str)
public static List<string>? String2ListSorted(string str)
{
try
{
@@ -133,8 +136,8 @@ namespace ServiceLib.Common
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return [];
}
return null;
}
/// <summary>
@@ -146,14 +149,14 @@ namespace ServiceLib.Common
{
try
{
byte[] plainTextBytes = Encoding.UTF8.GetBytes(plainText);
var plainTextBytes = Encoding.UTF8.GetBytes(plainText);
return Convert.ToBase64String(plainTextBytes);
}
catch (Exception ex)
{
Logging.SaveLog("Base64Encode", ex);
return string.Empty;
}
return string.Empty;
}
/// <summary>
@@ -179,30 +182,24 @@ namespace ServiceLib.Common
plainText = plainText.PadRight(plainText.Length + 4 - plainText.Length % 4, '=');
}
byte[] data = Convert.FromBase64String(plainText);
var data = Convert.FromBase64String(plainText);
return Encoding.UTF8.GetString(data);
}
catch (Exception ex)
{
Logging.SaveLog("Base64Decode", ex);
return string.Empty;
}
return string.Empty;
}
/// <summary>
/// 转Int
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static int ToInt(object? obj)
{
try
{
return Convert.ToInt32(obj ?? string.Empty);
}
catch //(Exception ex)
catch
{
//SaveLog(ex.Message, ex);
return 0;
}
}
@@ -213,50 +210,47 @@ namespace ServiceLib.Common
{
return Convert.ToBoolean(obj);
}
catch //(Exception ex)
catch
{
//SaveLog(ex.Message, ex);
return false;
}
}
public static string ToString(object obj)
public static string ToString(object? obj)
{
try
{
return obj?.ToString() ?? string.Empty;
}
catch// (Exception ex)
catch
{
//SaveLog(ex.Message, ex);
return string.Empty;
}
}
/// <summary>
/// byte 转成 有两位小数点的 方便阅读的数据
/// 比如 2.50 MB
/// byte 转成 有两位小数点的 方便阅读的数据 比如 2.50 MB
/// </summary>
/// <param name="amount">bytes</param>
/// <param name="result">转换之后的数据</param>
/// <param name="unit">单位</param>
public static void ToHumanReadable(long amount, out double result, out string unit)
private static void ToHumanReadable(long amount, out double result, out string unit)
{
uint factor = 1024u;
var factor = 1024u;
//long KBs = amount / factor;
long KBs = amount;
var KBs = amount;
if (KBs > 0)
{
// multi KB
long MBs = KBs / factor;
var MBs = KBs / factor;
if (MBs > 0)
{
// multi MB
long GBs = MBs / factor;
var GBs = MBs / factor;
if (GBs > 0)
{
// multi GB
long TBs = GBs / factor;
var TBs = GBs / factor;
if (TBs > 0)
{
result = TBs + ((GBs % factor) / (factor + 0.0));
@@ -284,20 +278,18 @@ namespace ServiceLib.Common
public static string HumanFy(long amount)
{
ToHumanReadable(amount, out double result, out string unit);
return $"{string.Format("{0:f1}", result)} {unit}";
ToHumanReadable(amount, out var result, out var unit);
return $"{result:f1} {unit}";
}
public static string UrlEncode(string url)
{
return Uri.EscapeDataString(url);
//return HttpUtility.UrlEncode(url);
}
public static string UrlDecode(string url)
{
return Uri.UnescapeDataString(url);
//return HttpUtility.UrlDecode(url);
}
public static NameValueCollection ParseQueryString(string query)
@@ -308,10 +300,10 @@ namespace ServiceLib.Common
return result;
}
var parts = query[1..].Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries);
var parts = query[1..].Split('&', StringSplitOptions.RemoveEmptyEntries);
foreach (var part in parts)
{
var keyValue = part.Split(['=']);
var keyValue = part.Split('=');
if (keyValue.Length != 2)
{
continue;
@@ -328,12 +320,12 @@ namespace ServiceLib.Common
return result;
}
public static string GetMD5(string str)
public static string GetMd5(string str)
{
byte[] byteOld = Encoding.UTF8.GetBytes(str);
byte[] byteNew = MD5.HashData(byteOld);
var byteOld = Encoding.UTF8.GetBytes(str);
var byteNew = MD5.HashData(byteOld);
StringBuilder sb = new(32);
foreach (byte b in byteNew)
foreach (var b in byteNew)
{
sb.Append(b.ToString("x2"));
}
@@ -373,12 +365,12 @@ namespace ServiceLib.Common
{
if (plainText.IsNullOrEmpty()) return false;
var buffer = new Span<byte>(new byte[plainText.Length]);
return Convert.TryFromBase64String(plainText, buffer, out int _);
return Convert.TryFromBase64String(plainText, buffer, out var _);
}
public static string Convert2Comma(string text)
{
if (Utils.IsNullOrEmpty(text))
if (IsNullOrEmpty(text))
{
return text;
}
@@ -396,16 +388,7 @@ namespace ServiceLib.Common
/// <returns></returns>
public static bool IsNumeric(string oText)
{
try
{
int var1 = ToInt(oText);
return true;
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return false;
}
return oText.All(char.IsNumber);
}
public static bool IsNullOrEmpty(string? text)
@@ -414,11 +397,7 @@ namespace ServiceLib.Common
{
return true;
}
if (text == "null")
{
return true;
}
return false;
return text == "null";
}
public static bool IsNotEmpty(string? text)
@@ -426,41 +405,6 @@ namespace ServiceLib.Common
return !string.IsNullOrEmpty(text);
}
/// <summary>
/// 验证IP地址是否合法
/// </summary>
/// <param name="ip"></param>
public static bool IsIP(string ip)
{
//如果为空
if (IsNullOrEmpty(ip))
{
return false;
}
//清除要验证字符串中的空格
//ip = ip.TrimEx();
//可能是CIDR
if (ip.IndexOf(@"/") > 0)
{
string[] cidr = ip.Split('/');
if (cidr.Length == 2)
{
if (!IsNumeric(cidr[0]))
{
return false;
}
ip = cidr[0];
}
}
//模式字符串
string pattern = @"^((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)$";
//验证
return IsMatch(ip, pattern);
}
/// <summary>
/// 验证Domain地址是否合法
/// </summary>
@@ -476,19 +420,9 @@ namespace ServiceLib.Common
return Uri.CheckHostName(domain) == UriHostNameType.Dns;
}
/// <summary>
/// 验证输入字符串是否与模式字符串匹配,匹配返回true
/// </summary>
/// <param name="input">输入字符串</param>
/// <param name="pattern">模式字符串</param>
public static bool IsMatch(string input, string pattern)
{
return Regex.IsMatch(input, pattern, RegexOptions.IgnoreCase);
}
public static bool IsIpv6(string ip)
{
if (IPAddress.TryParse(ip, out IPAddress? address))
if (IPAddress.TryParse(ip, out var address))
{
return address.AddressFamily switch
{
@@ -504,43 +438,20 @@ namespace ServiceLib.Common
#region
public static void SetSecurityProtocol(bool enableSecurityProtocolTls13)
private static bool PortInUse(int port)
{
if (enableSecurityProtocolTls13)
{
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
}
else
{
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
}
ServicePointManager.DefaultConnectionLimit = 256;
}
public static bool PortInUse(int port)
{
bool inUse = false;
try
{
IPGlobalProperties ipProperties = IPGlobalProperties.GetIPGlobalProperties();
IPEndPoint[] ipEndPoints = ipProperties.GetActiveTcpListeners();
var lstIpEndPoints = new List<IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
foreach (IPEndPoint endPoint in ipEndPoints)
{
if (endPoint.Port == port)
{
inUse = true;
break;
}
}
var ipProperties = IPGlobalProperties.GetIPGlobalProperties();
var ipEndPoints = ipProperties.GetActiveTcpListeners();
//var lstIpEndPoints = new List<IPEndPoint>(IPGlobalProperties.GetIPGlobalProperties().GetActiveTcpListeners());
return ipEndPoints.Any(endPoint => endPoint.Port == port);
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
}
return inUse;
return false;
}
public static int GetFreePort(int defaultPort = 9090)
@@ -554,7 +465,7 @@ namespace ServiceLib.Common
TcpListener l = new(IPAddress.Loopback, 0);
l.Start();
int port = ((IPEndPoint)l.LocalEndpoint).Port;
var port = ((IPEndPoint)l.LocalEndpoint).Port;
l.Stop();
return port;
}
@@ -578,23 +489,18 @@ namespace ServiceLib.Common
{
if (blFull)
{
return string.Format("{0} - V{1} - {2}",
Global.AppName,
GetVersionInfo(),
File.GetLastWriteTime(GetExePath()).ToString("yyyy/MM/dd"));
return $"{Global.AppName} - V{GetVersionInfo()} - {File.GetLastWriteTime(GetExePath()):yyyy/MM/dd}";
}
else
{
return string.Format("{0}/{1}",
Global.AppName,
GetVersionInfo());
return $"{Global.AppName}/{GetVersionInfo()}";
}
}
catch (Exception ex)
{
Logging.SaveLog(ex.Message, ex);
return Global.AppName;
}
return Global.AppName;
}
public static string GetVersionInfo()
@@ -614,7 +520,7 @@ namespace ServiceLib.Common
/// 取得GUID
/// </summary>
/// <returns></returns>
public static string GetGUID(bool full = true)
public static string GetGuid(bool full = true)
{
try
{
@@ -634,14 +540,6 @@ namespace ServiceLib.Common
return string.Empty;
}
public static string GetDownloadFileName(string url)
{
var fileName = Path.GetFileName(url);
fileName += "_temp";
return fileName;
}
public static bool IsGuidByParse(string strSrc)
{
return Guid.TryParse(strSrc, out _);
@@ -667,12 +565,12 @@ namespace ServiceLib.Common
public static Dictionary<string, string> GetSystemHosts()
{
var systemHosts = new Dictionary<string, string>();
var hostfile = @"C:\Windows\System32\drivers\etc\hosts";
var hostFile = @"C:\Windows\System32\drivers\etc\hosts";
try
{
if (File.Exists(hostfile))
if (File.Exists(hostFile))
{
var hosts = File.ReadAllText(hostfile).Replace("\r", "");
var hosts = File.ReadAllText(hostFile).Replace("\r", "");
var hostsList = hosts.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var host in hostsList)
@@ -693,10 +591,10 @@ namespace ServiceLib.Common
public static async Task<string?> GetCliWrapOutput(string filePath, string? arg)
{
return await GetCliWrapOutput(filePath, arg != null ? [arg] : null);
return await GetCliWrapOutput(filePath, arg != null ? new List<string>() { arg } : null);
}
public static async Task<string?> GetCliWrapOutput(string filePath, IEnumerable<string>? args)
private static async Task<string?> GetCliWrapOutput(string filePath, IEnumerable<string>? args)
{
try
{
@@ -736,7 +634,7 @@ namespace ServiceLib.Common
/// <returns></returns>
public static string GetPath(string fileName)
{
string startupPath = StartupPath();
var startupPath = StartupPath();
if (IsNullOrEmpty(fileName))
{
return startupPath;
@@ -760,113 +658,104 @@ namespace ServiceLib.Common
public static string GetTempPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiTemps");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "guiTemps");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
if (IsNullOrEmpty(filename))
{
return _tempPath;
return tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
}
public static string UnGzip(byte[] buf)
{
using MemoryStream sb = new();
using GZipStream input = new(new MemoryStream(buf), CompressionMode.Decompress, false);
input.CopyTo(sb);
sb.Position = 0;
return new StreamReader(sb, Encoding.UTF8).ReadToEnd();
}
public static string GetBackupPath(string filename)
{
string _tempPath = Path.Combine(StartupPath(), "guiBackups");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "guiBackups");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
public static string GetConfigPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiConfigs");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "guiConfigs");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return _tempPath;
return tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
}
public static string GetBinPath(string filename, string? coreType = null)
{
string _tempPath = Path.Combine(StartupPath(), "bin");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "bin");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
if (coreType != null)
{
_tempPath = Path.Combine(_tempPath, coreType.ToString());
if (!Directory.Exists(_tempPath))
tempPath = Path.Combine(tempPath, coreType.ToString());
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
}
if (Utils.IsNullOrEmpty(filename))
if (IsNullOrEmpty(filename))
{
return _tempPath;
return tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
}
public static string GetLogPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiLogs");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "guiLogs");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return _tempPath;
return tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
}
public static string GetFontsPath(string filename = "")
{
string _tempPath = Path.Combine(StartupPath(), "guiFonts");
if (!Directory.Exists(_tempPath))
var tempPath = Path.Combine(StartupPath(), "guiFonts");
if (!Directory.Exists(tempPath))
{
Directory.CreateDirectory(_tempPath);
Directory.CreateDirectory(tempPath);
}
if (Utils.IsNullOrEmpty(filename))
{
return _tempPath;
return tempPath;
}
else
{
return Path.Combine(_tempPath, filename);
return Path.Combine(tempPath, filename);
}
}
@@ -882,14 +771,7 @@ namespace ServiceLib.Common
public static string GetExeName(string name)
{
if (IsWindows())
{
return $"{name}.exe";
}
else
{
return name;
}
return IsWindows() ? $"{name}.exe" : name;
}
public static bool IsAdministrator()
@@ -901,7 +783,7 @@ namespace ServiceLib.Common
else
{
var id = GetLinuxUserId().Result ?? "1000";
if (int.TryParse(id, out int userId))
if (int.TryParse(id, out var userId))
{
return userId == 0;
}
@@ -914,7 +796,8 @@ namespace ServiceLib.Common
private static async Task<string?> GetLinuxUserId()
{
return await GetCliWrapOutput("/bin/bash", ["-c", "id -u"]);
var arg = new List<string>() { "-c", "id -u" };
return await GetCliWrapOutput("/bin/bash", arg);
}
#endregion Platform
+3 -3
View File
@@ -21,7 +21,7 @@ namespace ServiceLib.Common
.Build();
try
{
T obj = deserializer.Deserialize<T>(str);
var obj = deserializer.Deserialize<T>(str);
return obj;
}
catch (Exception ex)
@@ -36,9 +36,9 @@ namespace ServiceLib.Common
/// </summary>
/// <param name="obj"></param>
/// <returns></returns>
public static string ToYaml(Object? obj)
public static string ToYaml(object? obj)
{
string result = string.Empty;
var result = string.Empty;
if (obj == null)
{
return result;
+5
View File
@@ -114,6 +114,11 @@
@"http://www.msftconnecttest.com/connecttest.txt",
};
public static readonly List<string> GeoFilesSources = new() {
GeoUrl,
@"https://github.com/runetfreedom/russia-v2ray-rules-dat/releases/latest/download/{0}.dat",
};
public static readonly Dictionary<string, string> UserAgentTexts = new()
{
{"chrome","Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36" },
@@ -2,11 +2,14 @@
{
public sealed class AppHandler
{
#region Property
private static readonly Lazy<AppHandler> _instance = new(() => new());
private Config _config;
private int? _statePort;
private int? _statePort2;
private Job? _processJob;
private bool? _isAdministrator;
public static AppHandler Instance => _instance.Value;
public Config Config => _config;
@@ -28,6 +31,17 @@
}
}
public bool IsAdministrator
{
get
{
_isAdministrator ??= Utils.IsAdministrator();
return _isAdministrator.Value;
}
}
#endregion Property
#region Init
public AppHandler()
@@ -1,6 +1,5 @@
using System.Data;
using System.Text.RegularExpressions;
using System.Web;
namespace ServiceLib.Handler
{
@@ -494,7 +493,7 @@ namespace ServiceLib.Handler
return -1;
}
var ext = Path.GetExtension(fileName);
string newFileName = $"{Utils.GetGUID()}{ext}";
string newFileName = $"{Utils.GetGuid()}{ext}";
//newFileName = Path.Combine(Utile.GetTempPath(), newFileName);
try
@@ -934,7 +933,7 @@ namespace ServiceLib.Handler
var maxSort = -1;
if (Utils.IsNullOrEmpty(profileItem.indexId))
{
profileItem.indexId = Utils.GetGUID(false);
profileItem.indexId = Utils.GetGuid(false);
maxSort = ProfileExHandler.Instance.GetMaxSort();
}
if (!toFile && maxSort < 0)
@@ -1002,7 +1001,7 @@ namespace ServiceLib.Handler
public static int AddCustomServer4Multiple(Config config, List<ProfileItem> selecteds, ECoreType coreType, out string indexId)
{
indexId = Utils.GetMD5(Global.CoreMultipleLoadConfigFileName);
indexId = Utils.GetMd5(Global.CoreMultipleLoadConfigFileName);
string configPath = Utils.GetConfigPath(Global.CoreMultipleLoadConfigFileName);
if (CoreConfigHandler.GenerateClientMultipleLoadConfig(config, configPath, selecteds, coreType, out string msg) != 0)
{
@@ -1341,7 +1340,7 @@ namespace ServiceLib.Handler
try
{
var uri = new Uri(url);
var queryVars = HttpUtility.ParseQueryString(uri.Query);
var queryVars = Utils.ParseQueryString(uri.Query);
subItem.remarks = queryVars["remarks"] ?? "import_sub";
}
catch (UriFormatException)
@@ -1378,7 +1377,7 @@ namespace ServiceLib.Handler
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
item.id = Utils.GetGuid(false);
if (item.sort <= 0)
{
@@ -1461,7 +1460,7 @@ namespace ServiceLib.Handler
{
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
item.id = Utils.GetGuid(false);
}
if (SQLiteHelper.Instance.Replace(item) > 0)
@@ -1495,14 +1494,14 @@ namespace ServiceLib.Handler
foreach (var item in lstRules)
{
item.id = Utils.GetGUID(false);
item.id = Utils.GetGuid(false);
}
routingItem.ruleNum = lstRules.Count;
routingItem.ruleSet = JsonUtils.Serialize(lstRules, false);
if (Utils.IsNullOrEmpty(routingItem.id))
{
routingItem.id = Utils.GetGUID(false);
routingItem.id = Utils.GetGuid(false);
}
if (SQLiteHelper.Instance.Replace(routingItem) > 0)
@@ -1711,7 +1710,7 @@ namespace ServiceLib.Handler
{
if (Utils.IsNullOrEmpty(item.id))
{
item.id = Utils.GetGUID(false);
item.id = Utils.GetGuid(false);
}
if (SQLiteHelper.Instance.Replace(item) > 0)
@@ -197,7 +197,7 @@ namespace ServiceLib.Handler.Fmt
protected static string WriteAllText(string strData, string ext = "json")
{
var fileName = Utils.GetTempPath($"{Utils.GetGUID(false)}.{ext}");
var fileName = Utils.GetTempPath($"{Utils.GetGuid(false)}.{ext}");
File.WriteAllText(fileName, strData);
return fileName;
}
@@ -70,12 +70,12 @@
item.network = Global.DefaultNetwork;
item.headerType = Global.None;
item.configVersion = Utils.ToInt(vmessQRCode.v);
item.configVersion = vmessQRCode.v;
item.remarks = Utils.ToString(vmessQRCode.ps);
item.address = Utils.ToString(vmessQRCode.add);
item.port = Utils.ToInt(vmessQRCode.port);
item.port = vmessQRCode.port;
item.id = Utils.ToString(vmessQRCode.id);
item.alterId = Utils.ToInt(vmessQRCode.aid);
item.alterId = vmessQRCode.aid;
item.security = Utils.ToString(vmessQRCode.scy);
item.security = Utils.IsNotEmpty(vmessQRCode.scy) ? vmessQRCode.scy : Global.DefaultSecurity;
@@ -140,6 +140,7 @@
{
public string defIEProxyExceptions { get; set; }
public string subConvertUrl { get; set; } = string.Empty;
public string? geoSourceUrl { get; set; }
}
[Serializable]
@@ -58,7 +58,7 @@ namespace ServiceLib.Models
return summary;
}
public List<string> GetAlpn()
public List<string>? GetAlpn()
{
if (Utils.IsNullOrEmpty(alpn))
{
@@ -120,10 +120,10 @@
public string? version { get; set; }
public string? network { get; set; }
public string? packet_encoding { get; set; }
public string[]? local_address { get; set; }
public List<string>? local_address { get; set; }
public string? private_key { get; set; }
public string? peer_public_key { get; set; }
public int[]? reserved { get; set; }
public List<int>? reserved { get; set; }
public int? mtu { get; set; }
public string? plugin { get; set; }
public string? plugin_opts { get; set; }
@@ -138,11 +138,11 @@
public class Tls4Sbox
{
public bool enabled { get; set; }
public string server_name { get; set; }
public string? server_name { get; set; }
public bool? insecure { get; set; }
public List<string> alpn { get; set; }
public Utls4Sbox utls { get; set; }
public Reality4Sbox reality { get; set; }
public List<string>? alpn { get; set; }
public Utls4Sbox? utls { get; set; }
public Reality4Sbox? reality { get; set; }
}
public class Multiplex4Sbox
@@ -647,12 +647,12 @@ namespace ServiceLib.Models
/// <summary>
///
/// </summary>
public string path { get; set; }
public string? path { get; set; }
/// <summary>
///
/// </summary>
public List<string> host { get; set; }
public List<string>? host { get; set; }
}
public class QuicSettings4Ray
+9
View File
@@ -3004,6 +3004,15 @@ namespace ServiceLib.Resx {
}
}
/// <summary>
/// 查找类似 Geo files source (optional) 的本地化字符串。
/// </summary>
public static string TbSettingsGeoFilesSource {
get {
return ResourceManager.GetString("TbSettingsGeoFilesSource", resourceCulture);
}
}
/// <summary>
/// 查找类似 HTTP Port 的本地化字符串。
/// </summary>
+4 -1
View File
@@ -1322,9 +1322,12 @@
<value>Host filter</value>
</data>
<data name="TipActiveServer" xml:space="preserve">
<value>Active</value>
<value>Active</value>
</data>
<data name="menuStorageUI" xml:space="preserve">
<value>Save Interface Layout</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo files source (optional)</value>
</data>
</root>
@@ -1324,4 +1324,7 @@
<data name="menuStorageUI" xml:space="preserve">
<value>保存界面布局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo文件来源(可选)</value>
</data>
</root>
@@ -1204,4 +1204,7 @@
<data name="menuStorageUI" xml:space="preserve">
<value>儲存介面佈局</value>
</data>
<data name="TbSettingsGeoFilesSource" xml:space="preserve">
<value>Geo文件來源(可選)</value>
</data>
</root>
@@ -3,13 +3,13 @@
{
"tag": "remote",
"address": "8.8.8.8",
"strategy": "ipv4_only",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
{
"tag": "local",
"address": "223.5.5.5",
"strategy": "ipv4_only",
"strategy": "prefer_ipv4",
"detour": "direct"
},
{
@@ -3,13 +3,13 @@
{
"tag": "remote",
"address": "8.8.8.8",
"strategy": "ipv4_only",
"strategy": "prefer_ipv4",
"detour": "proxy"
},
{
"tag": "local",
"address": "223.5.5.5",
"strategy": "ipv4_only",
"strategy": "prefer_ipv4",
"detour": "direct"
},
{
@@ -678,8 +678,8 @@ namespace ServiceLib.Services.CoreConfig
{
outbound.private_key = node.id;
outbound.peer_public_key = node.publicKey;
outbound.reserved = Utils.String2List(node.path).Select(int.Parse).ToArray();
outbound.local_address = [.. Utils.String2List(node.requestHost)];
outbound.reserved = Utils.String2List(node.path)?.Select(int.Parse).ToList();
outbound.local_address = Utils.String2List(node.requestHost);
outbound.mtu = Utils.ToInt(node.shortId.IsNullOrEmpty() ? Global.TunMtus.FirstOrDefault() : node.shortId);
break;
}
@@ -732,7 +732,7 @@ namespace ServiceLib.Services.CoreConfig
}
else if (Utils.IsNotEmpty(node.requestHost))
{
server_name = Utils.String2List(node.requestHost)[0];
server_name = Utils.String2List(node.requestHost)?.First();
}
var tls = new Tls4Sbox()
{
@@ -829,7 +829,7 @@ namespace ServiceLib.Services.CoreConfig
}
else if (Utils.IsNotEmpty(host))
{
tlsSettings.serverName = Utils.String2List(host)[0];
tlsSettings.serverName = Utils.String2List(host)?.First();
}
streamSettings.tlsSettings = tlsSettings;
}
@@ -30,7 +30,7 @@ namespace ServiceLib.Services
{
try
{
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var progress = new Progress<string>();
progress.ProgressChanged += (sender, value) =>
@@ -62,7 +62,7 @@ namespace ServiceLib.Services
{
try
{
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
UpdateCompleted?.Invoke(this, new ResultEventArgs(false, $"{ResUI.Downloading} {url}"));
var progress = new Progress<double>();
@@ -92,7 +92,7 @@ namespace ServiceLib.Services
public async Task<string?> UrlRedirectAsync(string url, bool blProxy)
{
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webRequestHandler = new SocketsHttpHandler
{
AllowAutoRedirect = false,
@@ -181,7 +181,7 @@ namespace ServiceLib.Services
{
try
{
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
var client = new HttpClient(new SocketsHttpHandler()
{
@@ -226,7 +226,7 @@ namespace ServiceLib.Services
{
try
{
Utils.SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
SetSecurityProtocol(AppHandler.Instance.Config.guiItem.enableSecurityProtocolTls13);
var webProxy = GetWebProxy(blProxy);
@@ -337,5 +337,18 @@ namespace ServiceLib.Services
return false;
}
}
private static void SetSecurityProtocol(bool enableSecurityProtocolTls13)
{
if (enableSecurityProtocolTls13)
{
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls13;
}
else
{
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12;
}
ServicePointManager.DefaultConnectionLimit = 256;
}
}
}
@@ -56,7 +56,7 @@ namespace ServiceLib.Services
_updateFunc?.Invoke(false, args.Msg);
url = args.Url;
fileName = Utils.GetTempPath(Utils.GetGUID());
fileName = Utils.GetTempPath(Utils.GetGuid());
await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);
}
else
@@ -108,7 +108,7 @@ namespace ServiceLib.Services
url = args.Url;
var ext = Path.GetExtension(url);
fileName = Utils.GetTempPath(Utils.GetGUID() + ext);
fileName = Utils.GetTempPath(Utils.GetGuid() + ext);
await downloadHandle.DownloadFileAsync(url, fileName, true, _timeout);
}
else
@@ -255,8 +255,8 @@ namespace ServiceLib.Services
public async Task UpdateGeoFileAll(Config config, Action<bool, string> updateFunc)
{
await UpdateGeoFile("geosite", _config, updateFunc);
await UpdateGeoFile("geoip", _config, updateFunc);
await UpdateGeoFile("geosite", config, updateFunc);
await UpdateGeoFile("geoip", config, updateFunc);
_updateFunc?.Invoke(true, string.Format(ResUI.MsgDownloadGeoFileSuccessfully, "geo"));
}
@@ -450,8 +450,12 @@ namespace ServiceLib.Services
{
_config = config;
_updateFunc = updateFunc;
var geoUrl = string.IsNullOrEmpty(config?.constItem.geoSourceUrl)
? Global.GeoUrl
: config.constItem.geoSourceUrl;
var url = string.Format(Global.GeoUrl, geoName);
var fileName = Utils.GetTempPath(Utils.GetGUID());
var fileName = Utils.GetTempPath(Utils.GetGuid());
DownloadService downloadHandle = new();
downloadHandle.UpdateCompleted += (sender2, args) =>
@@ -85,7 +85,7 @@ namespace ServiceLib.ViewModels
private async Task RemoteRestore()
{
DisplayOperationMsg();
var fileName = Utils.GetTempPath(Utils.GetGUID());
var fileName = Utils.GetTempPath(Utils.GetGuid());
var result = await WebDavHandler.Instance.GetRawFile(fileName);
if (result)
{
@@ -414,7 +414,7 @@ namespace ServiceLib.ViewModels
var ret = await _updateView?.Invoke(EViewAction.OptionSettingWindow, null);
if (ret == true)
{
Locator.Current.GetService<StatusBarViewModel>()?.InboundDisplayStaus();
Locator.Current.GetService<StatusBarViewModel>()?.InboundDisplayStatus();
Reload();
}
}
@@ -65,6 +65,7 @@ namespace ServiceLib.ViewModels
[Reactive] public bool EnableHWA { get; set; }
[Reactive] public string SubConvertUrl { get; set; }
[Reactive] public int MainGirdOrientation { get; set; }
[Reactive] public string GeoFileSourceUrl { get; set; }
#endregion UI
@@ -164,6 +165,7 @@ namespace ServiceLib.ViewModels
EnableHWA = _config.guiItem.enableHWA;
SubConvertUrl = _config.constItem.subConvertUrl;
MainGirdOrientation = (int)_config.uiItem.mainGirdOrientation;
GeoFileSourceUrl = _config.constItem.geoSourceUrl;
#endregion UI
@@ -316,6 +318,7 @@ namespace ServiceLib.ViewModels
_config.guiItem.enableHWA = EnableHWA;
_config.constItem.subConvertUrl = SubConvertUrl;
_config.uiItem.mainGirdOrientation = (EGirdOrientation)MainGirdOrientation;
_config.constItem.geoSourceUrl = GeoFileSourceUrl;
//systemProxy
_config.systemProxyItem.systemProxyExceptions = systemProxyExceptions;
@@ -34,7 +34,7 @@ namespace ServiceLib.ViewModels
if (rulesItem.id.IsNullOrEmpty())
{
rulesItem.id = Utils.GetGUID(false);
rulesItem.id = Utils.GetGuid(false);
rulesItem.outboundTag = Global.ProxyTag;
rulesItem.enabled = true;
SelectedSource = rulesItem;
@@ -232,7 +232,7 @@ namespace ServiceLib.ViewModels
var item = SelectedRouting;
foreach (var it in _rules)
{
it.id = Utils.GetGUID(false);
it.id = Utils.GetGuid(false);
}
item.ruleNum = _rules.Count;
item.ruleSet = JsonUtils.Serialize(_rules, false);
@@ -322,7 +322,7 @@ namespace ServiceLib.ViewModels
}
foreach (var rule in lstRules)
{
rule.id = Utils.GetGUID(false);
rule.id = Utils.GetGuid(false);
}
if (blReplace)
@@ -10,8 +10,6 @@ namespace ServiceLib.ViewModels
{
public class StatusBarViewModel : MyReactiveObject
{
private bool _isAdministrator { get; set; }
#region ObservableCollection
private IObservableCollection<RoutingItem> _routingItems = new ObservableCollectionExtended<RoutingItem>();
@@ -108,19 +106,16 @@ namespace ServiceLib.ViewModels
public StatusBarViewModel(Func<EViewAction, object?, Task<bool>>? updateView)
{
_config = AppHandler.Instance.Config;
_updateView = updateView;
if (_updateView != null)
if (updateView != null)
{
MessageBus.Current.Listen<string>(EMsgCommand.RefreshProfiles.ToString())
.Subscribe(async x => await _updateView?.Invoke(EViewAction.DispatcherRefreshServersBiz, null));
Init(updateView);
}
SelectedRouting = new();
SelectedServer = new();
_isAdministrator = Utils.IsAdministrator();
if (_config.tunModeItem.enableTun && _isAdministrator)
if (_config.tunModeItem.enableTun && AppHandler.Instance.IsAdministrator)
{
EnableTun = true;
}
@@ -130,7 +125,7 @@ namespace ServiceLib.ViewModels
}
RefreshRoutingsMenu();
InboundDisplayStaus();
InboundDisplayStatus();
ChangeSystemProxyAsync(_config.systemProxyItem.sysProxyType, true);
#region WhenAnyValue && ReactiveCommand
@@ -414,7 +409,7 @@ namespace ServiceLib.ViewModels
{
_config.tunModeItem.enableTun = EnableTun;
// When running as a non-administrator, reboot to administrator mode
if (EnableTun && !_isAdministrator)
if (EnableTun && !AppHandler.Instance.IsAdministrator)
{
_config.tunModeItem.enableTun = false;
Locator.Current.GetService<MainWindowViewModel>()?.RebootAsAdmin();
@@ -429,19 +424,12 @@ namespace ServiceLib.ViewModels
#region UI
public void InboundDisplayStaus()
public void InboundDisplayStatus()
{
StringBuilder sb = new();
sb.Append($"[{EInboundProtocol.socks}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.socks)}]");
sb.Append(" | ");
//if (_config.systemProxyItem.sysProxyType == ESysProxyType.ForcedChange)
//{
// sb.Append($"[{Global.InboundHttp}({ResUI.SystemProxy}):{LazyConfig.Instance.GetLocalPort(Global.InboundHttp)}]");
//}
//else
//{
sb.Append($"[{EInboundProtocol.http}:{AppHandler.Instance.GetLocalPort(EInboundProtocol.http)}]");
//}
InboundDisplay = $"{ResUI.LabLocal}:{sb}";
if (_config.inbound[0].allowLANConn)
+1 -1
View File
@@ -43,7 +43,7 @@ public partial class App : Application
private void OnStartup(string[]? Args)
{
var exePathKey = Utils.GetMD5(Utils.GetExePath());
var exePathKey = Utils.GetMd5(Utils.GetExePath());
var rebootas = (Args ?? new string[] { }).Any(t => t == Global.RebootAs);
//ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
@@ -272,7 +272,7 @@ namespace v2rayN.Desktop.Views
private void btnGUID_Click(object? sender, RoutedEventArgs e)
{
txtId.Text =
txtId5.Text = Utils.GetGUID();
txtId5.Text = Utils.GetGuid();
}
private void SetHeaderType()
@@ -80,30 +80,35 @@ namespace v2rayN.Desktop.Views
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
switch (_config.uiItem.mainGirdOrientation)
{
gridMain.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
}
else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
{
gridMain1.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);
}
else
{
gridMain2.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);
case EGirdOrientation.Horizontal:
gridMain.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
break;
case EGirdOrientation.Vertical:
gridMain1.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView1.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);
break;
case EGirdOrientation.Tab:
default:
gridMain2.IsVisible = true;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.IsVisible).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.IsVisible).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);
break;
}
});
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (Utils.IsWindows())
{
menuGlobalHotkeySetting.IsVisible = false;
@@ -115,26 +120,29 @@ namespace v2rayN.Desktop.Views
menuGlobalHotkeySetting.IsVisible = false;
}
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
switch (_config.uiItem.mainGirdOrientation)
{
tabProfiles.Content ??= new ProfilesView(this);
tabMsgView.Content ??= new MsgView();
tabClashProxies.Content ??= new ClashProxiesView();
tabClashConnections.Content ??= new ClashConnectionsView();
}
else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
{
tabProfiles1.Content ??= new ProfilesView(this);
tabMsgView1.Content ??= new MsgView();
tabClashProxies1.Content ??= new ClashProxiesView();
tabClashConnections1.Content ??= new ClashConnectionsView();
}
else
{
tabProfiles2.Content ??= new ProfilesView(this);
tabMsgView2.Content ??= new MsgView();
tabClashProxies2.Content ??= new ClashProxiesView();
tabClashConnections2.Content ??= new ClashConnectionsView();
case EGirdOrientation.Horizontal:
tabProfiles.Content ??= new ProfilesView(this);
tabMsgView.Content ??= new MsgView();
tabClashProxies.Content ??= new ClashProxiesView();
tabClashConnections.Content ??= new ClashConnectionsView();
break;
case EGirdOrientation.Vertical:
tabProfiles1.Content ??= new ProfilesView(this);
tabMsgView1.Content ??= new MsgView();
tabClashProxies1.Content ??= new ClashProxiesView();
tabClashConnections1.Content ??= new ClashConnectionsView();
break;
case EGirdOrientation.Tab:
default:
tabProfiles2.Content ??= new ProfilesView(this);
tabMsgView2.Content ??= new MsgView();
tabClashProxies2.Content ??= new ClashProxiesView();
tabClashConnections2.Content ??= new ClashConnectionsView();
break;
}
conTheme.Content ??= new ThemeSettingView();
@@ -32,7 +32,7 @@
Cursor="Hand" />
</StackPanel>
<TabControl HorizontalContentAlignment="Left">
<TabControl HorizontalContentAlignment="Stretch">
<TabItem Header="{x:Static resx:ResUI.TbSettingsCore}">
<ScrollViewer VerticalScrollBarVisibility="Visible">
<Grid Classes="Margin8">
@@ -364,6 +364,7 @@
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
@@ -610,6 +611,19 @@
Grid.Column="1"
Width="300"
Classes="Margin8" />
<TextBlock
Grid.Row="22"
Grid.Column="0"
VerticalAlignment="Center"
Classes="Margin8"
Text="{x:Static resx:ResUI.TbSettingsGeoFilesSource}" />
<ComboBox
x:Name="cmbGetFilesSourceUrl"
Grid.Row="22"
Grid.Column="1"
Width="300"
Classes="Margin8" />
</Grid>
</ScrollViewer>
</TabItem>
@@ -83,6 +83,10 @@ namespace v2rayN.Desktop.Views
{
cmbSubConvertUrl.Items.Add(it);
});
Global.GeoFilesSources.ForEach(it =>
{
cmbGetFilesSourceUrl.Items.Add(it);
});
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
{
cmbMainGirdOrientation.Items.Add(it.ToString());
@@ -132,6 +136,7 @@ namespace v2rayN.Desktop.Views
this.Bind(ViewModel, vm => vm.SpeedPingTestUrl, v => v.cmbSpeedPingTestUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.SelectedValue).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.SelectedValue).DisposeWith(disposables);
+30 -6
View File
@@ -24,23 +24,47 @@
<conv:InverseBooleanConverter x:Key="InverseBooleanConverter" />
<Thickness
x:Key="ServerItemMargin"
x:Key="Margin4"
Bottom="4"
Left="4"
Right="4"
Top="4" />
<Thickness
x:Key="SettingItemMargin"
x:Key="Margin8"
Bottom="8"
Left="8"
Right="8"
Top="8" />
<Thickness
x:Key="OutlinedTextBoxDefaultPadding"
Bottom="12"
Left="16"
Right="12"
Top="12" />
Bottom="8"
Left="8"
Right="8"
Top="8" />
<Thickness
x:Key="MarginLeftRight4"
Bottom="0"
Left="4"
Right="4"
Top="0" />
<Thickness
x:Key="MarginLeftRight8"
Bottom="0"
Left="8"
Right="8"
Top="0" />
<Thickness
x:Key="MarginLeft8"
Bottom="0"
Left="8"
Right="0"
Top="0" />
<Thickness
x:Key="MarginRight8"
Bottom="0"
Left="0"
Right="8"
Top="0" />
<Style
x:Key="ModuleTitle"
BasedOn="{StaticResource MaterialDesignTextBlock}"
+1 -1
View File
@@ -26,7 +26,7 @@ namespace v2rayN
/// <param name="e"></param>
protected override void OnStartup(StartupEventArgs e)
{
var exePathKey = Utils.GetMD5(Utils.GetExePath());
var exePathKey = Utils.GetMd5(Utils.GetExePath());
var rebootas = (e.Args ?? new string[] { }).Any(t => t == Global.RebootAs);
ProgramStarted = new EventWaitHandle(false, EventResetMode.AutoReset, exePathKey, out bool bCreatedNew);
+1 -1
View File
@@ -218,7 +218,7 @@ namespace v2rayN
{
try
{
var autoRunName = $"{AutoRunName}_{Utils.GetMD5(Utils.StartupPath())}";
var autoRunName = $"{AutoRunName}_{Utils.GetMd5(Utils.StartupPath())}";
//delete first
RegWriteValue(AutoRunRegPath, autoRunName, "");
if (Utils.IsAdministrator())
@@ -22,9 +22,9 @@
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -37,7 +37,7 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
@@ -72,14 +72,14 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.menuServers}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRemarks}" />
@@ -89,7 +89,7 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource MyOutlinedTextBox}" />
@@ -97,7 +97,7 @@
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAddress}" />
@@ -106,7 +106,7 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -118,12 +118,12 @@
Orientation="Horizontal">
<Button
x:Name="btnBrowse"
Margin="2,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
<Button
x:Name="btnEdit"
Margin="2,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbEdit}"
Style="{StaticResource DefButton}" />
</StackPanel>
@@ -131,7 +131,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbCoreType}" />
@@ -140,7 +140,7 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
MaxDropDownHeight="1000"
Style="{StaticResource MyOutlinedTextComboBox}" />
@@ -148,18 +148,18 @@
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbDisplayLog}" />
<StackPanel
Grid.Row="4"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
Orientation="Horizontal">
<ToggleButton x:Name="togDisplayLog" HorizontalAlignment="Left" />
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TipDisplayLog}" />
@@ -168,7 +168,7 @@
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPreSocksPort}" />
@@ -177,7 +177,7 @@
Grid.Row="5"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
AcceptsReturn="True"
Style="{StaticResource MyOutlinedTextBox}" />
@@ -193,7 +193,7 @@
TextWrapping="Wrap" />
<TextBlock
Width="500"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.CustomServerTips}"
+90 -90
View File
@@ -22,9 +22,9 @@
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -37,7 +37,7 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
@@ -76,7 +76,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.menuServers}" />
<StackPanel
@@ -86,7 +86,7 @@
<ComboBox
x:Name="cmbCoreType"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.TbCoreType}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
@@ -94,7 +94,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRemarks}" />
@@ -103,13 +103,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAddress}" />
@@ -118,13 +118,13 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPort}" />
@@ -133,7 +133,7 @@
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
@@ -162,7 +162,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId}" />
@@ -171,20 +171,20 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<Button
x:Name="btnGUID"
Grid.Row="1"
Grid.Column="2"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbGUID}"
Style="{StaticResource DefButton}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAlterId}" />
@@ -193,14 +193,14 @@
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSecurity}" />
@@ -209,7 +209,7 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -230,7 +230,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId3}" />
@@ -239,13 +239,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSecurity3}" />
@@ -254,7 +254,7 @@
Grid.Row="2"
Grid.Column="1"
Width="300"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -275,7 +275,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSecurity4}" />
@@ -284,13 +284,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId4}" />
@@ -299,7 +299,7 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
</Grid>
<Grid
@@ -321,7 +321,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId5}" />
@@ -330,20 +330,20 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<Button
x:Name="btnGUID5"
Grid.Row="1"
Grid.Column="2"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbGUID}"
Style="{StaticResource DefButton}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFlow5}" />
@@ -352,13 +352,13 @@
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSecurity5}" />
@@ -367,7 +367,7 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
@@ -389,7 +389,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId3}" />
@@ -398,13 +398,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFlow5}" />
@@ -413,7 +413,7 @@
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -434,7 +434,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId3}" />
@@ -443,13 +443,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPath7}" />
@@ -458,7 +458,7 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
</Grid>
<Grid
@@ -479,7 +479,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId}" />
@@ -488,13 +488,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbId3}" />
@@ -503,13 +503,13 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbHeaderType8}" />
@@ -518,7 +518,7 @@
Grid.Row="3"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -541,7 +541,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPrivateKey}" />
@@ -550,13 +550,13 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPublicKey}" />
@@ -565,14 +565,14 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbReserved}" />
@@ -581,13 +581,13 @@
Grid.Row="3"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbLocalAddress}" />
@@ -596,13 +596,13 @@
Grid.Row="4"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="Mtu" />
@@ -611,7 +611,7 @@
Grid.Row="5"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
@@ -642,14 +642,14 @@
<TextBlock
Grid.Row="0"
Grid.ColumnSpan="2"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.GbTransport}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbNetwork}" />
@@ -658,12 +658,12 @@
Grid.Row="1"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TipNetwork}" />
@@ -672,7 +672,7 @@
x:Name="labHeaderType"
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbHeaderType}" />
@@ -681,13 +681,13 @@
Grid.Row="2"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
x:Name="tipHeaderType"
Grid.Row="2"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbHeaderType}" />
@@ -695,7 +695,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRequestHost}" />
@@ -704,13 +704,13 @@
Grid.Row="3"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
x:Name="tipRequestHost"
Grid.Row="3"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRequestHost}" />
@@ -718,7 +718,7 @@
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPath}" />
@@ -727,13 +727,13 @@
Grid.Row="4"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefTextBox}" />
<TextBlock
x:Name="tipPath"
Grid.Row="4"
Grid.Column="2"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPath}" />
@@ -760,7 +760,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbStreamSecurity}" />
@@ -769,7 +769,7 @@
Grid.Row="0"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -791,7 +791,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSNI}" />
@@ -800,14 +800,14 @@
Grid.Row="1"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFingerprint}" />
@@ -816,14 +816,14 @@
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAlpn}" />
@@ -832,13 +832,13 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAllowInsecure}" />
@@ -847,7 +847,7 @@
Grid.Row="4"
Grid.Column="1"
Width="100"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</Grid>
<Grid
@@ -869,7 +869,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSNI}" />
@@ -878,14 +878,14 @@
Grid.Row="0"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbFingerprint}" />
@@ -894,14 +894,14 @@
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbPublicKey}" />
@@ -910,14 +910,14 @@
Grid.Row="2"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbShortId}" />
@@ -926,14 +926,14 @@
Grid.Row="3"
Grid.Column="1"
Width="200"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSpiderX}" />
@@ -942,7 +942,7 @@
Grid.Row="4"
Grid.Column="1"
Width="400"
Margin="{StaticResource ServerItemMargin}"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
</Grid>
@@ -267,7 +267,7 @@ namespace v2rayN.Views
private void btnGUID_Click(object sender, RoutedEventArgs e)
{
txtId.Text =
txtId5.Text = Utils.GetGUID();
txtId5.Text = Utils.GetGuid();
}
private void SetHeaderType()
@@ -21,11 +21,11 @@
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<DockPanel Margin="16">
<DockPanel Margin="8" DockPanel.Dock="Bottom">
<DockPanel Margin="{StaticResource Margin8}">
<DockPanel Margin="{StaticResource Margin8}" DockPanel.Dock="Bottom">
<Button
Width="100"
Margin="8"
Margin="{StaticResource Margin8}"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.menuClose}"
DockPanel.Dock="Right"
@@ -35,14 +35,14 @@
<TextBlock
x:Name="txtMsg"
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
Style="{StaticResource ToolbarTextBlock}" />
</DockPanel>
<StackPanel>
<materialDesign:Card Width="Auto" Margin="8">
<Grid Margin="8">
<materialDesign:Card Width="Auto" Margin="{StaticResource Margin8}">
<Grid Margin="{StaticResource Margin8}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@@ -56,14 +56,14 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.menuLocalBackupAndRestore}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuLocalBackup}" />
@@ -71,7 +71,7 @@
x:Name="menuLocalBackup"
Grid.Row="1"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Content="{x:Static resx:ResUI.menuLocalBackup}"
Style="{StaticResource DefButton}" />
@@ -84,7 +84,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuLocalRestore}" />
@@ -92,14 +92,14 @@
x:Name="menuLocalRestore"
Grid.Row="3"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Content="{x:Static resx:ResUI.menuLocalRestore}"
Style="{StaticResource DefButton}" />
</Grid>
</materialDesign:Card>
<materialDesign:Card Width="Auto" Margin="8">
<Grid Margin="8">
<materialDesign:Card Width="Auto" Margin="{StaticResource Margin8}">
<Grid Margin="{StaticResource Margin8}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@@ -115,7 +115,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.menuRemoteBackupAndRestore}" />
@@ -124,7 +124,7 @@
HorizontalAlignment="Right"
StaysOpen="True"
Style="{StaticResource MaterialDesignToolForegroundPopupBox}">
<StackPanel Margin="16">
<StackPanel Margin="{StaticResource Margin8}">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
@@ -140,7 +140,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvWebDavUrl}" />
@@ -149,7 +149,7 @@
x:Name="txtWebDavUrl"
Grid.Row="0"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}"
TextWrapping="Wrap" />
@@ -157,7 +157,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvWebDavUserName}" />
@@ -166,14 +166,14 @@
x:Name="txtWebDavUserName"
Grid.Row="1"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvWebDavPassword}" />
@@ -182,14 +182,14 @@
x:Name="txtWebDavPassword"
Grid.Row="2"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvWebDavDirName}" />
@@ -198,7 +198,7 @@
x:Name="txtWebDavDirName"
Grid.Row="3"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource DefTextBox}" />
@@ -206,7 +206,7 @@
x:Name="menuWebDavCheck"
Grid.Row="4"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Content="{x:Static resx:ResUI.LvWebDavCheck}"
Style="{StaticResource DefButton}" />
@@ -218,7 +218,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuRemoteBackup}" />
@@ -226,7 +226,7 @@
x:Name="menuRemoteBackup"
Grid.Row="1"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Content="{x:Static resx:ResUI.menuRemoteBackup}"
Style="{StaticResource DefButton}" />
@@ -238,7 +238,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuRemoteRestore}" />
@@ -246,7 +246,7 @@
x:Name="menuRemoteRestore"
Grid.Row="3"
Grid.Column="1"
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Content="{x:Static resx:ResUI.menuRemoteRestore}"
Style="{StaticResource DefButton}" />
@@ -15,27 +15,27 @@
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<DockPanel Margin="16">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsEnableCheckPreReleaseUpdate}" />
<ToggleButton
x:Name="togEnableCheckPreReleaseUpdate"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
<Button
x:Name="btnCheckUpdate"
Width="100"
Margin="8"
Margin="{StaticResource Margin8}"
Content="{x:Static resx:ResUI.menuCheckUpdate}"
IsCancel="True"
IsDefault="True"
@@ -43,7 +43,7 @@
<Button
Width="100"
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.menuClose}"
@@ -67,7 +67,7 @@
<Border
Width="500"
Height="50"
Margin="8"
Margin="{StaticResource Margin8}"
Padding="0"
VerticalAlignment="Center">
<Grid>
@@ -82,7 +82,7 @@
<ToggleButton
x:Name="togAutoRefresh"
Grid.Column="0"
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left"
IsChecked="{Binding IsSelected}" />
<TextBlock
@@ -13,9 +13,9 @@
x:TypeArguments="vms:ClashConnectionsViewModel"
mc:Ignorable="d">
<DockPanel Margin="2">
<DockPanel Margin="{StaticResource Margin4}">
<WrapPanel
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
@@ -23,21 +23,21 @@
<TextBox
x:Name="txtHostFilter"
Width="200"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalContentAlignment="Center"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.ConnectionsHostFilterTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
Style="{StaticResource DefTextBox}" />
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox
x:Name="cmbSorting"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingUpSpeed}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDownSpeed}" />
@@ -51,20 +51,20 @@
x:Name="btnConnectionCloseAll"
Width="24"
Height="24"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuConnectionCloseAll}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Close" />
</Button>
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAutoRefresh}" />
<ToggleButton
x:Name="togAutoRefresh"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
HorizontalAlignment="Left" />
</WrapPanel>
@@ -20,22 +20,22 @@
<converters:DelayColorConverter x:Key="DelayColorConverter" />
</UserControl.Resources>
<DockPanel Margin="2">
<DockPanel Margin="{StaticResource Margin4}">
<WrapPanel
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.menuRulemode}" />
<ComboBox
x:Name="cmbRulemode"
Width="80"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.menuModeRule}" />
<ComboBoxItem Content="{x:Static resx:ResUI.menuModeGlobal}" />
@@ -43,14 +43,14 @@
</ComboBox>
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSorting}" />
<ComboBox
x:Name="cmbSorting"
Width="60"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource DefComboBox}">
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingDelay}" />
<ComboBoxItem Content="{x:Static resx:ResUI.TbSortingName}" />
@@ -61,7 +61,7 @@
x:Name="menuProxiesReload"
Width="24"
Height="24"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProxiesReload}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Reload" />
@@ -71,26 +71,26 @@
x:Name="menuProxiesDelaytest"
Width="24"
Height="24"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProxiesDelaytest}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="LightningBolt" />
</Button>
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAutoRefresh}" />
<ToggleButton
x:Name="togAutoRefresh"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
HorizontalAlignment="Left" />
</WrapPanel>
<DockPanel>
<ListView
x:Name="lstProxyGroups"
Margin="0,0,5,0"
Margin="{StaticResource MarginRight8}"
BorderThickness="0"
DockPanel.Dock="Left"
ItemContainerStyle="{StaticResource lvItemSelected}"
@@ -106,10 +106,10 @@
<DataTemplate>
<Border
Width="160"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
Padding="0">
<DockPanel>
<Grid Grid.Column="0" Margin="4">
<Grid Grid.Column="0" Margin="{StaticResource Margin4}">
<Grid.RowDefinitions>
<RowDefinition />
<RowDefinition />
@@ -162,7 +162,7 @@
CornerRadius="4"
DockPanel.Dock="Left"
Visibility="{Binding Path=isActive, Converter={StaticResource BoolToVisConverter}}" />
<Grid Margin="4">
<Grid Margin="{StaticResource Margin4}">
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition Height="1*" />
@@ -22,9 +22,9 @@
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -37,7 +37,7 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
@@ -47,15 +47,15 @@
<TabControl HorizontalContentAlignment="Left">
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDns}">
<DockPanel Margin="{StaticResource SettingItemMargin}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsRemoteDNS}" />
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsObjectDoc_Click">
@@ -65,7 +65,7 @@
</TextBlock>
<Button
x:Name="btnImportDefConfig4V2ray"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
@@ -74,39 +74,39 @@
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsUseSystemHosts}" />
<ToggleButton
x:Name="togUseSystemHosts"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Left" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Freedom}" />
<ComboBox
x:Name="cmbdomainStrategy4Freedom"
Width="150"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress"
Width="150"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
@@ -114,7 +114,7 @@
<TextBox
x:Name="txtnormalDNS"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Stretch"
materialDesign:HintAssist.Hint="HTTP/SOCKS"
AcceptsReturn="True"
@@ -126,10 +126,10 @@
</TabItem>
<TabItem Header="{x:Static resx:ResUI.TbSettingsCoreDnsSingbox}">
<DockPanel Margin="{StaticResource SettingItemMargin}">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel DockPanel.Dock="Top" Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkDnsSingboxObjectDoc_Click">
@@ -139,7 +139,7 @@
</TextBlock>
<Button
x:Name="btnImportDefConfig4Singbox"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
Content="{x:Static resx:ResUI.TbSettingDnsImportDefConfig}"
Cursor="Hand"
Style="{StaticResource DefButton}" />
@@ -148,33 +148,33 @@
<WrapPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainStrategy4Out}" />
<ComboBox
x:Name="cmbdomainStrategy4Out"
Width="150"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<StackPanel Orientation="Horizontal">
<TextBlock
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSettingsDomainDNSAddress}" />
<ComboBox
x:Name="cmbdomainDNSAddress2"
Width="150"
Margin="{StaticResource SettingItemMargin}"
Margin="{StaticResource Margin8}"
IsEditable="True"
Style="{StaticResource DefComboBox}" />
</StackPanel>
</WrapPanel>
<Grid Margin="{StaticResource SettingItemMargin}">
<Grid Margin="{StaticResource Margin8}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10" />
@@ -23,16 +23,16 @@
TextElement.Foreground="{DynamicResource MaterialDesignBody}"
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel Margin="8">
<DockPanel Margin="{StaticResource Margin8}">
<StackPanel
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Center"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
<Button
x:Name="btnReset"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbReset}"
Style="{StaticResource DefButton}" />
<Button
@@ -44,7 +44,7 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
@@ -77,14 +77,14 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
Style="{StaticResource ModuleTitle}"
Text="{x:Static resx:ResUI.TbGlobalHotkeySetting}" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbDisplayGUI}" />
@@ -93,7 +93,7 @@
x:Name="txtGlobalHotkey0"
Grid.Row="1"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -103,7 +103,7 @@
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbClearSystemProxy}" />
@@ -111,7 +111,7 @@
x:Name="txtGlobalHotkey1"
Grid.Row="2"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -121,7 +121,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSetSystemProxy}" />
@@ -129,7 +129,7 @@
x:Name="txtGlobalHotkey2"
Grid.Row="3"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -138,7 +138,7 @@
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbNotChangeSystemProxy}" />
@@ -146,7 +146,7 @@
x:Name="txtGlobalHotkey3"
Grid.Row="4"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -155,7 +155,7 @@
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbSystemProxyPac}" />
@@ -163,7 +163,7 @@
x:Name="txtGlobalHotkey4"
Grid.Row="5"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
IsReadOnly="True"
@@ -173,7 +173,7 @@
<TextBlock
Grid.Row="1"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbGlobalHotkeySettingTip}" />
+15 -43
View File
@@ -50,7 +50,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Server" />
<TextBlock Text="{x:Static resx:ResUI.menuServers}" />
@@ -114,7 +114,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="BookClockOutline" />
<TextBlock Text="{x:Static resx:ResUI.menuSubscription}" />
@@ -149,7 +149,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="SettingsOutline" />
<TextBlock Text="{x:Static resx:ResUI.menuSetting}" />
@@ -201,7 +201,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Reload" />
<TextBlock Text="{x:Static resx:ResUI.menuReload}" />
@@ -215,7 +215,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Update" />
<TextBlock Text="{x:Static resx:ResUI.menuCheckUpdate}" />
@@ -229,7 +229,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="HelpCircleOutline" />
<TextBlock Text="{x:Static resx:ResUI.menuHelp}" />
@@ -243,7 +243,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="VolumeHigh" />
<TextBlock Text="{x:Static resx:ResUI.menuPromotion}" />
@@ -257,7 +257,7 @@
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Minimize" />
<TextBlock Text="{x:Static resx:ResUI.menuClose}" />
@@ -313,11 +313,7 @@
<TabItem x:Name="tabMsgView1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="MessageTextOutline" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="MessageTextOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -328,11 +324,7 @@
<TabItem x:Name="tabClashProxies1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="ArrowDecisionOutline" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="ArrowDecisionOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -343,11 +335,7 @@
<TabItem x:Name="tabClashConnections1">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="LanConnect" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="LanConnect" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -366,11 +354,7 @@
<TabItem x:Name="tabProfiles2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="Server" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="Server" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -381,11 +365,7 @@
<TabItem x:Name="tabMsgView2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="MessageTextOutline" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="MessageTextOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -396,11 +376,7 @@
<TabItem x:Name="tabClashProxies2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="ArrowDecisionOutline" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="ArrowDecisionOutline" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
@@ -411,11 +387,7 @@
<TabItem x:Name="tabClashConnections2">
<TabItem.Header>
<StackPanel>
<materialDesign:PackIcon
Width="24"
Height="24"
HorizontalAlignment="Center"
Kind="LanConnect" />
<materialDesign:PackIcon HorizontalAlignment="Center" Kind="LanConnect" />
<TextBlock
HorizontalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
+47 -39
View File
@@ -41,26 +41,29 @@ namespace v2rayN.Views
Locator.CurrentMutable.RegisterLazySingleton(() => ViewModel, typeof(MainWindowViewModel));
WindowsHandler.Instance.RegisterGlobalHotkey(_config, OnHotkeyHandler, null);
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
switch (_config.uiItem.mainGirdOrientation)
{
tabProfiles.Content ??= new ProfilesView();
tabMsgView.Content ??= new MsgView();
tabClashProxies.Content ??= new ClashProxiesView();
tabClashConnections.Content ??= new ClashConnectionsView();
}
else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
{
tabProfiles1.Content ??= new ProfilesView();
tabMsgView1.Content ??= new MsgView();
tabClashProxies1.Content ??= new ClashProxiesView();
tabClashConnections1.Content ??= new ClashConnectionsView();
}
else
{
tabProfiles2.Content ??= new ProfilesView();
tabMsgView2.Content ??= new MsgView();
tabClashProxies2.Content ??= new ClashProxiesView();
tabClashConnections2.Content ??= new ClashConnectionsView();
case EGirdOrientation.Horizontal:
tabProfiles.Content ??= new ProfilesView();
tabMsgView.Content ??= new MsgView();
tabClashProxies.Content ??= new ClashProxiesView();
tabClashConnections.Content ??= new ClashConnectionsView();
break;
case EGirdOrientation.Vertical:
tabProfiles1.Content ??= new ProfilesView();
tabMsgView1.Content ??= new MsgView();
tabClashProxies1.Content ??= new ClashProxiesView();
tabClashConnections1.Content ??= new ClashConnectionsView();
break;
case EGirdOrientation.Tab:
default:
tabProfiles2.Content ??= new ProfilesView();
tabMsgView2.Content ??= new MsgView();
tabClashProxies2.Content ??= new ClashProxiesView();
tabClashConnections2.Content ??= new ClashConnectionsView();
break;
}
pbTheme.Content ??= new ThemeSettingView();
@@ -99,30 +102,35 @@ namespace v2rayN.Views
this.BindCommand(ViewModel, vm => vm.ReloadCmd, v => v.menuReload).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.BlReloadEnabled, v => v.menuReload.IsEnabled).DisposeWith(disposables);
if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Horizontal)
switch (_config.uiItem.mainGirdOrientation)
{
gridMain.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
}
else if (_config.uiItem.mainGirdOrientation == EGirdOrientation.Vertical)
{
gridMain1.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);
}
else
{
gridMain2.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);
case EGirdOrientation.Horizontal:
gridMain.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain.SelectedIndex).DisposeWith(disposables);
break;
case EGirdOrientation.Vertical:
gridMain1.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabMsgView1.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies1.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections1.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain1.SelectedIndex).DisposeWith(disposables);
break;
case EGirdOrientation.Tab:
default:
gridMain2.Visibility = Visibility.Visible;
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashProxies2.Visibility).DisposeWith(disposables);
this.OneWayBind(ViewModel, vm => vm.ShowClashUI, v => v.tabClashConnections2.Visibility).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.TabMainSelectedIndex, v => v.tabMain2.SelectedIndex).DisposeWith(disposables);
break;
}
});
this.Title = $"{Utils.GetVersion()} - {(Utils.IsAdministrator() ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
this.Title = $"{Utils.GetVersion()} - {(AppHandler.Instance.IsAdministrator ? ResUI.RunAsAdmin : ResUI.NotRunAsAdmin)}";
if (!_config.guiItem.enableHWA)
{
+9 -9
View File
@@ -13,9 +13,9 @@
x:TypeArguments="vms:MsgViewModel"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<DockPanel Margin="2">
<DockPanel Margin="{StaticResource Margin4}">
<WrapPanel
Margin="8"
Margin="{StaticResource Margin8}"
VerticalAlignment="Center"
DockPanel.Dock="Top"
Orientation="Horizontal">
@@ -23,7 +23,7 @@
<ComboBox
x:Name="cmbMsgFilter"
Width="200"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgFilterTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
IsEditable="True"
@@ -32,7 +32,7 @@
x:Name="btnCopy"
Width="24"
Height="24"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuMsgViewCopyAll}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="ContentCopy" />
@@ -41,29 +41,29 @@
x:Name="btnClear"
Width="24"
Height="24"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuMsgViewClear}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Delete" />
</Button>
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAutoRefresh}" />
<ToggleButton
x:Name="togAutoRefresh"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
HorizontalAlignment="Left"
IsChecked="True" />
<TextBlock
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbAutoScrollToEnd}" />
<ToggleButton
x:Name="togScrollToEnd"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
HorizontalAlignment="Left"
IsChecked="True" />
</WrapPanel>
File diff suppressed because it is too large Load Diff
@@ -85,6 +85,10 @@ namespace v2rayN.Views
{
cmbSubConvertUrl.Items.Add(it);
});
Global.GeoFilesSources.ForEach(it =>
{
cmbGetFilesSourceUrl.Items.Add(it);
});
foreach (EGirdOrientation it in Enum.GetValues(typeof(EGirdOrientation)))
{
cmbMainGirdOrientation.Items.Add(it.ToString());
@@ -145,6 +149,7 @@ namespace v2rayN.Views
this.Bind(ViewModel, vm => vm.EnableHWA, v => v.togEnableHWA.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.SubConvertUrl, v => v.cmbSubConvertUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.MainGirdOrientation, v => v.cmbMainGirdOrientation.SelectedIndex).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.GeoFileSourceUrl, v => v.cmbGetFilesSourceUrl.Text).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.notProxyLocalAddress, v => v.tognotProxyLocalAddress.IsChecked).DisposeWith(disposables);
this.Bind(ViewModel, vm => vm.systemProxyAdvancedProtocol, v => v.cmbsystemProxyAdvancedProtocol.Text).DisposeWith(disposables);
+5 -5
View File
@@ -21,7 +21,7 @@
</UserControl.Resources>
<Grid>
<DockPanel>
<WrapPanel Margin="2" DockPanel.Dock="Top">
<WrapPanel Margin="{StaticResource Margin4}" DockPanel.Dock="Top">
<ListBox
x:Name="lstGroup"
MaxHeight="200"
@@ -39,7 +39,7 @@
x:Name="btnEditSub"
Width="30"
Height="30"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuSubEdit}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Edit" />
@@ -48,7 +48,7 @@
x:Name="btnAddSub"
Width="30"
Height="30"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuSubAdd}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="Plus" />
@@ -58,7 +58,7 @@
x:Name="btnAutofitColumnWidth"
Width="30"
Height="30"
Margin="20,0"
Margin="{StaticResource MarginLeftRight8}"
Style="{StaticResource MaterialDesignFloatingActionMiniLightButton}"
ToolTip="{x:Static resx:ResUI.menuProfileAutofitColumnWidth}">
<materialDesign:PackIcon VerticalAlignment="Center" Kind="ArrowSplitVertical" />
@@ -66,7 +66,7 @@
<TextBox
x:Name="txtServerFilter"
Width="200"
Margin="4,0"
Margin="{StaticResource MarginLeftRight4}"
VerticalContentAlignment="Center"
materialDesign:HintAssist.Hint="{x:Static resx:ResUI.MsgServerTitle}"
materialDesign:TextFieldAssist.HasClearButton="True"
+2 -2
View File
@@ -10,7 +10,7 @@
d:DesignWidth="300"
Style="{StaticResource ViewGlobal}"
mc:Ignorable="d">
<Grid Margin="30">
<Grid Margin="32">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@@ -38,7 +38,7 @@
<Button
Grid.Row="2"
Width="100"
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
Command="{x:Static materialDesign:DialogHost.CloseDialogCommand}"
Content="{x:Static resx:ResUI.TbConfirm}"
@@ -23,7 +23,7 @@
WindowStartupLocation="CenterScreen"
mc:Ignorable="d">
<DockPanel>
<Grid Margin="8" DockPanel.Dock="Top">
<Grid Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@@ -41,7 +41,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvRemarks}" />
@@ -50,20 +50,20 @@
Grid.Row="0"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<ToggleButton
x:Name="togEnabled"
Grid.Row="0"
Grid.Column="2"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left" />
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="outboundTag" />
@@ -72,13 +72,13 @@
Grid.Row="1"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
MaxDropDownHeight="1000"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="1"
Grid.Column="2"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRuleMatchingTips}" />
@@ -86,7 +86,7 @@
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="port" />
@@ -95,13 +95,13 @@
Grid.Row="2"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource DefTextBox}" />
<TextBlock
Grid.Row="2"
Grid.Column="2"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkRuleobjectDoc_Click">
@@ -113,7 +113,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="protocol" />
@@ -121,7 +121,7 @@
x:Name="clbProtocol"
Grid.Row="3"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
@@ -129,7 +129,7 @@
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="inboundTag" />
@@ -137,14 +137,14 @@
x:Name="clbInboundTag"
Grid.Row="4"
Grid.Column="1"
Margin="4"
Margin="{StaticResource Margin4}"
FontSize="{DynamicResource StdFontSize}"
Style="{StaticResource MaterialDesignFilterChipPrimaryListBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="network" />
@@ -153,21 +153,21 @@
Grid.Row="5"
Grid.Column="1"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
MaxDropDownHeight="1000"
Style="{StaticResource DefComboBox}" />
<TextBlock
Grid.Row="5"
Grid.Column="2"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbRoutingTips}" />
</Grid>
<StackPanel
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -188,14 +188,14 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
Style="{StaticResource DefButton}" />
</StackPanel>
<Grid Margin="{StaticResource SettingItemMargin}">
<Grid Margin="{StaticResource Margin8}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="1*" />
<ColumnDefinition Width="10" />
@@ -32,7 +32,7 @@
<Button x:Name="menuRuleAdd">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Plus" />
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuRuleAdd}" />
@@ -42,7 +42,7 @@
<Button x:Name="menuImportRulesFromFile">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Import" />
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromFile}" />
@@ -52,7 +52,7 @@
<Button x:Name="menuImportRulesFromClipboard">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Import" />
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromClipboard}" />
@@ -62,7 +62,7 @@
<Button x:Name="menuImportRulesFromUrl">
<StackPanel Orientation="Horizontal">
<materialDesign:PackIcon
Margin="0,0,8,0"
Margin="{StaticResource MarginRight8}"
VerticalAlignment="Center"
Kind="Import" />
<TextBlock Style="{StaticResource ToolbarTextBlock}" Text="{x:Static resx:ResUI.menuImportRulesFromUrl}" />
@@ -72,7 +72,7 @@
</ToolBarTray>
<StackPanel
Margin="8"
Margin="{StaticResource Margin8}"
HorizontalAlignment="Right"
DockPanel.Dock="Bottom"
Orientation="Horizontal">
@@ -85,14 +85,14 @@
<Button
x:Name="btnCancel"
Width="100"
Margin="8,0"
Margin="{StaticResource MarginLeftRight8}"
Content="{x:Static resx:ResUI.TbCancel}"
Cursor="Hand"
IsCancel="true"
Style="{StaticResource DefButton}" />
</StackPanel>
<Grid Margin="8" DockPanel.Dock="Top">
<Grid Margin="{StaticResource Margin8}" DockPanel.Dock="Top">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
@@ -109,7 +109,7 @@
<TextBlock
Grid.Row="0"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvRemarks}" />
@@ -123,7 +123,7 @@
Grid.Row="0"
Grid.Column="1"
Width="300"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
VerticalAlignment="Top"
AcceptsReturn="True"
@@ -131,14 +131,14 @@
TextWrapping="Wrap" />
<TextBlock
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvSort}" />
<TextBox
x:Name="txtSort"
Width="100"
Margin="4"
Margin="{StaticResource Margin4}"
HorizontalAlignment="Left"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}" />
@@ -147,7 +147,7 @@
<TextBlock
Grid.Row="1"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbdomainStrategy}" />
@@ -158,24 +158,24 @@
<ComboBox
x:Name="cmbdomainStrategy"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
<TextBlock
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.TbdomainStrategy4Singbox}" />
<ComboBox
x:Name="cmbdomainStrategy4Singbox"
Width="200"
Margin="4"
Margin="{StaticResource Margin4}"
Style="{StaticResource DefComboBox}" />
</StackPanel>
<TextBlock
Grid.Row="2"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvUrl}" />
@@ -184,7 +184,7 @@
Grid.Row="2"
Grid.Column="1"
Width="600"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
@@ -193,7 +193,7 @@
<TextBlock
Grid.Row="3"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}"
Text="{x:Static resx:ResUI.LvCustomIcon}" />
@@ -202,7 +202,7 @@
Grid.Row="3"
Grid.Column="1"
Width="600"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
@@ -211,14 +211,14 @@
x:Name="btnBrowseCustomIcon"
Grid.Row="3"
Grid.Column="2"
Margin="2,0,8,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
<TextBlock
Grid.Row="4"
Grid.Column="0"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Center"
Style="{StaticResource ToolbarTextBlock}">
<Hyperlink Click="linkCustomRulesetPath4Singbox">
@@ -231,7 +231,7 @@
Grid.Row="4"
Grid.Column="1"
Width="600"
Margin="4"
Margin="{StaticResource Margin4}"
VerticalAlignment="Top"
AcceptsReturn="True"
Style="{StaticResource DefTextBox}"
@@ -240,7 +240,7 @@
x:Name="btnBrowseCustomRulesetPath4Singbox"
Grid.Row="4"
Grid.Column="2"
Margin="2,0,8,0"
Margin="{StaticResource MarginLeftRight4}"
Content="{x:Static resx:ResUI.TbBrowse}"
Style="{StaticResource DefButton}" />
</Grid>

Some files were not shown because too many files have changed in this diff Show More