mirror of
https://github.com/eondrcode/obsidian-manager.git
synced 2026-07-22 11:40:24 +00:00
fix: 修复重载BUG
This commit is contained in:
parent
ae0deaeb58
commit
f666a20319
4 changed files with 369 additions and 363 deletions
2
LICENSE
2
LICENSE
|
|
@ -1,6 +1,6 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2024 zero
|
||||
Copyright (c) 2026 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
|
||||
|
|
|
|||
4
package-lock.json
generated
4
package-lock.json
generated
|
|
@ -1,12 +1,12 @@
|
|||
{
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "obsidian-sample-plugin",
|
||||
"version": "1.0.0",
|
||||
"version": "1.0.1",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"@types/node": "^16.11.6",
|
||||
|
|
|
|||
663
src/main.ts
663
src/main.ts
|
|
@ -6,10 +6,10 @@ import { ManagerModal } from './modal/manager-modal';
|
|||
import Commands from './command';
|
||||
import Agreement from 'src/agreement';
|
||||
import { RepoResolver, ensureBpmTagExists, BPM_TAG_ID } from './repo-resolver';
|
||||
import { Notice, Platform, requestUrl } from 'obsidian';
|
||||
import { BetaSource, ManagerPlugin, BPM_IGNORE_TAG } from './data/types';
|
||||
import { Notice, Platform, requestUrl } from 'obsidian';
|
||||
import { BetaSource, ManagerPlugin, BPM_IGNORE_TAG } from './data/types';
|
||||
import { runMigrations } from './migrations';
|
||||
import { fetchReleaseVersions, installPluginFromGithub, installThemeFromGithub, ReleaseVersion, sanitizeRepo } from './github-install';
|
||||
import { fetchReleaseVersions, installPluginFromGithub, installThemeFromGithub, ReleaseVersion, sanitizeRepo } from './github-install';
|
||||
import { performSelfCheck } from './self-check';
|
||||
import { SystemRibbonManager } from './manager/system-ribbon-manager';
|
||||
import { RibbonItem } from './data/types';
|
||||
|
|
@ -39,7 +39,7 @@ export default class Manager extends Plugin {
|
|||
public agreement: Agreement;
|
||||
public repoResolver: RepoResolver;
|
||||
public systemRibbonManager: SystemRibbonManager;
|
||||
public updateStatus: Record<string, UpdateStatus> = {};
|
||||
public updateStatus: Record<string, UpdateStatus> = {};
|
||||
private updateProgressNotice: Notice | null = null;
|
||||
|
||||
|
||||
|
|
@ -61,37 +61,37 @@ export default class Manager extends Plugin {
|
|||
this.settings.LANGUAGE = this.getAppLanguage();
|
||||
this.settings.LANGUAGE_INITIALIZED = true;
|
||||
await this.saveSettings();
|
||||
}
|
||||
// 初始化语言系统
|
||||
this.translator = new Translator(this);
|
||||
let builtinTagsChanged = false;
|
||||
const tagCountBeforeBpmEnsure = this.settings.TAGS.length;
|
||||
ensureBpmTagExists(this);
|
||||
builtinTagsChanged = this.settings.TAGS.length !== tagCountBeforeBpmEnsure;
|
||||
this.ensureBpmTagAndRecords();
|
||||
this.ensureSelfPluginRecord();
|
||||
|
||||
// 确保 BPM Ignore 标签存在
|
||||
if (!this.settings.TAGS.some(t => t.id === BPM_IGNORE_TAG)) {
|
||||
}
|
||||
// 初始化语言系统
|
||||
this.translator = new Translator(this);
|
||||
let builtinTagsChanged = false;
|
||||
const tagCountBeforeBpmEnsure = this.settings.TAGS.length;
|
||||
ensureBpmTagExists(this);
|
||||
builtinTagsChanged = this.settings.TAGS.length !== tagCountBeforeBpmEnsure;
|
||||
this.ensureBpmTagAndRecords();
|
||||
this.ensureSelfPluginRecord();
|
||||
|
||||
// 确保 BPM Ignore 标签存在
|
||||
if (!this.settings.TAGS.some(t => t.id === BPM_IGNORE_TAG)) {
|
||||
this.settings.TAGS.push({
|
||||
id: BPM_IGNORE_TAG,
|
||||
name: this.translator.t("标签_BPM忽略_名称") || "BPM Ignored",
|
||||
color: "#6c757d" // 灰色
|
||||
});
|
||||
builtinTagsChanged = true;
|
||||
}
|
||||
if (this.normalizeBuiltinTagNames() || builtinTagsChanged) await this.saveSettings();
|
||||
|
||||
this.repoResolver = new RepoResolver(this);
|
||||
|
||||
// 初始化 Ribbon 管理器。功能编排不写入 Obsidian workspace 配置,只用 BPM 数据驱动运行时样式。
|
||||
this.systemRibbonManager = new SystemRibbonManager(this.app, this);
|
||||
const savedRibbonItems = [...(this.settings.RIBBON_SETTINGS || [])]
|
||||
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
||||
const orderedRibbonIds = savedRibbonItems.map((item) => item.id);
|
||||
const hiddenRibbonStatus: Record<string, boolean> = {};
|
||||
savedRibbonItems.forEach((item) => hiddenRibbonStatus[item.id] = !item.visible);
|
||||
await this.syncRibbonConfig(orderedRibbonIds, hiddenRibbonStatus);
|
||||
name: this.translator.t("标签_BPM忽略_名称") || "BPM Ignored",
|
||||
color: "#6c757d" // 灰色
|
||||
});
|
||||
builtinTagsChanged = true;
|
||||
}
|
||||
if (this.normalizeBuiltinTagNames() || builtinTagsChanged) await this.saveSettings();
|
||||
|
||||
this.repoResolver = new RepoResolver(this);
|
||||
|
||||
// 初始化 Ribbon 管理器。功能编排不写入 Obsidian workspace 配置,只用 BPM 数据驱动运行时样式。
|
||||
this.systemRibbonManager = new SystemRibbonManager(this.app, this);
|
||||
const savedRibbonItems = [...(this.settings.RIBBON_SETTINGS || [])]
|
||||
.sort((a, b) => (a.order ?? 0) - (b.order ?? 0));
|
||||
const orderedRibbonIds = savedRibbonItems.map((item) => item.id);
|
||||
const hiddenRibbonStatus: Record<string, boolean> = {};
|
||||
savedRibbonItems.forEach((item) => hiddenRibbonStatus[item.id] = !item.visible);
|
||||
await this.syncRibbonConfig(orderedRibbonIds, hiddenRibbonStatus);
|
||||
|
||||
// 初始化侧边栏图标
|
||||
this.addRibbonIcon('folder-cog', this.translator.t('通用_管理器_文本'), () => { this.managerModal = new ManagerModal(this.app, this); this.managerModal.open(); });
|
||||
|
|
@ -100,11 +100,11 @@ export default class Manager extends Plugin {
|
|||
this.settings.DELAY ? this.enableDelay() : this.disableDelay();
|
||||
Commands(this.app, this);
|
||||
|
||||
this.agreement = new Agreement(this);
|
||||
this.startupCheckForUpdates();
|
||||
this.startupMaintainBetaSources();
|
||||
|
||||
this.registerObsidianProtocolHandler("BPM-plugin-install", async (params: ObsidianProtocolData) => {
|
||||
this.agreement = new Agreement(this);
|
||||
this.startupCheckForUpdates();
|
||||
this.startupMaintainBetaSources();
|
||||
|
||||
this.registerObsidianProtocolHandler("BPM-plugin-install", async (params: ObsidianProtocolData) => {
|
||||
await this.agreement.parsePluginInstall(params);
|
||||
});
|
||||
this.registerObsidianProtocolHandler("BPM-plugin-github", async (params: ObsidianProtocolData) => {
|
||||
|
|
@ -122,10 +122,10 @@ export default class Manager extends Plugin {
|
|||
// 延迟启动自检,确保 Obsidian 初始化完成,避免自动接管被覆盖
|
||||
setTimeout(() => {
|
||||
this.cleanRibbonItems(); // 启动后清理一次
|
||||
if (this.settings.DELAY) performSelfCheck(this);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
if (this.settings.DELAY) performSelfCheck(this);
|
||||
}, 2000);
|
||||
});
|
||||
}
|
||||
|
||||
public async onunload() {
|
||||
if (this.dragObserverCleanup) {
|
||||
|
|
@ -134,14 +134,14 @@ export default class Manager extends Plugin {
|
|||
}
|
||||
|
||||
if (this.settings.DELAY) this.disableDelaysForAllPlugins();
|
||||
if (this.menuObserver) {
|
||||
if (this.menuObserver) {
|
||||
this.menuObserver.disconnect();
|
||||
}
|
||||
|
||||
// 临走前再清理一次
|
||||
this.cleanRibbonItems();
|
||||
|
||||
this.systemRibbonManager?.stopWatch();
|
||||
// 临走前再清理一次
|
||||
this.cleanRibbonItems();
|
||||
|
||||
this.systemRibbonManager?.stopWatch();
|
||||
}
|
||||
|
||||
private setupDragToHideObserver() {
|
||||
|
|
@ -235,51 +235,51 @@ export default class Manager extends Plugin {
|
|||
// 保存设置 (这将更新 RIBBON_SETTINGS 到 data.json)
|
||||
await this.saveSettings();
|
||||
|
||||
const orderedIds = this.settings.RIBBON_SETTINGS.map(i => i.id);
|
||||
const hiddenStatus: Record<string, boolean> = {};
|
||||
this.settings.RIBBON_SETTINGS.forEach(i => hiddenStatus[i.id] = !i.visible);
|
||||
|
||||
this.applyRibbonConfigToMemory(orderedIds, hiddenStatus);
|
||||
// 更新 CSS 样式 (重要:这控制了实际的显隐)
|
||||
this.updateRibbonStyles();
|
||||
const orderedIds = this.settings.RIBBON_SETTINGS.map(i => i.id);
|
||||
const hiddenStatus: Record<string, boolean> = {};
|
||||
this.settings.RIBBON_SETTINGS.forEach(i => hiddenStatus[i.id] = !i.visible);
|
||||
|
||||
this.applyRibbonConfigToMemory(orderedIds, hiddenStatus);
|
||||
// 更新 CSS 样式 (重要:这控制了实际的显隐)
|
||||
this.updateRibbonStyles();
|
||||
|
||||
// 如果 BPM 设置面板打开着,尝试刷新它
|
||||
this.reloadIfCurrentModal();
|
||||
|
||||
this.applyRibbonConfigToMemory(orderedIds, hiddenStatus);
|
||||
this.updateRibbonStyles();
|
||||
this.applyRibbonConfigToMemory(orderedIds, hiddenStatus);
|
||||
this.updateRibbonStyles();
|
||||
|
||||
new Notice(this.translator.t("Ribbon_已隐藏_通知", { name: label }));
|
||||
new Notice(this.translator.t("Ribbon_已隐藏_通知", { name: label }));
|
||||
}
|
||||
}
|
||||
|
||||
public async loadSettings() { this.settings = Object.assign({}, DEFAULT_SETTINGS, await this.loadData()); }
|
||||
public async saveSettings() { await this.saveData(this.settings); }
|
||||
|
||||
// 保存单个插件配置。保留方法名以兼容旧调用点。
|
||||
public async savePluginAndExport(pluginId: string) {
|
||||
await this.saveSettings();
|
||||
}
|
||||
// 保存单个插件配置。保留方法名以兼容旧调用点。
|
||||
public async savePluginAndExport(pluginId: string) {
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
public showUpdateProgress(total: number): { dispose: () => void; update: (processed: number, currentId?: string) => void; cancel: () => void; isCancelled: () => boolean } {
|
||||
if (this.updateProgressNotice) this.updateProgressNotice.hide();
|
||||
const baseText = this.translator.t("通知_检测更新中文案");
|
||||
const notice = new Notice(baseText, 0);
|
||||
const update = (p: number, currentId?: string) => {
|
||||
notice.setMessage(`${baseText} ${Math.min(p, total)}/${total}${currentId ? ` · ${currentId}` : ""}`);
|
||||
};
|
||||
this.updateProgressNotice = notice;
|
||||
update(0);
|
||||
return {
|
||||
public showUpdateProgress(total: number): { dispose: () => void; update: (processed: number, currentId?: string) => void; cancel: () => void; isCancelled: () => boolean } {
|
||||
if (this.updateProgressNotice) this.updateProgressNotice.hide();
|
||||
const baseText = this.translator.t("通知_检测更新中文案");
|
||||
const notice = new Notice(baseText, 0);
|
||||
const update = (p: number, currentId?: string) => {
|
||||
notice.setMessage(`${baseText} ${Math.min(p, total)}/${total}${currentId ? ` · ${currentId}` : ""}`);
|
||||
};
|
||||
this.updateProgressNotice = notice;
|
||||
update(0);
|
||||
return {
|
||||
dispose: () => {
|
||||
notice.hide();
|
||||
if (this.updateProgressNotice === notice) this.updateProgressNotice = null;
|
||||
},
|
||||
update,
|
||||
cancel: () => undefined,
|
||||
isCancelled: () => false
|
||||
};
|
||||
}
|
||||
},
|
||||
update,
|
||||
cancel: () => undefined,
|
||||
isCancelled: () => false
|
||||
};
|
||||
}
|
||||
|
||||
public async checkUpdatesWithNotice(): Promise<Record<string, UpdateStatus>> {
|
||||
const manifests = Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manifest.id) as PluginManifest[];
|
||||
|
|
@ -299,9 +299,9 @@ export default class Manager extends Plugin {
|
|||
}
|
||||
}
|
||||
|
||||
private async startupCheckForUpdates() {
|
||||
if (!this.settings.STARTUP_CHECK_UPDATES) return;
|
||||
try {
|
||||
private async startupCheckForUpdates() {
|
||||
if (!this.settings.STARTUP_CHECK_UPDATES) return;
|
||||
try {
|
||||
const manifests = Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manifest.id) as PluginManifest[];
|
||||
const progress = this.showUpdateProgress(manifests.length);
|
||||
let processed = 0;
|
||||
|
|
@ -319,159 +319,159 @@ export default class Manager extends Plugin {
|
|||
if (this.settings.DEBUG) console.error("[BPM] startup check updates failed", e);
|
||||
if (!this.settings.GITHUB_TOKEN) {
|
||||
new Notice(this.translator.t("通知_检查更新失败_建议Token"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sourceHasUpdate(source: BetaSource): boolean {
|
||||
const localVersion = source.localVersion || "";
|
||||
if (!source.latestVersion || !localVersion) return false;
|
||||
return this.compareVersions(source.latestVersion, localVersion) > 0;
|
||||
}
|
||||
|
||||
private pickBetaSourceVersion(source: BetaSource, versions: ReleaseVersion[]): string {
|
||||
if (source.mode === "frozen") return source.frozenVersion || source.latestVersion || versions[0]?.version || "";
|
||||
return versions.find(v => !v.prerelease)?.version || versions[0]?.version || "";
|
||||
}
|
||||
|
||||
private async checkBetaSource(source: BetaSource): Promise<void> {
|
||||
try {
|
||||
const versions = await fetchReleaseVersions(this, source.repo);
|
||||
const latestVersion = this.pickBetaSourceVersion(source, versions);
|
||||
source.latestVersion = latestVersion || "";
|
||||
source.lastChecked = Date.now();
|
||||
source.error = "";
|
||||
|
||||
if (source.type === "plugin") {
|
||||
const mappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (mappedId) source.id = mappedId;
|
||||
const pluginId = mappedId || source.id;
|
||||
source.localVersion = (this.appPlugins.manifests[pluginId] as PluginManifest | undefined)?.version || source.localVersion || "";
|
||||
}
|
||||
} catch (e) {
|
||||
source.error = (e as Error)?.message || String(e);
|
||||
source.lastChecked = Date.now();
|
||||
if (this.settings.DEBUG) console.error("[BPM] beta source check failed", source.repo, e);
|
||||
}
|
||||
}
|
||||
|
||||
private async startupCheckBetaSources() {
|
||||
if (!this.settings.SOURCE_STARTUP_CHECK_UPDATES) return;
|
||||
|
||||
const sources = (this.settings.BETA_SOURCES || []).filter(s => s.enabled);
|
||||
if (sources.length === 0) return;
|
||||
|
||||
for (const source of sources) {
|
||||
await this.checkBetaSource(source);
|
||||
}
|
||||
|
||||
await this.saveSettings();
|
||||
const count = sources.filter((source) => this.sourceHasUpdate(source)).length;
|
||||
if (count > 0) {
|
||||
new Notice(this.translator.t("通知_来源可更新数量", { count }), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
private async startupMaintainBetaSources() {
|
||||
await this.startupCheckBetaSources();
|
||||
await this.startupUpdateBetaSources();
|
||||
}
|
||||
|
||||
private async startupUpdateBetaSources() {
|
||||
if (!this.settings.SOURCE_AUTO_UPDATE) return;
|
||||
|
||||
const sources = (this.settings.BETA_SOURCES || []).filter(s => s.enabled && s.autoUpdate);
|
||||
if (sources.length === 0) return;
|
||||
for (const source of sources) {
|
||||
try {
|
||||
const checkedRecently = source.lastChecked && Date.now() - source.lastChecked < 60_000;
|
||||
let targetVersion = checkedRecently ? source.latestVersion || "" : "";
|
||||
if (!targetVersion) {
|
||||
const versions = await fetchReleaseVersions(this, source.repo);
|
||||
targetVersion = this.pickBetaSourceVersion(source, versions);
|
||||
source.latestVersion = targetVersion || "";
|
||||
source.lastChecked = Date.now();
|
||||
source.error = "";
|
||||
}
|
||||
|
||||
if (!targetVersion) continue;
|
||||
if (source.type === "plugin") {
|
||||
const mappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (mappedId) source.id = mappedId;
|
||||
const pluginId = mappedId || source.id;
|
||||
const localVersion = (this.appPlugins.manifests[pluginId] as PluginManifest | undefined)?.version || source.localVersion || "";
|
||||
source.localVersion = localVersion;
|
||||
const needsUpdate = source.mode === "frozen"
|
||||
? localVersion !== targetVersion
|
||||
: this.compareVersions(targetVersion, localVersion || "0.0.0") > 0;
|
||||
if (needsUpdate) {
|
||||
const ok = await installPluginFromGithub(this, source.repo, targetVersion, true);
|
||||
if (ok) {
|
||||
const nextMappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (nextMappedId) source.id = nextMappedId;
|
||||
const manifest = this.appPlugins.manifests[source.id] as PluginManifest | undefined;
|
||||
source.localVersion = manifest?.version || targetVersion;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const needsUpdate = source.mode === "frozen"
|
||||
? source.localVersion !== targetVersion
|
||||
: !source.localVersion || this.compareVersions(targetVersion, source.localVersion) > 0;
|
||||
if (needsUpdate) {
|
||||
const ok = await installThemeFromGithub(this, source.repo, targetVersion);
|
||||
if (ok) source.localVersion = targetVersion;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
source.error = (e as Error)?.message || String(e);
|
||||
source.lastChecked = Date.now();
|
||||
if (this.settings.DEBUG) console.error("[BPM] beta source auto update failed", source.repo, e);
|
||||
}
|
||||
}
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
public ensureBpmTagAndRecords() {
|
||||
ensureBpmTagExists(this);
|
||||
// 确保 BPM 安装的插件拥有标签
|
||||
this.settings.BPM_INSTALLED.forEach((id) => {
|
||||
const mp = this.settings.Plugins.find(p => p.id === id);
|
||||
if (mp && !mp.tags.includes(BPM_TAG_ID)) mp.tags.push(BPM_TAG_ID);
|
||||
});
|
||||
}
|
||||
|
||||
private normalizeBuiltinTagNames(): boolean {
|
||||
let changed = false;
|
||||
const normalize = (id: string, name: string, legacyNames: string[], color: string) => {
|
||||
const tag = this.settings.TAGS.find((item) => item.id === id);
|
||||
if (!tag) return;
|
||||
if (!tag.name || legacyNames.includes(tag.name)) {
|
||||
tag.name = name;
|
||||
changed = true;
|
||||
}
|
||||
if (!tag.color) {
|
||||
tag.color = color;
|
||||
changed = true;
|
||||
}
|
||||
};
|
||||
|
||||
normalize(BPM_TAG_ID, this.translator.t("标签_BPM安装_名称") || "BPM 安装", [
|
||||
"bpm install",
|
||||
"bpm安装",
|
||||
"BPM Install",
|
||||
"BPM Installed",
|
||||
], "#409EFF");
|
||||
normalize(BPM_IGNORE_TAG, this.translator.t("标签_BPM忽略_名称") || "BPM 忽略", [
|
||||
"BPM Ignore",
|
||||
"BPM Ignored",
|
||||
], "#6c757d");
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 确保 BPM 自身也存在于插件记录中(用于面板显示)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private sourceHasUpdate(source: BetaSource): boolean {
|
||||
const localVersion = source.localVersion || "";
|
||||
if (!source.latestVersion || !localVersion) return false;
|
||||
return this.compareVersions(source.latestVersion, localVersion) > 0;
|
||||
}
|
||||
|
||||
private pickBetaSourceVersion(source: BetaSource, versions: ReleaseVersion[]): string {
|
||||
if (source.mode === "frozen") return source.frozenVersion || source.latestVersion || versions[0]?.version || "";
|
||||
return versions.find(v => !v.prerelease)?.version || versions[0]?.version || "";
|
||||
}
|
||||
|
||||
private async checkBetaSource(source: BetaSource): Promise<void> {
|
||||
try {
|
||||
const versions = await fetchReleaseVersions(this, source.repo);
|
||||
const latestVersion = this.pickBetaSourceVersion(source, versions);
|
||||
source.latestVersion = latestVersion || "";
|
||||
source.lastChecked = Date.now();
|
||||
source.error = "";
|
||||
|
||||
if (source.type === "plugin") {
|
||||
const mappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (mappedId) source.id = mappedId;
|
||||
const pluginId = mappedId || source.id;
|
||||
source.localVersion = (this.appPlugins.manifests[pluginId] as PluginManifest | undefined)?.version || source.localVersion || "";
|
||||
}
|
||||
} catch (e) {
|
||||
source.error = (e as Error)?.message || String(e);
|
||||
source.lastChecked = Date.now();
|
||||
if (this.settings.DEBUG) console.error("[BPM] beta source check failed", source.repo, e);
|
||||
}
|
||||
}
|
||||
|
||||
private async startupCheckBetaSources() {
|
||||
if (!this.settings.SOURCE_STARTUP_CHECK_UPDATES) return;
|
||||
|
||||
const sources = (this.settings.BETA_SOURCES || []).filter(s => s.enabled);
|
||||
if (sources.length === 0) return;
|
||||
|
||||
for (const source of sources) {
|
||||
await this.checkBetaSource(source);
|
||||
}
|
||||
|
||||
await this.saveSettings();
|
||||
const count = sources.filter((source) => this.sourceHasUpdate(source)).length;
|
||||
if (count > 0) {
|
||||
new Notice(this.translator.t("通知_来源可更新数量", { count }), 5000);
|
||||
}
|
||||
}
|
||||
|
||||
private async startupMaintainBetaSources() {
|
||||
await this.startupCheckBetaSources();
|
||||
await this.startupUpdateBetaSources();
|
||||
}
|
||||
|
||||
private async startupUpdateBetaSources() {
|
||||
if (!this.settings.SOURCE_AUTO_UPDATE) return;
|
||||
|
||||
const sources = (this.settings.BETA_SOURCES || []).filter(s => s.enabled && s.autoUpdate);
|
||||
if (sources.length === 0) return;
|
||||
for (const source of sources) {
|
||||
try {
|
||||
const checkedRecently = source.lastChecked && Date.now() - source.lastChecked < 60_000;
|
||||
let targetVersion = checkedRecently ? source.latestVersion || "" : "";
|
||||
if (!targetVersion) {
|
||||
const versions = await fetchReleaseVersions(this, source.repo);
|
||||
targetVersion = this.pickBetaSourceVersion(source, versions);
|
||||
source.latestVersion = targetVersion || "";
|
||||
source.lastChecked = Date.now();
|
||||
source.error = "";
|
||||
}
|
||||
|
||||
if (!targetVersion) continue;
|
||||
if (source.type === "plugin") {
|
||||
const mappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (mappedId) source.id = mappedId;
|
||||
const pluginId = mappedId || source.id;
|
||||
const localVersion = (this.appPlugins.manifests[pluginId] as PluginManifest | undefined)?.version || source.localVersion || "";
|
||||
source.localVersion = localVersion;
|
||||
const needsUpdate = source.mode === "frozen"
|
||||
? localVersion !== targetVersion
|
||||
: this.compareVersions(targetVersion, localVersion || "0.0.0") > 0;
|
||||
if (needsUpdate) {
|
||||
const ok = await installPluginFromGithub(this, source.repo, targetVersion, true);
|
||||
if (ok) {
|
||||
const nextMappedId = Object.entries(this.settings.REPO_MAP || {})
|
||||
.find(([, repo]) => sanitizeRepo(repo) === sanitizeRepo(source.repo))?.[0];
|
||||
if (nextMappedId) source.id = nextMappedId;
|
||||
const manifest = this.appPlugins.manifests[source.id] as PluginManifest | undefined;
|
||||
source.localVersion = manifest?.version || targetVersion;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
const needsUpdate = source.mode === "frozen"
|
||||
? source.localVersion !== targetVersion
|
||||
: !source.localVersion || this.compareVersions(targetVersion, source.localVersion) > 0;
|
||||
if (needsUpdate) {
|
||||
const ok = await installThemeFromGithub(this, source.repo, targetVersion);
|
||||
if (ok) source.localVersion = targetVersion;
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
source.error = (e as Error)?.message || String(e);
|
||||
source.lastChecked = Date.now();
|
||||
if (this.settings.DEBUG) console.error("[BPM] beta source auto update failed", source.repo, e);
|
||||
}
|
||||
}
|
||||
await this.saveSettings();
|
||||
}
|
||||
|
||||
public ensureBpmTagAndRecords() {
|
||||
ensureBpmTagExists(this);
|
||||
// 确保 BPM 安装的插件拥有标签
|
||||
this.settings.BPM_INSTALLED.forEach((id) => {
|
||||
const mp = this.settings.Plugins.find(p => p.id === id);
|
||||
if (mp && !mp.tags.includes(BPM_TAG_ID)) mp.tags.push(BPM_TAG_ID);
|
||||
});
|
||||
}
|
||||
|
||||
private normalizeBuiltinTagNames(): boolean {
|
||||
let changed = false;
|
||||
const normalize = (id: string, name: string, legacyNames: string[], color: string) => {
|
||||
const tag = this.settings.TAGS.find((item) => item.id === id);
|
||||
if (!tag) return;
|
||||
if (!tag.name || legacyNames.includes(tag.name)) {
|
||||
tag.name = name;
|
||||
changed = true;
|
||||
}
|
||||
if (!tag.color) {
|
||||
tag.color = color;
|
||||
changed = true;
|
||||
}
|
||||
};
|
||||
|
||||
normalize(BPM_TAG_ID, this.translator.t("标签_BPM安装_名称") || "BPM 安装", [
|
||||
"bpm install",
|
||||
"bpm安装",
|
||||
"BPM Install",
|
||||
"BPM Installed",
|
||||
], "#409EFF");
|
||||
normalize(BPM_IGNORE_TAG, this.translator.t("标签_BPM忽略_名称") || "BPM 忽略", [
|
||||
"BPM Ignore",
|
||||
"BPM Ignored",
|
||||
], "#6c757d");
|
||||
return changed;
|
||||
}
|
||||
|
||||
// 确保 BPM 自身也存在于插件记录中(用于面板显示)
|
||||
public ensureSelfPluginRecord() {
|
||||
const id = this.manifest.id;
|
||||
const existing = this.settings.Plugins.find(p => p.id === id);
|
||||
|
|
@ -488,10 +488,10 @@ export default class Manager extends Plugin {
|
|||
enabled: true,
|
||||
delay: "",
|
||||
note: "",
|
||||
});
|
||||
this.saveSettings();
|
||||
return;
|
||||
}
|
||||
});
|
||||
this.saveSettings();
|
||||
return;
|
||||
}
|
||||
existing.name = existing.name || this.manifest.name;
|
||||
existing.desc = existing.desc || this.manifest.description;
|
||||
existing.enabled = true;
|
||||
|
|
@ -533,21 +533,21 @@ export default class Manager extends Plugin {
|
|||
}
|
||||
|
||||
// 开启延时 调用
|
||||
private isBpmIgnoredPlugin(pluginId: string): boolean {
|
||||
return Boolean(this.settings.Plugins.find(plugin => plugin.id === pluginId)?.tags.includes(BPM_IGNORE_TAG));
|
||||
}
|
||||
|
||||
private getDelayManagedPluginManifests(): PluginManifest[] {
|
||||
return Object.values(this.appPlugins.manifests)
|
||||
.filter((pm: PluginManifest) => pm.id !== this.manifest.id && !this.isBpmIgnoredPlugin(pm.id)) as PluginManifest[];
|
||||
}
|
||||
|
||||
public enableDelay() {
|
||||
private isBpmIgnoredPlugin(pluginId: string): boolean {
|
||||
return Boolean(this.settings.Plugins.find(plugin => plugin.id === pluginId)?.tags.includes(BPM_IGNORE_TAG));
|
||||
}
|
||||
|
||||
private getDelayManagedPluginManifests(): PluginManifest[] {
|
||||
return Object.values(this.appPlugins.manifests)
|
||||
.filter((pm: PluginManifest) => pm.id !== this.manifest.id && !this.isBpmIgnoredPlugin(pm.id)) as PluginManifest[];
|
||||
}
|
||||
|
||||
public enableDelay() {
|
||||
const plugins = Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manifest.id) as PluginManifest[];
|
||||
// 同步插件
|
||||
this.synchronizePlugins(plugins);
|
||||
// 开始延时启动插件
|
||||
this.getDelayManagedPluginManifests().forEach((plugin: PluginManifest) => this.startPluginWithDelay(plugin.id));
|
||||
this.getDelayManagedPluginManifests().forEach((plugin: PluginManifest) => this.startPluginWithDelay(plugin.id));
|
||||
}
|
||||
|
||||
// 为所有插件启动延迟
|
||||
|
|
@ -557,7 +557,7 @@ export default class Manager extends Plugin {
|
|||
// 同步插件
|
||||
this.synchronizePlugins(plugins);
|
||||
|
||||
this.getDelayManagedPluginManifests().forEach(async (plugin: PluginManifest) => {
|
||||
this.getDelayManagedPluginManifests().forEach(async (plugin: PluginManifest) => {
|
||||
// 插件状态
|
||||
const isEnabled = this.appPlugins.enabledPlugins.has(plugin.id);
|
||||
if (isEnabled) {
|
||||
|
|
@ -582,7 +582,7 @@ export default class Manager extends Plugin {
|
|||
|
||||
// 为所有插件关闭延迟
|
||||
public disableDelaysForAllPlugins() {
|
||||
const plugins = this.getDelayManagedPluginManifests();
|
||||
const plugins = this.getDelayManagedPluginManifests();
|
||||
plugins.forEach(async (pm: PluginManifest) => {
|
||||
const plugin = this.settings.Plugins.find(p => p.id === pm.id)
|
||||
if (plugin) {
|
||||
|
|
@ -595,10 +595,10 @@ export default class Manager extends Plugin {
|
|||
}
|
||||
|
||||
// 延时启动指定插件
|
||||
private startPluginWithDelay(id: string) {
|
||||
if (id === this.manifest.id) return;
|
||||
if (this.isBpmIgnoredPlugin(id)) return;
|
||||
const plugin = this.settings.Plugins.find(p => p.id === id);
|
||||
private startPluginWithDelay(id: string) {
|
||||
if (id === this.manifest.id) return;
|
||||
if (this.isBpmIgnoredPlugin(id)) return;
|
||||
const plugin = this.settings.Plugins.find(p => p.id === id);
|
||||
if (plugin && plugin.enabled) {
|
||||
const delay = this.settings.DELAYS.find(item => item.id === plugin.delay);
|
||||
const time = delay ? delay.time : 0;
|
||||
|
|
@ -608,17 +608,18 @@ export default class Manager extends Plugin {
|
|||
|
||||
// 同步插件到配置文件
|
||||
public synchronizePlugins(p1: PluginManifest[]) {
|
||||
const p2 = this.settings.Plugins;
|
||||
p2.forEach(p2Item => {
|
||||
if (p2Item.id === this.manifest.id) return;
|
||||
if (!p1.some(p1Item => p1Item.id === p2Item.id)) {
|
||||
this.settings.Plugins = this.settings.Plugins.filter(pm => pm.id !== p2Item.id);
|
||||
}
|
||||
const manifestIds = new Set(p1.map((plugin) => plugin.id));
|
||||
const bpmInstalledIds = new Set(this.settings.BPM_INSTALLED || []);
|
||||
const nextPlugins = this.settings.Plugins.filter((plugin) => {
|
||||
return plugin.id === this.manifest.id || manifestIds.has(plugin.id);
|
||||
});
|
||||
const pluginSettingsById = new Map(nextPlugins.map((plugin) => [plugin.id, plugin]));
|
||||
|
||||
p1.forEach(p1Item => {
|
||||
if (!p2.some(p2Item => p2Item.id === p1Item.id)) {
|
||||
let mp = pluginSettingsById.get(p1Item.id);
|
||||
if (!mp) {
|
||||
const isEnabled = this.appPlugins.enabledPlugins.has(p1Item.id);
|
||||
this.settings.Plugins.push({
|
||||
mp = {
|
||||
'id': p1Item.id,
|
||||
'name': p1Item.name,
|
||||
'desc': p1Item.description,
|
||||
|
|
@ -627,18 +628,20 @@ export default class Manager extends Plugin {
|
|||
'enabled': isEnabled,
|
||||
'delay': '',
|
||||
'note': ''
|
||||
});
|
||||
};
|
||||
nextPlugins.push(mp);
|
||||
pluginSettingsById.set(p1Item.id, mp);
|
||||
}
|
||||
const mp = this.settings.Plugins.find(pm => pm.id === p1Item.id);
|
||||
if (mp && this.settings.BPM_INSTALLED.includes(p1Item.id) && !mp.tags.includes(BPM_TAG_ID)) {
|
||||
if (bpmInstalledIds.has(p1Item.id) && !mp.tags.includes(BPM_TAG_ID)) {
|
||||
mp.tags.push(BPM_TAG_ID);
|
||||
}
|
||||
});
|
||||
this.settings.Plugins = nextPlugins;
|
||||
// BPM 自身保持启用且不允许延迟
|
||||
this.ensureSelfPluginRecord();
|
||||
// 保存设置
|
||||
this.saveSettings();
|
||||
}
|
||||
// 保存设置
|
||||
this.saveSettings();
|
||||
}
|
||||
|
||||
// 工具函数
|
||||
public createTag(text: string, color: string, type: string) {
|
||||
|
|
@ -736,52 +739,52 @@ export default class Manager extends Plugin {
|
|||
const statusMap: Record<string, UpdateStatus> = {};
|
||||
|
||||
if (this.settings.DEBUG) console.log("[BPM] checkUpdates start, total manifests:", manifests.length);
|
||||
for (const pm of manifests) {
|
||||
if (opts?.isCancelled?.()) break;
|
||||
const localVersion = pm.version || "0.0.0";
|
||||
const st: UpdateStatus = { source: 'unknown', localVersion, checkedAt: Date.now() };
|
||||
try {
|
||||
// 1) 官方来源
|
||||
const official = officialMap[pm.id];
|
||||
if (official) {
|
||||
st.source = 'official';
|
||||
st.remoteVersion = official;
|
||||
st.repo = await this.repoResolver.resolveRepo(pm.id);
|
||||
if (st.repo) {
|
||||
st.versions = await this.fetchGithubVersions(st.repo);
|
||||
}
|
||||
st.hasUpdate = this.compareVersions(official, localVersion) > 0;
|
||||
if (this.settings.DEBUG) console.log("[BPM] update official match", pm.id, localVersion, "->", st.remoteVersion);
|
||||
} else {
|
||||
// 2) GitHub:BPM 安装或有仓库映射 / 用户填写
|
||||
let repo: string | null = this.settings.REPO_MAP[pm.id] || null;
|
||||
if (!repo) {
|
||||
try {
|
||||
repo = await this.repoResolver.resolveRepo(pm.id);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (repo) {
|
||||
st.source = 'github';
|
||||
st.repo = repo;
|
||||
st.versions = await this.fetchGithubVersions(repo);
|
||||
// 选择一个默认的远端版本:优先最新稳定,否则第一个
|
||||
const pick = st.versions?.find(v => !v.prerelease) ?? st.versions?.[0] ?? null;
|
||||
st.remoteVersion = pick?.version ?? await this.fetchGithubManifestVersion(repo);
|
||||
st.hasUpdate = st.remoteVersion ? this.compareVersions(st.remoteVersion, localVersion) > 0 : false;
|
||||
if (!st.remoteVersion) st.message = this.translator.t("更新_未获取到远端版本");
|
||||
if (this.settings.DEBUG) console.log("[BPM] update github match", pm.id, repo, localVersion, "->", st.remoteVersion);
|
||||
} else {
|
||||
st.source = 'unknown';
|
||||
st.message = this.translator.t("更新_无来源无法检测");
|
||||
if (this.settings.DEBUG) console.log("[BPM] update unknown source", pm.id);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
st.error = (e as Error)?.message || String(e);
|
||||
console.error("[BPM] checkUpdates error", pm.id, e);
|
||||
}
|
||||
for (const pm of manifests) {
|
||||
if (opts?.isCancelled?.()) break;
|
||||
const localVersion = pm.version || "0.0.0";
|
||||
const st: UpdateStatus = { source: 'unknown', localVersion, checkedAt: Date.now() };
|
||||
try {
|
||||
// 1) 官方来源
|
||||
const official = officialMap[pm.id];
|
||||
if (official) {
|
||||
st.source = 'official';
|
||||
st.remoteVersion = official;
|
||||
st.repo = await this.repoResolver.resolveRepo(pm.id);
|
||||
if (st.repo) {
|
||||
st.versions = await this.fetchGithubVersions(st.repo);
|
||||
}
|
||||
st.hasUpdate = this.compareVersions(official, localVersion) > 0;
|
||||
if (this.settings.DEBUG) console.log("[BPM] update official match", pm.id, localVersion, "->", st.remoteVersion);
|
||||
} else {
|
||||
// 2) GitHub:BPM 安装或有仓库映射 / 用户填写
|
||||
let repo: string | null = this.settings.REPO_MAP[pm.id] || null;
|
||||
if (!repo) {
|
||||
try {
|
||||
repo = await this.repoResolver.resolveRepo(pm.id);
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
if (repo) {
|
||||
st.source = 'github';
|
||||
st.repo = repo;
|
||||
st.versions = await this.fetchGithubVersions(repo);
|
||||
// 选择一个默认的远端版本:优先最新稳定,否则第一个
|
||||
const pick = st.versions?.find(v => !v.prerelease) ?? st.versions?.[0] ?? null;
|
||||
st.remoteVersion = pick?.version ?? await this.fetchGithubManifestVersion(repo);
|
||||
st.hasUpdate = st.remoteVersion ? this.compareVersions(st.remoteVersion, localVersion) > 0 : false;
|
||||
if (!st.remoteVersion) st.message = this.translator.t("更新_未获取到远端版本");
|
||||
if (this.settings.DEBUG) console.log("[BPM] update github match", pm.id, repo, localVersion, "->", st.remoteVersion);
|
||||
} else {
|
||||
st.source = 'unknown';
|
||||
st.message = this.translator.t("更新_无来源无法检测");
|
||||
if (this.settings.DEBUG) console.log("[BPM] update unknown source", pm.id);
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
st.error = (e as Error)?.message || String(e);
|
||||
console.error("[BPM] checkUpdates error", pm.id, e);
|
||||
}
|
||||
statusMap[pm.id] = st;
|
||||
opts?.onProgress?.(pm.id);
|
||||
}
|
||||
|
|
@ -823,11 +826,11 @@ export default class Manager extends Plugin {
|
|||
const pick = st.versions?.find(v => !v.prerelease) ?? st.versions?.[0] ?? null;
|
||||
st.remoteVersion = pick?.version ?? await this.fetchGithubManifestVersion(repo);
|
||||
st.hasUpdate = st.remoteVersion ? this.compareVersions(st.remoteVersion, localVersion) > 0 : false;
|
||||
if (!st.remoteVersion) st.message = this.translator.t("更新_未获取到远端版本");
|
||||
if (!st.remoteVersion) st.message = this.translator.t("更新_未获取到远端版本");
|
||||
if (this.settings.DEBUG) console.log("[BPM] single update github", pm.id, repo, localVersion, "->", st.remoteVersion);
|
||||
} else {
|
||||
st.source = "unknown";
|
||||
st.message = this.translator.t("更新_无来源无法检测");
|
||||
st.message = this.translator.t("更新_无来源无法检测");
|
||||
if (this.settings.DEBUG) console.log("[BPM] single update unknown source", pm.id);
|
||||
}
|
||||
} catch (e) {
|
||||
|
|
@ -1003,16 +1006,16 @@ export default class Manager extends Plugin {
|
|||
baseSelector = `.side-dock-actions div.clickable-icon.side-dock-ribbon-action`;
|
||||
}
|
||||
|
||||
const cssRules = items.map(item => {
|
||||
if (!item.name) return "";
|
||||
const order = Number.isFinite(item.order) ? item.order : 9999;
|
||||
if (!item.visible) {
|
||||
const selector = this.generateMultiLineAriaLabelSelector(baseSelector, item.name);
|
||||
return `${selector} { order: ${order}; display: none !important; }`;
|
||||
}
|
||||
const selector = this.generateMultiLineAriaLabelSelector(baseSelector, item.name);
|
||||
return `${selector} { order: ${order}; }`;
|
||||
}).filter(rule => rule !== "").join("\n");
|
||||
const cssRules = items.map(item => {
|
||||
if (!item.name) return "";
|
||||
const order = Number.isFinite(item.order) ? item.order : 9999;
|
||||
if (!item.visible) {
|
||||
const selector = this.generateMultiLineAriaLabelSelector(baseSelector, item.name);
|
||||
return `${selector} { order: ${order}; display: none !important; }`;
|
||||
}
|
||||
const selector = this.generateMultiLineAriaLabelSelector(baseSelector, item.name);
|
||||
return `${selector} { order: ${order}; }`;
|
||||
}).filter(rule => rule !== "").join("\n");
|
||||
|
||||
styleEl.innerHTML = cssRules;
|
||||
}
|
||||
|
|
@ -1154,10 +1157,10 @@ export default class Manager extends Plugin {
|
|||
|
||||
|
||||
|
||||
// 功能编排只应用运行时样式,不写入 Obsidian workspace 配置或 Ribbon 内存状态。
|
||||
applyRibbonConfigToMemory(orderedIds: string[], hiddenStatus: Record<string, boolean>) {
|
||||
this.updateRibbonStyles();
|
||||
}
|
||||
// 功能编排只应用运行时样式,不写入 Obsidian workspace 配置或 Ribbon 内存状态。
|
||||
applyRibbonConfigToMemory(orderedIds: string[], hiddenStatus: Record<string, boolean>) {
|
||||
this.updateRibbonStyles();
|
||||
}
|
||||
|
||||
public async syncRibbonConfig(orderedIds: string[], hiddenStatus: Record<string, boolean>) {
|
||||
// 更新本地设置以匹配原生配置
|
||||
|
|
|
|||
|
|
@ -1340,10 +1340,18 @@ export class ManagerModal extends Modal {
|
|||
Object.values(manifestMap).forEach((mf: PluginManifest) => {
|
||||
uniqMap.set(mf.id, mf);
|
||||
});
|
||||
const uniquePlugins = Array.from(uniqMap.values()).sort((a, b) => a.name.localeCompare(b.name));
|
||||
const manifestById = new Map(uniquePlugins.map((plugin) => [plugin.id, plugin]));
|
||||
const layoutItems = this.getPluginLayout(uniquePlugins);
|
||||
const showSeparators = this.shouldRenderPluginLayoutSeparators();
|
||||
const uniquePlugins = Array.from(uniqMap.values()).sort((a, b) => a.name.localeCompare(b.name));
|
||||
const manifestById = new Map(uniquePlugins.map((plugin) => [plugin.id, plugin]));
|
||||
const layoutItems = this.getPluginLayout(uniquePlugins);
|
||||
const pluginSettingsById = new Map(this.manager.settings.Plugins.map((plugin) => [plugin.id, plugin]));
|
||||
const groupSettingsById = new Map(this.settings.GROUPS.map((group) => [group.id, group]));
|
||||
const tagSettingsById = new Map(this.settings.TAGS.map((tag) => [tag.id, tag]));
|
||||
const delaySettingsById = new Map(this.settings.DELAYS.map((delay) => [delay.id, delay]));
|
||||
const hiddenPluginIds = new Set(this.settings.HIDES || []);
|
||||
const lowerSearchText = this.searchText.toLowerCase();
|
||||
const getBasePath = (this.app.vault.adapter as any)?.getBasePath?.() as string | undefined;
|
||||
const basePath = getBasePath ? normalizePath(getBasePath) : "";
|
||||
const showSeparators = this.shouldRenderPluginLayoutSeparators();
|
||||
let pendingSeparator: string | null = null;
|
||||
if (this.settings.DEBUG) console.log("[BPM] render showData uniquePlugins:", uniquePlugins.map(p => p.id).join(","));
|
||||
|
||||
|
|
@ -1360,10 +1368,8 @@ export class ManagerModal extends Modal {
|
|||
if (!plugin) continue;
|
||||
if (renderedIds.has(plugin.id)) continue;
|
||||
renderedIds.add(plugin.id);
|
||||
const ManagerPlugin = this.manager.settings.Plugins.find((mp) => mp.id === plugin.id);
|
||||
const ManagerPlugin = pluginSettingsById.get(plugin.id);
|
||||
// 计算插件目录的绝对路径:基于 vault 根路径 + configDir + plugin.dir
|
||||
const getBasePath = (this.app.vault.adapter as any)?.getBasePath?.() as string | undefined;
|
||||
const basePath = getBasePath ? normalizePath(getBasePath) : "";
|
||||
const cfgDir = this.app.vault.configDir; // 默认 .obsidian
|
||||
const rawDir = plugin.dir || `plugins/${plugin.id}`;
|
||||
const isAbsolute = new RegExp("^(?:[a-zA-Z]:[\\\\/]|[\\\\/])").test(rawDir);
|
||||
|
|
@ -1428,9 +1434,9 @@ export class ManagerModal extends Modal {
|
|||
if (this.delay !== "" && ManagerPlugin.delay !== this.delay) continue;
|
||||
}
|
||||
// [过滤] 搜索
|
||||
if (this.searchText !== "" && ManagerPlugin.name.toLowerCase().indexOf(this.searchText.toLowerCase()) == -1 && ManagerPlugin.desc.toLowerCase().indexOf(this.searchText.toLowerCase()) == -1 && plugin.author.toLowerCase().indexOf(this.searchText.toLowerCase()) == -1) continue;
|
||||
if (lowerSearchText !== "" && ManagerPlugin.name.toLowerCase().indexOf(lowerSearchText) == -1 && ManagerPlugin.desc.toLowerCase().indexOf(lowerSearchText) == -1 && (plugin.author || "").toLowerCase().indexOf(lowerSearchText) == -1) continue;
|
||||
// [过滤] 隐藏
|
||||
if (!isSelf && this.settings.HIDES.includes(plugin.id)) continue;
|
||||
if (!isSelf && hiddenPluginIds.has(plugin.id)) continue;
|
||||
|
||||
if (pendingSeparator && this.displayPlugins.length > 0) {
|
||||
this.renderPluginLayoutSeparator(pendingSeparator);
|
||||
|
|
@ -1702,7 +1708,7 @@ export class ManagerModal extends Modal {
|
|||
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);
|
||||
const item = groupSettingsById.get(ManagerPlugin.group);
|
||||
if (item) {
|
||||
const tag = this.manager.createTag(item.name, item.color, this.settings.GROUP_STYLE);
|
||||
if (this.editorMode) tag.onclick = () => { new GroupModal(this.app, this.manager, this, ManagerPlugin).open(); };
|
||||
|
|
@ -1794,7 +1800,7 @@ export class ManagerModal extends Modal {
|
|||
|
||||
// [默认] 延迟
|
||||
if (this.settings.DELAY && !this.editorMode && !isSelf && ManagerPlugin.delay !== "") {
|
||||
const d = this.settings.DELAYS.find((item) => item.id === ManagerPlugin.delay);
|
||||
const d = delaySettingsById.get(ManagerPlugin.delay);
|
||||
if (d) {
|
||||
const delay = createSpan({ text: `${d.time}s`, cls: ["manager-item__name-delay"], });
|
||||
itemEl.nameEl.appendChild(delay);
|
||||
|
|
@ -1824,7 +1830,7 @@ export class ManagerModal extends Modal {
|
|||
itemEl.descEl.appendChild(tags);
|
||||
let visibleTagCount = 0;
|
||||
ManagerPlugin.tags.map((id: string) => {
|
||||
const item = this.settings.TAGS.find((item) => item.id === id);
|
||||
const item = tagSettingsById.get(id);
|
||||
if (item) {
|
||||
if ((item.id === BPM_TAG_ID || item.id === BPM_IGNORE_TAG) && this.settings.HIDE_BPM_TAG) {
|
||||
// skip render
|
||||
|
|
@ -2086,20 +2092,17 @@ export class ManagerModal extends Modal {
|
|||
});
|
||||
}
|
||||
|
||||
const openRepoButton = this.createConfiguredItemAction(itemEl.controlEl, "openRepo");
|
||||
if (openRepoButton) {
|
||||
openRepoButton.setIcon("github");
|
||||
openRepoButton.setTooltip(this.manager.translator.t("管理器_仓库检测中_提示"));
|
||||
openRepoButton.setDisabled(true);
|
||||
const repo = await this.manager.repoResolver.resolveRepo(plugin.id);
|
||||
if (!this.isRenderCurrent(renderGeneration, page)) return;
|
||||
const repoState = this.resolvePluginRepoAction(plugin.id, repo);
|
||||
openRepoButton.setTooltip(repoState.tooltip);
|
||||
openRepoButton.setDisabled(repoState.disabled);
|
||||
openRepoButton.onClick(async () => {
|
||||
await this.openPluginRepo(plugin.id, repoState.repo);
|
||||
});
|
||||
}
|
||||
const openRepoButton = this.createConfiguredItemAction(itemEl.controlEl, "openRepo");
|
||||
if (openRepoButton) {
|
||||
openRepoButton.setIcon("github");
|
||||
const knownRepo = this.manager.settings.REPO_MAP?.[plugin.id] || null;
|
||||
const repoState = this.resolvePluginRepoAction(plugin.id, knownRepo);
|
||||
openRepoButton.setTooltip(knownRepo ? repoState.tooltip : this.manager.translator.t("管理器_打开仓库_标题"));
|
||||
openRepoButton.setDisabled(false);
|
||||
openRepoButton.onClick(async () => {
|
||||
await this.openPluginRepo(plugin.id, knownRepo);
|
||||
});
|
||||
}
|
||||
|
||||
// [按钮] 打开设置
|
||||
openPluginSetting = this.createConfiguredItemAction(itemEl.controlEl, "openSettings");
|
||||
|
|
@ -2266,10 +2269,10 @@ export class ManagerModal extends Modal {
|
|||
const cards = Array.from(this.contentEl.querySelectorAll(".manager-item"));
|
||||
console.log("[BPM] render showData after loop, cards:", cards.length, "ids:", cards.map(el => el.getAttribute("data-plugin-id")).filter(Boolean).join(","));
|
||||
}
|
||||
// 计算页尾
|
||||
this.updateStats();
|
||||
}
|
||||
}
|
||||
}
|
||||
// 计算页尾
|
||||
this.updateStats();
|
||||
}
|
||||
|
||||
private getCounts() {
|
||||
let totalCount = 0;
|
||||
|
|
|
|||
Loading…
Reference in a new issue