订阅列表可以调顺序

每行末尾两个箭头,鼠标划过那一行才显现。proxy-providers 是映射,顺序只
影响界面呈现,内核不看;交换的是两个用户订阅在映射里的位置,中间夹着的
链式副本留在原地——它们不在列表上,跟着挪只会把 diff 撑大。

顺序写在配置文件里,所以走保存链路,不是运行时动作。
This commit is contained in:
2026-08-14 14:06:11 +08:00
parent 23aa28fbea
commit 0f0ac3c4b7
4 changed files with 175 additions and 19 deletions
+43
View File
@@ -5,6 +5,7 @@ import {
addFileSubscription,
addSubscription,
listSubscriptions,
moveSubscription,
providerNames,
removeSubscription,
renameSubscription,
@@ -280,6 +281,48 @@ describe('删除前的引用检查', () => {
})
})
describe('调整订阅顺序', () => {
/** 三个用户订阅,外加一份接在中间的订阅副本。 */
function three(): ConfigObject {
let data: ConfigObject = {}
for (const name of ['A', 'B', 'C']) data = addSubscription(data, name, `https://${name}.example`)
return data
}
it('上移和下移交换相邻两个订阅', () => {
expect(listSubscriptions(moveSubscription(three(), 'B', -1)).map((s) => s.name)).toEqual([
'B',
'A',
'C',
])
expect(listSubscriptions(moveSubscription(three(), 'B', 1)).map((s) => s.name)).toEqual([
'A',
'C',
'B',
])
})
it('到头了原样返回,配置对象不变', () => {
const data = three()
expect(moveSubscription(data, 'A', -1)).toBe(data)
expect(moveSubscription(data, 'C', 1)).toBe(data)
expect(moveSubscription(data, '不存在', 1)).toBe(data)
})
it('夹在中间的订阅副本留在原地', () => {
const withCopy = applySetup(
{ ...three(), listeners: [{ name: 'test1', type: 'mixed', port: 7778 }] },
'test1',
{ proxy: { sources: ['B'], filter: null }, chain: { sources: ['B'], filter: null } },
)
const copy = chainProviderName('test1', 'B')
const before = Object.keys(withCopy['proxy-providers'] as ConfigObject).indexOf(copy)
const after = moveSubscription(withCopy, 'A', 1)
expect(listSubscriptions(after).map((s) => s.name)).toEqual(['B', 'A', 'C'])
expect(Object.keys(after['proxy-providers'] as ConfigObject).indexOf(copy)).toBe(before)
})
})
describe('缓存路径撞名', () => {
it('名字只差符号时净化成同一个路径,能认出来', () => {
const data = addSubscription({}, '订阅 A', 'https://a.example/sub')