mirror of
https://github.com/eondrcode/obsidian-manager.git
synced 2026-07-22 11:40:24 +00:00
0.0.1
This commit is contained in:
commit
4b94eeaa81
32 changed files with 3845 additions and 0 deletions
10
.editorconfig
Normal file
10
.editorconfig
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
indent_style = tab
|
||||
indent_size = 4
|
||||
tab_width = 4
|
||||
3
.eslintignore
Normal file
3
.eslintignore
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
node_modules/
|
||||
|
||||
main.js
|
||||
23
.eslintrc
Normal file
23
.eslintrc
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"root": true,
|
||||
"parser": "@typescript-eslint/parser",
|
||||
"env": { "node": true },
|
||||
"plugins": [
|
||||
"@typescript-eslint"
|
||||
],
|
||||
"extends": [
|
||||
"eslint:recommended",
|
||||
"plugin:@typescript-eslint/eslint-recommended",
|
||||
"plugin:@typescript-eslint/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"sourceType": "module"
|
||||
},
|
||||
"rules": {
|
||||
"no-unused-vars": "off",
|
||||
"@typescript-eslint/no-unused-vars": ["error", { "args": "none" }],
|
||||
"@typescript-eslint/ban-ts-comment": "off",
|
||||
"no-prototype-builtins": "off",
|
||||
"@typescript-eslint/no-empty-function": "off"
|
||||
}
|
||||
}
|
||||
27
.gitignore
vendored
Normal file
27
.gitignore
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# vscode
|
||||
.vscode
|
||||
|
||||
# Intellij
|
||||
*.iml
|
||||
.idea
|
||||
|
||||
# npm
|
||||
node_modules
|
||||
|
||||
# 不要将编译后的 `main.js` 文件放入代码库中。应该将其上传到 GitHub 发布版中。
|
||||
main.js
|
||||
|
||||
# Exclude sourcemaps
|
||||
*.map
|
||||
|
||||
# obsidian
|
||||
data.json
|
||||
|
||||
# 排除macOS Finder (System Explorer)视图状态
|
||||
.DS_Store
|
||||
|
||||
# 无
|
||||
笔记.md
|
||||
repealed.ts
|
||||
README.md
|
||||
i18n
|
||||
1
.npmrc
Normal file
1
.npmrc
Normal file
|
|
@ -0,0 +1 @@
|
|||
tag-version-prefix=""
|
||||
21
LICENSE
Normal file
21
LICENSE
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 zero
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
44
esbuild.config.mjs
Normal file
44
esbuild.config.mjs
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
import esbuild from "esbuild";
|
||||
import process from "process";
|
||||
import builtins from "builtin-modules";
|
||||
|
||||
const banner = ``;
|
||||
|
||||
const prod = (process.argv[2] === "production");
|
||||
|
||||
const context = await esbuild.context({
|
||||
banner: {
|
||||
js: banner,
|
||||
},
|
||||
// 修改启动路径
|
||||
entryPoints: ["main.ts"],
|
||||
bundle: true,
|
||||
external: [
|
||||
"obsidian",
|
||||
"electron",
|
||||
"@codemirror/autocomplete",
|
||||
"@codemirror/collab",
|
||||
"@codemirror/commands",
|
||||
"@codemirror/language",
|
||||
"@codemirror/lint",
|
||||
"@codemirror/search",
|
||||
"@codemirror/state",
|
||||
"@codemirror/view",
|
||||
"@lezer/common",
|
||||
"@lezer/highlight",
|
||||
"@lezer/lr",
|
||||
...builtins],
|
||||
format: "cjs",
|
||||
target: "es2018",
|
||||
logLevel: "info",
|
||||
sourcemap: prod ? false : "inline",
|
||||
treeShaking: true,
|
||||
outfile: "main.js",
|
||||
});
|
||||
|
||||
if (prod) {
|
||||
await context.rebuild();
|
||||
process.exit(0);
|
||||
} else {
|
||||
await context.watch();
|
||||
}
|
||||
3
main.ts
Normal file
3
main.ts
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
import I18n from './src/main'
|
||||
|
||||
export default I18n
|
||||
10
manifest.json
Normal file
10
manifest.json
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
{
|
||||
"id": "manager",
|
||||
"name": "Manager",
|
||||
"version": "0.0.1",
|
||||
"minAppVersion": "1.5.8",
|
||||
"description": "打造您的极致插件管理体验,让插件管理变得更加直观、高效,同时提升您的工作流程和个性化设置。",
|
||||
"author": "zero",
|
||||
"authorUrl": "https://github.com/0011000000110010/",
|
||||
"isDesktopOnly": true
|
||||
}
|
||||
2089
package-lock.json
generated
Normal file
2089
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load diff
24
package.json
Normal file
24
package.json
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
{
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"description": "This is a sample plugin for Obsidian (https://obsidian.md)",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
"dev": "node esbuild.config.mjs",
|
||||
"build": "tsc -noEmit -skipLibCheck && node esbuild.config.mjs production",
|
||||
"version": "node version-bump.mjs && git add manifest.json versions.json"
|
||||
},
|
||||
"keywords": [],
|
||||
"author": "",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
"@typescript-eslint/eslint-plugin": "5.29.0",
|
||||
"@typescript-eslint/parser": "5.29.0",
|
||||
"builtin-modules": "3.3.0",
|
||||
"esbuild": "0.17.3",
|
||||
"obsidian": "latest",
|
||||
"tslib": "2.4.0",
|
||||
"typescript": "4.7.4"
|
||||
}
|
||||
}
|
||||
14
src/command.ts
Normal file
14
src/command.ts
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
import { App } from "obsidian";
|
||||
import I18N from "./main";
|
||||
import { ManagerModal } from "./modal/manager-modal";
|
||||
import { t } from "./lang/inxdex";
|
||||
|
||||
const Commands = (app: App, i18n: I18N) => {
|
||||
i18n.addCommand({
|
||||
id: 'i18n-translate',
|
||||
name: t('命令_管理面板_描述'),
|
||||
callback: () => { new ManagerModal(app, i18n).open() }
|
||||
});
|
||||
}
|
||||
|
||||
export default Commands
|
||||
20
src/data/data.ts
Normal file
20
src/data/data.ts
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
export const ITEM_STYLE = {
|
||||
'alwaysExpand': '始终展开',
|
||||
'neverExpand': '永不展开',
|
||||
'hoverExpand': '悬浮展开',
|
||||
'clickExpand': '单击展开'
|
||||
}
|
||||
|
||||
export const GROUP_STYLE = {
|
||||
'a': '样式一',
|
||||
'b': '样式二',
|
||||
'c': '样式三',
|
||||
'd': '样式四'
|
||||
}
|
||||
|
||||
export const TAG_STYLE = {
|
||||
'a': '样式一',
|
||||
'b': '样式二',
|
||||
'c': '样式三',
|
||||
'd': '样式四'
|
||||
}
|
||||
22
src/data/types.ts
Normal file
22
src/data/types.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
export interface ManagerPlugin {
|
||||
id: string;
|
||||
name: string;
|
||||
desc: string;
|
||||
group: string;
|
||||
tags: string[];
|
||||
enabled: boolean;
|
||||
delay: number;
|
||||
}
|
||||
|
||||
export interface Type {
|
||||
id: string;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
export interface Tag {
|
||||
id: string;
|
||||
name: string;
|
||||
color: string;
|
||||
}
|
||||
|
||||
12
src/lang/inxdex.ts
Normal file
12
src/lang/inxdex.ts
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { moment } from "obsidian";
|
||||
import zh_cn from './locale/zh_cn';
|
||||
|
||||
const localeMap: { [k: string]: Partial<typeof zh_cn> } = {
|
||||
'zh-cn': zh_cn,
|
||||
};
|
||||
|
||||
const locale = localeMap[moment.locale()];
|
||||
|
||||
export function t(str: keyof typeof zh_cn): string {
|
||||
return (locale && locale[str]) || zh_cn[str];
|
||||
}
|
||||
40
src/lang/locale/zh_cn.ts
Normal file
40
src/lang/locale/zh_cn.ts
Normal file
|
|
@ -0,0 +1,40 @@
|
|||
export default {
|
||||
通用_管理器_文本: '插件管理器',
|
||||
通用_成功_文本: '成功',
|
||||
通用_失败_文本: '失败',
|
||||
通用_新增_文本: '新增',
|
||||
通用_操作_文本: '操作',
|
||||
通用_搜索_文本: '搜索',
|
||||
|
||||
管理器_GITHUB_描述: '访问作者的GitHub页面,查看项目详情、更新日志、参与讨论和贡献代码。',
|
||||
管理器_编辑模式_描述: '启用编辑模式,允许对插件的配置进行更深入的自定义和调整。',
|
||||
管理器_重载插件_描述: '重新加载所有插件,使更改立即生效而无需重启Obsidian。',
|
||||
管理器_检查更新_描述: '检查插件是否有可用的更新,保持插件最新以获得最佳体验。',
|
||||
管理器_一键禁用_描述: '一键禁用插件,帮助你快速重置插件设置或解决性能问题。',
|
||||
管理器_一键启用_描述: '一键启用插件,快速恢复到默认的插件启用状态。',
|
||||
管理器_插件设置_描述: '管理插件的设置,调整功能和行为以满足个人需求。',
|
||||
管理器_仅启用_描述: '仅显示当前已启用的插件,快速管理和调整启用状态。',
|
||||
管理器_打开设置_描述: '打开插件的设置界面,在这里你可以调整插件管理的相关选项和偏好设置。',
|
||||
管理器_还原内容_描述: '将插件展示内容还原到初始状态,撤销所有之前的更改,恢复到默认配置。',
|
||||
管理器_打开目录_描述: '打开包含所有插件文件的目录,方便你进行手动检查、编辑或备份插件文件。',
|
||||
管理器_删除插件_描述: '从你的系统中彻底删除选定的插件,包括其所有文件和设置。请谨慎操作,因为此操作不可撤销。',
|
||||
管理器_切换状态_描述: '“切换插件的启用或禁用状态。点击启用以运行插件,点击禁用以停止插件功能,而不删除插件。',
|
||||
|
||||
设置_基础设置_前缀: '基础',
|
||||
设置_分组设置_前缀: '分组',
|
||||
设置_标签设置_前缀: '标签',
|
||||
|
||||
设置_基础设置_样式_标题: '样式',
|
||||
设置_基础设置_目录样式_标题: '目录样式',
|
||||
设置_基础设置_目录样式_描述: '选择分组的样式,以提升浏览体验。',
|
||||
设置_基础设置_分组样式_标题: '分组样式',
|
||||
设置_基础设置_分组样式_描述: '选择分组的样式,使分组更加明显,便于识别。',
|
||||
设置_基础设置_标签样式_标题: '标签样式',
|
||||
设置_基础设置_标签样式_描述: '选择标签的样式,使标签更加明显,便于识别。',
|
||||
|
||||
设置_基础设置_功能_标题: '功能',
|
||||
设置_基础设置_淡化插件_标题: '淡化插件',
|
||||
设置_基础设置_淡化插件_描述: '为未启用的插件提供视觉淡化效果,以便清晰地区分启用和未启用的插件。',
|
||||
|
||||
命令_管理面板_描述: '开启插件管理器',
|
||||
}
|
||||
85
src/main.ts
Normal file
85
src/main.ts
Normal file
|
|
@ -0,0 +1,85 @@
|
|||
import { Plugin, PluginManifest } from 'obsidian';
|
||||
import { DEFAULT_SETTINGS, ManagerSettings } from './settings/data';
|
||||
import { ManagerSettingTab } from './settings';
|
||||
import { t } from './lang/inxdex';
|
||||
|
||||
import { ManagerModal } from './modal/manager-modal';
|
||||
import Commands from './command';
|
||||
import { ManagerPlugin } from './data/types';
|
||||
|
||||
|
||||
export default class Manager extends Plugin {
|
||||
settings: ManagerSettings;
|
||||
managerModal: ManagerModal;
|
||||
|
||||
appPlugins: any;
|
||||
|
||||
async onload() {
|
||||
// @ts-ignore
|
||||
this.appPlugins = this.app.plugins;
|
||||
|
||||
console.log(`%c ${this.manifest.name} %c v${this.manifest.version} `, `padding: 2px; border-radius: 2px 0 0 2px; color: #fff; background: #5B5B5B;`, `padding: 2px; border-radius: 0 2px 2px 0; color: #fff; background: #409EFF;`);
|
||||
Commands(this.app, this);
|
||||
await this.loadSettings();
|
||||
|
||||
this.addRibbonIcon('folder-cog', t('通用_管理器_文本'), () => {
|
||||
this.managerModal = new ManagerModal(this.app, this);
|
||||
this.managerModal.open();
|
||||
});
|
||||
|
||||
this.addSettingTab(new ManagerSettingTab(this.app, this));
|
||||
const plugins = Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manifest.id);
|
||||
plugins.forEach((plugin: PluginManifest) => this.initPlugin(plugin));
|
||||
plugins.forEach((plugin: PluginManifest) => this.startPlugin(plugin.id));
|
||||
}
|
||||
|
||||
async onunload() {
|
||||
const plugins = Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manifest.id);
|
||||
plugins.forEach(async (pm: PluginManifest) => {
|
||||
const plugin = this.settings.Plugins.find(p => p.id === pm.id)
|
||||
if (plugin) {
|
||||
if (plugin.enabled) {
|
||||
await this.appPlugins.disablePlugin(pm.id);
|
||||
await this.appPlugins.enablePluginAndSave(pm.id);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
async loadSettings() {
|
||||
this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData());
|
||||
}
|
||||
|
||||
async saveSettings() {
|
||||
await this.saveData(this.settings);
|
||||
}
|
||||
|
||||
private async initPlugin(plugin: PluginManifest) {
|
||||
const isEnabled = this.appPlugins.enabledPlugins.has(plugin.id);
|
||||
if (isEnabled) await this.appPlugins.disablePluginAndSave(plugin.id);
|
||||
if (!(this.settings.Plugins.some(p => p.id === plugin.id))) {
|
||||
const mp: ManagerPlugin = {
|
||||
'id': plugin.id,
|
||||
'name': plugin.name,
|
||||
'desc': plugin.description,
|
||||
'group': '',
|
||||
'tags': [],
|
||||
'enabled': isEnabled,
|
||||
'delay': 0,
|
||||
}
|
||||
this.settings.Plugins.push(mp);
|
||||
this.saveSettings();
|
||||
}
|
||||
}
|
||||
|
||||
private async startPlugin(id: string) {
|
||||
const plugin = this.settings.Plugins.find(p => p.id === id);
|
||||
if (plugin && plugin.enabled)
|
||||
setTimeout(async () => {
|
||||
await this.appPlugins.enablePlugin(id);
|
||||
}, plugin.delay * 1000);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
63
src/modal/delete-modal.ts
Normal file
63
src/modal/delete-modal.ts
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
import { App, ExtraButtonComponent, Modal, Setting } from 'obsidian';
|
||||
import { ManagerSettings } from '../settings/data';
|
||||
|
||||
export class DeleteModal extends Modal {
|
||||
settings: ManagerSettings;
|
||||
|
||||
private deleteCallback: () => void;
|
||||
|
||||
constructor(app: App, deleteCallback: () => void) {
|
||||
super(app);
|
||||
this.deleteCallback = deleteCallback;
|
||||
}
|
||||
|
||||
private async showHead() {
|
||||
//@ts-ignore
|
||||
const modalEl: HTMLElement = this.contentEl.parentElement;
|
||||
modalEl.addClass('manager-editor__container');
|
||||
modalEl.removeChild(modalEl.getElementsByClassName('modal-close-button')[0]);
|
||||
this.titleEl.parentElement?.addClass('manager-container__header');
|
||||
this.contentEl.addClass('manager-item-container');
|
||||
|
||||
// [标题行]
|
||||
const titleBar = new Setting(this.titleEl)
|
||||
titleBar.setClass('manager-delete__title')
|
||||
titleBar.setName('卸载插件');
|
||||
|
||||
// [标题行] 关闭按钮
|
||||
const closeButton = new ExtraButtonComponent(titleBar.controlEl)
|
||||
closeButton.setIcon('circle-x')
|
||||
closeButton.onClick(() => this.close());
|
||||
}
|
||||
|
||||
private async showData() {
|
||||
const titleBar = new Setting(this.titleEl)
|
||||
titleBar.setName('你确定要卸载此插件吗?这将删除插件的文件夹。');
|
||||
const actionBar = new Setting(this.titleEl)
|
||||
actionBar.setClass('manager-delete__action')
|
||||
actionBar.addButton(cb => cb
|
||||
.setWarning()
|
||||
.setButtonText('卸载')
|
||||
.onClick(() => {
|
||||
this.deleteCallback();
|
||||
this.close();
|
||||
})
|
||||
);
|
||||
actionBar.addButton(cb => cb
|
||||
.setButtonText('取消')
|
||||
.onClick(() => {
|
||||
this.close();
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
async onOpen() {
|
||||
await this.showHead();
|
||||
await this.showData();
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
}
|
||||
|
||||
75
src/modal/group-modal.ts
Normal file
75
src/modal/group-modal.ts
Normal file
|
|
@ -0,0 +1,75 @@
|
|||
import { App, ExtraButtonComponent, Modal, Setting } from 'obsidian';
|
||||
import { ManagerSettings } from '../settings/data';
|
||||
import Manager from 'main';
|
||||
import { ManagerModal } from './manager-modal';
|
||||
import { ManagerPlugin } from 'src/data/types';
|
||||
|
||||
export class GroupModal extends Modal {
|
||||
settings: ManagerSettings;
|
||||
manager: Manager;
|
||||
managerModal: ManagerModal;
|
||||
managerPlugin: ManagerPlugin;
|
||||
|
||||
constructor(app: App, manager: Manager, managerModal: ManagerModal, managerPlugin: ManagerPlugin) {
|
||||
super(app);
|
||||
this.settings = manager.settings;
|
||||
this.manager = manager;
|
||||
this.managerModal = managerModal;
|
||||
this.managerPlugin = managerPlugin;
|
||||
}
|
||||
|
||||
private async showHead() {
|
||||
//@ts-ignore
|
||||
const modalEl: HTMLElement = this.contentEl.parentElement;
|
||||
modalEl.addClass('manager-editor__container');
|
||||
modalEl.removeChild(modalEl.getElementsByClassName('modal-close-button')[0]);
|
||||
this.titleEl.parentElement?.addClass('manager-container__header');
|
||||
this.contentEl.addClass('manager-item-container');
|
||||
|
||||
// [标题行]
|
||||
const titleBar = new Setting(this.titleEl).setClass('manager-bar__title').setName(this.managerPlugin.name);
|
||||
|
||||
// [标题行] 关闭按钮
|
||||
const closeButton = new ExtraButtonComponent(titleBar.controlEl)
|
||||
closeButton.setIcon('circle-x')
|
||||
closeButton.onClick(() => this.close());
|
||||
}
|
||||
|
||||
private async showData() {
|
||||
// @ts-ignore
|
||||
const allGroups: Record<string, string> = this.settings.GROUPS.reduce((acc, item) => { acc[item.id] = item.name; return acc; }, {});
|
||||
for (const group in allGroups) {
|
||||
new Setting(this.contentEl)
|
||||
.setClass('manager-editor__item')
|
||||
.setName(allGroups[group])
|
||||
.addToggle(cb => cb
|
||||
.setValue(group === this.managerPlugin.group)
|
||||
.onChange(() => {
|
||||
this.managerPlugin.group = group;
|
||||
this.manager.saveSettings();
|
||||
this.managerModal.reloadShowData();
|
||||
this.reloadShowData();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async reloadShowData() {
|
||||
let scrollTop = 0;
|
||||
const modalElement: HTMLElement = this.contentEl;
|
||||
scrollTop = modalElement.scrollTop;
|
||||
modalElement.empty();
|
||||
await this.showData();
|
||||
modalElement.scrollTo(0, scrollTop);
|
||||
}
|
||||
|
||||
async onOpen() {
|
||||
await this.showHead();
|
||||
await this.showData();
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
}
|
||||
|
||||
513
src/modal/manager-modal.ts
Normal file
513
src/modal/manager-modal.ts
Normal file
|
|
@ -0,0 +1,513 @@
|
|||
import * as path from 'path';
|
||||
import { App, ButtonComponent, DropdownComponent, ExtraButtonComponent, Modal, Notice, PluginManifest, SearchComponent, Setting, SliderComponent, ToggleComponent } from 'obsidian';
|
||||
|
||||
import { ManagerSettings } from '../settings/data';
|
||||
import { managerOpen } from '../utils';
|
||||
|
||||
import { t } from '../lang/inxdex';
|
||||
import Manager from 'main';
|
||||
import { GroupModal } from './group-modal';
|
||||
import { TagsModal } from './tags-modal';
|
||||
import { DeleteModal } from './delete-modal';
|
||||
|
||||
// ==============================
|
||||
// 侧边栏 对话框 翻译
|
||||
// ==============================
|
||||
export class ManagerModal extends Modal {
|
||||
manager: Manager;
|
||||
settings: ManagerSettings;
|
||||
// this.app.plugins
|
||||
appPlugins;
|
||||
// this.app.settings
|
||||
appSetting;
|
||||
// [本地][变量] 插件路径
|
||||
basePath: string;
|
||||
// [本地][变量] 展示插件列表
|
||||
displayPlugins: PluginManifest[] = [];
|
||||
|
||||
// 分组内容
|
||||
group = '';
|
||||
// 标签内容
|
||||
tag = '';
|
||||
// 搜索内容
|
||||
searchText = '';
|
||||
// 编辑模式
|
||||
editorMode = false;
|
||||
// 仅启用
|
||||
onlyEnabled = false;
|
||||
// 测试模式
|
||||
developerMode = false;
|
||||
|
||||
constructor(app: App, manager: Manager) {
|
||||
super(app);
|
||||
// @ts-ignore
|
||||
this.appSetting = this.app.setting;
|
||||
// @ts-ignore
|
||||
this.appPlugins = this.app.plugins;
|
||||
this.manager = manager;
|
||||
this.settings = manager.settings;
|
||||
// @ts-ignore
|
||||
this.basePath = path.normalize(this.app.vault.adapter.getBasePath());
|
||||
}
|
||||
|
||||
public async showHead() {
|
||||
//@ts-ignore
|
||||
const modalEl: HTMLElement = this.contentEl.parentElement;
|
||||
modalEl.addClass('manager-container');
|
||||
modalEl.removeChild(modalEl.getElementsByClassName('modal-close-button')[0]);
|
||||
this.titleEl.parentElement?.addClass('manager-container__header');
|
||||
this.contentEl.addClass('manager-item-container');
|
||||
|
||||
// [操作行]
|
||||
const actionBar = new Setting(this.titleEl).setClass('manager-bar__action').setName(t('通用_操作_文本'));
|
||||
|
||||
// [操作行] Github
|
||||
const githubButton = new ButtonComponent(actionBar.controlEl)
|
||||
githubButton.setIcon('github')
|
||||
githubButton.setTooltip(t('管理器_GITHUB_描述'))
|
||||
githubButton.onClick(() => {
|
||||
window.open(this.manager.manifest.authorUrl)
|
||||
});
|
||||
|
||||
// [操作行] 编辑模式
|
||||
const editorButton = new ButtonComponent(actionBar.controlEl)
|
||||
this.editorMode ? editorButton.setIcon('pen') : editorButton.setIcon('pen-off');
|
||||
if (this.editorMode) editorButton.setCta();
|
||||
editorButton.setTooltip(t('管理器_编辑模式_描述'))
|
||||
editorButton.onClick(() => {
|
||||
this.editorMode = !this.editorMode;
|
||||
this.editorMode ? editorButton.setIcon('pen') : editorButton.setIcon('pen-off');
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [操作行] 重载插件
|
||||
const reloadButton = new ButtonComponent(actionBar.controlEl)
|
||||
reloadButton.setIcon('refresh-ccw')
|
||||
reloadButton.setTooltip(t('管理器_重载插件_描述'))
|
||||
reloadButton.onClick(async () => {
|
||||
new Notice('重新加载第三方插件');
|
||||
await this.appPlugins.loadManifests();
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [操作行] 检查更新
|
||||
const updateButton = new ButtonComponent(actionBar.controlEl)
|
||||
updateButton.setIcon('rss')
|
||||
updateButton.setTooltip(t('管理器_检查更新_描述'))
|
||||
updateButton.onClick(() => {
|
||||
console.log(this.appPlugins.checkForUpdates());
|
||||
});
|
||||
|
||||
// [操作行] 一键禁用
|
||||
const disableButton = new ButtonComponent(actionBar.controlEl)
|
||||
disableButton.setIcon('square')
|
||||
disableButton.setTooltip(t('管理器_一键禁用_描述'))
|
||||
disableButton.onClick(async () => {
|
||||
for (const plugin of this.displayPlugins) {
|
||||
await this.appPlugins.disablePlugin(plugin.id);
|
||||
const ManagerPlugin = this.manager.settings.Plugins.find(mp => mp.id === plugin.id);
|
||||
if (ManagerPlugin) ManagerPlugin.enabled = false;
|
||||
this.manager.saveSettings();
|
||||
}
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [操作行] 一键启用
|
||||
const enableButton = new ButtonComponent(actionBar.controlEl)
|
||||
enableButton.setIcon('square-check')
|
||||
enableButton.setTooltip(t('管理器_一键启用_描述'))
|
||||
enableButton.onClick(async () => {
|
||||
for (const plugin of this.displayPlugins) {
|
||||
await this.appPlugins.enablePlugin(plugin.id);
|
||||
const ManagerPlugin = this.manager.settings.Plugins.find(mp => mp.id === plugin.id);
|
||||
if (ManagerPlugin) ManagerPlugin.enabled = true;
|
||||
this.manager.saveSettings();
|
||||
}
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [操作行] 插件设置
|
||||
const settingsButton = new ButtonComponent(actionBar.controlEl)
|
||||
settingsButton.setIcon('settings')
|
||||
settingsButton.setTooltip(t('管理器_插件设置_描述'))
|
||||
settingsButton.onClick(() => {
|
||||
this.appSetting.open();
|
||||
this.appSetting.openTabById(this.manager.manifest.id);
|
||||
this.close();
|
||||
});
|
||||
|
||||
// [测试行] 刷新插件
|
||||
if (this.developerMode) {
|
||||
const testButton = new ButtonComponent(actionBar.controlEl)
|
||||
testButton.setIcon('refresh-ccw')
|
||||
testButton.setTooltip('刷新插件')
|
||||
testButton.onClick(async () => {
|
||||
this.close();
|
||||
await this.appPlugins.disablePlugin(this.manager.manifest.id);
|
||||
await this.appPlugins.enablePlugin(this.manager.manifest.id);
|
||||
});
|
||||
}
|
||||
|
||||
// [搜索行]
|
||||
const searchBar = new Setting(this.titleEl).setClass('manager-bar__search').setName(t('通用_搜索_文本'));
|
||||
|
||||
// [搜索行] 仅启用
|
||||
const onlyEnabled = new ButtonComponent(searchBar.controlEl)
|
||||
this.onlyEnabled ? onlyEnabled.setIcon('toggle-right') : onlyEnabled.setIcon('toggle-left');
|
||||
onlyEnabled.setTooltip(t('管理器_仅启用_描述'))
|
||||
onlyEnabled.onClick(() => {
|
||||
this.onlyEnabled = !this.onlyEnabled;
|
||||
this.onlyEnabled ? onlyEnabled.setIcon('toggle-right') : onlyEnabled.setIcon('toggle-left');
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [搜索行] 分组选择列表
|
||||
// @ts-ignore
|
||||
const groups = this.settings.GROUPS.reduce((acc, item) => { acc[item.id] = item.name; return acc; }, { '': '无分组' });
|
||||
const groupsDropdown = new DropdownComponent(searchBar.controlEl)
|
||||
groupsDropdown.addOptions(groups)
|
||||
groupsDropdown.setValue(this.group !== '' ? this.group : '')
|
||||
groupsDropdown.onChange((value) => {
|
||||
this.group = value;
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [搜索行] 标签选择列表
|
||||
// @ts-ignore
|
||||
const tags = this.settings.TAGS.reduce((acc, item) => { acc[item.id] = item.name; return acc; }, { '': '无标签' });
|
||||
const tagsDropdown = new DropdownComponent(searchBar.controlEl)
|
||||
tagsDropdown.addOptions(tags)
|
||||
tagsDropdown.setValue(this.tag)
|
||||
tagsDropdown.onChange((value) => {
|
||||
this.tag = value;
|
||||
this.reloadShowData();
|
||||
});
|
||||
|
||||
// [搜索行] 搜索框
|
||||
const search = new SearchComponent(searchBar.controlEl)
|
||||
search.onChange((value) => {
|
||||
this.searchText = value;
|
||||
this.reloadShowData();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
public async showData() {
|
||||
const plugins: PluginManifest[] = Object.values(this.appPlugins.manifests);
|
||||
plugins.sort((item1, item2) => { return item1.name.localeCompare(item2.name) });
|
||||
this.displayPlugins = [];
|
||||
|
||||
for (const plugin of plugins) {
|
||||
const ManagerPlugin = this.manager.settings.Plugins.find(mp => mp.id === plugin.id);
|
||||
const pluginDir = path.join(this.basePath, plugin.dir ? plugin.dir : '');
|
||||
|
||||
if (ManagerPlugin) {
|
||||
// [搜索] 仅启用
|
||||
if (this.onlyEnabled && !ManagerPlugin.enabled) continue;
|
||||
// [搜索] 分组
|
||||
if (this.group !== '' && ManagerPlugin.group !== this.group) continue;
|
||||
// [搜索] 标签
|
||||
if (this.tag !== '' && !(ManagerPlugin.tags.includes(this.tag))) continue;
|
||||
// [搜索] 标题
|
||||
if (this.searchText !== '' && ManagerPlugin.name.toLowerCase().indexOf(this.searchText.toLowerCase()) == -1) continue;
|
||||
// [禁用] 自己
|
||||
if (plugin.id === this.manager.manifest.id) continue;
|
||||
|
||||
const itemEl = new Setting(this.contentEl);
|
||||
itemEl.setClass('manager-item');
|
||||
itemEl.nameEl.addClass('manager-item__name-container');
|
||||
itemEl.descEl.addClass('manager-item__description-container');
|
||||
|
||||
// [淡化插件]
|
||||
if (this.settings.FADE_OUT_DISABLED_PLUGINS && !ManagerPlugin.enabled) itemEl.settingEl.addClass('inactive');
|
||||
|
||||
// [批量操作]
|
||||
this.displayPlugins.push(plugin);
|
||||
|
||||
// [目录样式]
|
||||
if (!this.editorMode) {
|
||||
switch (this.settings.ITEM_STYLE) {
|
||||
case 'alwaysExpand':
|
||||
itemEl.descEl.style.display = 'block';
|
||||
break;
|
||||
case 'neverExpand':
|
||||
itemEl.descEl.style.display = 'none';
|
||||
break;
|
||||
case 'hoverExpand':
|
||||
itemEl.descEl.style.display = 'none';
|
||||
itemEl.settingEl.addEventListener('mouseenter', function () {
|
||||
itemEl.descEl.style.display = 'block';
|
||||
});
|
||||
itemEl.settingEl.addEventListener('mouseleave', function () {
|
||||
itemEl.descEl.style.display = 'none';
|
||||
});
|
||||
break;
|
||||
case 'clickExpand':
|
||||
itemEl.descEl.style.display = 'none';
|
||||
itemEl.settingEl.addEventListener('click', function (event) {
|
||||
const excludedButtons = Array.from(itemEl.controlEl.querySelectorAll('div'));
|
||||
// @ts-ignore
|
||||
if (excludedButtons.includes(event.target)) {
|
||||
event.stopPropagation();
|
||||
return;
|
||||
}
|
||||
if (itemEl.descEl.style.display === 'none') {
|
||||
itemEl.descEl.style.display = 'block';
|
||||
} else {
|
||||
itemEl.descEl.style.display = 'none';
|
||||
}
|
||||
});
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// [默认] 分组
|
||||
if (ManagerPlugin.group !== '') {
|
||||
const group = createSpan({
|
||||
cls: 'manager-item__name-group'
|
||||
})
|
||||
itemEl.nameEl.appendChild(group);
|
||||
const item = this.settings.GROUPS.find(t => t.id === ManagerPlugin.group);
|
||||
if (item) {
|
||||
const tag = this.createTag(item.name, item.color, this.settings.GROUP_STYLE);
|
||||
if (this.editorMode) tag.onclick = () => { new GroupModal(this.app, this.manager, this, ManagerPlugin).open(); }
|
||||
group.appendChild(tag);
|
||||
}
|
||||
}
|
||||
// [编辑] 分组
|
||||
if (ManagerPlugin.group === '' && this.editorMode) {
|
||||
const group = createSpan({ cls: 'manager-item__name-group' })
|
||||
if (this.editorMode) itemEl.nameEl.appendChild(group);
|
||||
const tag = this.createTag('+', '', '');
|
||||
if (this.editorMode) tag.onclick = () => { new GroupModal(this.app, this.manager, this, ManagerPlugin).open(); }
|
||||
if (this.editorMode) group.appendChild(tag);
|
||||
}
|
||||
|
||||
// [默认] 名称
|
||||
const title = createSpan({
|
||||
text: ManagerPlugin.name,
|
||||
title: plugin.name,
|
||||
cls: 'manager-item__name-title'
|
||||
})
|
||||
itemEl.nameEl.appendChild(title);
|
||||
// [编辑] 名称
|
||||
if (this.editorMode) {
|
||||
title.setAttribute('style', 'border-width: 1px;border-style: dashed;')
|
||||
title.setAttribute('contenteditable', 'true');
|
||||
title.addEventListener('input', () => {
|
||||
if (title.textContent) {
|
||||
ManagerPlugin.name = title.textContent;
|
||||
this.manager.saveSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// [默认] 版本
|
||||
const version = createSpan({
|
||||
text: `[${plugin.version}]`,
|
||||
cls: ['manager-item__name-version'],
|
||||
title: plugin.author
|
||||
})
|
||||
itemEl.nameEl.appendChild(version);
|
||||
|
||||
// [默认] 延迟
|
||||
if (!this.editorMode && ManagerPlugin.delay !== 0) {
|
||||
const delay = createSpan({
|
||||
text: `${ManagerPlugin.delay}s`,
|
||||
cls: ['manager-item__name-delay'],
|
||||
title: plugin.author
|
||||
})
|
||||
itemEl.nameEl.appendChild(delay);
|
||||
}
|
||||
// [编辑] 延迟
|
||||
if (this.editorMode) {
|
||||
const delay = new SliderComponent(itemEl.nameEl);
|
||||
delay.setLimits(0, 50, 1)
|
||||
delay.setValue(ManagerPlugin.delay)
|
||||
delay.setDynamicTooltip()
|
||||
delay.onChange((value) => {
|
||||
ManagerPlugin.delay = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
}
|
||||
|
||||
// [默认] 描述
|
||||
const desc = createDiv({
|
||||
text: ManagerPlugin.desc,
|
||||
title: plugin.description,
|
||||
cls: ['manager-item__name-desc']
|
||||
})
|
||||
itemEl.descEl.appendChild(desc);
|
||||
// [编辑] 描述
|
||||
if (this.editorMode) {
|
||||
desc.setAttribute('style', 'border-width: 1px;border-style: dashed')
|
||||
desc.setAttribute('contenteditable', 'true');
|
||||
desc.addEventListener('input', () => {
|
||||
if (desc.textContent) {
|
||||
ManagerPlugin.desc = desc.textContent;
|
||||
this.manager.saveSettings();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// [默认] 标签组
|
||||
const tags = createDiv();
|
||||
itemEl.descEl.appendChild(tags);
|
||||
ManagerPlugin.tags.map((id: string) => {
|
||||
const item = this.settings.TAGS.find(item => item.id === id);
|
||||
if (item) {
|
||||
const tag = this.createTag(item.name, item.color, this.settings.TAG_STYLE);
|
||||
tags.appendChild(tag);
|
||||
}
|
||||
});
|
||||
|
||||
// [编辑] 标签组
|
||||
if (this.editorMode) {
|
||||
const tag = this.createTag('+', '', '')
|
||||
tag.onclick = () => { new TagsModal(this.app, this.manager, this, ManagerPlugin).open(); }
|
||||
tags.appendChild(tag);
|
||||
}
|
||||
|
||||
// [按钮] 打开设置
|
||||
if (ManagerPlugin.enabled) {
|
||||
const openPluginSetting = new ExtraButtonComponent(itemEl.controlEl)
|
||||
openPluginSetting.setIcon('settings')
|
||||
openPluginSetting.setTooltip(t('管理器_打开设置_描述'))
|
||||
openPluginSetting.onClick(() => {
|
||||
openPluginSetting.setDisabled(true);
|
||||
this.appSetting.open();
|
||||
this.appSetting.openTabById(plugin.id);
|
||||
openPluginSetting.setDisabled(false);
|
||||
});
|
||||
}
|
||||
|
||||
// [按钮] 还原内容
|
||||
if (this.editorMode) {
|
||||
const reloadButton = new ExtraButtonComponent(itemEl.controlEl)
|
||||
reloadButton.setIcon('refresh-ccw')
|
||||
reloadButton.setTooltip(t('管理器_还原内容_描述'))
|
||||
reloadButton.onClick(() => {
|
||||
ManagerPlugin.name = plugin.name;
|
||||
ManagerPlugin.desc = plugin.description;
|
||||
ManagerPlugin.group = '';
|
||||
ManagerPlugin.tags = [];
|
||||
this.manager.saveSettings();
|
||||
this.reloadShowData();
|
||||
});
|
||||
}
|
||||
|
||||
// [按钮] 打开目录
|
||||
const openPluginDirButton = new ExtraButtonComponent(itemEl.controlEl)
|
||||
openPluginDirButton.setIcon('folder-open')
|
||||
openPluginDirButton.setTooltip(t('管理器_打开目录_描述'))
|
||||
openPluginDirButton.onClick(() => {
|
||||
openPluginDirButton.setDisabled(true);
|
||||
managerOpen(pluginDir);
|
||||
openPluginDirButton.setDisabled(false);
|
||||
});
|
||||
|
||||
// [按钮] 删除插件
|
||||
const deletePluginButton = new ExtraButtonComponent(itemEl.controlEl)
|
||||
deletePluginButton.setIcon('trash')
|
||||
deletePluginButton.setTooltip(t('管理器_删除插件_描述'))
|
||||
deletePluginButton.onClick(async () => {
|
||||
new DeleteModal(this.app, async () => {
|
||||
await this.appPlugins.uninstallPlugin(plugin.id);
|
||||
await this.appPlugins.loadManifests();
|
||||
this.reloadShowData();
|
||||
new Notice('卸载成功');
|
||||
}).open();
|
||||
|
||||
});
|
||||
|
||||
// [按钮] 切换状态
|
||||
const toggleSwitch = new ToggleComponent(itemEl.controlEl)
|
||||
toggleSwitch.setTooltip(t('管理器_切换状态_描述'))
|
||||
toggleSwitch.setValue(ManagerPlugin.enabled)
|
||||
toggleSwitch.onChange(async () => {
|
||||
if (toggleSwitch.getValue()) {
|
||||
// await this.appPlugins.enablePluginAndSave(plugin.id);
|
||||
if (this.settings.FADE_OUT_DISABLED_PLUGINS) itemEl.settingEl.removeClass('inactive'); // [淡化插件]
|
||||
ManagerPlugin.enabled = true;
|
||||
this.manager.saveSettings();
|
||||
await this.appPlugins.enablePlugin(plugin.id);
|
||||
} else {
|
||||
// await this.appPlugins.disablePluginAndSave(plugin.id);
|
||||
if (this.settings.FADE_OUT_DISABLED_PLUGINS) itemEl.settingEl.addClass('inactive'); // [淡化插件]
|
||||
ManagerPlugin.enabled = false;
|
||||
this.manager.saveSettings();
|
||||
await this.appPlugins.disablePlugin(plugin.id);
|
||||
}
|
||||
this.reloadShowData();
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public async reloadShowData() {
|
||||
let scrollTop = 0;
|
||||
const modalElement: HTMLElement = this.contentEl;
|
||||
scrollTop = modalElement.scrollTop;
|
||||
modalElement.empty();
|
||||
await this.showData();
|
||||
modalElement.scrollTo(0, scrollTop);
|
||||
}
|
||||
|
||||
public async onOpen() {
|
||||
await this.showHead();
|
||||
await this.showData();
|
||||
}
|
||||
|
||||
public async onClose() {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
|
||||
private createTag(text: string, color: string, type: string) {
|
||||
const style = this.generateTagStyle(color, type);
|
||||
const tag = createEl('span', {
|
||||
text: text,
|
||||
cls: 'manager-tag',
|
||||
attr: { 'style': style }
|
||||
})
|
||||
return tag;
|
||||
}
|
||||
|
||||
private generateTagStyle(color: string, type: string) {
|
||||
let style;
|
||||
const [r, g, b] = this.hexToRgbArray(color);
|
||||
switch (type) {
|
||||
case 'a':
|
||||
style = `color: #fff; background-color: ${color}; border-color: ${color};`;
|
||||
break;
|
||||
case 'b':
|
||||
style = `color: ${color}; background-color: transparent; border-color: ${color};`;
|
||||
break;
|
||||
case 'c':
|
||||
style = `color: ${color}; background-color: rgba(${r}, ${g}, ${b}, 0.3); border-color: ${color};`;
|
||||
break;
|
||||
case 'd':
|
||||
style = `color: ${color}; background-color: ${this.adjustColorBrightness(color, 50)}; border-color: ${this.adjustColorBrightness(color, 50)};`;
|
||||
break;
|
||||
default:
|
||||
style = `background-color: transparent;border-style: dashed;`;
|
||||
}
|
||||
|
||||
return style;
|
||||
}
|
||||
|
||||
private hexToRgbArray(hex: string) {
|
||||
const rgb = parseInt(hex.slice(1), 16);
|
||||
const r = (rgb >> 16);
|
||||
const g = ((rgb >> 8) & 0x00FF);
|
||||
const b = (rgb & 0x0000FF);
|
||||
return [r, g, b];
|
||||
}
|
||||
|
||||
private adjustColorBrightness(hex: string, amount: number) {
|
||||
const rgb = parseInt(hex.slice(1), 16);
|
||||
const r = Math.min(255, Math.max(0, ((rgb >> 16) & 0xFF) + amount));
|
||||
const g = Math.min(255, Math.max(0, ((rgb >> 8) & 0xFF) + amount));
|
||||
const b = Math.min(255, Math.max(0, (rgb & 0xFF) + amount));
|
||||
return `#${((1 << 24) + (r << 16) + (g << 8) + b).toString(16).slice(1).toUpperCase()}`;
|
||||
}
|
||||
}
|
||||
78
src/modal/tags-modal.ts
Normal file
78
src/modal/tags-modal.ts
Normal file
|
|
@ -0,0 +1,78 @@
|
|||
import { App, ExtraButtonComponent, Modal, Setting } from 'obsidian';
|
||||
import { ManagerSettings } from '../settings/data';
|
||||
import Manager from 'main';
|
||||
import { ManagerModal } from './manager-modal';
|
||||
import { ManagerPlugin } from 'src/data/types';
|
||||
|
||||
export class TagsModal extends Modal {
|
||||
settings: ManagerSettings;
|
||||
manager: Manager;
|
||||
managerModal: ManagerModal;
|
||||
managerPlugin: ManagerPlugin;
|
||||
|
||||
constructor(app: App, manager: Manager, managerModal: ManagerModal, managerPlugin: ManagerPlugin) {
|
||||
super(app);
|
||||
this.settings = manager.settings;
|
||||
this.manager = manager;
|
||||
this.managerModal = managerModal;
|
||||
this.managerPlugin = managerPlugin;
|
||||
}
|
||||
|
||||
private async showHead() {
|
||||
//@ts-ignore
|
||||
const modalEl: HTMLElement = this.contentEl.parentElement;
|
||||
modalEl.addClass('manager-editor__container');
|
||||
modalEl.removeChild(modalEl.getElementsByClassName('modal-close-button')[0]);
|
||||
this.titleEl.parentElement?.addClass('manager-container__header');
|
||||
this.contentEl.addClass('manager-item-container');
|
||||
// [标题行]
|
||||
const titleBar = new Setting(this.titleEl).setClass('manager-bar__title').setName(this.managerPlugin.name);
|
||||
// [标题行] 关闭按钮
|
||||
const closeButton = new ExtraButtonComponent(titleBar.controlEl)
|
||||
closeButton.setIcon('circle-x')
|
||||
closeButton.onClick(() => this.close());
|
||||
}
|
||||
|
||||
private async showData() {
|
||||
// @ts-ignore
|
||||
const allTags: Record<string, string> = this.settings.TAGS.reduce((acc, item) => { acc[item.id] = item.name; return acc; }, {});
|
||||
for (const tag in allTags) {
|
||||
const item = new Setting(this.contentEl)
|
||||
item.setClass('manager-editor__item')
|
||||
item.setName(allTags[tag])
|
||||
item.addToggle(cb => cb
|
||||
.setValue(this.managerPlugin.tags.includes(tag))
|
||||
.onChange((isChecked) => {
|
||||
if (isChecked) {
|
||||
// 添加开启的标签
|
||||
if (!this.managerPlugin.tags.includes(tag)) this.managerPlugin.tags.push(tag);
|
||||
} else {
|
||||
// 移除关闭的标签
|
||||
this.managerPlugin.tags = this.managerPlugin.tags.filter(t => t !== tag);
|
||||
}
|
||||
this.manager.saveSettings();
|
||||
this.managerModal.reloadShowData();
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
private async reloadShowData() {
|
||||
let scrollTop = 0;
|
||||
const modalElement: HTMLElement = this.contentEl;
|
||||
scrollTop = modalElement.scrollTop;
|
||||
modalElement.empty();
|
||||
await this.showData();
|
||||
modalElement.scrollTo(0, scrollTop);
|
||||
}
|
||||
|
||||
async onOpen() {
|
||||
await this.showHead();
|
||||
await this.showData();
|
||||
}
|
||||
|
||||
async onClose() {
|
||||
this.contentEl.empty();
|
||||
}
|
||||
}
|
||||
|
||||
23
src/settings/base-setting.ts
Normal file
23
src/settings/base-setting.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import Manager from 'src/main';
|
||||
import { ManagerSettingTab } from '.';
|
||||
import { ManagerSettings } from './data';
|
||||
import { App } from 'obsidian';
|
||||
|
||||
export default abstract class BaseSetting {
|
||||
protected settingTab: ManagerSettingTab;
|
||||
protected manager: Manager;
|
||||
protected settings: ManagerSettings;
|
||||
public containerEl: HTMLElement;
|
||||
protected app: App;
|
||||
|
||||
constructor(obj: ManagerSettingTab) {
|
||||
this.settingTab = obj;
|
||||
this.manager = obj.i18n;
|
||||
this.settings = obj.i18n.settings;
|
||||
this.containerEl = obj.contentEl;
|
||||
this.app = obj.app;
|
||||
}
|
||||
|
||||
public abstract main(): void;
|
||||
public display(): void { this.main() }
|
||||
}
|
||||
33
src/settings/data.ts
Normal file
33
src/settings/data.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { ManagerPlugin, Tag, Type } from '../data/types';
|
||||
|
||||
export interface ManagerSettings {
|
||||
ITEM_STYLE: string;
|
||||
GROUP_STYLE: string;
|
||||
TAG_STYLE: string;
|
||||
FADE_OUT_DISABLED_PLUGINS: boolean,
|
||||
GROUPS: Type[];
|
||||
TAGS: Tag[];
|
||||
Plugins: ManagerPlugin[];
|
||||
}
|
||||
|
||||
export const DEFAULT_SETTINGS: ManagerSettings = {
|
||||
ITEM_STYLE: "alwaysExpand",
|
||||
GROUP_STYLE: "a",
|
||||
TAG_STYLE: "b",
|
||||
FADE_OUT_DISABLED_PLUGINS: true,
|
||||
GROUPS: [
|
||||
{
|
||||
"id": "default",
|
||||
"name": "默认组",
|
||||
"color": "#A079FF"
|
||||
},
|
||||
],
|
||||
TAGS: [
|
||||
{
|
||||
"id": "default",
|
||||
"name": "默认标签",
|
||||
"color": "#A079FF"
|
||||
},
|
||||
],
|
||||
Plugins: [],
|
||||
}
|
||||
55
src/settings/index.ts
Normal file
55
src/settings/index.ts
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import { App, PluginSettingTab } from 'obsidian';
|
||||
import I18N from "../main";
|
||||
|
||||
import ManagerBasis from './ui/manager-basis';
|
||||
import ManagerGroup from './ui/manager-group';
|
||||
import ManagerTag from './ui/manager-tag';
|
||||
import { t } from 'src/lang/inxdex';
|
||||
|
||||
class ManagerSettingTab extends PluginSettingTab {
|
||||
i18n: I18N;
|
||||
app: App;
|
||||
contentEl: HTMLDivElement;
|
||||
|
||||
constructor(app: App, i18n: I18N) {
|
||||
super(app, i18n);
|
||||
this.i18n = i18n;
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
display(): void {
|
||||
const { containerEl } = this;
|
||||
containerEl.empty();
|
||||
containerEl.addClass('manager-setting__container');
|
||||
const tabsEl = this.containerEl.createEl('div');
|
||||
tabsEl.addClass('manager-setting__tabs');
|
||||
this.contentEl = this.containerEl.createEl('div');
|
||||
this.contentEl.addClass('manager-setting__content');
|
||||
|
||||
const tabItems = [
|
||||
{ text: t('设置_基础设置_前缀'), content: () => this.basisDisplay() },
|
||||
{ text: t('设置_分组设置_前缀'), content: () => this.groupDisplay() },
|
||||
{ text: t('设置_标签设置_前缀'), content: () => this.tagDisplay() },
|
||||
];
|
||||
const tabItemsEls: HTMLDivElement[] = [];
|
||||
|
||||
tabItems.forEach((item, index) => {
|
||||
const itemEl = tabsEl.createEl('div');
|
||||
itemEl.addClass('manager-setting__tabs-item');
|
||||
itemEl.textContent = item.text;
|
||||
tabItemsEls.push(itemEl);
|
||||
if (index === 0) { itemEl.addClass('manager-setting__tabs-item_is-active'); item.content(); }
|
||||
itemEl.addEventListener('click', () => {
|
||||
tabItemsEls.forEach(tabEl => { tabEl.removeClass('manager-setting__tabs-item_is-active') });
|
||||
itemEl.addClass('manager-setting__tabs-item_is-active');
|
||||
item.content();
|
||||
});
|
||||
});
|
||||
}
|
||||
basisDisplay() { this.contentEl.empty(); new ManagerBasis(this).display(); }
|
||||
groupDisplay() { this.contentEl.empty(); new ManagerGroup(this).display(); }
|
||||
tagDisplay() { this.contentEl.empty(); new ManagerTag(this).display(); }
|
||||
}
|
||||
|
||||
export { ManagerSettingTab };
|
||||
|
||||
47
src/settings/ui/manager-basis.ts
Normal file
47
src/settings/ui/manager-basis.ts
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
import BaseSetting from "../base-setting";
|
||||
import { DropdownComponent, Setting, ToggleComponent } from "obsidian";
|
||||
import { GROUP_STYLE, ITEM_STYLE, TAG_STYLE } from "src/data/data";
|
||||
import { t } from "src/lang/inxdex";
|
||||
|
||||
export default class ManagerBasis extends BaseSetting {
|
||||
main(): void {
|
||||
new Setting(this.containerEl).setName(t('设置_基础设置_样式_标题')).setHeading();
|
||||
|
||||
const itemStyleBar = new Setting(this.containerEl).setName(t('设置_基础设置_目录样式_标题')).setDesc(t('设置_基础设置_目录样式_描述'));
|
||||
const itemStyleDropdown = new DropdownComponent(itemStyleBar.controlEl);
|
||||
itemStyleDropdown.addOptions(ITEM_STYLE);
|
||||
itemStyleDropdown.setValue(this.settings.ITEM_STYLE);
|
||||
itemStyleDropdown.onChange((value) => {
|
||||
this.settings.ITEM_STYLE = value;
|
||||
this.manager.saveSettings();
|
||||
});
|
||||
|
||||
const groupStyleBar = new Setting(this.containerEl).setName(t('设置_基础设置_分组样式_标题')).setDesc(t('设置_基础设置_分组样式_描述'));
|
||||
const groupStyleDropdown = new DropdownComponent(groupStyleBar.controlEl);
|
||||
groupStyleDropdown.addOptions(GROUP_STYLE);
|
||||
groupStyleDropdown.setValue(this.settings.GROUP_STYLE);
|
||||
groupStyleDropdown.onChange((value) => {
|
||||
this.settings.GROUP_STYLE = value;
|
||||
this.manager.saveSettings();
|
||||
});
|
||||
|
||||
const tagStyleBar = new Setting(this.containerEl).setName(t('设置_基础设置_标签样式_标题')).setDesc(t('设置_基础设置_标签样式_描述'));
|
||||
const tagStyleDropdown = new DropdownComponent(tagStyleBar.controlEl);
|
||||
tagStyleDropdown.addOptions(TAG_STYLE);
|
||||
tagStyleDropdown.setValue(this.settings.TAG_STYLE);
|
||||
tagStyleDropdown.onChange((value) => {
|
||||
this.settings.TAG_STYLE = value;
|
||||
this.manager.saveSettings();
|
||||
});
|
||||
|
||||
new Setting(this.containerEl).setName(t('设置_基础设置_功能_标题')).setHeading();
|
||||
|
||||
const fadeOutDisabledPluginsBar = new Setting(this.containerEl).setName(t('设置_基础设置_淡化插件_标题')).setDesc(t('设置_基础设置_淡化插件_描述'));
|
||||
const fadeOutDisabledPluginsToggle = new ToggleComponent(fadeOutDisabledPluginsBar.controlEl);
|
||||
fadeOutDisabledPluginsToggle.setValue(this.settings.FADE_OUT_DISABLED_PLUGINS);
|
||||
fadeOutDisabledPluginsToggle.onChange((value) => {
|
||||
this.settings.FADE_OUT_DISABLED_PLUGINS = value;
|
||||
this.manager.saveSettings();
|
||||
});
|
||||
}
|
||||
}
|
||||
82
src/settings/ui/manager-group.ts
Normal file
82
src/settings/ui/manager-group.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { t } from "src/lang/inxdex";
|
||||
import BaseSetting from "../base-setting";
|
||||
import { Notice, Setting } from "obsidian";
|
||||
|
||||
export default class ManagerGroup extends BaseSetting {
|
||||
main(): void {
|
||||
let id = '';
|
||||
let name = '';
|
||||
let color = '';
|
||||
new Setting(this.containerEl)
|
||||
.setHeading()
|
||||
.setName(t('通用_新增_文本'))
|
||||
.addColorPicker(cb => cb
|
||||
.setValue(color)
|
||||
.onChange((value) => {
|
||||
color = value;
|
||||
})
|
||||
)
|
||||
.addText(cb => cb
|
||||
.setPlaceholder('ID')
|
||||
.onChange((value) => {
|
||||
id = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
.addText(cb => cb
|
||||
.setPlaceholder('名称')
|
||||
.onChange((value) => {
|
||||
name = value;
|
||||
})
|
||||
)
|
||||
.addExtraButton(cb => cb
|
||||
.setIcon('plus')
|
||||
.onClick(() => {
|
||||
const containsId = this.manager.settings.GROUPS.some(tag => tag.id === id);
|
||||
if (!containsId && id !== '') {
|
||||
if (color === '') color = '#000000';
|
||||
this.manager.settings.GROUPS.push({ id, name, color });
|
||||
this.manager.saveSettings();
|
||||
this.settingTab.groupDisplay();
|
||||
new Notice('[分组] 分组已添加');
|
||||
} else {
|
||||
new Notice('[分组] ID已存在或为空');
|
||||
}
|
||||
})
|
||||
)
|
||||
this.manager.settings.GROUPS.forEach((tag, index) => {
|
||||
const item = new Setting(this.containerEl)
|
||||
item.settingEl.addClass('manager-setting-group__item')
|
||||
item.setName(`第${index + 1}项: ${tag.id}`)
|
||||
item.addColorPicker(cb => cb
|
||||
.setValue(tag.color)
|
||||
.onChange((value) => {
|
||||
tag.color = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
item.addText(cb => cb
|
||||
.setValue(tag.name)
|
||||
.onChange((value) => {
|
||||
tag.name = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
item.addExtraButton(cb => cb
|
||||
.setIcon('trash-2')
|
||||
.onClick(() => {
|
||||
const hasTestGroup = this.settings.Plugins.some(plugin => plugin.group === tag.id);
|
||||
if (!hasTestGroup) {
|
||||
this.manager.settings.GROUPS = this.manager.settings.GROUPS.filter(t => t.id !== tag.id);
|
||||
this.manager.saveSettings();
|
||||
this.settingTab.groupDisplay();
|
||||
new Notice('[分组] 分组删除成功');
|
||||
} else {
|
||||
new Notice('[分组] 无法删除此分组,此分组下存在插件');
|
||||
}
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
82
src/settings/ui/manager-tag.ts
Normal file
82
src/settings/ui/manager-tag.ts
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
import { t } from "src/lang/inxdex";
|
||||
import BaseSetting from "../base-setting";
|
||||
import { Notice, Setting } from "obsidian";
|
||||
|
||||
export default class ManagerTag extends BaseSetting {
|
||||
main(): void {
|
||||
let id = '';
|
||||
let name = '';
|
||||
let color = '';
|
||||
new Setting(this.containerEl)
|
||||
.setHeading()
|
||||
.setName(t('通用_新增_文本'))
|
||||
.addColorPicker(cb => cb
|
||||
.setValue(color)
|
||||
.onChange((value) => {
|
||||
color = value;
|
||||
})
|
||||
)
|
||||
.addText(cb => cb
|
||||
.setPlaceholder('ID')
|
||||
.onChange((value) => {
|
||||
id = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
.addText(cb => cb
|
||||
.setPlaceholder('名称')
|
||||
.onChange((value) => {
|
||||
name = value;
|
||||
})
|
||||
)
|
||||
.addExtraButton(cb => cb
|
||||
.setIcon('plus')
|
||||
.onClick(() => {
|
||||
const containsId = this.manager.settings.TAGS.some(tag => tag.id === id);
|
||||
if (!containsId && id !== '') {
|
||||
if (color === '') color = '#000000';
|
||||
this.manager.settings.TAGS.push({ id, name, color });
|
||||
this.manager.saveSettings();
|
||||
this.settingTab.tagDisplay();
|
||||
new Notice('[标签] 标签已添加');
|
||||
} else {
|
||||
new Notice('[标签] ID已存在或为空');
|
||||
}
|
||||
})
|
||||
)
|
||||
this.manager.settings.TAGS.forEach((tag, index) => {
|
||||
const item = new Setting(this.containerEl)
|
||||
item.setClass('manager-setting-tag__item')
|
||||
item.setName(`第${index + 1}项: ${tag.id}`)
|
||||
item.addColorPicker(cb => cb
|
||||
.setValue(tag.color)
|
||||
.onChange((value) => {
|
||||
tag.color = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
item.addText(cb => cb
|
||||
.setValue(tag.name)
|
||||
.onChange((value) => {
|
||||
tag.name = value;
|
||||
this.manager.saveSettings();
|
||||
})
|
||||
)
|
||||
item.addExtraButton(cb => cb
|
||||
.setIcon('trash-2')
|
||||
.onClick(() => {
|
||||
const hasTestTag = this.settings.Plugins.some(plugin => plugin.tags && plugin.tags.includes(tag.id));
|
||||
if (!hasTestTag) {
|
||||
this.manager.settings.TAGS = this.manager.settings.TAGS.filter(t => t.id !== tag.id);
|
||||
this.manager.saveSettings();
|
||||
this.settingTab.tagDisplay();
|
||||
new Notice('[标签] 标签删除成功');
|
||||
} else {
|
||||
new Notice('[标签] 无法删除此标签,此标签下存在插件');
|
||||
}
|
||||
})
|
||||
)
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
23
src/utils.ts
Normal file
23
src/utils.ts
Normal file
|
|
@ -0,0 +1,23 @@
|
|||
import { Notice } from 'obsidian';
|
||||
import { exec } from 'child_process';
|
||||
import { t } from './lang/inxdex';
|
||||
|
||||
/**
|
||||
* 打开文件或文件夹的操作系统命令。
|
||||
* @param i18n - 国际化对象,用于显示操作结果的通知。
|
||||
* @param dir - 要打开的文件夹路径。
|
||||
* @description 根据操作系统执行相应的命令来打开文件夹。在Windows上使用'start'命令,在Mac上使用'open'命令。
|
||||
* 如果操作成功,显示成功通知;如果失败,显示错误通知。
|
||||
*/
|
||||
export const managerOpen = (dir: string) => {
|
||||
if (navigator.userAgent.match(/Win/i)) {
|
||||
exec(`start "" "${dir}"`, (error) => {
|
||||
if (error) { new Notice(t('通用_失败_文本')); } else { new Notice(t('通用_成功_文本')); }
|
||||
});
|
||||
}
|
||||
if (navigator.userAgent.match(/Mac/i)) {
|
||||
exec(`open ${dir}`, (error) => {
|
||||
if (error) { new Notice(t('通用_失败_文本')); } else { new Notice(t('通用_成功_文本')); }
|
||||
});
|
||||
}
|
||||
}
|
||||
283
styles.css
Normal file
283
styles.css
Normal file
|
|
@ -0,0 +1,283 @@
|
|||
:root {
|
||||
--i18n-border-radius: 4px;
|
||||
--el-font-size-base: 14px;
|
||||
--i18n-button-font-weight: 500px;
|
||||
--i18n-tag-font-size: 10px;
|
||||
--i18n-tag-border-radius: 3px;
|
||||
--i18n-tag-border-radius-rounded: 9999px;
|
||||
}
|
||||
|
||||
body {
|
||||
--item-inactive: 0.75;
|
||||
}
|
||||
|
||||
body.theme-dark {
|
||||
--item-inactive: 0.5;
|
||||
}
|
||||
|
||||
/* [通用] Tag (标签)
|
||||
---------------------------------------------------------------- */
|
||||
.manager-tag {
|
||||
display: inline-flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
vertical-align: middle;
|
||||
height: 20px;
|
||||
padding: 0 6px;
|
||||
margin-left: 5px;
|
||||
font-size: var(--i18n-tag-font-size);
|
||||
line-height: 1;
|
||||
border-width: 1px;
|
||||
border-style: solid;
|
||||
border-radius: var(--i18n-tag-border-radius);
|
||||
box-sizing: border-box;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.manager-tag:first-child {
|
||||
margin-left: 0px;
|
||||
}
|
||||
|
||||
|
||||
/* 插件管理器 模块
|
||||
---------------------------------------------------------------- */
|
||||
.manager-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 100;
|
||||
width: 800px;
|
||||
min-width: 550px;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
.manager-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.manager-container__header {
|
||||
margin-bottom: 0px;
|
||||
}
|
||||
|
||||
.manager-bar__action {
|
||||
margin: 0;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
border: #fff solid 0px;
|
||||
}
|
||||
|
||||
.manager-bar__action:first-child {
|
||||
padding-top: 0px;
|
||||
}
|
||||
|
||||
.manager-bar__search {
|
||||
margin: 0;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 10px;
|
||||
border: #fff solid 0px;
|
||||
}
|
||||
|
||||
/* 目录容器 */
|
||||
.manager-item-container {
|
||||
overflow: auto;
|
||||
}
|
||||
|
||||
.manager-item-container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
/* 目录项 */
|
||||
.manager-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 6px 10px;
|
||||
border: #fff solid 0px;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
background-color: var(--background-modifier-hover);
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.manager-item:first-child {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.manager-item:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
.manager-item.inactive {
|
||||
filter: brightness(var(--item-inactive));
|
||||
}
|
||||
|
||||
/* 目录项 名称行*/
|
||||
.manager-item__name-container {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: auto;
|
||||
line-height: 20px;
|
||||
font-weight: bold;
|
||||
font-size: 15px;
|
||||
}
|
||||
|
||||
.manager-item__name-group {
|
||||
display: flex;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.manager-item__name-title {
|
||||
display: flex;
|
||||
margin-right: 5px;
|
||||
}
|
||||
|
||||
.manager-item__name-version {
|
||||
display: flex;
|
||||
font-size: 9px;
|
||||
}
|
||||
|
||||
.manager-item__name-desc {
|
||||
margin-bottom: 4px;
|
||||
}
|
||||
|
||||
/* 目录项 描述行*/
|
||||
.manager-item__description-container {
|
||||
margin-left: 0px;
|
||||
transition: opacity 3s ease-out;
|
||||
}
|
||||
|
||||
.manager-editor__container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
z-index: 200;
|
||||
width: 350px;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
background-color: var(--background-primary);
|
||||
}
|
||||
|
||||
.manager-editor__container::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.manager-bar__title {
|
||||
margin: 0;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 6px;
|
||||
border: #fff solid 0px;
|
||||
}
|
||||
|
||||
.manager-editor__item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
height: 100%;
|
||||
padding: 6px 0px;
|
||||
border: #fff solid 0px;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
}
|
||||
|
||||
.manager-editor__item:first-child {
|
||||
padding-top: 6px;
|
||||
}
|
||||
|
||||
.manager-editor__item:hover {
|
||||
background-color: var(--i18n-background-modifier-hover);
|
||||
}
|
||||
|
||||
|
||||
/* 设置界面CSS */
|
||||
.manager-setting__container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.manager-setting__tabs {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
height: 40px;
|
||||
border-bottom: 1px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
.manager-setting__content {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
margin-top: 25px;
|
||||
overflow-y: auto;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.manager-setting__content::-webkit-scrollbar {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.manager-setting__tabs-item {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding: 0 15px;
|
||||
height: 40px;
|
||||
font-weight: bold;
|
||||
font-size: 14px;
|
||||
border-top: 1px solid var(--interactive-accent);
|
||||
border-right: 1px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
.manager-setting__tabs-item:first-child {
|
||||
border-top-left-radius: 4px;
|
||||
border-left: 1px solid var(--interactive-accent);
|
||||
}
|
||||
|
||||
.manager-setting__tabs-item:last-child {
|
||||
border-top-right-radius: 4px;
|
||||
}
|
||||
|
||||
.manager-setting__tabs-item_is-active {
|
||||
color: var(--interactive-accent);
|
||||
}
|
||||
|
||||
/* 标签设置页面 */
|
||||
.manager-setting-tag__container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex-wrap: wrap;
|
||||
margin-top: 10px;
|
||||
}
|
||||
|
||||
.manager-setting-tag__item {
|
||||
padding: 3px 0px;
|
||||
border-top: 0px solid #fff;
|
||||
}
|
||||
|
||||
.manager-setting-tag__item:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
/* 分组设置页面 */
|
||||
.manager-setting-group__container {
|
||||
padding: 3px;
|
||||
border-top: 0px solid #fff;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
}
|
||||
|
||||
.manager-setting-group__item {
|
||||
padding: 3px 0px;
|
||||
border-top: 0px solid #fff;
|
||||
border-radius: var(--i18n-border-radius);
|
||||
}
|
||||
|
||||
.manager-setting-group__item:hover {
|
||||
background-color: var(--background-modifier-hover);
|
||||
}
|
||||
|
||||
/* 卸载 */
|
||||
|
||||
.manager-delete__title {
|
||||
margin: 0;
|
||||
padding-top: 0px;
|
||||
padding-bottom: 6px;
|
||||
border: #fff solid 0px;
|
||||
}
|
||||
.manager-delete__action{
|
||||
padding-bottom: 0px;
|
||||
}
|
||||
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
|
|
@ -0,0 +1,25 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"inlineSourceMap": true,
|
||||
"inlineSources": true,
|
||||
"module": "ESNext",
|
||||
"target": "ES6",
|
||||
"allowJs": true,
|
||||
"noImplicitAny": true,
|
||||
"moduleResolution": "node",
|
||||
"importHelpers": true,
|
||||
"isolatedModules": true,
|
||||
"strictNullChecks": true,
|
||||
"lib": [
|
||||
"DOM",
|
||||
"ES5",
|
||||
"ES6",
|
||||
"ES7",
|
||||
"ES2021"
|
||||
]
|
||||
},
|
||||
"include": [
|
||||
"**/*.ts"
|
||||
]
|
||||
}
|
||||
12
version-bump.mjs
Normal file
12
version-bump.mjs
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import { readFileSync, writeFileSync } from "fs";
|
||||
|
||||
const targetVersion = process.env.npm_package_version;
|
||||
|
||||
let manifest = JSON.parse(readFileSync("manifest.json", "utf8"));
|
||||
const { minAppVersion } = manifest;
|
||||
manifest.version = targetVersion;
|
||||
writeFileSync("manifest.json", JSON.stringify(manifest, null, "\t"));
|
||||
|
||||
let versions = JSON.parse(readFileSync("versions.json", "utf8"));
|
||||
versions[targetVersion] = minAppVersion;
|
||||
writeFileSync("versions.json", JSON.stringify(versions, null, "\t"));
|
||||
3
versions.json
Normal file
3
versions.json
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
{
|
||||
"1.0.0": "0.15.0"
|
||||
}
|
||||
Loading…
Reference in a new issue