Files
ShortX_ToolHub/code/th_14_schema_editor.js
2026-05-23 01:48:19 +08:00

328 lines
14 KiB
JavaScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// ToolHub - Schema 编辑器模块
// 依赖th_14_panels.js 中的设置页基础 UI / showPanelAvoidBallth_05_persistence.js 的 ConfigManager。
// 注意:加载顺序必须位于 th_14_panels.js 之后、th_15_extra.js 之前。
// =======================【Schema 编辑面板】======================
FloatBallAppWM.prototype.buildSchemaEditorPanelView = function() {
var self = this;
if (this.state.editingSchemaIndex === undefined) {
this.state.editingSchemaIndex = null;
}
if (!this.state.keepSchemaEditorState || !this.state.tempSchema) {
var current = ConfigManager.loadSchema();
this.state.tempSchema = JSON.parse(JSON.stringify(current));
}
this.state.keepSchemaEditorState = false;
var schema = this.state.tempSchema;
var isEditing = (this.state.editingSchemaIndex !== null);
var isDark = this.isDarkTheme();
var C = this.ui.colors;
var bgColor = isDark ? C.bgDark : C.bgLight;
var cardColor = isDark ? C.cardDark : C.cardLight;
var textColor = isDark ? C.textPriDark : C.textPriLight;
var subTextColor = isDark ? C.textSecDark : C.textSecLight;
var dividerColor = isDark ? C.dividerDark : C.dividerLight;
var inputBgColor = isDark ? C.inputBgDark : C.inputBgLight;
var panel = this.ui.createStyledPanel(this, 16);
// --- Header ---
var header = this.ui.createStyledHeader(this, 12);
// Title removed to avoid redundancy with Wrapper Title
// var titleTv = new android.widget.TextView(context);
// titleTv.setText(isEditing ? (this.state.editingSchemaIndex === -1 ? "新增项" : "编辑项") : "设置布局管理");
// ...
// header.addView(titleTv);
// Placeholder to push buttons to right
header.addView(this.ui.createSpacer(this));
function refreshPanel() {
self.state.keepSchemaEditorState = true;
self.showPanelAvoidBall("schema_editor");
}
if (!isEditing) {
// List Mode
header.addView(self.ui.createFlatButton(self, "重置", C.danger, function() {
ConfigManager.resetSchema();
self.state.tempSchema = null;
self.toast("已重置为默认布局");
refreshPanel();
}));
header.addView(self.ui.createFlatButton(self, "新增", C.primary, function() {
self.state.editingSchemaIndex = -1;
if (self.state.toolAppActive && self.pushToolAppPage) self.pushToolAppPage("schema_editor");
else refreshPanel();
}));
var btnClose = self.ui.createFlatButton(self, "✕", C.textSecLight, function() {
self.state.tempSchema = null;
self.hideAllPanels();
});
header.addView(btnClose);
panel.addView(header);
panel.setTag(header); // 暴露 Header
// Save Button
var btnSaveAll = self.ui.createSolidButton(self, "保存生效", C.primary, android.graphics.Color.WHITE, function() {
ConfigManager.saveSchema(schema);
self.state.tempSchema = null;
self.toast("布局已保存");
if (self.state.toolAppActive && self.popToolAppPage) {
self.state.editingSchemaIndex = null;
self.popToolAppPage("schema_save_all");
} else {
self.hideAllPanels();
self.showPanelAvoidBall("settings");
}
});
var saveLp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
saveLp.setMargins(0, 0, 0, self.dp(8));
btnSaveAll.setLayoutParams(saveLp);
panel.addView(btnSaveAll);
// List
var scroll = new android.widget.ScrollView(context);
try { scroll.setVerticalScrollBarEnabled(false); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var list = new android.widget.LinearLayout(context);
list.setOrientation(android.widget.LinearLayout.VERTICAL);
list.setPadding(0, self.dp(4), 0, self.dp(4));
for (var i = 0; i < schema.length; i++) {
(function(idx) {
var item = schema[idx];
var card = new android.widget.LinearLayout(context);
card.setOrientation(android.widget.LinearLayout.HORIZONTAL);
card.setGravity(android.view.Gravity.CENTER_VERTICAL);
card.setBackground(self.ui.createRoundDrawable(cardColor, self.dp(8)));
try { card.setElevation(self.dp(2)); } catch(e) { safeLog(null, 'e', "catch " + String(e)); }
var cardLp = new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
cardLp.setMargins(self.dp(2), self.dp(4), self.dp(2), self.dp(4));
card.setLayoutParams(cardLp);
card.setPadding(self.dp(12), self.dp(12), self.dp(8), self.dp(12));
// Info
var infoBox = new android.widget.LinearLayout(context);
infoBox.setOrientation(android.widget.LinearLayout.VERTICAL);
var infoLp = new android.widget.LinearLayout.LayoutParams(0, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT);
infoLp.weight = 1;
infoBox.setLayoutParams(infoLp);
var nameTv = new android.widget.TextView(context);
nameTv.setText(String(item.name || item.key || "未命名"));
nameTv.setTextColor(textColor);
nameTv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 14);
if (item.type === "section") nameTv.setTypeface(null, android.graphics.Typeface.BOLD);
infoBox.addView(nameTv);
var typeTv = new android.widget.TextView(context);
var typeTxt = item.type;
if (item.type !== "section") typeTxt += " (" + (item.key || "?") + ")";
typeTv.setText(String(typeTxt));
typeTv.setTextColor(subTextColor);
typeTv.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 12);
infoBox.addView(typeTv);
card.addView(infoBox);
// Actions
var actions = new android.widget.LinearLayout(context);
actions.setOrientation(android.widget.LinearLayout.HORIZONTAL);
if (idx > 0) {
actions.addView(self.ui.createFlatButton(self, "↑", subTextColor, function() {
var temp = schema[idx];
schema[idx] = schema[idx - 1];
schema[idx - 1] = temp;
refreshPanel();
}));
}
if (idx < schema.length - 1) {
actions.addView(self.ui.createFlatButton(self, "↓", subTextColor, function() {
var temp = schema[idx];
schema[idx] = schema[idx + 1];
schema[idx + 1] = temp;
refreshPanel();
}));
}
actions.addView(self.ui.createFlatButton(self, "✎", C.primary, function() {
self.state.editingSchemaIndex = idx;
if (self.state.toolAppActive && self.pushToolAppPage) self.pushToolAppPage("schema_editor");
else refreshPanel();
}));
actions.addView(self.ui.createFlatButton(self, "✕", C.danger, function() {
schema.splice(idx, 1);
refreshPanel();
}));
card.addView(actions);
list.addView(card);
})(i);
}
scroll.addView(list);
panel.addView(scroll);
} else {
// Edit Mode
var editIdx = this.state.editingSchemaIndex;
var editItem = (editIdx === -1) ? { type: "bool", name: "", key: "" } : JSON.parse(JSON.stringify(schema[editIdx]));
var btnBack = self.ui.createFlatButton(self, "返回", C.textSecLight, function() {
self.state.editingSchemaIndex = null;
if (self.state.toolAppActive && self.popToolAppPage) {
self.state.keepSchemaEditorState = true;
self.popToolAppPage("schema_edit_back");
} else refreshPanel();
});
header.addView(btnBack);
panel.addView(header);
panel.setTag(header); // 暴露 Header
var schemaInlineNotice = new android.widget.TextView(context);
schemaInlineNotice.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 12);
schemaInlineNotice.setPadding(self.dp(12), self.dp(8), self.dp(12), self.dp(8));
schemaInlineNotice.setGravity(android.view.Gravity.CENTER_VERTICAL);
schemaInlineNotice.setVisibility(android.view.View.GONE);
function updateSchemaInlineNotice(msg, kind) {
try {
var k = String(kind || "info");
var color = (k === "error") ? C.error : C.primary;
var bg = (k === "error") ? self.withAlpha(C.error, isDark ? 0.20 : 0.10) : self.withAlpha(C.primary, isDark ? 0.18 : 0.10);
var stroke = (k === "error") ? self.withAlpha(C.error, isDark ? 0.44 : 0.30) : self.withAlpha(C.primary, isDark ? 0.34 : 0.22);
schemaInlineNotice.setText(String(msg || ""));
schemaInlineNotice.setTextColor(color);
schemaInlineNotice.setBackground(self.ui.createStrokeDrawable(bg, stroke, self.dp(1), self.dp(14)));
schemaInlineNotice.setVisibility(android.view.View.VISIBLE);
} catch(eSIN) { safeLog(null, 'e', "catch " + String(eSIN)); }
}
var scroll = new android.widget.ScrollView(context);
var form = new android.widget.LinearLayout(context);
form.setOrientation(android.widget.LinearLayout.VERTICAL);
form.addView(schemaInlineNotice, new android.widget.LinearLayout.LayoutParams(android.widget.LinearLayout.LayoutParams.MATCH_PARENT, android.widget.LinearLayout.LayoutParams.WRAP_CONTENT));
scroll.addView(form);
function createInput(label, key, inputType, hint) {
var box = new android.widget.LinearLayout(context);
box.setOrientation(android.widget.LinearLayout.VERTICAL);
box.setPadding(0, 0, 0, self.dp(12));
var lb = new android.widget.TextView(context);
lb.setText(label);
lb.setTextColor(subTextColor);
lb.setTextSize(android.util.TypedValue.COMPLEX_UNIT_SP, 12);
box.addView(lb);
var et = new android.widget.EditText(context);
et.setText(String(editItem[key] !== undefined ? editItem[key] : ""));
et.setTextColor(textColor);
et.setHint(hint || "");
et.setHintTextColor(self.withAlpha(subTextColor, 0.5));
et.setBackground(self.ui.createRoundDrawable(inputBgColor, self.dp(8)));
et.setPadding(self.dp(12), self.dp(8), self.dp(12), self.dp(8));
if (inputType) et.setInputType(inputType);
box.addView(et);
form.addView(box);
return {
getValue: function() { return String(et.getText()); },
getView: function() { return box; }
};
}
// Type Selector
var typeBox = new android.widget.LinearLayout(context);
typeBox.setOrientation(android.widget.LinearLayout.HORIZONTAL);
typeBox.setGravity(android.view.Gravity.CENTER_VERTICAL);
typeBox.setPadding(0, 0, 0, self.dp(12));
var typeLb = new android.widget.TextView(context);
typeLb.setText("类型: ");
typeLb.setTextColor(textColor);
typeBox.addView(typeLb);
var types = ["section", "bool", "int", "float", "text", "action"];
var typeBtn = self.ui.createSolidButton(self, editItem.type, C.accent, android.graphics.Color.WHITE, function(v) {
var currIdx = types.indexOf(editItem.type);
var nextIdx = (currIdx + 1) % types.length;
editItem.type = types[nextIdx];
refreshPanel();
});
typeBox.addView(typeBtn);
form.addView(typeBox);
var inputName = createInput("显示名称 (Name)", "name", android.text.InputType.TYPE_CLASS_TEXT, "例如:悬浮球大小");
var inputKey = null;
var inputMin = null;
var inputMax = null;
var inputStep = null;
var inputAction = null;
if (editItem.type !== "section") {
inputKey = createInput("配置键名 (Key)", "key", android.text.InputType.TYPE_CLASS_TEXT | android.text.InputType.TYPE_TEXT_FLAG_NO_SUGGESTIONS, "例如BALL_SIZE_DP");
}
if (editItem.type === "int" || editItem.type === "float") {
inputMin = createInput("最小值 (Min)", "min", android.text.InputType.TYPE_CLASS_NUMBER | android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
inputMax = createInput("最大值 (Max)", "max", android.text.InputType.TYPE_CLASS_NUMBER | android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL | android.text.InputType.TYPE_NUMBER_FLAG_SIGNED);
inputStep = createInput("步进 (Step)", "step", android.text.InputType.TYPE_CLASS_NUMBER | android.text.InputType.TYPE_NUMBER_FLAG_DECIMAL);
}
if (editItem.type === "action") {
inputAction = createInput("动作ID (Action)", "action", android.text.InputType.TYPE_CLASS_TEXT, "例如open_btn_mgr");
}
panel.addView(scroll);
// Save Button
var btnSave = self.ui.createSolidButton(self, "暂存", C.primary, android.graphics.Color.WHITE, function() {
try {
editItem.name = inputName.getValue();
if (inputKey) editItem.key = inputKey.getValue();
if (inputMin) editItem.min = Number(inputMin.getValue());
if (inputMax) editItem.max = Number(inputMax.getValue());
if (inputStep) editItem.step = Number(inputStep.getValue());
if (inputAction) editItem.action = inputAction.getValue();
// Clean up properties based on type
if (editItem.type === "section") { delete editItem.key; delete editItem.min; delete editItem.max; delete editItem.step; delete editItem.action; }
else if (editItem.type === "bool") { delete editItem.min; delete editItem.max; delete editItem.step; delete editItem.action; }
else if (editItem.type === "int" || editItem.type === "float") { delete editItem.action; }
else if (editItem.type === "action") { delete editItem.min; delete editItem.max; delete editItem.step; }
if (editIdx === -1) {
schema.push(editItem);
} else {
schema[editIdx] = editItem;
}
self.state.editingSchemaIndex = null;
if (self.state.toolAppActive && self.popToolAppPage) {
self.state.keepSchemaEditorState = true;
self.popToolAppPage("schema_edit_save");
} else refreshPanel();
} catch (e) {
updateSchemaInlineNotice("暂存失败: " + e, "error");
try { scroll.post(new java.lang.Runnable({ run: function() { try { scroll.fullScroll(android.view.View.FOCUS_UP); } catch(eScrollSchema) {} } })); } catch(ePostSchema) {}
}
});
var bottomBar = new android.widget.LinearLayout(context);
bottomBar.setOrientation(android.widget.LinearLayout.VERTICAL);
bottomBar.setPadding(0, self.dp(8), 0, 0);
bottomBar.addView(btnSave);
panel.addView(bottomBar);
}
return panel;
};