pref(UI): 优化移动端UI

This commit is contained in:
dangehub 2026-01-01 12:23:24 +08:00
parent 1cb87e02ba
commit a1978d3c1c
9 changed files with 493 additions and 85 deletions

View file

@ -15,8 +15,9 @@ export default {
_禁用_文本: 'Disable',
_关闭_文本: 'Disable',
_开启_文本: 'Enable',
_保存_文本: 'Save settings',
_取消_文本: 'Cancel',
_保存_文本: 'Save settings',
_取消_文本: 'Cancel',
_返回_文本: 'Back',
_正文提示: 'Body section: you can edit or replace this content.',
@ -90,13 +91,14 @@ export default {
_重载插件_描述: 'Reload plugins to take effect immediately',
_重载插件_开始提示: 'Refreshing plugin manifests…',
_重载插件_失败提示: 'Reload failed. Please try again (see console for details).',
_检查更新_描述: 'Check for plugin updates',
_一键禁用_描述: 'Disable all plugins at once',
_一键启用_描述: 'Enable all plugins at once',
_插件设置_描述: 'Manage plugin settings',
_仅启用_描述: 'Only display enabled plugins',
_未分组_描述: 'Filter all ungrouped plugins',
_打开设置_描述: 'Open the settings interface',
_检查更新_描述: 'Check for plugin updates',
_更多操作_描述: 'More actions',
_一键禁用_描述: 'Disable all plugins at once',
_一键启用_描述: 'Enable all plugins at once',
_插件设置_描述: 'Manage plugin settings',
_仅启用_描述: 'Only display enabled plugins',
_未分组_描述: 'Filter all ungrouped plugins',
_打开设置_描述: 'Open the settings interface',
_还原内容_描述: 'Restore to the initial state',
_打开目录_描述: 'Open the plugin directory',
_删除插件_描述: 'Completely delete the plugin',
@ -106,6 +108,7 @@ export default {
_重启中_提示: 'Restarting… please wait',
_仓库检测中_提示: 'Detecting repository…',
_打开仓库_提示: 'Open repo: {repo}',
_打开仓库_标题: 'Open repository',
_仓库未记录_提示: 'Repository not recorded',
_仓库需手动添加_提示: 'This plugin is not installed via official/BPM. Please set the source manually.',
_缺少仓库提示: 'Missing repository source; cannot download update.',

View file

@ -11,15 +11,17 @@ export default {
_无延迟_文本: 'Sin retraso',
_过滤_文本: 'Filtrar',
_总计_文本: 'Total',
_启用_文本: 'Habilitar',
_禁用_文本: 'Deshabilitar',
_启用_文本: 'Habilitar',
_禁用_文本: 'Deshabilitar',
_返回_文本: 'Volver',
_GITHUB_描述: 'Visite la página de GitHub del autor para ver detalles del proyecto, registros de actualizaciones, participar en discusiones y contribuir con código.',
_视频教程_描述: 'Acceder a tutoriales en video',
_编辑模式_描述: 'Habilitar modo de edición para una personalización profunda de la configuración del plugin',
_重载插件_描述: 'Recargar plugins para que surtan efecto inmediatamente',
_检查更新_描述: 'Comprobar actualizaciones de plugins',
_检查更新_描述: 'Comprobar actualizaciones de plugins',
_更多操作_描述: 'Más acciones',
_一键禁用_描述: 'Deshabilitar todos los plugins a la vez',
_一键启用_描述: 'Habilitar todos los plugins a la vez',
_插件设置_描述: 'Administrar configuración de plugins',
@ -64,6 +66,7 @@ export default {
_重启中_提示: 'Reiniciando… espera un momento',
_仓库检测中_提示: 'Detectando repositorio…',
_打开仓库_提示: 'Abrir repo: {repo}',
_打开仓库_标题: 'Abrir repositorio',
_仓库未记录_提示: 'Repositorio no registrado',
_仓库需手动添加_提示: 'Este plugin no es oficial/instalado por BPM. Añade el origen manualmente.',
_缺少仓库提示: 'Falta el repositorio; no se puede descargar la actualización.',

View file

@ -17,6 +17,7 @@ export default {
_开启_文本: 'Ouvrir',
_保存_文本: 'Enregistrer',
_取消_文本: 'Annuler',
_返回_文本: 'Retour',
_正文提示: 'Section corps : vous pouvez modifier ou remplacer ce contenu.',
@ -196,4 +197,6 @@ export default {
_错误_通用: 'Échec de linstallation. Vérifiez dépôt/version ou réseau.',
_基础设置_调试模式_标题: 'Mode debug',
_基础设置_调试模式_描述: 'Désactivé : erreurs uniquement. Activé : logs de debug.',
_更多操作_描述: 'Plus dactions',
_打开仓库_标题: 'Ouvrir le dépôt',
}

View file

@ -12,7 +12,8 @@ export default {
_过滤_文本: 'フィルター',
_总计_文本: '合計',
_启用_文本: '有効',
_禁用_文本: '無効',
_禁用_文本: '無効',
_返回_文本: '戻る',
_GITHUB_描述: '著者のGitHubページを訪れ、プロジェクトの詳細、更新ログ、議論への参加、コードへの貢献を確認してください。',
@ -125,6 +126,8 @@ export default {
_分组_全部: 'グループ:全部',
_标签_全部: 'タグ:全部',
_延迟_全部: '遅延:全部',
_管理面板_描述: 'プラグインマネージャーを開く',
}
_管理面板_描述: 'プラグインマネージャーを開く',
_更多操作_描述: 'その他の操作',
_打开仓库_标题: 'リポジトリを開く',
}

View file

@ -1,4 +1,4 @@
export default {
export default {
_管理器_文本: '플러그인 관리자',
_成功_文本: '성공',
_失败_文本: '실패',
@ -12,7 +12,8 @@ export default {
_过滤_文本: '필터',
_总计_文本: '총계',
_启用_文本: '활성화',
_禁用_文本: '비활성화',
_禁用_文本: '비활성화',
_返回_文本: '뒤로',
_GITHUB_描述: '저자의 GitHub 페이지를 방문하여 프로젝트 세부 정보, 업데이트 로그, 토론 참여, 코드 기여를 확인하세요.',
@ -125,4 +126,6 @@ export default {
_仓库未记录_提示: '저장소가 기록되지 않았습니다',
_仓库需手动添加_提示: '이 플러그인은 공식/BPM 설치가 아닙니다. 소스를 수동으로 설정하세요.',
_缺少仓库提示: '저장소 정보가 없어 업데이트를 다운로드할 수 없습니다.',
_更多操作_描述: '더 많은 작업',
_打开仓库_标题: '저장소 열기',
}

View file

@ -17,6 +17,7 @@ export default {
_开启_文本: 'Открыть',
_保存_文本: 'Сохранить',
_取消_文本: 'Отмена',
_返回_文本: 'Назад',
_正文提示: 'Основной текст: вы можете изменить или заменить этот контент.',
@ -195,4 +196,6 @@ export default {
_仓库未记录_提示: 'Репозиторий не указан',
_仓库需手动添加_提示: 'Плагин не из официального/BPM источника. Укажите источник вручную.',
_缺少仓库提示: 'Нет источника репозитория — невозможно скачать обновление.',
_更多操作_描述: 'Дополнительные действия',
_打开仓库_标题: 'Открыть репозиторий',
}

View file

@ -15,8 +15,9 @@ export default {
_禁用_文本: '禁用',
_关闭_文本: '关闭',
_开启_文本: '开启',
_保存_文本: '保存设置',
_取消_文本: '取消',
_保存_文本: '保存设置',
_取消_文本: '取消',
_返回_文本: '返回',
_正文提示: '正文区:这里的内容可自行编辑或替换。',
@ -32,12 +33,13 @@ export default {
_重载插件_描述: '重载插件,即时生效',
_重载插件_开始提示: '正在重新读取插件清单…',
_重载插件_失败提示: '重载失败,请稍后重试(详情见控制台)。',
_检查更新_描述: '检查插件更新',
_一键禁用_描述: '一键禁用所有插件',
_一键启用_描述: '一键启用所有插件',
_插件设置_描述: '管理插件设置',
_仅启用_描述: '仅显示已启用插件',
_未分组_描述: '筛选所有未分组插件',
_检查更新_描述: '检查插件更新',
_更多操作_描述: '更多操作',
_一键禁用_描述: '一键禁用所有插件',
_一键启用_描述: '一键启用所有插件',
_插件设置_描述: '管理插件设置',
_仅启用_描述: '仅显示已启用插件',
_未分组_描述: '筛选所有未分组插件',
_打开设置_描述: '打开设置界面',
_还原内容_描述: '还原初始状态',
_打开目录_描述: '打开插件目录',
@ -48,6 +50,7 @@ export default {
_重启中_提示: '重启中,请稍等',
_仓库检测中_提示: '正在检测仓库地址...',
_打开仓库_提示: '打开仓库:{repo}',
_打开仓库_标题: '打开仓库',
_仓库未记录_提示: '未记录仓库地址',
_仓库需手动添加_提示: '本插件非官方/bpm安装请手动添加来源',
_缺少仓库提示: '缺少仓库来源,无法下载更新',

View file

@ -76,6 +76,7 @@ export class ManagerModal extends Modal {
actionCollapsed = false;
filterCollapsed = false;
private reloadingManifests = false;
private mobileFiltersCollapsed = true;
private showInlineProgress(text: string, subText?: string) {
const notice = new Notice("", 0);
@ -184,12 +185,12 @@ export class ManagerModal extends Modal {
return plugins;
}
public async showHead() {
//@ts-ignore
const modalEl: HTMLElement = this.contentEl.parentElement;
this.modalContainer = modalEl;
modalEl.addClass("manager-container");
if (Platform.isMobileApp) modalEl.addClass("manager-container--mobile");
public async showHead() {
//@ts-ignore
const modalEl: HTMLElement = this.contentEl.parentElement;
this.modalContainer = modalEl;
modalEl.addClass("manager-container");
if (Platform.isMobileApp) modalEl.addClass("manager-container--mobile");
// 靠上
if (!this.settings.CENTER && !Platform.isMobileApp) modalEl.addClass("manager-container__top");
if (this.editorMode) modalEl.addClass("manager-container--editing");
@ -200,10 +201,15 @@ export class ManagerModal extends Modal {
// 添加页尾
this.footEl = document.createElement("div");
this.footEl.addClass("manager-food");
this.modalEl.appendChild(this.footEl);
// [操作行]
const actionWrapper = this.titleEl.createDiv("manager-section manager-section--row");
this.modalEl.appendChild(this.footEl);
if (Platform.isMobileApp) {
this.showHeadMobile();
return;
}
// [操作行]
const actionWrapper = this.titleEl.createDiv("manager-section manager-section--row");
const actionHeader = actionWrapper.createDiv("manager-section__header");
const actionArrow = actionHeader.createSpan({ text: this.actionCollapsed ? "▼" : "▲" });
actionArrow.addClass("manager-section__arrow");
@ -414,7 +420,7 @@ export class ManagerModal extends Modal {
});
// [操作行] 插件设置
const settingsButton = new ButtonComponent(actionBar.controlEl);
const settingsButton = new ButtonComponent(actionBar.controlEl);
settingsButton.setIcon("settings");
settingsButton.setTooltip(this.manager.translator.t("管理器_插件设置_描述"));
this.bindLongPressTooltip(settingsButton.buttonEl, this.manager.translator.t("管理器_插件设置_描述"));
@ -568,8 +574,182 @@ export class ManagerModal extends Modal {
this.reloadShowData();
});
}
private showHeadMobile() {
const t = (k: any) => this.manager.translator.t(k);
this.titleEl.empty();
const header = this.titleEl.createDiv("bpm-mobile-header");
const topRow = header.createDiv("bpm-mobile-header__top");
const title = topRow.createDiv("bpm-mobile-header__title");
title.setText(this.manager.manifest.name);
const topActions = topRow.createDiv("bpm-mobile-header__actions");
// 编辑模式(常驻)
const editorBtn = new ButtonComponent(topActions);
editorBtn.setIcon(this.editorMode ? "pen-off" : "pen");
editorBtn.setTooltip(t("管理器_编辑模式_描述"));
this.bindLongPressTooltip(editorBtn.buttonEl, t("管理器_编辑模式_描述"));
editorBtn.onClick(async () => {
this.editorMode = !this.editorMode;
this.applyEditingStyle();
// 退出编辑模式需要刷新筛选项统计,但要保留滚动位置
if (!this.editorMode) {
await this.refreshFilterOptions(true);
} else {
this.renderContent();
}
this.showHeadMobile();
});
// 安装/返回(切换安装模式)
const installBtn = new ButtonComponent(topActions);
installBtn.setIcon(this.installMode ? "arrow-left" : "download");
installBtn.setTooltip(this.installMode ? t("通用_返回_文本") : t("管理器_安装_GITHUB_描述"));
this.bindLongPressTooltip(installBtn.buttonEl, this.installMode ? t("通用_返回_文本") : t("管理器_安装_GITHUB_描述"));
installBtn.onClick(() => {
this.installMode = !this.installMode;
if (this.searchBarEl) {
this.installMode ? this.searchBarEl.addClass("manager-display-none") : this.searchBarEl.removeClass("manager-display-none");
}
this.renderContent();
this.showHeadMobile();
});
// 更多操作菜单
const moreBtn = new ButtonComponent(topActions);
moreBtn.setIcon("more-vertical");
moreBtn.setTooltip(t("管理器_更多操作_描述"));
this.bindLongPressTooltip(moreBtn.buttonEl, t("管理器_更多操作_描述"));
moreBtn.buttonEl.addEventListener("click", (ev) => {
const menu = new Menu();
menu.addItem((item) => item.setTitle(t("管理器_检查更新_描述")).setIcon("rss").onClick(async () => {
await this.manager.checkUpdatesWithNotice();
await this.reloadShowData();
}));
menu.addItem((item) => item.setTitle(t("管理器_重载插件_描述")).setIcon("refresh-ccw").onClick(async () => {
await this.appPlugins.loadManifests();
await this.reloadShowData();
}));
menu.addSeparator();
menu.addItem((item) => item.setTitle(t("管理器_插件设置_描述")).setIcon("settings").onClick(() => {
this.appSetting.open();
this.appSetting.openTabById(this.manager.manifest.id);
}));
menu.addItem((item) => item.setTitle(t("管理器_GITHUB_描述")).setIcon("github").onClick(() => {
window.open("https://github.com/zenozero-dev/obsidian-manager");
}));
menu.addItem((item) => item.setTitle(t("管理器_视频教程_描述")).setIcon("book-open").onClick(() => {
window.open("https://www.bilibili.com/video/BV1WyrkYMEce/");
}));
menu.showAtMouseEvent(ev as MouseEvent);
});
const searchWrap = header.createDiv("bpm-mobile-header__search");
this.searchEl = new SearchComponent(searchWrap);
if (this.settings.PERSISTENCE && typeof this.settings.FILTER_SEARCH === "string") {
this.searchText = this.settings.FILTER_SEARCH;
this.searchEl.inputEl.value = this.searchText;
}
this.searchEl.onChange((value: string) => {
this.searchText = value;
if (this.settings.PERSISTENCE) {
this.settings.FILTER_SEARCH = value;
this.manager.saveSettings();
}
this.reloadShowData();
});
const filterHeader = header.createDiv("bpm-mobile-header__filters-toggle");
const arrow = filterHeader.createSpan({ cls: "bpm-mobile-header__filters-arrow" });
arrow.setText(this.mobileFiltersCollapsed ? "▼" : "▲");
filterHeader.createSpan({ text: t("通用_过滤_文本") });
filterHeader.toggleClass("is-open", !this.mobileFiltersCollapsed);
filterHeader.addEventListener("click", () => {
this.mobileFiltersCollapsed = !this.mobileFiltersCollapsed;
filterPanel.toggleClass("is-collapsed", this.mobileFiltersCollapsed);
filterHeader.toggleClass("is-open", !this.mobileFiltersCollapsed);
arrow.setText(this.mobileFiltersCollapsed ? "▼" : "▲");
});
const filterPanel = header.createDiv(`bpm-mobile-header__filters${this.mobileFiltersCollapsed ? " is-collapsed" : ""}`);
// 状态
const statusSetting = new Setting(filterPanel).setName(t("筛选_状态_全部"));
statusSetting.addDropdown((dd) => {
dd.addOptions({
"all": t("筛选_状态_全部"),
"enabled": t("筛选_仅启用_描述"),
"disabled": t("筛选_仅禁用_描述"),
"grouped": t("筛选_已分组_描述"),
"ungrouped": t("筛选_未分组_描述"),
"tagged": t("筛选_有标签_描述"),
"untagged": t("筛选_无标签_描述"),
"noted": t("筛选_有笔记_描述"),
});
dd.setValue(this.filter || "all");
dd.onChange((v) => { this.filter = v; this.reloadShowData(); });
});
// 分组
const groupCounts = this.settings.Plugins.reduce((acc: { [key: string]: number }, plugin) => { const groupId = plugin.group || ""; acc[groupId] = (acc[groupId] || 0) + 1; return acc; }, { "": 0 });
const groups = this.settings.GROUPS.reduce((acc: { [key: string]: string }, item) => { acc[item.id] = `${item.name} [${groupCounts[item.id] || 0}]`; return acc; }, { "": t("筛选_分组_全部") });
const groupSetting = new Setting(filterPanel).setName(t("筛选_分组_全部"));
groupSetting.addDropdown((dd) => {
dd.addOptions(groups);
dd.setValue(this.settings.PERSISTENCE ? this.settings.FILTER_GROUP : this.group);
dd.onChange((value) => {
if (this.settings.PERSISTENCE) {
this.settings.FILTER_GROUP = value;
this.manager.saveSettings();
} else {
this.group = value;
}
this.reloadShowData();
});
});
// 标签
const tagCounts: { [key: string]: number } = this.settings.Plugins.reduce((acc, plugin) => { plugin.tags.forEach((tag) => { acc[tag] = (acc[tag] || 0) + 1; }); return acc; }, {} as { [key: string]: number });
const tags = this.settings.TAGS.reduce((acc: { [key: string]: string }, item) => { acc[item.id] = `${item.name} [${tagCounts[item.id] || 0}]`; return acc; }, { "": t("筛选_标签_全部") });
const tagSetting = new Setting(filterPanel).setName(t("筛选_标签_全部"));
tagSetting.addDropdown((dd) => {
dd.addOptions(tags);
dd.setValue(this.settings.PERSISTENCE ? this.settings.FILTER_TAG : this.tag);
dd.onChange((value) => {
if (this.settings.PERSISTENCE) {
this.settings.FILTER_TAG = value;
this.manager.saveSettings();
} else {
this.tag = value;
}
this.reloadShowData();
});
});
// 延迟
if (this.settings.DELAY) {
const delayCounts = this.settings.Plugins.reduce((acc: { [key: string]: number }, plugin) => { const delay = plugin.delay || ""; acc[delay] = (acc[delay] || 0) + 1; return acc; }, { "": 0 });
const delays = this.settings.DELAYS.reduce((acc: { [key: string]: string }, item) => { acc[item.id] = `${item.name} (${delayCounts[item.id] || 0})`; return acc; }, { "": t("筛选_延迟_全部") });
const delaySetting = new Setting(filterPanel).setName(t("筛选_延迟_全部"));
delaySetting.addDropdown((dd) => {
dd.addOptions(delays);
dd.setValue(this.settings.PERSISTENCE ? this.settings.FILTER_DELAY : this.delay);
dd.onChange((value) => {
if (this.settings.PERSISTENCE) {
this.settings.FILTER_DELAY = value;
this.manager.saveSettings();
} else {
this.delay = value;
}
this.reloadShowData();
});
});
}
}
public async showData() {
public async showData() {
// 使用 manifests 按 id 去重,防止重复渲染
const manifestMap = this.appPlugins.manifests;
if (this.settings.DEBUG) console.log("[BPM] render showData manifests size:", Object.keys(manifestMap).length);
@ -922,20 +1102,20 @@ export class ManagerModal extends Modal {
const arrow = createSpan({ text: "→", cls: ["manager-item__name-remote-arrow"] });
versionWrap.appendChild(arrow);
const remote = createSpan({ text: `${updateInfo.remoteVersion}`, cls: ["manager-item__name-remote"] });
versionWrap.appendChild(remote);
if (!this.editorMode) {
const downloadBtn = new ExtraButtonComponent(itemEl.controlEl);
downloadBtn.setIcon("download");
downloadBtn.setTooltip(this.manager.translator.t("管理器_下载更新_描述"));
downloadBtn.onClick(() => {
const versions = updateInfo.versions && updateInfo.versions.length > 0
? updateInfo.versions
: [{ version: updateInfo.remoteVersion!, prerelease: false }];
new UpdateModal(this.app, this.manager, plugin.id, versions, updateInfo.remoteVersion, updateInfo.repo || undefined).open();
});
}
}
itemEl.nameEl.appendChild(versionWrap);
versionWrap.appendChild(remote);
if (!this.editorMode && !Platform.isMobileApp) {
const downloadBtn = new ExtraButtonComponent(itemEl.controlEl);
downloadBtn.setIcon("download");
downloadBtn.setTooltip(this.manager.translator.t("管理器_下载更新_描述"));
downloadBtn.onClick(() => {
const versions = updateInfo.versions && updateInfo.versions.length > 0
? updateInfo.versions
: [{ version: updateInfo.remoteVersion!, prerelease: false }];
new UpdateModal(this.app, this.manager, plugin.id, versions, updateInfo.remoteVersion, updateInfo.repo || undefined).open();
});
}
}
itemEl.nameEl.appendChild(versionWrap);
// [默认] 笔记图标
if (ManagerPlugin.note?.length > 0) {
@ -993,8 +1173,89 @@ export class ManagerModal extends Modal {
tags.appendChild(tag);
}
if (!this.editorMode) {
// [按钮] 打开仓库
if (!this.editorMode) {
const isMobile = Platform.isMobileApp;
let openPluginSetting: ExtraButtonComponent | null = null;
let openPluginSettingEl: HTMLElement | undefined;
if (isMobile) {
const moreButton = new ExtraButtonComponent(itemEl.controlEl);
moreButton.setIcon("more-vertical");
moreButton.setTooltip(this.manager.translator.t("管理器_更多操作_描述"));
const moreEl = ((moreButton as any).extraSettingsEl || (moreButton as any).buttonEl) as HTMLElement | undefined;
this.bindLongPressTooltip(moreEl, this.manager.translator.t("管理器_更多操作_描述"));
moreEl?.addEventListener("click", (event) => {
event.preventDefault();
event.stopPropagation();
const menu = new Menu();
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_检查更新_描述"))
.setIcon("rss")
.onClick(async () => {
await this.manager.checkUpdateForPlugin(plugin.id);
await this.reloadShowData();
}));
if (updateInfo?.hasUpdate && updateInfo.remoteVersion) {
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_下载更新_描述"))
.setIcon("download")
.onClick(() => {
const versions = updateInfo.versions && updateInfo.versions.length > 0
? updateInfo.versions
: [{ version: updateInfo.remoteVersion!, prerelease: false }];
new UpdateModal(this.app, this.manager, plugin.id, versions, updateInfo.remoteVersion, updateInfo.repo || undefined).open();
}));
}
menu.addSeparator();
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_打开设置_描述"))
.setIcon("settings")
.setDisabled(!isEnabled)
.onClick(() => {
this.appSetting.open();
this.appSetting.openTabById(plugin.id);
}));
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_打开目录_描述"))
.setIcon("folder-open")
.onClick(() => {
managerOpen(pluginDir, this.manager);
}));
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_打开仓库_标题"))
.setIcon("github")
.onClick(async () => {
const repo = await this.manager.repoResolver.resolveRepo(plugin.id);
if (repo) {
window.open(`https://github.com/${repo}`);
} else {
const isBpmInstall = this.manager.settings.BPM_INSTALLED.includes(plugin.id);
new Notice(isBpmInstall
? this.manager.translator.t("管理器_仓库未记录_提示")
: this.manager.translator.t("管理器_仓库需手动添加_提示"));
}
}));
menu.addSeparator();
menu.addItem((item) => item
.setTitle(this.manager.translator.t("管理器_删除插件_描述"))
.setIcon("trash")
.setDisabled(isSelf)
.onClick(async () => {
if (isSelf) return;
new DeleteModal(this.app, this.manager, async () => {
await this.appPlugins.uninstallPlugin(plugin.id);
await this.appPlugins.loadManifests();
this.reloadShowData();
Commands(this.app, this.manager);
this.manager.synchronizePlugins(Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manager.manifest.id) as PluginManifest[]);
new Notice(this.manager.translator.t("卸载_通知_一"));
}).open();
}));
menu.showAtMouseEvent(event as MouseEvent);
});
} else {
// [按钮] 打开仓库
const openRepoButton = new ExtraButtonComponent(itemEl.controlEl);
openRepoButton.setIcon("github");
openRepoButton.setTooltip(this.manager.translator.t("管理器_仓库检测中_提示"));
@ -1012,23 +1273,23 @@ export class ManagerModal extends Modal {
}
// [按钮] 打开设置
const openPluginSetting = new ExtraButtonComponent(itemEl.controlEl);
openPluginSetting = new ExtraButtonComponent(itemEl.controlEl);
openPluginSetting.setIcon("settings");
openPluginSetting.setTooltip(this.manager.translator.t("管理器_打开设置_描述"));
openPluginSetting.onClick(() => {
openPluginSetting.setDisabled(true);
openPluginSetting?.setDisabled(true);
this.appSetting.open();
this.appSetting.openTabById(plugin.id);
openPluginSetting.setDisabled(false);
openPluginSetting?.setDisabled(false);
});
const openPluginSettingEl = ((openPluginSetting as any).extraSettingsEl || (openPluginSetting as any).buttonEl) as HTMLElement | undefined;
openPluginSettingEl = ((openPluginSetting as any).extraSettingsEl || (openPluginSetting as any).buttonEl) as HTMLElement | undefined;
if (!isEnabled) {
openPluginSetting.setDisabled(true);
if (openPluginSettingEl) openPluginSettingEl.style.display = "none";
}
// [按钮] 打开目录
const openPluginDirButton = new ExtraButtonComponent(itemEl.controlEl);
// [按钮] 打开目录
const openPluginDirButton = new ExtraButtonComponent(itemEl.controlEl);
openPluginDirButton.setIcon("folder-open");
openPluginDirButton.setTooltip(this.manager.translator.t("管理器_打开目录_描述"));
openPluginDirButton.onClick(() => {
@ -1052,10 +1313,11 @@ export class ManagerModal extends Modal {
Commands(this.app, this.manager);
// 删除同理
this.manager.synchronizePlugins(Object.values(this.appPlugins.manifests).filter((pm: PluginManifest) => pm.id !== this.manager.manifest.id) as PluginManifest[]);
new Notice(this.manager.translator.t("卸载_通知_一"));
}).open();
});
new Notice(this.manager.translator.t("卸载_通知_一"));
}).open();
});
}
// [按钮] 切换状态
const toggleSwitch = new ToggleComponent(itemEl.controlEl);
toggleSwitch.setTooltip(this.manager.translator.t("管理器_切换状态_描述"));
@ -1073,8 +1335,10 @@ export class ManagerModal extends Modal {
itemEl.settingEl.toggleClass("inactive", !targetEnabled);
}
// 同步“打开设置”按钮(启用后出现,禁用后隐藏)
openPluginSetting.setDisabled(!targetEnabled);
if (openPluginSettingEl) openPluginSettingEl.style.display = targetEnabled ? "" : "none";
if (openPluginSetting) {
openPluginSetting.setDisabled(!targetEnabled);
if (openPluginSettingEl) openPluginSettingEl.style.display = targetEnabled ? "" : "none";
}
// 按需从当前视图移除,避免全量重绘
if (removeByFilter) {
itemEl.settingEl.detach();

View file

@ -217,20 +217,40 @@ body.theme-dark {
gap: 6px;
}
.manager-container--mobile .manager-item {
flex-direction: column;
align-items: flex-start;
padding: clamp(10px, 2vw, 14px);
border: 1px solid var(--background-modifier-border);
border-radius: 12px;
background-color: var(--background-secondary);
}
.manager-container--mobile .manager-item__name-container {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
.manager-container--mobile .manager-item {
flex-direction: column;
align-items: flex-start;
padding: clamp(10px, 2vw, 14px);
border: 1px solid var(--background-modifier-border);
border-radius: 12px;
background-color: var(--background-secondary);
}
.manager-container--mobile .manager-item__controls.setting-item-control {
width: 100%;
display: flex;
align-items: center;
justify-content: flex-end;
gap: 10px;
flex-wrap: nowrap;
}
.manager-container--mobile .manager-item__controls .clickable-icon {
width: 40px;
height: 40px;
border-radius: 12px;
background: var(--background-primary);
border: 1px solid var(--background-modifier-border);
display: inline-flex;
align-items: center;
justify-content: center;
}
.manager-container--mobile .manager-item__name-container {
width: 100%;
display: flex;
justify-content: space-between;
align-items: center;
}
.manager-container--mobile .manager-item__description-container {
@ -390,7 +410,7 @@ body.theme-dark {
}
}
@media (min-width: 600px) and (orientation: landscape) {
@media (min-width: 600px) and (orientation: landscape) {
.manager-container--mobile {
top: calc(3vh + env(safe-area-inset-top, 0px));
height: calc(100vh - 6vh - env(safe-area-inset-top, 0px));
@ -406,9 +426,112 @@ body.theme-dark {
.manager-container--mobile .manager-item-container {
max-height: calc(100vh - 200px);
}
}
/* 目录容器 */
}
/* mobile header (separate UI) */
.manager-container--mobile .bpm-mobile-header {
display: flex;
flex-direction: column;
gap: 10px;
padding: 10px 12px 8px;
margin: 0 8px 10px;
border: 1px solid var(--background-modifier-border);
border-radius: 12px;
background: var(--background-secondary);
}
.manager-container--mobile .bpm-mobile-header__top {
display: flex;
align-items: center;
justify-content: space-between;
gap: 10px;
}
.manager-container--mobile .bpm-mobile-header__title {
flex: 1 1 auto;
min-width: 0;
font-size: 16px;
font-weight: 700;
color: var(--text-normal);
line-height: 1.2;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.manager-container--mobile .bpm-mobile-header__actions {
flex: 0 0 auto;
display: flex;
align-items: center;
gap: 8px;
}
.manager-container--mobile .bpm-mobile-header__actions button {
width: 40px;
height: 40px;
padding: 0;
border-radius: 12px;
display: inline-flex;
align-items: center;
justify-content: center;
background: var(--background-primary);
border: 1px solid var(--background-modifier-border);
}
.manager-container--mobile .bpm-mobile-header__actions button svg {
width: 18px;
height: 18px;
}
.manager-container--mobile .bpm-mobile-header__search .search-input-container,
.manager-container--mobile .bpm-mobile-header__search .search-input-container input {
width: 100%;
}
.manager-container--mobile .bpm-mobile-header__filters-toggle {
display: flex;
align-items: center;
gap: 8px;
padding: 10px 12px;
border: 1px solid var(--background-modifier-border);
border-radius: 12px;
background: var(--background-primary);
cursor: pointer;
font-weight: 600;
user-select: none;
}
.manager-container--mobile .bpm-mobile-header__filters-toggle.is-open {
border-color: color-mix(in srgb, var(--text-accent) 55%, var(--background-modifier-border));
background: var(--background-secondary-alt);
color: var(--text-accent);
}
.manager-container--mobile .bpm-mobile-header__filters-arrow {
font-size: 12px;
line-height: 1;
}
.manager-container--mobile .bpm-mobile-header__filters {
padding: 8px 10px;
border: 1px solid var(--background-modifier-border);
border-radius: 12px;
background: var(--background-primary);
}
.manager-container--mobile .bpm-mobile-header__filters.is-collapsed {
display: none !important;
}
.manager-container--mobile .bpm-mobile-header__filters .setting-item {
padding: 8px 0;
}
.manager-container--mobile .bpm-mobile-header__filters .setting-item + .setting-item {
border-top: 1px solid var(--background-modifier-border);
}
/* 目录容器 */
.manager-item-container {
overflow: auto;
padding: 8px;