V2rayN 订阅分组设置界面 更新时间单位修改为小时

需求

v2rayN订阅分组设置里的自动更新间隔单位是分钟

订阅地址的自动更新间隔改为按小时计算. 

https://github.com/2dust/v2rayN/issues/4271


思路

修改界面显示的文字.

修改自动更新的定时器逻辑.


具体实践

安装 Microsoft Visual Studio

在 Microsoft Store 里有

https://apps.microsoft.com/store/detail/XPDCFJDKLZJLP8

安装组件选 .NET 桌面开发

Visual Studio安装时勾选.NET桌面开发工作负荷


下载源码

https://github.com/2dust/v2rayN

在GitHub用Code菜单下载v2rayN源码ZIP

解压, 进入 v2ray-master 目录, 进入 v2rayN 目录, 打开 .sln 文件.

进入v2rayN目录打开v2rayN.sln解决方案

修改界面文本显示

v2rayN 因为界面支持多语言, 所以你实际上不能直接去修改界面元素的属性. 而是要去修改资源文件.

我们先打开软件, 找到要替换的显示文本是哪些.

1. 订阅分组管理窗口

文本为 自动更新间隔(分钟)

订阅分组管理窗口里的自动更新间隔(分钟)是要改的文本

2. 添加订阅分组窗口

文本为 自动更新间隔(分钟)

添加订阅分组窗口也有同一处文本


Ctrl + Shift + F 在项目中搜索关键字 自动更新间隔

全项目搜索关键字自动更新间隔

看到查找结果, 双击.

查找结果指向ResUI.zh-Hans.resx资源文件

把这个资源文件中的文本修改为 小时

把资源文本改成小时,注意资源ID是LvAutoUpdateInterval

同步的, 还要修改其它资源文件. (如果你不在乎, 也可以不改了, 跳过这一步)

你可以看到这个资源的 ID 是 LvAutoUpdateInterval

查看这个资源ID对应的键值内容

Ctrl + Shift + F 在项目中搜索关键字 LvAutoUpdateInterval

可以修改其它语言的资源文本. 比如, 繁体中文的文本资源.

搜索LvAutoUpdateInterval同步改其它语言资源

我这里就避免翻译问题, 简单粗暴都修改为 xxxxxxxxx (hour)


检查阶段性成果

可以保存编译运行起来看一下, 界面文本是不是修改成功了. 如果修改了各语言的资源文件, 也可以切换语言看一下显示效果.

用菜单也可以, 用快捷键也可以, 用快捷按钮也可以.

保存编译跑起来,确认界面文本已改


修改代码逻辑

打开 添加订阅分组窗口 设计文件

打开添加订阅分组窗口的设计文件SubEditWindow.xaml

选中更新间隔的数值的界面元素 (TextBox)

在设计器里选中更新间隔的输入框

在右边的 属性窗口 中找到界面元素的ID为 txtAutoUpdateInterval

属性窗口里控件ID是txtAutoUpdateInterval

Ctrl + Shift + F 在项目中搜索关键字 txtAutoUpdateInterval

搜索txtAutoUpdateInterval找到数据绑定的变量名

可以找到在 添加订阅分组窗口 和 订阅分组管理窗口 的22段代码.

粗浅的理解, 就是把界面元素的数据 连接/映射/绑定 某个数据结构的值/变量. 那么 autoUpdateInterval 就是数据结构的变量名了. 推测在设置定时器的时候, 就应该是用的这个变量.

Ctrl + Shift + F 在项目中搜索关键字 autoUpdateInterval 

把搜索到的地方都点开看一下, 找到实现定时器的逻辑在 MainFormHandler.cs 文件中 UpdateTaskRunSubscription 函数.

定时器逻辑在UpdateTaskRunSubscription函数里

如果你是直接在解决方案管理器中找, 那么位置在这里:

在Handler目录下找到UpdateTaskRunSubscription

这个函数里面写的什么意思呢? 我们找 GPT 问一下. 提问内容就是"帮助我理解以下代码", 接着就把函数全部粘贴, 回车.

https://poe.com/s/g6RbhSms1FdxwJ2FF7vq

GPT的回答如下:

这段代码是一个异步方法 UpdateTaskRunSubscription,它接受两个参数:config 和 update,并返回一个 Task 对象。
代码的主要逻辑如下:
1. 等待 60 秒(60000 毫秒)。
2. 调用 Utils.SaveLog 方法,将日志信息写入日志文件,日志信息为 "UpdateTaskRunSubscription"。
3. 创建一个 UpdateHandle 对象。
4. 进入一个无限循环。
5. 获取当前时间的 Unix 时间戳(以秒为单位),存储在 updateTime 变量中。
6. 获取 LazyConfig.Instance.SubItems() 的列表,并进行一系列筛选操作:
 - 筛选出 autoUpdateInterval 大于 0 的项。
 - 筛选出满足条件 (updateTime - t.updateTime) >= t.autoUpdateInterval * 60 的项。
 - 将筛选结果存储在 lstSubs 列表中。
7. 遍历 lstSubs 列表中的每一项:
 - 调用 updateHandle.UpdateSubscriptionProcess 方法,并传递参数 config、item.id、true 和回调函数 (bool success, string msg) => { ... }。
 - 如果回调函数中的 success 为 true,则调用 Utils.SaveLog 方法,将日志信息写入日志文件,日志信息为 "subscription" + msg。
 - 更新 item 的 updateTime 属性为 updateTime。
 - 使用 ConfigHandler.AddSubItem 方法,将 item 添加到 config 中。
 - 等待 5 秒。
8. 等待 60 秒。
9. 重复步骤 5 到步骤 8。
简单来说,这段代码的作用是在一个定时任务中循环执行一些操作。首先等待一段时间,然后根据一些条件从配置中获取需要更新的订阅项。接着遍历每个订阅项,执行订阅更新的操作,并更新相关的记录和配置。然后等待一段时间,再次重复这个过程。

把整个逻辑理一遍, updateTime的单位是秒, autoUpdateInterval的单位是分钟.

现在我们想把autoUpdateInterval的单位改成小时. 那么把 t.autoUpdateInterval * 60 改成 *60 *60 就行了.

把autoUpdateInterval乘60改成再乘60,单位就是小时

保存, 编译, 开始调试(或执行). 

用菜单也可以, 用快捷键也可以, 用快捷按钮也可以.

保存编译跑起来,确认界面文本已改


=======

完


正确答案放在GitHub上

https://github.com/crazypeace/v2rayN/tree/SubAutoUpdateInterval

评论