poi-plugin-inventory-cleaner 1.16.2 → 1.18.0
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 +5 -1
- package/i18n/zh-CN.json +5 -1
- package/index.js +142 -16
- package/lib/inventory.js +1 -1
- package/lib/quest-needs.js +0 -6
- package/lib/quest-status.js +107 -6
- package/lib/style.js +71 -3
- package/package.json +1 -1
package/i18n/en-US.json
CHANGED
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"stock.consumeQuestEquip": "quest (equip)",
|
|
30
30
|
"stock.consumeQuestStore": "quest (store)",
|
|
31
31
|
"stock.consumeOther": "other",
|
|
32
|
-
"stock.consumeHidden": "{{count}} completed quest(s) hidden",
|
|
32
|
+
"stock.consumeHidden": "{{count}} completed quest(s) hidden (click to view/undo)",
|
|
33
|
+
"stock.markDone": "Mark as completed",
|
|
34
|
+
"stock.undoDone": "Undo completed mark",
|
|
35
|
+
"stock.undo": "Undo",
|
|
33
36
|
"stock.keepLabel": "Keep",
|
|
34
37
|
"stock.keepUnit": "",
|
|
35
38
|
"stock.keepPlaceholder": "guide",
|
|
@@ -39,6 +42,7 @@
|
|
|
39
42
|
"stock.batchToggle": "Batch keep",
|
|
40
43
|
"stock.categoryAll": "All categories",
|
|
41
44
|
"stock.backToTop": "Back to top",
|
|
45
|
+
"stock.refreshQuest": "Reload quest data",
|
|
42
46
|
"stock.categoryTitle": "Filter by in-game equipment type",
|
|
43
47
|
"stock.sortTitle": "Sort by",
|
|
44
48
|
"stock.sortVerdict": "Guide verdict",
|
package/i18n/zh-CN.json
CHANGED
|
@@ -29,7 +29,10 @@
|
|
|
29
29
|
"stock.consumeQuestEquip": "任务·装",
|
|
30
30
|
"stock.consumeQuestStore": "任务·库",
|
|
31
31
|
"stock.consumeOther": "其他",
|
|
32
|
-
"stock.consumeHidden": "已隐藏 {{count}}
|
|
32
|
+
"stock.consumeHidden": "已隐藏 {{count}} 个已完成任务(点击查看/撤销)",
|
|
33
|
+
"stock.markDone": "标记为已完成",
|
|
34
|
+
"stock.undoDone": "撤销完成标记",
|
|
35
|
+
"stock.undo": "撤销",
|
|
33
36
|
"stock.keepLabel": "保留",
|
|
34
37
|
"stock.keepUnit": "件",
|
|
35
38
|
"stock.keepPlaceholder": "攻略",
|
|
@@ -39,6 +42,7 @@
|
|
|
39
42
|
"stock.batchToggle": "批量保留",
|
|
40
43
|
"stock.categoryAll": "全部类别",
|
|
41
44
|
"stock.backToTop": "回到顶部",
|
|
45
|
+
"stock.refreshQuest": "重新读取任务数据",
|
|
42
46
|
"stock.categoryTitle": "按游戏装备类型筛选",
|
|
43
47
|
"stock.sortTitle": "排序方式",
|
|
44
48
|
"stock.sortVerdict": "按攻略判定",
|
package/index.js
CHANGED
|
@@ -10,9 +10,16 @@ const {
|
|
|
10
10
|
stepKeep,
|
|
11
11
|
sortRows,
|
|
12
12
|
summarize,
|
|
13
|
+
questNoFromText,
|
|
13
14
|
OTHER_CATEGORY,
|
|
14
15
|
} = require('./lib/inventory')
|
|
15
|
-
const { buildQuestNeeds } = require('./lib/quest-needs')
|
|
16
|
+
const { buildQuestNeeds, resetCaches: resetQuestNeeds } = require('./lib/quest-needs')
|
|
17
|
+
const {
|
|
18
|
+
markManual,
|
|
19
|
+
recordQuestStates,
|
|
20
|
+
resetCaches: resetQuestStatus,
|
|
21
|
+
unmarkManual,
|
|
22
|
+
} = require('./lib/quest-status')
|
|
16
23
|
const { CSS } = require('./lib/style')
|
|
17
24
|
|
|
18
25
|
const DICTIONARIES = {
|
|
@@ -71,18 +78,34 @@ function getState() {
|
|
|
71
78
|
let snapshot = null
|
|
72
79
|
let snapshotEquips = null
|
|
73
80
|
let snapshotConst = null
|
|
81
|
+
let snapshotQuests = null
|
|
82
|
+
let snapshotExtQuest = null
|
|
74
83
|
|
|
75
84
|
function getSnapshot() {
|
|
76
85
|
const state = getState()
|
|
77
86
|
const equips =
|
|
78
87
|
state && state.info && state.info.equips ? state.info.equips : null
|
|
79
88
|
const constant = state ? state.const : null
|
|
80
|
-
|
|
89
|
+
const quests =
|
|
90
|
+
state && state.info && state.info.quests ? state.info.quests : null
|
|
91
|
+
const ext = state && state.ext ? state.ext : null
|
|
92
|
+
const extQuest =
|
|
93
|
+
(ext && (ext['poi-plugin-quest-info-2'] || ext['poi-plugin-quest-info'])) || null
|
|
94
|
+
|
|
95
|
+
if (
|
|
96
|
+
snapshot &&
|
|
97
|
+
snapshotEquips === equips &&
|
|
98
|
+
snapshotConst === constant &&
|
|
99
|
+
snapshotQuests === quests &&
|
|
100
|
+
snapshotExtQuest === extQuest
|
|
101
|
+
) {
|
|
81
102
|
return snapshot
|
|
82
103
|
}
|
|
83
104
|
snapshotEquips = equips
|
|
84
105
|
snapshotConst = constant
|
|
85
|
-
|
|
106
|
+
snapshotQuests = quests
|
|
107
|
+
snapshotExtQuest = extQuest
|
|
108
|
+
snapshot = state ? { info: { equips, quests }, const: constant, ext } : null
|
|
86
109
|
return snapshot
|
|
87
110
|
}
|
|
88
111
|
|
|
@@ -257,7 +280,7 @@ function CategoryPicker({ value, groups, onChange }) {
|
|
|
257
280
|
)
|
|
258
281
|
}
|
|
259
282
|
|
|
260
|
-
function StockRow({ row, onKeepChange }) {
|
|
283
|
+
function StockRow({ row, onKeepChange, onMarkDone, onUndoDone }) {
|
|
261
284
|
const verdict = VERDICT[row.verdict] || VERDICT.unknown
|
|
262
285
|
return h(
|
|
263
286
|
'div',
|
|
@@ -365,20 +388,63 @@ function StockRow({ row, onKeepChange }) {
|
|
|
365
388
|
h(
|
|
366
389
|
'ol',
|
|
367
390
|
{ className: 'stock-consume-list' },
|
|
368
|
-
row.consumedItems
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
391
|
+
row.consumedItems
|
|
392
|
+
.filter((item) => !item.done)
|
|
393
|
+
.map((item, index) =>
|
|
394
|
+
h(
|
|
395
|
+
'li',
|
|
396
|
+
{ key: index, className: 'is-' + item.kind },
|
|
397
|
+
h('span', { className: 'stock-consume-tag' }, consumeLabel(item.tag)),
|
|
398
|
+
h('span', { className: 'stock-consume-text' }, item.text),
|
|
399
|
+
item.kind === 'quest'
|
|
400
|
+
? h(
|
|
401
|
+
'button',
|
|
402
|
+
{
|
|
403
|
+
type: 'button',
|
|
404
|
+
className: 'stock-consume-done',
|
|
405
|
+
title: t('stock.markDone'),
|
|
406
|
+
onClick: () =>
|
|
407
|
+
onMarkDone(questNoFromText(item.text), item.text),
|
|
408
|
+
},
|
|
409
|
+
'✓',
|
|
410
|
+
)
|
|
411
|
+
: null,
|
|
412
|
+
),
|
|
374
413
|
),
|
|
375
|
-
),
|
|
376
414
|
),
|
|
377
415
|
row.consumedHidden > 0
|
|
378
416
|
? h(
|
|
379
|
-
'
|
|
417
|
+
'details',
|
|
380
418
|
{ className: 'stock-consume-hidden' },
|
|
381
|
-
|
|
419
|
+
h(
|
|
420
|
+
'summary',
|
|
421
|
+
null,
|
|
422
|
+
t('stock.consumeHidden', { count: row.consumedHidden }),
|
|
423
|
+
),
|
|
424
|
+
h(
|
|
425
|
+
'ul',
|
|
426
|
+
{ className: 'stock-consume-done-list' },
|
|
427
|
+
row.consumedItems
|
|
428
|
+
.filter((item) => item.done)
|
|
429
|
+
.map((item, index) =>
|
|
430
|
+
h(
|
|
431
|
+
'li',
|
|
432
|
+
{ key: index, className: 'is-' + item.kind },
|
|
433
|
+
h('span', { className: 'stock-consume-tag' }, consumeLabel(item.tag)),
|
|
434
|
+
h('span', { className: 'stock-consume-text' }, item.text),
|
|
435
|
+
h(
|
|
436
|
+
'button',
|
|
437
|
+
{
|
|
438
|
+
type: 'button',
|
|
439
|
+
className: 'stock-consume-undo',
|
|
440
|
+
title: t('stock.undoDone'),
|
|
441
|
+
onClick: () => onUndoDone(questNoFromText(item.text)),
|
|
442
|
+
},
|
|
443
|
+
t('stock.undo'),
|
|
444
|
+
),
|
|
445
|
+
),
|
|
446
|
+
),
|
|
447
|
+
),
|
|
382
448
|
)
|
|
383
449
|
: null,
|
|
384
450
|
)
|
|
@@ -435,8 +501,50 @@ function App() {
|
|
|
435
501
|
const [batchOpen, setBatchOpen] = React.useState(false)
|
|
436
502
|
const [batchValues, setBatchValues] = React.useState({})
|
|
437
503
|
const [showTop, setShowTop] = React.useState(false)
|
|
504
|
+
const [questTick, setQuestTick] = React.useState(0)
|
|
438
505
|
const rootRef = React.useRef(null)
|
|
439
506
|
|
|
507
|
+
React.useEffect(() => {
|
|
508
|
+
const onResponse = (event) => {
|
|
509
|
+
const detail = event && event.detail
|
|
510
|
+
const path = detail && detail.path ? String(detail.path) : ''
|
|
511
|
+
if (!/questlist/.test(path)) return
|
|
512
|
+
try {
|
|
513
|
+
recordQuestStates(detail)
|
|
514
|
+
} catch (_error) {
|
|
515
|
+
// 记录失败不影响刷新
|
|
516
|
+
}
|
|
517
|
+
resetQuestNeeds()
|
|
518
|
+
resetQuestStatus()
|
|
519
|
+
setQuestTick((value) => value + 1)
|
|
520
|
+
window.setTimeout(() => {
|
|
521
|
+
resetQuestNeeds()
|
|
522
|
+
resetQuestStatus()
|
|
523
|
+
setQuestTick((value) => value + 1)
|
|
524
|
+
}, 1500)
|
|
525
|
+
}
|
|
526
|
+
window.addEventListener('game.response', onResponse)
|
|
527
|
+
return () => window.removeEventListener('game.response', onResponse)
|
|
528
|
+
}, [])
|
|
529
|
+
|
|
530
|
+
const refreshQuestData = React.useCallback(() => {
|
|
531
|
+
resetQuestNeeds()
|
|
532
|
+
resetQuestStatus()
|
|
533
|
+
setQuestTick((value) => value + 1)
|
|
534
|
+
}, [])
|
|
535
|
+
|
|
536
|
+
const handleMarkDone = React.useCallback((no, title) => {
|
|
537
|
+
if (!no) return
|
|
538
|
+
markManual(no, title)
|
|
539
|
+
setQuestTick((value) => value + 1)
|
|
540
|
+
}, [])
|
|
541
|
+
|
|
542
|
+
const handleUndoDone = React.useCallback((no) => {
|
|
543
|
+
if (!no) return
|
|
544
|
+
unmarkManual(no)
|
|
545
|
+
setQuestTick((value) => value + 1)
|
|
546
|
+
}, [])
|
|
547
|
+
|
|
440
548
|
const handleScroll = React.useCallback((event) => {
|
|
441
549
|
setShowTop(event.currentTarget.scrollTop > 400)
|
|
442
550
|
}, [])
|
|
@@ -488,10 +596,10 @@ function App() {
|
|
|
488
596
|
saveKeeps(keeps)
|
|
489
597
|
}, [keeps])
|
|
490
598
|
|
|
491
|
-
const needs = React.useMemo(() => buildQuestNeeds(state), [state])
|
|
599
|
+
const needs = React.useMemo(() => buildQuestNeeds(state), [state, questTick])
|
|
492
600
|
const rows = React.useMemo(
|
|
493
601
|
() => buildInventory(state, { questNeeds: needs, keeps }),
|
|
494
|
-
[state, needs, keeps],
|
|
602
|
+
[state, needs, keeps, questTick],
|
|
495
603
|
)
|
|
496
604
|
const summary = React.useMemo(() => summarize(rows), [rows])
|
|
497
605
|
|
|
@@ -606,6 +714,16 @@ function App() {
|
|
|
606
714
|
h('option', { value: 'name' }, t('stock.sortName')),
|
|
607
715
|
h('option', { value: 'category' }, t('stock.sortCategory')),
|
|
608
716
|
),
|
|
717
|
+
h(
|
|
718
|
+
'button',
|
|
719
|
+
{
|
|
720
|
+
type: 'button',
|
|
721
|
+
className: 'stock-chip stock-refresh',
|
|
722
|
+
title: t('stock.refreshQuest'),
|
|
723
|
+
onClick: refreshQuestData,
|
|
724
|
+
},
|
|
725
|
+
'↻',
|
|
726
|
+
),
|
|
609
727
|
h(
|
|
610
728
|
'div',
|
|
611
729
|
{ className: 'stock-views' },
|
|
@@ -729,7 +847,15 @@ function App() {
|
|
|
729
847
|
: h(
|
|
730
848
|
'div',
|
|
731
849
|
{ className: 'stock-list' },
|
|
732
|
-
visible.map((row) =>
|
|
850
|
+
visible.map((row) =>
|
|
851
|
+
h(StockRow, {
|
|
852
|
+
key: row.id,
|
|
853
|
+
row,
|
|
854
|
+
onKeepChange: handleKeepChange,
|
|
855
|
+
onMarkDone: handleMarkDone,
|
|
856
|
+
onUndoDone: handleUndoDone,
|
|
857
|
+
}),
|
|
858
|
+
),
|
|
733
859
|
),
|
|
734
860
|
h('p', { className: 'stock-warn' }, t('stock.warn')),
|
|
735
861
|
h('p', { className: 'stock-source' }, t('stock.source')),
|
package/lib/inventory.js
CHANGED
|
@@ -168,7 +168,7 @@ function buildInventory(state, options = {}) {
|
|
|
168
168
|
usage: rule ? rule.usage : '',
|
|
169
169
|
obtain: rule ? rule.obtain : '',
|
|
170
170
|
consumed,
|
|
171
|
-
consumedItems: allConsumed
|
|
171
|
+
consumedItems: allConsumed,
|
|
172
172
|
consumedHidden: allConsumed.filter((item) => item.done).length,
|
|
173
173
|
stage: guide ? guide.stage : '',
|
|
174
174
|
note: guide ? guide.note : '',
|
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
|
@@ -57,15 +57,107 @@ function questPlannerStatePath() {
|
|
|
57
57
|
return path.join(root, 'state.json')
|
|
58
58
|
}
|
|
59
59
|
|
|
60
|
+
function pluginDataDir() {
|
|
61
|
+
return path.join(appDataPath(), 'poi', 'plugin-data', 'poi-plugin-inventory-cleaner')
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function readJsonFile(file) {
|
|
65
|
+
try {
|
|
66
|
+
return JSON.parse(fs.readFileSync(file, 'utf8').replace(/^\uFEFF/, ''))
|
|
67
|
+
} catch (_error) {
|
|
68
|
+
return null
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function writeJsonFile(file, value) {
|
|
73
|
+
try {
|
|
74
|
+
fs.mkdirSync(path.dirname(file), { recursive: true })
|
|
75
|
+
fs.writeFileSync(file, JSON.stringify(value, null, 1), 'utf8')
|
|
76
|
+
} catch (_error) {
|
|
77
|
+
// 写不进就只影响本次
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function manualPath() {
|
|
82
|
+
return path.join(pluginDataDir(), 'quest-manual.json')
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function autoPath() {
|
|
86
|
+
return path.join(pluginDataDir(), 'quest-auto.json')
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
function readMarked(file) {
|
|
90
|
+
const raw = readJsonFile(file)
|
|
91
|
+
const nos = new Set()
|
|
92
|
+
if (raw && typeof raw === 'object') {
|
|
93
|
+
for (const key of Object.keys(raw)) {
|
|
94
|
+
const no = Number(key)
|
|
95
|
+
if (no) nos.add(no)
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
return nos
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** 用户手动标记完成的任务。 */
|
|
102
|
+
function getManualCompleted() {
|
|
103
|
+
return readMarked(manualPath())
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/** 从任务列表响应里记下来的「达成」任务(api_state === 3)。 */
|
|
107
|
+
function getAutoCompleted() {
|
|
108
|
+
return readMarked(autoPath())
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
function markManual(no, title) {
|
|
112
|
+
const value = Number(no)
|
|
113
|
+
if (!value) return false
|
|
114
|
+
const file = manualPath()
|
|
115
|
+
const raw = readJsonFile(file) || {}
|
|
116
|
+
raw[String(value)] = { at: Date.now(), title: String(title || '') }
|
|
117
|
+
writeJsonFile(file, raw)
|
|
118
|
+
return true
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
function unmarkManual(no) {
|
|
122
|
+
const value = Number(no)
|
|
123
|
+
if (!value) return false
|
|
124
|
+
const file = manualPath()
|
|
125
|
+
const raw = readJsonFile(file) || {}
|
|
126
|
+
if (!raw[String(value)]) return false
|
|
127
|
+
delete raw[String(value)]
|
|
128
|
+
writeJsonFile(file, raw)
|
|
129
|
+
return true
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
/**
|
|
133
|
+
* 记录一次 questlist 响应:api_state === 3 的任务记为已完成,长期保存。
|
|
134
|
+
*/
|
|
135
|
+
function recordQuestStates(detail) {
|
|
136
|
+
const body = detail && detail.body
|
|
137
|
+
const list = body && Array.isArray(body.api_list) ? body.api_list : null
|
|
138
|
+
if (!list || list.length === 0) return 0
|
|
139
|
+
|
|
140
|
+
const file = autoPath()
|
|
141
|
+
const raw = readJsonFile(file) || {}
|
|
142
|
+
let added = 0
|
|
143
|
+
for (const quest of list) {
|
|
144
|
+
if (!quest) continue
|
|
145
|
+
const no = Number(quest.api_no)
|
|
146
|
+
if (!no || Number(quest.api_state) !== 3) continue
|
|
147
|
+
if (!raw[String(no)]) {
|
|
148
|
+
raw[String(no)] = { at: Date.now(), title: String(quest.api_title || '') }
|
|
149
|
+
added += 1
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
if (added > 0) writeJsonFile(file, raw)
|
|
153
|
+
return added
|
|
154
|
+
}
|
|
155
|
+
|
|
60
156
|
function emptyPlannerState() {
|
|
61
157
|
return { completed: new Set(), available: new Set() }
|
|
62
158
|
}
|
|
63
159
|
|
|
64
160
|
function readPlannerState(now = Date.now()) {
|
|
65
|
-
if (plannerCache.completed && now - plannerCache.at < CACHE_TTL) {
|
|
66
|
-
return plannerCache
|
|
67
|
-
}
|
|
68
|
-
|
|
69
161
|
const file = questPlannerStatePath()
|
|
70
162
|
try {
|
|
71
163
|
const stat = fs.statSync(file)
|
|
@@ -189,8 +281,10 @@ function expandCompleted(completed, available) {
|
|
|
189
281
|
}
|
|
190
282
|
}
|
|
191
283
|
|
|
192
|
-
//
|
|
193
|
-
for (const no of available)
|
|
284
|
+
// 还能接的任务不算完成;但如果它同时出现在「确定完成」里,以确定完成为准
|
|
285
|
+
for (const no of available) {
|
|
286
|
+
if (!completed.has(no)) result.delete(no)
|
|
287
|
+
}
|
|
194
288
|
return result
|
|
195
289
|
}
|
|
196
290
|
|
|
@@ -201,6 +295,8 @@ function getCompletedQuestNos(state) {
|
|
|
201
295
|
const completed = new Set([
|
|
202
296
|
...fromState.completed,
|
|
203
297
|
...planner.completed,
|
|
298
|
+
...getManualCompleted(),
|
|
299
|
+
...getAutoCompleted(),
|
|
204
300
|
])
|
|
205
301
|
const available = new Set([
|
|
206
302
|
...fromState.available,
|
|
@@ -217,8 +313,13 @@ function resetCaches() {
|
|
|
217
313
|
|
|
218
314
|
module.exports = {
|
|
219
315
|
expandCompleted,
|
|
316
|
+
getAutoCompleted,
|
|
220
317
|
getCompletedQuestNos,
|
|
318
|
+
getManualCompleted,
|
|
319
|
+
markManual,
|
|
221
320
|
readCachedAvailable,
|
|
222
321
|
readPlannerState,
|
|
322
|
+
recordQuestStates,
|
|
223
323
|
resetCaches,
|
|
324
|
+
unmarkManual,
|
|
224
325
|
}
|
package/lib/style.js
CHANGED
|
@@ -438,9 +438,77 @@ const CSS = `
|
|
|
438
438
|
}
|
|
439
439
|
|
|
440
440
|
.stock-consume-hidden {
|
|
441
|
-
margin-top:
|
|
442
|
-
font-size:
|
|
443
|
-
opacity: 0.
|
|
441
|
+
margin-top: 4px;
|
|
442
|
+
font-size: 10.5px;
|
|
443
|
+
opacity: 0.55;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
.stock-consume-hidden > summary {
|
|
447
|
+
cursor: pointer;
|
|
448
|
+
list-style: none;
|
|
449
|
+
user-select: none;
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
.stock-consume-hidden > summary::-webkit-details-marker {
|
|
453
|
+
display: none;
|
|
454
|
+
}
|
|
455
|
+
|
|
456
|
+
.stock-consume-done-list {
|
|
457
|
+
margin: 4px 0 0;
|
|
458
|
+
padding: 0;
|
|
459
|
+
list-style: none;
|
|
460
|
+
display: grid;
|
|
461
|
+
gap: 3px;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
.stock-consume-done-list li {
|
|
465
|
+
display: flex;
|
|
466
|
+
align-items: baseline;
|
|
467
|
+
gap: 6px;
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
.stock-consume-done-list .stock-consume-text {
|
|
471
|
+
text-decoration: line-through;
|
|
472
|
+
opacity: 0.7;
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
.stock-consume-done {
|
|
476
|
+
flex: none;
|
|
477
|
+
width: 20px;
|
|
478
|
+
height: 20px;
|
|
479
|
+
padding: 0;
|
|
480
|
+
border: 1px solid var(--stock-border);
|
|
481
|
+
border-radius: 5px;
|
|
482
|
+
color: var(--stock-green);
|
|
483
|
+
background: transparent;
|
|
484
|
+
font-family: inherit;
|
|
485
|
+
font-size: 11px;
|
|
486
|
+
line-height: 1;
|
|
487
|
+
cursor: pointer;
|
|
488
|
+
opacity: 0.55;
|
|
489
|
+
}
|
|
490
|
+
|
|
491
|
+
.stock-consume-done:hover {
|
|
492
|
+
opacity: 1;
|
|
493
|
+
border-color: var(--stock-green);
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
.stock-consume-undo {
|
|
497
|
+
flex: none;
|
|
498
|
+
height: 18px;
|
|
499
|
+
padding: 0 6px;
|
|
500
|
+
border: 1px solid var(--stock-border);
|
|
501
|
+
border-radius: 5px;
|
|
502
|
+
color: inherit;
|
|
503
|
+
background: transparent;
|
|
504
|
+
font-family: inherit;
|
|
505
|
+
font-size: 9.5px;
|
|
506
|
+
cursor: pointer;
|
|
507
|
+
}
|
|
508
|
+
|
|
509
|
+
.stock-consume-undo:hover {
|
|
510
|
+
border-color: var(--stock-indigo);
|
|
511
|
+
color: var(--stock-indigo);
|
|
444
512
|
}
|
|
445
513
|
|
|
446
514
|
.stock-consume-text {
|