poi-plugin-inventory-cleaner 1.16.1 → 1.17.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/i18n/en-US.json +1 -0
- package/i18n/zh-CN.json +1 -0
- package/index.js +90 -5
- package/lib/quest-needs.js +0 -6
- package/lib/quest-status.js +4 -6
- package/package.json +1 -1
package/i18n/en-US.json
CHANGED
|
@@ -39,6 +39,7 @@
|
|
|
39
39
|
"stock.batchToggle": "Batch keep",
|
|
40
40
|
"stock.categoryAll": "All categories",
|
|
41
41
|
"stock.backToTop": "Back to top",
|
|
42
|
+
"stock.refreshQuest": "Reload quest data",
|
|
42
43
|
"stock.categoryTitle": "Filter by in-game equipment type",
|
|
43
44
|
"stock.sortTitle": "Sort by",
|
|
44
45
|
"stock.sortVerdict": "Guide verdict",
|
package/i18n/zh-CN.json
CHANGED
package/index.js
CHANGED
|
@@ -12,7 +12,8 @@ const {
|
|
|
12
12
|
summarize,
|
|
13
13
|
OTHER_CATEGORY,
|
|
14
14
|
} = require('./lib/inventory')
|
|
15
|
-
const { buildQuestNeeds } = require('./lib/quest-needs')
|
|
15
|
+
const { buildQuestNeeds, resetCaches: resetQuestNeeds } = require('./lib/quest-needs')
|
|
16
|
+
const { resetCaches: resetQuestStatus } = require('./lib/quest-status')
|
|
16
17
|
const { CSS } = require('./lib/style')
|
|
17
18
|
|
|
18
19
|
const DICTIONARIES = {
|
|
@@ -71,18 +72,34 @@ function getState() {
|
|
|
71
72
|
let snapshot = null
|
|
72
73
|
let snapshotEquips = null
|
|
73
74
|
let snapshotConst = null
|
|
75
|
+
let snapshotQuests = null
|
|
76
|
+
let snapshotExtQuest = null
|
|
74
77
|
|
|
75
78
|
function getSnapshot() {
|
|
76
79
|
const state = getState()
|
|
77
80
|
const equips =
|
|
78
81
|
state && state.info && state.info.equips ? state.info.equips : null
|
|
79
82
|
const constant = state ? state.const : null
|
|
80
|
-
|
|
83
|
+
const quests =
|
|
84
|
+
state && state.info && state.info.quests ? state.info.quests : null
|
|
85
|
+
const ext = state && state.ext ? state.ext : null
|
|
86
|
+
const extQuest =
|
|
87
|
+
(ext && (ext['poi-plugin-quest-info-2'] || ext['poi-plugin-quest-info'])) || null
|
|
88
|
+
|
|
89
|
+
if (
|
|
90
|
+
snapshot &&
|
|
91
|
+
snapshotEquips === equips &&
|
|
92
|
+
snapshotConst === constant &&
|
|
93
|
+
snapshotQuests === quests &&
|
|
94
|
+
snapshotExtQuest === extQuest
|
|
95
|
+
) {
|
|
81
96
|
return snapshot
|
|
82
97
|
}
|
|
83
98
|
snapshotEquips = equips
|
|
84
99
|
snapshotConst = constant
|
|
85
|
-
|
|
100
|
+
snapshotQuests = quests
|
|
101
|
+
snapshotExtQuest = extQuest
|
|
102
|
+
snapshot = state ? { info: { equips, quests }, const: constant, ext } : null
|
|
86
103
|
return snapshot
|
|
87
104
|
}
|
|
88
105
|
|
|
@@ -435,8 +452,33 @@ function App() {
|
|
|
435
452
|
const [batchOpen, setBatchOpen] = React.useState(false)
|
|
436
453
|
const [batchValues, setBatchValues] = React.useState({})
|
|
437
454
|
const [showTop, setShowTop] = React.useState(false)
|
|
455
|
+
const [questTick, setQuestTick] = React.useState(0)
|
|
438
456
|
const rootRef = React.useRef(null)
|
|
439
457
|
|
|
458
|
+
React.useEffect(() => {
|
|
459
|
+
const onResponse = (event) => {
|
|
460
|
+
const detail = event && event.detail
|
|
461
|
+
const path = detail && detail.path ? String(detail.path) : ''
|
|
462
|
+
if (!/questlist/.test(path)) return
|
|
463
|
+
resetQuestNeeds()
|
|
464
|
+
resetQuestStatus()
|
|
465
|
+
setQuestTick((value) => value + 1)
|
|
466
|
+
window.setTimeout(() => {
|
|
467
|
+
resetQuestNeeds()
|
|
468
|
+
resetQuestStatus()
|
|
469
|
+
setQuestTick((value) => value + 1)
|
|
470
|
+
}, 1500)
|
|
471
|
+
}
|
|
472
|
+
window.addEventListener('game.response', onResponse)
|
|
473
|
+
return () => window.removeEventListener('game.response', onResponse)
|
|
474
|
+
}, [])
|
|
475
|
+
|
|
476
|
+
const refreshQuestData = React.useCallback(() => {
|
|
477
|
+
resetQuestNeeds()
|
|
478
|
+
resetQuestStatus()
|
|
479
|
+
setQuestTick((value) => value + 1)
|
|
480
|
+
}, [])
|
|
481
|
+
|
|
440
482
|
const handleScroll = React.useCallback((event) => {
|
|
441
483
|
setShowTop(event.currentTarget.scrollTop > 400)
|
|
442
484
|
}, [])
|
|
@@ -446,6 +488,39 @@ function App() {
|
|
|
446
488
|
if (element) element.scrollTo({ top: 0, behavior: 'smooth' })
|
|
447
489
|
}, [])
|
|
448
490
|
|
|
491
|
+
// 窗口位置自愈:如果记住的位置在所有屏幕之外,挪回主屏
|
|
492
|
+
React.useEffect(() => {
|
|
493
|
+
try {
|
|
494
|
+
const remote = require('@electron/remote')
|
|
495
|
+
const windows = remote.BrowserWindow.getAllWindows()
|
|
496
|
+
const target = windows.find((win) =>
|
|
497
|
+
String(win.webContents.getURL() || '').includes('poi-plugin-inventory-cleaner'),
|
|
498
|
+
)
|
|
499
|
+
if (!target) return
|
|
500
|
+
const bounds = target.getBounds()
|
|
501
|
+
const displays = remote.screen.getAllDisplays()
|
|
502
|
+
const onScreen = displays.some((display) => {
|
|
503
|
+
const area = display.workArea
|
|
504
|
+
return (
|
|
505
|
+
bounds.x < area.x + area.width &&
|
|
506
|
+
bounds.x + bounds.width > area.x &&
|
|
507
|
+
bounds.y < area.y + area.height &&
|
|
508
|
+
bounds.y + bounds.height > area.y
|
|
509
|
+
)
|
|
510
|
+
})
|
|
511
|
+
if (onScreen) return
|
|
512
|
+
const area = remote.screen.getPrimaryDisplay().workArea
|
|
513
|
+
target.setBounds({
|
|
514
|
+
x: area.x + 80,
|
|
515
|
+
y: area.y + 60,
|
|
516
|
+
width: Math.min(1200, area.width - 160),
|
|
517
|
+
height: Math.min(900, area.height - 120),
|
|
518
|
+
})
|
|
519
|
+
} catch (_error) {
|
|
520
|
+
// 非 Electron 环境或没有权限时忽略
|
|
521
|
+
}
|
|
522
|
+
}, [])
|
|
523
|
+
|
|
449
524
|
const firstKeepSave = React.useRef(true)
|
|
450
525
|
React.useEffect(() => {
|
|
451
526
|
if (firstKeepSave.current) {
|
|
@@ -455,10 +530,10 @@ function App() {
|
|
|
455
530
|
saveKeeps(keeps)
|
|
456
531
|
}, [keeps])
|
|
457
532
|
|
|
458
|
-
const needs = React.useMemo(() => buildQuestNeeds(state), [state])
|
|
533
|
+
const needs = React.useMemo(() => buildQuestNeeds(state), [state, questTick])
|
|
459
534
|
const rows = React.useMemo(
|
|
460
535
|
() => buildInventory(state, { questNeeds: needs, keeps }),
|
|
461
|
-
[state, needs, keeps],
|
|
536
|
+
[state, needs, keeps, questTick],
|
|
462
537
|
)
|
|
463
538
|
const summary = React.useMemo(() => summarize(rows), [rows])
|
|
464
539
|
|
|
@@ -573,6 +648,16 @@ function App() {
|
|
|
573
648
|
h('option', { value: 'name' }, t('stock.sortName')),
|
|
574
649
|
h('option', { value: 'category' }, t('stock.sortCategory')),
|
|
575
650
|
),
|
|
651
|
+
h(
|
|
652
|
+
'button',
|
|
653
|
+
{
|
|
654
|
+
type: 'button',
|
|
655
|
+
className: 'stock-chip stock-refresh',
|
|
656
|
+
title: t('stock.refreshQuest'),
|
|
657
|
+
onClick: refreshQuestData,
|
|
658
|
+
},
|
|
659
|
+
'↻',
|
|
660
|
+
),
|
|
576
661
|
h(
|
|
577
662
|
'div',
|
|
578
663
|
{ className: 'stock-views' },
|
package/lib/quest-needs.js
CHANGED
|
@@ -123,8 +123,6 @@ function clampCount(value) {
|
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
function readCachedQuests(now = Date.now()) {
|
|
126
|
-
if (cacheState.quests && now - cacheState.at < CACHE_TTL) return cacheState.quests
|
|
127
|
-
|
|
128
126
|
const file = questCachePath()
|
|
129
127
|
try {
|
|
130
128
|
const stat = fs.statSync(file)
|
|
@@ -185,10 +183,6 @@ function questPlannerStatePath() {
|
|
|
185
183
|
* 里面的 observed 是它见过的任务(含标题/说明/状态),completed 是已完成集合。
|
|
186
184
|
*/
|
|
187
185
|
function readQuestPlanner(now = Date.now()) {
|
|
188
|
-
if (plannerCache.quests && now - plannerCache.at < CACHE_TTL) {
|
|
189
|
-
return plannerCache.quests
|
|
190
|
-
}
|
|
191
|
-
|
|
192
186
|
const file = questPlannerStatePath()
|
|
193
187
|
try {
|
|
194
188
|
const stat = fs.statSync(file)
|
package/lib/quest-status.js
CHANGED
|
@@ -62,10 +62,6 @@ function emptyPlannerState() {
|
|
|
62
62
|
}
|
|
63
63
|
|
|
64
64
|
function readPlannerState(now = Date.now()) {
|
|
65
|
-
if (plannerCache.completed && now - plannerCache.at < CACHE_TTL) {
|
|
66
|
-
return plannerCache
|
|
67
|
-
}
|
|
68
|
-
|
|
69
65
|
const file = questPlannerStatePath()
|
|
70
66
|
try {
|
|
71
67
|
const stat = fs.statSync(file)
|
|
@@ -189,8 +185,10 @@ function expandCompleted(completed, available) {
|
|
|
189
185
|
}
|
|
190
186
|
}
|
|
191
187
|
|
|
192
|
-
//
|
|
193
|
-
for (const no of available)
|
|
188
|
+
// 还能接的任务不算完成;但如果它同时出现在「确定完成」里,以确定完成为准
|
|
189
|
+
for (const no of available) {
|
|
190
|
+
if (!completed.has(no)) result.delete(no)
|
|
191
|
+
}
|
|
194
192
|
return result
|
|
195
193
|
}
|
|
196
194
|
|