You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
AdLike2048/assets/mx/module/gm/GmEasy.ts

184 lines
4.9 KiB

1 day ago
import { GmBuiltinPanelId, GmKind, type IGmCommand, type IGmConfirmData, type IGmNumberStepperData, type IGmTextAreaData } from './GmTypes';
import { GmRegistry } from './GmRegistry';
/**
* 极简 GM 注册器:链式写几行即可挂命令,不必手拼 IGmCommand。
*
* @example
* ```ts
* new GmEasy()
* .tab('常用')
* .btn('复制存档', () => copy())
* .sw('显示广告', () => on, v => set(v))
* .num('金钱', () => get(), v => set(v))
* .page('道具', 'itemPicker', () => '点选')
* .commit();
* ```
*/
export class GmEasy {
private readonly _cmds: IGmCommand[] = [];
private _group = '常用';
private _order = 0;
private _seq = 0;
/**
* 切换 Tab 分组(后续命令都进这个分组)。
*/
tab(name: string): this {
if (!name) {
console.warn('[GmEasy] tab 名为空');
return this;
}
this._group = name;
return this;
}
/**
* 快捷按钮:点一下执行。
*/
btn(title: string, run: () => void | Promise<void>): this {
this._push({
id: this._id('btn'),
title,
group: this._group,
kind: GmKind.Quick,
order: ++this._order,
run,
});
return this;
}
/**
* 滑动开关。
*/
sw(title: string, get: () => boolean, set: (on: boolean) => void): this {
this._push({
id: this._id('sw'),
title,
group: this._group,
kind: GmKind.Toggle,
order: ++this._order,
get,
set,
});
return this;
}
/**
* 数值:列表内「设为」覆盖 + ± 增减。
* @param setValue 写入绝对值(增减由壳层算好再传入)
*/
num(title: string, getValue: () => number, setValue: (v: number) => void, min = 0): this {
const panelData: IGmNumberStepperData = {
getValue,
apply: (v) => setValue(v),
min,
defaultMode: 'set',
};
this._push({
id: this._id('num'),
title,
group: this._group,
kind: GmKind.Content,
order: ++this._order,
panelId: GmBuiltinPanelId.numberStepper,
panelData,
summary: () => `${Math.floor(Number(getValue()) || 0)}`,
});
return this;
}
/**
* 打开已注册的内容面板(如道具点选)。
*/
page(title: string, panelId: string, summary?: () => string, panelData?: unknown): this {
this._push({
id: this._id('page'),
title,
group: this._group,
kind: GmKind.Content,
order: ++this._order,
panelId,
panelData,
summary: summary ?? (() => '›'),
});
return this;
}
/**
* 危险操作(二次确认)。
*/
danger(title: string, message: string, onConfirm: () => void): this {
const panelData: IGmConfirmData = { message, onConfirm };
this._push({
id: this._id('danger'),
title,
group: this._group,
kind: GmKind.Content,
order: ++this._order,
panelId: GmBuiltinPanelId.confirmQuick,
panelData,
summary: () => '危险',
});
return this;
}
/**
* 大段文本(如粘贴存档 JSON)。
*/
text(title: string, apply: (raw: string) => void, placeholder = '粘贴内容'): this {
const panelData: IGmTextAreaData = { placeholder, apply };
this._push({
id: this._id('text'),
title,
group: this._group,
kind: GmKind.Content,
order: ++this._order,
panelId: GmBuiltinPanelId.textArea,
panelData,
summary: () => '粘贴',
});
return this;
}
/**
* 当前 Tab 直接嵌入内容面板(整页展示,无列表入口)。
*/
embed(panelId: string): this {
this._push({
id: this._id('embed'),
title: this._group,
group: this._group,
kind: GmKind.Content,
order: ++this._order,
panelId,
embed: true,
});
return this;
}
/**
* 提交注册到 Registry。
*/
commit(): void {
if (this._cmds.length <= 0) {
console.warn('[GmEasy] commit 时没有任何命令');
return;
}
GmRegistry.register(this._cmds);
}
private _id(prefix: string): string {
this._seq++;
return `easy.${prefix}.${this._seq}`;
}
private _push(cmd: IGmCommand): void {
if (!cmd.title) {
console.warn('[GmEasy] 跳过无标题命令');
return;
}
this._cmds.push(cmd);
}
}