poi-plugin-kai-planner 1.0.14 → 1.0.15

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "poi-plugin-kai-planner",
3
- "version": "1.0.14",
3
+ "version": "1.0.15",
4
4
  "main": "index.js",
5
5
  "author": "aulu",
6
6
  "contributors": ["aulu"],
@@ -2,13 +2,24 @@
2
2
  const { DailyTabV2 } = require("./tabs/daily/DailyTabV2");
3
3
  const { checkAndUpdateData } = require("../services/static/version/dataUpdateManager");
4
4
  const { readMeta } = require("../services/static/version/versionStore");
5
+ const {
6
+ DEFAULT_THEME_TOKENS,
7
+ readPoiTheme,
8
+ buildPlannerThemeTokens,
9
+ subscribePoiTheme,
10
+ themeTokensToCssVars,
11
+ } = require("./theme/poiTheme");
5
12
 
6
- const placeholderStyle = {
7
- padding: 12,
8
- background: "#111827",
9
- color: "#e5e7eb",
10
- borderRadius: 8,
11
- };
13
+ function buildPlaceholderStyle(themeTokens) {
14
+ const theme = themeTokens || DEFAULT_THEME_TOKENS;
15
+ return {
16
+ padding: 12,
17
+ background: theme.surfacePanel,
18
+ color: theme.textPrimary,
19
+ borderRadius: 8,
20
+ border: `1px solid ${theme.borderSubtle}`,
21
+ };
22
+ }
12
23
 
13
24
  function pad2(n) {
14
25
  return String(n).padStart(2, "0");
@@ -25,7 +36,6 @@ function formatSimpleTime(iso) {
25
36
 
26
37
  function readBundledManifestUpdatedAt() {
27
38
  try {
28
- // eslint-disable-next-line global-require
29
39
  const manifest = require("../data/static/data_manifest.json");
30
40
  if (manifest && manifest.updated_at) return String(manifest.updated_at);
31
41
  } catch {}
@@ -34,7 +44,6 @@ function readBundledManifestUpdatedAt() {
34
44
 
35
45
  function readEnableDebugFlag() {
36
46
  try {
37
- // eslint-disable-next-line global-require
38
47
  const pkg = require("../../package.json");
39
48
  const poiPlugin = pkg && pkg.poiPlugin ? pkg.poiPlugin : {};
40
49
  if (poiPlugin.enableDebug == null) return true;
@@ -55,19 +64,43 @@ class KaiPlannerApp extends React.Component {
55
64
  checkingUpdate: false,
56
65
  lastUpdateAtText: "-",
57
66
  updateTip: "",
67
+ themeTokens: buildPlannerThemeTokens(readPoiTheme(props.envWindow)),
58
68
  };
59
69
  this._WishlistTab = null;
60
70
  this._AcquisitionTab = null;
61
71
  this._DebugTab = null;
72
+ this._unsubscribeTheme = null;
73
+ this._themeWarmupTimer = null;
62
74
  this.enableDebug = readEnableDebugFlag();
63
75
  this.handleCheckUpdate = this.handleCheckUpdate.bind(this);
76
+ this.syncTheme = this.syncTheme.bind(this);
64
77
  }
65
78
 
66
79
  componentDidMount() {
80
+ this.syncTheme();
81
+ this._unsubscribeTheme = subscribePoiTheme(this.props.envWindow, (hostTheme) => {
82
+ this.setState({ themeTokens: buildPlannerThemeTokens(hostTheme) });
83
+ });
84
+ const schedule = this.props.envWindow && this.props.envWindow.setTimeout ? this.props.envWindow.setTimeout.bind(this.props.envWindow) : setTimeout;
85
+ this._themeWarmupTimer = schedule(() => this.syncTheme(), 0);
67
86
  this.syncUpdateMeta();
68
87
  this.handleCheckUpdate(false);
69
88
  }
70
89
 
90
+ componentWillUnmount() {
91
+ if (typeof this._unsubscribeTheme === "function") this._unsubscribeTheme();
92
+ if (this._themeWarmupTimer != null) {
93
+ const clear = this.props.envWindow && this.props.envWindow.clearTimeout ? this.props.envWindow.clearTimeout.bind(this.props.envWindow) : clearTimeout;
94
+ clear(this._themeWarmupTimer);
95
+ this._themeWarmupTimer = null;
96
+ }
97
+ }
98
+
99
+ syncTheme() {
100
+ const hostTheme = readPoiTheme(this.props.envWindow);
101
+ this.setState({ themeTokens: buildPlannerThemeTokens(hostTheme) });
102
+ }
103
+
71
104
  syncUpdateMeta() {
72
105
  try {
73
106
  const meta = readMeta();
@@ -98,14 +131,22 @@ class KaiPlannerApp extends React.Component {
98
131
  }
99
132
 
100
133
  render() {
134
+ const themeTokens = this.state.themeTokens || DEFAULT_THEME_TOKENS;
135
+ const placeholderStyle = buildPlaceholderStyle(themeTokens);
136
+ const rootStyle = {
137
+ padding: 12,
138
+ color: themeTokens.textPrimary,
139
+ background: themeTokens.surfaceBase,
140
+ ...themeTokensToCssVars(themeTokens),
141
+ };
101
142
  const tab = !this.enableDebug && this.state.tab === "debug" ? "daily" : this.state.tab;
102
143
  const tabButtonStyle = (key) => ({
103
144
  padding: "6px 10px",
104
145
  borderRadius: 8,
105
146
  cursor: "pointer",
106
- border: "1px solid #374151",
107
- background: tab === key ? "#1f2937" : "transparent",
108
- color: "#e5e7eb",
147
+ border: `1px solid ${themeTokens.borderSubtle}`,
148
+ background: tab === key ? themeTokens.buttonActiveBg : "transparent",
149
+ color: themeTokens.textPrimary,
109
150
  marginRight: 8,
110
151
  fontSize: 14,
111
152
  });
@@ -115,11 +156,11 @@ class KaiPlannerApp extends React.Component {
115
156
  content = React.createElement(DailyTabV2, {
116
157
  envWindow: this.props.envWindow,
117
158
  envCtx: this.props.envCtx,
159
+ themeTokens,
118
160
  });
119
161
  } else if (tab === "wishlist") {
120
162
  if (!this._WishlistTab && !this.state.wishlistLoadError) {
121
163
  try {
122
- // eslint-disable-next-line global-require
123
164
  this._WishlistTab = require("./tabs/wishlist/WishlistTabV2");
124
165
  } catch (error) {
125
166
  this.setState({ wishlistLoadError: String(error && error.stack ? error.stack : error) });
@@ -136,6 +177,7 @@ class KaiPlannerApp extends React.Component {
136
177
  content = React.createElement(this._WishlistTab, {
137
178
  envWindow: this.props.envWindow,
138
179
  envCtx: this.props.envCtx,
180
+ themeTokens,
139
181
  });
140
182
  } else {
141
183
  content = React.createElement("div", { style: placeholderStyle }, "【改修规划】加载中...");
@@ -143,7 +185,6 @@ class KaiPlannerApp extends React.Component {
143
185
  } else if (tab === "acquisition") {
144
186
  if (!this._AcquisitionTab && !this.state.acquisitionLoadError) {
145
187
  try {
146
- // eslint-disable-next-line global-require
147
188
  this._AcquisitionTab = require("./tabs/acquisition/AcquisitionTab");
148
189
  } catch (error) {
149
190
  this.setState({ acquisitionLoadError: String(error && error.stack ? error.stack : error) });
@@ -160,6 +201,7 @@ class KaiPlannerApp extends React.Component {
160
201
  content = React.createElement(this._AcquisitionTab, {
161
202
  envWindow: this.props.envWindow,
162
203
  envCtx: this.props.envCtx,
204
+ themeTokens,
163
205
  });
164
206
  } else {
165
207
  content = React.createElement("div", { style: placeholderStyle }, "【装备获取规划】加载中...");
@@ -167,7 +209,6 @@ class KaiPlannerApp extends React.Component {
167
209
  } else if (tab === "debug") {
168
210
  if (!this._DebugTab && !this.state.debugLoadError) {
169
211
  try {
170
- // eslint-disable-next-line global-require
171
212
  this._DebugTab = require("./tabs/debug/DebugTab");
172
213
  } catch (error) {
173
214
  this.setState({ debugLoadError: String(error && error.stack ? error.stack : error) });
@@ -184,6 +225,7 @@ class KaiPlannerApp extends React.Component {
184
225
  content = React.createElement(this._DebugTab, {
185
226
  envWindow: this.props.envWindow,
186
227
  envCtx: this.props.envCtx,
228
+ themeTokens,
187
229
  });
188
230
  } else {
189
231
  content = React.createElement("div", { style: placeholderStyle }, "【Debug】加载中...");
@@ -194,7 +236,7 @@ class KaiPlannerApp extends React.Component {
194
236
 
195
237
  return React.createElement(
196
238
  "div",
197
- { style: { padding: 12 } },
239
+ { className: "kai-planner-root", style: rootStyle },
198
240
  React.createElement(
199
241
  "div",
200
242
  { style: { marginBottom: 12, display: "flex", alignItems: "center", justifyContent: "space-between", gap: 12 } },
@@ -211,13 +253,13 @@ class KaiPlannerApp extends React.Component {
211
253
  React.createElement(
212
254
  "div",
213
255
  { style: { display: "flex", alignItems: "center", gap: 8, flexWrap: "wrap", justifyContent: "flex-end" } },
214
- React.createElement("span", { style: { fontSize: 14, opacity: 0.8 } }, `上一次数据源更新:${this.state.lastUpdateAtText}`),
256
+ React.createElement("span", { style: { fontSize: 14, color: themeTokens.textMuted } }, `上一次数据源更新:${this.state.lastUpdateAtText}`),
215
257
  React.createElement(
216
258
  "button",
217
259
  { style: tabButtonStyle("__check__"), onClick: () => this.handleCheckUpdate(true), disabled: this.state.checkingUpdate },
218
260
  this.state.checkingUpdate ? "检查中..." : "检查更新"
219
261
  ),
220
- this.state.updateTip ? React.createElement("span", { style: { fontSize: 14, opacity: 0.85 } }, this.state.updateTip) : null
262
+ this.state.updateTip ? React.createElement("span", { style: { fontSize: 14, color: themeTokens.textMuted } }, this.state.updateTip) : null
221
263
  )
222
264
  ),
223
265
  content
@@ -2,6 +2,7 @@
2
2
  const { MouseComboBox } = require("../wishlist/components/MouseComboBox");
3
3
  const { EVENT_COMBO_CLOSE_ALL, isInComboRoot } = require("../../../services/wishlist/dropdownInteraction");
4
4
  const { countNoteUnits } = require("../../../services/common/noteText");
5
+ const { DEFAULT_THEME_TOKENS } = require("../../theme/poiTheme");
5
6
 
6
7
  const NOTE_MAX_UNITS = 100;
7
8
 
@@ -18,26 +19,36 @@ function AcquisitionPlanForm({
18
19
  onClearEquip,
19
20
  onSubmit,
20
21
  onCancel,
22
+ themeTokens,
21
23
  }) {
22
24
  if (!visible) return null;
23
25
 
26
+ const theme = themeTokens || DEFAULT_THEME_TOKENS;
24
27
  const panelStyle = {
25
28
  marginTop: 10,
26
29
  padding: 10,
27
- border: "1px solid rgba(255,255,255,0.12)",
30
+ border: `1px solid ${theme.borderSubtle}`,
28
31
  borderRadius: 8,
29
- background: "rgba(0,0,0,0.12)",
32
+ background: theme.surfaceElevated,
30
33
  };
31
34
  const formRow = { display: "flex", gap: 8, alignItems: "center", flexWrap: "wrap", marginTop: 8 };
32
- const labelStyle = { width: 96, opacity: 0.88, fontWeight: 700 };
35
+ const labelStyle = { width: 96, color: theme.textMuted, fontWeight: 700 };
33
36
  const inputStyle = {
34
37
  padding: "6px 8px",
35
38
  borderRadius: 8,
36
- border: "1px solid rgba(255,255,255,0.12)",
37
- background: "rgba(0,0,0,0.15)",
38
- color: "#e5e7eb",
39
+ border: `1px solid ${theme.borderSubtle}`,
40
+ background: theme.surfaceInput,
41
+ color: theme.textPrimary,
39
42
  minWidth: 180,
40
43
  };
44
+ const chipStyle = {
45
+ border: `1px solid ${theme.info}`,
46
+ background: theme.mode === "light" ? "rgba(37,99,235,0.12)" : "rgba(59,130,246,0.14)",
47
+ color: theme.info,
48
+ borderRadius: 8,
49
+ padding: "4px 8px",
50
+ cursor: "pointer",
51
+ };
41
52
  const noteCount = countNoteUnits(form.note || "");
42
53
 
43
54
  return React.createElement(
@@ -64,6 +75,7 @@ function AcquisitionPlanForm({
64
75
  placeholder: mode === "edit" ? "编辑模式下不可修改装备" : "搜索并选择装备(名称/equipId)",
65
76
  onInputChange: (value) => onPatch({ equipQuery: value }),
66
77
  options: equipOptions,
78
+ themeTokens: theme,
67
79
  emptyText: "无匹配装备",
68
80
  onSelect: (value, option) => onSelectEquip(value, option),
69
81
  }),
@@ -73,14 +85,7 @@ function AcquisitionPlanForm({
73
85
  {
74
86
  type: "button",
75
87
  onClick: () => onClearEquip && onClearEquip(),
76
- style: {
77
- border: "1px solid rgba(147,197,253,0.45)",
78
- background: "rgba(59,130,246,0.14)",
79
- color: "#93c5fd",
80
- borderRadius: 8,
81
- padding: "4px 8px",
82
- cursor: "pointer",
83
- },
88
+ style: chipStyle,
84
89
  },
85
90
  `已选:${selectedEquipText} ×`
86
91
  )
@@ -116,7 +121,7 @@ function AcquisitionPlanForm({
116
121
  }),
117
122
  React.createElement(
118
123
  "div",
119
- { style: { marginTop: 4, opacity: 0.7, fontSize: 12, textAlign: "right" } },
124
+ { style: { marginTop: 4, color: theme.textMuted, fontSize: 12, textAlign: "right" } },
120
125
  `当前字数 ${noteCount}/${NOTE_MAX_UNITS}`
121
126
  )
122
127
  )
@@ -127,9 +132,8 @@ function AcquisitionPlanForm({
127
132
  React.createElement("button", { onClick: onSubmit }, mode === "edit" ? "保存" : "确认新增"),
128
133
  React.createElement("button", { onClick: onCancel }, "取消")
129
134
  ),
130
- error ? React.createElement("div", { style: { marginTop: 8, color: "#fca5a5" } }, error) : null
135
+ error ? React.createElement("div", { style: { marginTop: 8, color: theme.danger } }, error) : null
131
136
  );
132
137
  }
133
138
 
134
139
  module.exports = { AcquisitionPlanForm };
135
-