From a120e450e946d02bdc8836c25f4289c37a11e564 Mon Sep 17 00:00:00 2001 From: Wanxp <977741432@qq.com> Date: Mon, 24 Feb 2025 17:08:56 +0800 Subject: [PATCH] =?UTF-8?q?fix=20#139=20#128=201.=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E9=85=8D=E7=BD=AE=E5=B0=86=E9=85=8D=E7=BD=AE=E9=A1=B5=E9=9D=A2?= =?UTF-8?q?=E8=B0=83=E6=95=B4=E4=B8=BAtab=202.=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=96=87=E4=BB=B6=E5=A4=B9=E9=80=89=E5=8F=96=E6=96=B9=E5=BC=8F?= =?UTF-8?q?=E9=81=BF=E5=85=8D=E5=8D=A1=E9=A1=BF=203.=20=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E6=A8=A1=E6=9D=BF=E6=96=87=E4=BB=B6=E9=80=89=E5=8F=96=E6=96=B9?= =?UTF-8?q?=E5=BC=8F=E9=81=BF=E5=85=8D=E5=8D=A1=E9=A1=BF=204.=20=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E8=AE=BE=E7=BD=AE=E7=9A=84=E5=AF=BC=E5=85=A5=E5=AF=BC?= =?UTF-8?q?=E5=87=BA=E7=94=A8=E4=BB=A5=E5=A4=87=E4=BB=BD=205.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E5=8A=A0=E8=BD=BD=E6=8F=92=E4=BB=B6=E7=9A=84=E5=8D=A1?= =?UTF-8?q?=E9=A1=BF=E9=97=AE=E9=A2=98=EF=BC=8C=E7=8E=B0=E5=9C=A8=E5=8A=A0?= =?UTF-8?q?=E8=BD=BD=E4=BC=9A=E9=9D=9E=E5=B8=B8=E5=BF=AB=206.=20=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E4=BA=86=E9=85=8D=E7=BD=AE=E7=9A=84=E6=96=87=E6=9C=AC?= =?UTF-8?q?=EF=BC=8C=E7=AE=80=E5=8C=96=E4=BA=86=E6=96=87=E6=9C=AC=E5=86=85?= =?UTF-8?q?=E5=AE=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../douban/component/ConfirmDialogModal.ts | 41 +++- .../douban/component/DoubanHumanCheckModel.ts | 2 +- .../douban/component/DoubanLoginModel.ts | 2 +- .../douban/component/DoubanLogoutModel.ts | 2 +- .../douban/setting/AdvancedSettingsHelper.ts | 75 +++++-- .../setting/ArrayDisplayTypeSettingsHelper.ts | 50 ++--- .../douban/setting/BasicSettingsHelper.ts | 167 +-------------- .../setting/CustomPropertySettingsHelper.ts | 3 +- .../wanxp/douban/setting/DoubanSettingTab.ts | 59 +++++- .../douban/setting/LoginSettingsHelper.ts | 192 ++++++++++++++++++ .../douban/setting/OutputSettingsHelper.ts | 17 +- .../wanxp/douban/setting/SettingsManager.ts | 19 ++ .../douban/setting/TemplateSettingHelper.ts | 46 +++-- .../setting/TemplateVariableSettingsHelper.ts | 3 +- .../model/CreateTemplateSelectParams.ts | 1 + .../setting/model/FileTreeSelectSuggest.ts | 79 +++++++ .../setting/model/FolderTreeSelectSuggest.ts | 78 +++++++ src/org/wanxp/lang/locale/en.ts | 44 ++-- src/org/wanxp/lang/locale/zh-cn.ts | 45 ++-- src/org/wanxp/main.ts | 27 +-- src/org/wanxp/utils/TimeUtil.ts | 25 +++ styles.css | 56 +++++ 22 files changed, 737 insertions(+), 296 deletions(-) create mode 100644 src/org/wanxp/douban/setting/LoginSettingsHelper.ts create mode 100644 src/org/wanxp/douban/setting/model/FileTreeSelectSuggest.ts create mode 100644 src/org/wanxp/douban/setting/model/FolderTreeSelectSuggest.ts diff --git a/src/org/wanxp/douban/component/ConfirmDialogModal.ts b/src/org/wanxp/douban/component/ConfirmDialogModal.ts index d9ce712..1d5bb29 100644 --- a/src/org/wanxp/douban/component/ConfirmDialogModal.ts +++ b/src/org/wanxp/douban/component/ConfirmDialogModal.ts @@ -1,12 +1,18 @@ -import {ButtonComponent, Modal} from "obsidian"; +import {App, ButtonComponent, Modal} from "obsidian"; import {i18nHelper} from "../../lang/helper"; +import {create} from "istanbul-reports"; +import DoubanPlugin from "../../main"; +import {logger} from "bs-logger"; +import {log} from "../../utils/Logutil"; export class ConfirmDialogModal extends Modal { private promise:Promise; private message:string; + private doubanPlugin: DoubanPlugin; - constructor(app: any, message:string, promise: Promise) { - super(app); + constructor(doubanPlugin: DoubanPlugin, message:string, promise: Promise) { + super(doubanPlugin.app); + this.doubanPlugin = doubanPlugin; this.message = message; this.promise = promise; } @@ -23,7 +29,12 @@ export class ConfirmDialogModal extends Modal { .setButtonText(i18nHelper.getMessage('110152')) .setCta() .onClick(async () => { - await this.promise; + //临时特殊处理导入文件 + if (this.message == i18nHelper.getMessage('125046')) { + createFileSelectModal(this.doubanPlugin); + }else { + await this.promise; + } this.close(); }).setClass( "obsidian_douban_search_button"); new ButtonComponent(controls) @@ -33,3 +44,25 @@ export class ConfirmDialogModal extends Modal { }).setClass( "obsidian_douban_cancel_button"); } } + + +function createFileSelectModal(doubanPlugin: DoubanPlugin) { + const input = document.createElement('input'); + input.type = 'file'; + input.accept = '.json'; + input.multiple = false; + input.onchange = async () => { + const file = input.files[0]; + const reader = new FileReader(); + reader.onload = async () => { + const settings:object = JSON.parse(reader.result as string); + try { + await doubanPlugin.settingsManager.loadAndSaveSettings(settings); + }catch (e) { + log.error(i18nHelper.getMessage('125043'), e); + } + log.notice(i18nHelper.getMessage('125044')) + }; + reader.readAsText(file); + }; + input.click();} \ No newline at end of file diff --git a/src/org/wanxp/douban/component/DoubanHumanCheckModel.ts b/src/org/wanxp/douban/component/DoubanHumanCheckModel.ts index 2b5aa8b..e034e85 100644 --- a/src/org/wanxp/douban/component/DoubanHumanCheckModel.ts +++ b/src/org/wanxp/douban/component/DoubanHumanCheckModel.ts @@ -3,7 +3,7 @@ import { log } from 'src/org/wanxp/utils/Logutil'; import {i18nHelper} from "../../lang/helper"; import {DoubanSettingTab} from "../setting/DoubanSettingTab"; import SettingsManager from "../setting/SettingsManager"; -import {constructDoubanTokenSettingsUI} from "../setting/BasicSettingsHelper"; +import {constructDoubanTokenSettingsUI} from "../setting/LoginSettingsHelper"; // Credits go to zhaohongxuan's Weread Plugin : https://github.com/zhaohongxuan/obsidian-weread-plugin diff --git a/src/org/wanxp/douban/component/DoubanLoginModel.ts b/src/org/wanxp/douban/component/DoubanLoginModel.ts index dc7e91f..b0e1d41 100644 --- a/src/org/wanxp/douban/component/DoubanLoginModel.ts +++ b/src/org/wanxp/douban/component/DoubanLoginModel.ts @@ -3,7 +3,7 @@ import { log } from 'src/org/wanxp/utils/Logutil'; import {i18nHelper} from "../../lang/helper"; import {DoubanSettingTab} from "../setting/DoubanSettingTab"; import SettingsManager from "../setting/SettingsManager"; -import {constructDoubanTokenSettingsUI} from "../setting/BasicSettingsHelper"; +import {constructDoubanTokenSettingsUI} from "../setting/LoginSettingsHelper"; import StringUtil from "../../utils/StringUtil"; import {Integer} from "schema-dts"; diff --git a/src/org/wanxp/douban/component/DoubanLogoutModel.ts b/src/org/wanxp/douban/component/DoubanLogoutModel.ts index 2427909..c002ecf 100644 --- a/src/org/wanxp/douban/component/DoubanLogoutModel.ts +++ b/src/org/wanxp/douban/component/DoubanLogoutModel.ts @@ -1,7 +1,7 @@ import {DoubanSettingTab} from "../setting/DoubanSettingTab"; import {i18nHelper} from "../../lang/helper"; import SettingsManager from "../setting/SettingsManager"; -import {constructDoubanTokenSettingsUI, constructLoginSettingsUI} from "../setting/BasicSettingsHelper"; +import {constructDoubanTokenSettingsUI, constructLoginSettingsUI} from "../setting/LoginSettingsHelper"; import {log} from "../../utils/Logutil"; // Credits go to zhaohongxuan's Weread Plugin : https://github.com/zhaohongxuan/obsidian-weread-plugin diff --git a/src/org/wanxp/douban/setting/AdvancedSettingsHelper.ts b/src/org/wanxp/douban/setting/AdvancedSettingsHelper.ts index 7d9eb2a..abf35eb 100644 --- a/src/org/wanxp/douban/setting/AdvancedSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/AdvancedSettingsHelper.ts @@ -8,31 +8,74 @@ import User from "../user/User"; import {createFolderSelectionSetting} from "./TemplateSettingHelper"; import { log } from "../../utils/Logutil"; import {ConfirmDialogModal} from "../component/ConfirmDialogModal"; +import {DoubanSearchModal} from "../data/search/DoubanSearchModal"; +import {DoubanPluginSetting} from "./model/DoubanPluginSetting"; +import TimeUtil from "../../utils/TimeUtil"; export function constructAdvancedUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1250') }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1250') }); containerEl.createEl('p', { text: i18nHelper.getMessage('1252') }); - const settings:Setting = new Setting(containerEl); - const advancedSettings = containerEl.createDiv('advanced-settings'); - settings.setDesc(i18nHelper.getMessage('1251')).addExtraButton((extraButton) => { - extraButton - .setIcon('reset') - .setTooltip(i18nHelper.getMessage('121905')) - .onClick(async () => { - resetAdvanced(manager); - await manager.plugin.saveSettings(); - showAdvancedSettings(advancedSettings, manager) - }); - }) - showAdvancedSettings(advancedSettings, manager); + // const settings:Setting = new Setting(containerEl); + const advancedSettings = containerEl.createDiv('advanced-settings'); +// settings.setDesc(i18nHelper.getMessage('1251')).addExtraButton((extraButton) => { +// extraButton +// .setIcon('reset') +// .setTooltip(i18nHelper.getMessage('121905')) +// .onClick(async () => { +// resetAdvanced(manager); +// await manager.plugin.saveSettings(); +// showAdvancedSettings(advancedSettings, manager) +// }); +// }) + showAdvancedSettings(advancedSettings, manager); +// } function showAdvancedSettings(containerEl: HTMLElement, manager: SettingsManager) { containerEl.empty(); const promise:Promise = new Promise((resolve, reject) => {resolve(null)}); + + + //导出 + new Setting(containerEl) + .setName(i18nHelper.getMessage('125034')) + .setDesc(i18nHelper.getMessage('125035')) + .addButton((buttonComponent) => { + buttonComponent + .setIcon('folder') + .setButtonText(i18nHelper.getMessage('125047')) + .onClick(async (value) => { + const settings = manager.getSettings() + const settingsString = JSON.stringify(settings, null, 2); + const blob = new Blob([settingsString], { type: 'application/json' }); + const url = URL.createObjectURL(blob); + const a = document.createElement('a'); + a.href = url; + a.download = `obsidian_douban_plugin_settings_${TimeUtil.formatDate(new Date(), 'yyyy-MM-dd_HH-mm-ss')}.json`; + a.click(); + URL.revokeObjectURL(url); + + }); + }); + //导入 + new Setting(containerEl) + .setName(i18nHelper.getMessage('125036')) + .setDesc(i18nHelper.getMessage('125037')) + .addButton((buttonComponent) => { + buttonComponent + .setIcon('document') + .setButtonText(i18nHelper.getMessage('125039')) + .onClick(async (value) => { + showConfirmDialog(i18nHelper.getMessage('125046'), promise.then(() => { + }), manager); + }); + }); + + + new Setting(containerEl) .setName(i18nHelper.getMessage('125001')) .setDesc(i18nHelper.getMessage('125002')) @@ -79,6 +122,7 @@ function showAdvancedSettings(containerEl: HTMLElement, manager: SettingsManager }), manager) }); }); + new Setting(containerEl) .setName(i18nHelper.getMessage('125031')) .setDesc(i18nHelper.getMessage('125032')) @@ -92,6 +136,7 @@ function showAdvancedSettings(containerEl: HTMLElement, manager: SettingsManager }), manager); }); }); + } function resetAdvanced( manager: SettingsManager) { @@ -100,7 +145,7 @@ function resetAdvanced( manager: SettingsManager) { } function showConfirmDialog(message:string, promise:Promise, manager: SettingsManager) { - new ConfirmDialogModal(manager.plugin.app, message, promise + new ConfirmDialogModal(manager.plugin, message, promise .then( () => { manager.plugin.saveSettings(); }) diff --git a/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts b/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts index cc09879..3105c49 100644 --- a/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/ArrayDisplayTypeSettingsHelper.ts @@ -4,14 +4,15 @@ import {Setting, TextComponent} from "obsidian"; import {i18nHelper} from "../../lang/helper"; import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings"; import {DEFAULT_SETTINGS_ARRAY_INPUT_SIZE} from "../../constant/Constsant"; +import DoubanPlugin from "../../main"; export function arraySettingDisplayUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', {text: i18nHelper.getMessage('120601')}); - arraySettingDisplay(containerEl.createDiv('array-settings'), manager, false); + // containerEl.createEl('h3', {text: i18nHelper.getMessage('120601')}); + arraySettingDisplay(containerEl.createDiv('array-settings'), manager, true); } -export function arraySettingDisplay(containerEl: HTMLElement, manager: SettingsManager, displayExtraListTypeFlag: boolean = false) { +export function arraySettingDisplay(containerEl: HTMLElement, manager: SettingsManager, displayExtraListTypeFlag: boolean = true) { containerEl.empty(); const arraySet = new Setting(containerEl) .setName(i18nHelper.getMessage('120601')) @@ -25,27 +26,28 @@ export function arraySettingDisplay(containerEl: HTMLElement, manager: SettingsM arraySettingDisplay(containerEl, manager, true); }); }); - if (displayExtraListTypeFlag) { - arraySettingDisplayItem(containerEl, manager, manager.getArraySetting(DEFAULT_SETTINGS_ARRAY_NAME)); - displayExtraListType(manager, containerEl); - arraySet.addButton((button) => { - button - .setIcon('down-chevron-glyph') - .setTooltip(i18nHelper.getMessage('120608')) - .onClick(async () => { - arraySettingDisplay(containerEl, manager, false); - }); - }); - }else { - arraySet.addButton((button) => { - button - .setIcon('right-chevron-glyph') - .setTooltip(i18nHelper.getMessage('120608')) - .onClick(async () => { - arraySettingDisplay(containerEl, manager, true); - }); - }); - } + // if (displayExtraListTypeFlag) { + new Setting(containerEl) + arraySettingDisplayItem(containerEl, manager, manager.getArraySetting(DEFAULT_SETTINGS_ARRAY_NAME)); + displayExtraListType(manager, containerEl); + // arraySet.addButton((button) => { + // button + // .setIcon('down-chevron-glyph') + // .setTooltip(i18nHelper.getMessage('120608')) + // .onClick(async () => { + // arraySettingDisplay(containerEl, manager, false); + // }); + // }); + // }else { + // arraySet.addButton((button) => { + // button + // .setIcon('right-chevron-glyph') + // .setTooltip(i18nHelper.getMessage('120608')) + // .onClick(async () => { + // arraySettingDisplay(containerEl, manager, true); + // }); + // }); + // } } function arraySettingDisplayItem(containerEl: HTMLElement, manager: SettingsManager, arraySetting:ArraySetting) { diff --git a/src/org/wanxp/douban/setting/BasicSettingsHelper.ts b/src/org/wanxp/douban/setting/BasicSettingsHelper.ts index 8b381ec..14946b2 100644 --- a/src/org/wanxp/douban/setting/BasicSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/BasicSettingsHelper.ts @@ -8,12 +8,11 @@ import User from "../user/User"; import {createFolderSelectionSetting} from "./TemplateSettingHelper"; import StringUtil from "../../utils/StringUtil"; import {log} from "../../utils/Logutil"; +import DoubanPlugin from "../../main"; export function constructBasicUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') }); - containerEl.createDiv('login-setting', async (loginSettingEl) => { - constructDoubanTokenSettingsUI(loginSettingEl, manager); - }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') }); + new Setting(containerEl).setName(i18nHelper.getMessage('120501')).then((setting) => { setting.addMomentFormat((mf) => { @@ -101,163 +100,3 @@ export function constructBasicUI(containerEl: HTMLElement, manager: SettingsMana } -export function constructDoubanTokenSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.empty(); - let login = manager.plugin.userComponent.isLogin(); - manager.debug(`配置界面:展示豆瓣状态:${login?'已登录':'未登录'}`) - if (Platform.isDesktopApp) { - if(login) { - constructHasLoginSettingsUI(containerEl, manager); - }else { - constructLoginSettingsUI(containerEl, manager); - } - } else { - if(login) { - showMobileLogout(containerEl, manager); - }else { - showMobileLogin(containerEl, manager); - } - } - - -} - - -export function constructLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { - manager.debug(`配置界面:未登录-展示登录按钮`) - let loginSetting = containerEl.createDiv("login-button"); - let loginCookie = containerEl.createDiv("login-button-cookie"); - - new Setting(loginSetting).setName(i18nHelper.getMessage('100131')).addButton((button) => { - return button - .setButtonText(i18nHelper.getMessage('100130')) - .onClick(async () => { - button.setDisabled(true); - manager.debug(`配置界面:点击登录按钮`) - const loginModel = new DoubanLoginModel(containerEl, manager); - await loginModel.doLogin(); - }); - }); - const loginCookieSetting:Setting = new Setting(loginSetting).setName(i18nHelper.getMessage('100133')); - // .setDesc(i18nHelper.getMessage('100134')) - loginCookieSetting.addButton((button) => { - loginCookieSetting.descEl.appendChild( - createFragment((frag) => { - frag.appendText( - i18nHelper.getMessage('100134') - ); - frag.createEl( - 'a', - { - text: i18nHelper.getMessage('100139'), - href: 'https://obsidian-douban.wanxuping.com/20_howtouse_25_setting_login_douban_cookie.html', - }, - (a) => { - a.setAttr('target', '_blank'); - } - ); - frag.appendText(i18nHelper.getMessage('100138')); - }) - ); - - - return button - .setButtonText(i18nHelper.getMessage('100135')) - .onClick(async () => { - button.setDisabled(true); - manager.debug(`配置界面:点击登录异常处理按钮`) - constructLoginCookieSettingsUI(loginCookie, containerEl, manager); - }); - }); -} - -export function constructLoginCookieSettingsUI(containerEl: HTMLElement, parentContainerEl: HTMLElement, manager: SettingsManager) { - manager.debug(`配置界面:登录异常处理按钮-展示Cookie输入框`) - new Setting(containerEl).setName(i18nHelper.getMessage('100136')) - .setClass("obsidian_douban_settings_cookie_login").addTextArea((text) => { - text.onChange(value => manager.updateCookieTemp(value)); - return text; - }).addExtraButton((button) => { - return button - .setIcon('check') - .onClick(async () => { - manager.debug(`配置界面:确认输入Cookie`); - const user:User = await manager.plugin.userComponent.loginCookie(manager.getCookieTemp()) - if (!user || !user.id) { - log.notice(i18nHelper.getMessage('100137')) - return; - } - constructDoubanTokenSettingsUI(parentContainerEl, manager); - }); - }) - .addExtraButton((button) => { - return button - .setIcon('x') - .onClick(async () => { - button.setDisabled(true); - manager.debug(`配置界面:取消输入Cookie`); - constructDoubanTokenSettingsUI(parentContainerEl, manager); - }); - }); -} - -export function constructHasLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { - const user: User = manager.plugin.userComponent.getUser(); - let userDom = new DocumentFragment(); - userDom.createDiv().innerHTML = - `${i18nHelper.getMessage('100120')}
-${i18nHelper.getMessage('100123')}: ${user.id}
- ${i18nHelper.getMessage('100124')}: ${user.name}
-${i18nHelper.getMessage('100125')}`; - manager.debug(`配置界面:展示豆瓣登录信息:id:${StringUtil.confuse(user.id)}, 用户名:${StringUtil.confuse(user.name)}`) - new Setting(containerEl) - .setName(i18nHelper.getMessage('100126')) - .setDesc(userDom) - .addButton((button) => { - return button - .setButtonText(i18nHelper.getMessage('100128')) - .setCta() - .onClick(async () => { - button.setDisabled(true); - manager.debug(`配置界面:点击退出登录按钮,准备退出登录`) - // manager.debug(`配置界面:登出界面退出登录请求检测成功,准备退出登录`) - manager.plugin.userComponent.logout(); - manager.debug(`配置界面:退出登录成功`); - constructDoubanTokenSettingsUI(containerEl, manager); - - // const loginModel = new DoubanLogoutModel(containerEl, manager); - // await loginModel.doLogout(); - }); - }); -} - -function showMobileLogin(containerEl: HTMLElement, manager: SettingsManager) { - new Setting(containerEl) - .setName(i18nHelper.getMessage('100126')) - .setDesc(i18nHelper.getMessage('100129')) -} - -function showMobileLogout(containerEl: HTMLElement, manager: SettingsManager) { - const user: User = manager.plugin.userComponent.getUser(); - let userDom = new DocumentFragment(); - userDom.createDiv().innerHTML = - `${i18nHelper.getMessage('100120')}
-${i18nHelper.getMessage('100123')}: ${user.id}
- ${i18nHelper.getMessage('100124')}: ${user.name}
-${i18nHelper.getMessage('100125')}`; - new Setting(containerEl) - .setName(i18nHelper.getMessage('100126')) - .setDesc(userDom) - .addButton((button) => { - return button - .setButtonText(i18nHelper.getMessage('100128')) - .setCta() - .onClick(async () => { - button.setDisabled(true); - manager.updateSetting('loginCookiesContent', ''); - manager.updateSetting('loginHeadersContent', ''); - constructDoubanTokenSettingsUI(containerEl, manager); - }); - }); -} - diff --git a/src/org/wanxp/douban/setting/CustomPropertySettingsHelper.ts b/src/org/wanxp/douban/setting/CustomPropertySettingsHelper.ts index d6612db..7acaaab 100644 --- a/src/org/wanxp/douban/setting/CustomPropertySettingsHelper.ts +++ b/src/org/wanxp/douban/setting/CustomPropertySettingsHelper.ts @@ -3,9 +3,10 @@ import SettingsManager from "./SettingsManager"; import {CustomProperty} from "./model/CustomProperty"; import {ButtonComponent, DropdownComponent, ExtraButtonComponent, Setting, TextComponent} from "obsidian"; import {SupportType} from "../../constant/Constsant"; +import DoubanPlugin from "../../main"; export function constructCustomPropertySettingsUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1240') }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1240') }); containerEl.createEl('p', { text: i18nHelper.getMessage('1242') }); const customProperties = manager.plugin.settings.customProperties; new Setting(containerEl) diff --git a/src/org/wanxp/douban/setting/DoubanSettingTab.ts b/src/org/wanxp/douban/setting/DoubanSettingTab.ts index 43363c2..ff67f7a 100644 --- a/src/org/wanxp/douban/setting/DoubanSettingTab.ts +++ b/src/org/wanxp/douban/setting/DoubanSettingTab.ts @@ -9,11 +9,15 @@ import { constructTemplateVariablesUI } from "./TemplateVariableSettingsHelper"; import {constructCustomPropertySettingsUI } from "./CustomPropertySettingsHelper"; import { constructAdvancedUI } from "./AdvancedSettingsHelper"; import {arraySettingDisplay, arraySettingDisplayUI} from "./ArrayDisplayTypeSettingsHelper"; +import {i18nHelper} from "../../lang/helper"; +import {constructLoginUI} from "./LoginSettingsHelper"; /** * 部分逻辑参考以下项目 * obsidian-kanban */ + + export class DoubanSettingTab extends PluginSettingTab { plugin: DoubanPlugin; settingsManager: SettingsManager; @@ -25,18 +29,51 @@ export class DoubanSettingTab extends PluginSettingTab { } display(): void { - const {containerEl} = this; - containerEl.empty(); - containerEl.createEl("h2", {text: 'Obsidian Douban'}); - new Setting(containerEl); - constructBasicUI(containerEl, this.settingsManager); - constructTemplateUI(containerEl, this.settingsManager); - constructOutUI(containerEl, this.settingsManager); - arraySettingDisplayUI(containerEl, this.settingsManager); - constructCustomPropertySettingsUI(containerEl, this.settingsManager); - constructTemplateVariablesUI(containerEl, this.settingsManager); - constructAdvancedUI(containerEl, this.settingsManager); + const {containerEl} = this; + containerEl.empty(); + containerEl.createEl("h2", {text: 'Obsidian Douban'}); + // Create tab container + const tabContainer = containerEl.createEl("div", {cls: "obsidian_douban_settings_tab_container"}); + const tabHeaders = containerEl.createEl("div", {cls: "obsidian_douban_settings_tab_headers"}); + const tabContents = containerEl.createEl("div", {cls: "obsidian_douban_settings_tab_contents"}); + + // Create tabs + const tabs = [ + {name: i18nHelper.getMessage('1210'), construct: constructBasicUI}, + {name: i18nHelper.getMessage('1203'), construct: constructTemplateUI}, + {name: i18nHelper.getMessage('1260'), construct: constructLoginUI}, + {name: i18nHelper.getMessage('1220'), construct: constructOutUI}, + {name: i18nHelper.getMessage('120601'), construct: arraySettingDisplayUI}, + {name: i18nHelper.getMessage('1240'), construct: constructCustomPropertySettingsUI}, + {name: i18nHelper.getMessage('1230'), construct: constructTemplateVariablesUI}, + {name: i18nHelper.getMessage('1250'), construct: constructAdvancedUI} + ]; + + tabs.forEach((tab, index) => { + const tabHeader = tabHeaders.createEl("div", {cls: "obsidian_douban_settings_tab_header", text: tab.name}); + const tabContent = tabContents.createEl("div", {cls: "obsidian_douban_settings_tab_content"}); + tab.construct(tabContent, this.settingsManager); + + // Show the first tab by default + if (index === 0) { + tabHeader.addClass("active"); + tabContent.addClass("active"); + } + + tabHeader.addEventListener("click", () => { + // Remove active class from all headers and contents + tabHeaders.querySelectorAll(".obsidian_douban_settings_tab_header").forEach(header => header.removeClass("active")); + tabContents.querySelectorAll(".obsidian_douban_settings_tab_content").forEach(content => content.removeClass("active")); + + // Add active class to the clicked header and corresponding content + tabHeader.addClass("active"); + tabContent.addClass("active"); + }); + }); + + tabContainer.appendChild(tabHeaders); + tabContainer.appendChild(tabContents); } hide(): void { diff --git a/src/org/wanxp/douban/setting/LoginSettingsHelper.ts b/src/org/wanxp/douban/setting/LoginSettingsHelper.ts new file mode 100644 index 0000000..08f893b --- /dev/null +++ b/src/org/wanxp/douban/setting/LoginSettingsHelper.ts @@ -0,0 +1,192 @@ +import I18nHelper, {i18nHelper} from "../../lang/helper"; +import {Platform, Setting} from "obsidian"; +import SettingsManager from "./SettingsManager"; +import DoubanLoginModel from "../component/DoubanLoginModel"; +import User from "../user/User"; +import StringUtil from "../../utils/StringUtil"; +import {log} from "../../utils/Logutil"; + +export function constructLoginUI(containerEl: HTMLElement, manager: SettingsManager) { + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1210') }); + + const userComponent = manager.plugin.userComponent; + if (userComponent.needLogin()) { + try { + userComponent.login() + .then(() => { + constructDoubanLoginSettingsUI(containerEl, manager); + }); + }catch (e) { + log.debug(i18nHelper.getMessage('100101')); + constructDoubanLoginSettingsUI(containerEl, manager); + } + }else { + constructDoubanLoginSettingsUI(containerEl, manager); + } + +} + +export function constructDoubanLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { + containerEl.createDiv('login-setting', async (loginSettingEl) => { + constructDoubanTokenSettingsUI(loginSettingEl, manager); + }); +} + + +export function constructDoubanTokenSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { + containerEl.empty(); + let login = manager.plugin.userComponent.isLogin(); + manager.debug(`配置界面:展示豆瓣状态:${login?'已登录':'未登录'}`) + if (Platform.isDesktopApp) { + if(login) { + constructHasLoginSettingsUI(containerEl, manager); + }else { + constructLoginSettingsUI(containerEl, manager); + } + } else { + if(login) { + showMobileLogout(containerEl, manager); + }else { + showMobileLogin(containerEl, manager); + } + } + + +} + + +export function constructLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { + manager.debug(`配置界面:未登录-展示登录按钮`) + let loginSetting = containerEl.createDiv("login-button"); + let loginCookie = containerEl.createDiv("login-button-cookie"); + + new Setting(loginSetting).setName(i18nHelper.getMessage('100131')).addButton((button) => { + return button + .setButtonText(i18nHelper.getMessage('100130')) + .onClick(async () => { + button.setDisabled(true); + manager.debug(`配置界面:点击登录按钮`) + const loginModel = new DoubanLoginModel(containerEl, manager); + await loginModel.doLogin(); + }); + }); + const loginCookieSetting:Setting = new Setting(loginSetting).setName(i18nHelper.getMessage('100133')); + // .setDesc(i18nHelper.getMessage('100134')) + loginCookieSetting.addButton((button) => { + loginCookieSetting.descEl.appendChild( + createFragment((frag) => { + frag.appendText( + i18nHelper.getMessage('100134') + ); + frag.createEl( + 'a', + { + text: i18nHelper.getMessage('100139'), + href: 'https://obsidian-douban.wanxuping.com/20_howtouse_25_setting_login_douban_cookie.html', + }, + (a) => { + a.setAttr('target', '_blank'); + } + ); + frag.appendText(i18nHelper.getMessage('100138')); + }) + ); + + + return button + .setButtonText(i18nHelper.getMessage('100135')) + .onClick(async () => { + button.setDisabled(true); + manager.debug(`配置界面:点击登录异常处理按钮`) + constructLoginCookieSettingsUI(loginCookie, containerEl, manager); + }); + }); +} + +export function constructLoginCookieSettingsUI(containerEl: HTMLElement, parentContainerEl: HTMLElement, manager: SettingsManager) { + manager.debug(`配置界面:登录异常处理按钮-展示Cookie输入框`) + new Setting(containerEl).setName(i18nHelper.getMessage('100136')) + .setClass("obsidian_douban_settings_cookie_login").addTextArea((text) => { + text.onChange(value => manager.updateCookieTemp(value)); + return text; + }).addExtraButton((button) => { + return button + .setIcon('check') + .onClick(async () => { + manager.debug(`配置界面:确认输入Cookie`); + const user:User = await manager.plugin.userComponent.loginCookie(manager.getCookieTemp()) + if (!user || !user.id) { + log.notice(i18nHelper.getMessage('100137')) + return; + } + constructDoubanTokenSettingsUI(parentContainerEl, manager); + }); + }) + .addExtraButton((button) => { + return button + .setIcon('x') + .onClick(async () => { + button.setDisabled(true); + manager.debug(`配置界面:取消输入Cookie`); + constructDoubanTokenSettingsUI(parentContainerEl, manager); + }); + }); +} + +export function constructHasLoginSettingsUI(containerEl: HTMLElement, manager: SettingsManager) { + const user: User = manager.plugin.userComponent.getUser(); + let userDom = new DocumentFragment(); + userDom.createDiv().innerHTML = + `${i18nHelper.getMessage('100120')}
+${i18nHelper.getMessage('100123')}: ${user.id}
+ ${i18nHelper.getMessage('100124')}: ${user.name}
+${i18nHelper.getMessage('100125')}`; + manager.debug(`配置界面:展示豆瓣登录信息:id:${StringUtil.confuse(user.id)}, 用户名:${StringUtil.confuse(user.name)}`) + new Setting(containerEl) + .setName(i18nHelper.getMessage('100126')) + .setDesc(userDom) + .addButton((button) => { + return button + .setButtonText(i18nHelper.getMessage('100128')) + .setCta() + .onClick(async () => { + button.setDisabled(true); + manager.debug(`配置界面:点击退出登录按钮,准备退出登录`) + // manager.debug(`配置界面:登出界面退出登录请求检测成功,准备退出登录`) + manager.plugin.userComponent.logout(); + manager.debug(`配置界面:退出登录成功`); + constructDoubanTokenSettingsUI(containerEl, manager); + }); + }); +} + +function showMobileLogin(containerEl: HTMLElement, manager: SettingsManager) { + new Setting(containerEl) + .setName(i18nHelper.getMessage('100126')) + .setDesc(i18nHelper.getMessage('100129')) +} + +function showMobileLogout(containerEl: HTMLElement, manager: SettingsManager) { + const user: User = manager.plugin.userComponent.getUser(); + let userDom = new DocumentFragment(); + userDom.createDiv().innerHTML = + `${i18nHelper.getMessage('100120')}
+${i18nHelper.getMessage('100123')}: ${user.id}
+ ${i18nHelper.getMessage('100124')}: ${user.name}
+${i18nHelper.getMessage('100125')}`; + new Setting(containerEl) + .setName(i18nHelper.getMessage('100126')) + .setDesc(userDom) + .addButton((button) => { + return button + .setButtonText(i18nHelper.getMessage('100128')) + .setCta() + .onClick(async () => { + button.setDisabled(true); + manager.updateSetting('loginCookiesContent', ''); + manager.updateSetting('loginHeadersContent', ''); + constructDoubanTokenSettingsUI(containerEl, manager); + }); + }); +} + diff --git a/src/org/wanxp/douban/setting/OutputSettingsHelper.ts b/src/org/wanxp/douban/setting/OutputSettingsHelper.ts index 18d8030..7d5e4c5 100644 --- a/src/org/wanxp/douban/setting/OutputSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/OutputSettingsHelper.ts @@ -1,6 +1,6 @@ import {i18nHelper} from "../../lang/helper"; import {Setting, TextComponent, ToggleComponent} from "obsidian"; -import {createFolderSelectionSetting} from "./TemplateSettingHelper"; +import {createFolderSelectionSetting, createFolderSelectionSettingInput} from "./TemplateSettingHelper"; import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings"; import { DEFAULT_SETTINGS_ARRAY_INPUT_SIZE, EXAMPLE_RATE, EXAMPLE_RATE_MAX, @@ -14,6 +14,7 @@ import NumberUtil from "../../utils/NumberUtil"; import {VariableUtil} from "../../utils/VariableUtil"; import {FileUtil} from "../../utils/FileUtil"; import {ScoreSetting} from "./model/ScoreSetting"; +import DoubanPlugin from "../../main"; function showStarExample(containerEl: HTMLElement, manager: SettingsManager) { @@ -111,16 +112,21 @@ function scoreSettingDisplay(containerEl: HTMLElement, manager: SettingsManager) } export function constructOutUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1220') }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1220') }); new Setting(containerEl); const attachmentFileSetting = containerEl.createDiv({ cls: 'settings-item-attachment' }); constructAttachmentFileSettingsUI(attachmentFileSetting, manager); const folder = new Setting(containerEl); + const folderInput = new Setting(containerEl); + const outFolder = containerEl.createDiv({ cls: 'settings-item' }); const filePathDisplayExample = containerEl.createDiv('filePath-display-example'); - folder.then(createFolderSelectionSetting({name: '121501', desc: '121502', placeholder: '121503', key: 'dataFilePath', manager: manager}, filePathDisplayExample)); + + folder.then(createFolderSelectionSetting({containerEl: containerEl, name: '121501', desc: '121502', placeholder: null, key: null, manager: manager}, filePathDisplayExample)); + folderInput.then(createFolderSelectionSettingInput({containerEl: containerEl, name: null, desc: null, placeholder: '121503', key: 'dataFilePath', manager: manager}, filePathDisplayExample)); + constructOutputFileNameUI(outFolder, filePathDisplayExample, manager); @@ -215,7 +221,10 @@ export function constructAttachmentFileSettingsUI(containerEl: HTMLElement, mana if (manager.plugin.settings.pictureBedFlag) { constructAttachmentFilePictureBedSettingsUI(containerEl, manager); }else { - new Setting(containerEl).then(createFolderSelectionSetting({name: '121432', desc: '121433', placeholder: '121434', key: 'attachmentPath', manager: manager})); + new Setting(containerEl).then(createFolderSelectionSetting({containerEl: containerEl, name: '121432', desc: '121433', placeholder: null, key: null, manager: manager})); + new Setting(containerEl).then(createFolderSelectionSettingInput({containerEl: containerEl, name: null, desc: null, placeholder: '121434', key: 'attachmentPath', manager: manager})); + + ; } new Setting(containerEl) diff --git a/src/org/wanxp/douban/setting/SettingsManager.ts b/src/org/wanxp/douban/setting/SettingsManager.ts index b0113ee..963fc04 100644 --- a/src/org/wanxp/douban/setting/SettingsManager.ts +++ b/src/org/wanxp/douban/setting/SettingsManager.ts @@ -17,6 +17,8 @@ import { ArraySettingFieldName, DEFAULT_SETTINGS_ARRAY_NAME } from "./model/ArraySetting"; +import {logger} from "bs-logger"; +import {i18nHelper} from "../../lang/helper"; export default class SettingsManager { app: App; @@ -228,4 +230,21 @@ export default class SettingsManager { clearSyncCache() { this.settings.syncHandledDataArray = []; } + + async loadAndSaveSettings(config: object) { + this.validateSettings(config); + // @ts-ignore + this.settings = Object.assign({}, config); + await this.plugin.saveSettings(); + } + + private validateSettings(config: object) { + if (!config) { + this.innerLogger.warn(i18nHelper.getMessage('125040')); + } + } + + getSettings() { + return this.settings; + } } diff --git a/src/org/wanxp/douban/setting/TemplateSettingHelper.ts b/src/org/wanxp/douban/setting/TemplateSettingHelper.ts index 869870e..b2a7dde 100644 --- a/src/org/wanxp/douban/setting/TemplateSettingHelper.ts +++ b/src/org/wanxp/douban/setting/TemplateSettingHelper.ts @@ -7,43 +7,49 @@ import {getDefaultTemplateContent} from "../../constant/DefaultTemplateContent"; import {FolderSuggest} from "./model/FolderSuggest"; import SettingsManager from "./SettingsManager"; import {showFileExample} from "./OutputSettingsHelper"; +import {FileTreeSelectSuggest} from "./model/FileTreeSelectSuggest"; +import DoubanPlugin from "../../main"; +import {FolderTreeSelectSuggest} from "./model/FolderTreeSelectSuggest"; export function constructTemplateUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1203') }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1203') }); containerEl.createEl('p', { text: i18nHelper.getMessage('1204') }); new Setting(containerEl).setDesc(i18nHelper.getMessage('1205')) - new Setting(containerEl).then(createFileSelectionSetting({name: '120101', desc: '120102', placeholder: '121701', key: 'movieTemplateFile', manager: manager})); - new Setting(containerEl).then(createFileSelectionSetting({name: '120201', desc: '120202', placeholder: '121701', key: 'bookTemplateFile', manager: manager})); - new Setting(containerEl).then(createFileSelectionSetting({name: '120301', desc: '120302', placeholder: '121701', key: 'musicTemplateFile', manager: manager})); - new Setting(containerEl).then(createFileSelectionSetting({name: '120401', desc: '120402', placeholder: '121701', key: 'noteTemplateFile', manager: manager})); - new Setting(containerEl).then(createFileSelectionSetting({name: '121301', desc: '121302', placeholder: '121701', key: 'gameTemplateFile', manager: manager})); - new Setting(containerEl).then(createFileSelectionSetting({name: '121801', desc: '121802', placeholder: '121701', key: 'teleplayTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '120101', desc: '120102', placeholder: '121701', key: 'movieTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '120201', desc: '120202', placeholder: '121701', key: 'bookTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '120301', desc: '120302', placeholder: '121701', key: 'musicTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '120401', desc: '120402', placeholder: '121701', key: 'noteTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '121301', desc: '121302', placeholder: '121701', key: 'gameTemplateFile', manager: manager})); + new Setting(containerEl).then(createFileSelectionSetting({containerEl: containerEl, name: '121801', desc: '121802', placeholder: '121701', key: 'teleplayTemplateFile', manager: manager})); } -export function createFileSelectionSetting({name, desc, placeholder, key, manager +export function createFileSelectionSetting({containerEl, name, desc, placeholder, key, manager }: CreateTemplateSelectParams) { return (setting: Setting) => { + setting.controlEl.addClass('obsidian_douban_template_file_select'); // @ts-ignore setting.setName(i18nHelper.getMessage(name)); - // @ts-ignore - setting.setDesc(i18nHelper.getMessage(desc)); + // settingDesc.setDesc(i18nHelper.getMessage(desc)); setting.addSearch(async (search: SearchComponent) => { const [oldValue, defaultVal] = manager.getSettingWithDefault(key); let v = defaultVal; if (oldValue) { v = oldValue; } - new FileSuggest(manager.app, search.inputEl); + new FileTreeSelectSuggest(manager.app, search.inputEl); // @ts-ignore search.setValue(v); // @ts-ignore search.setPlaceholder(i18nHelper.getMessage(placeholder)); - search.onChange(async (value: string) => { + search.inputEl.addClass('obsidian_douban_template_file_select_input'); + search.inputEl.style.width = '100%'; + search.onChange(async (value: string) => { manager.updateSetting(key, value); }); }); + setting.addExtraButton((button) => { button .setIcon('copy') @@ -74,13 +80,25 @@ export function createFolderSelectionSetting({ setting.setName( i18nHelper.getMessage(name)); // @ts-ignore setting.setDesc( i18nHelper.getMessage(desc)); + }; +} + + + +export function createFolderSelectionSettingInput({ + name, desc, placeholder, key, manager, + }: CreateTemplateSelectParams, filePathDisplayExample?:HTMLDivElement) { + return (setting: Setting) => { + setting.controlEl.addClass('obsidian_douban_template_file_select'); setting.addSearch(async (search: SearchComponent) => { const [oldValue, defaultVal] = manager.getSettingWithDefault(key); let v = defaultVal; if (oldValue) { v = oldValue; } - new FolderSuggest(manager.app, search.inputEl); + new FolderTreeSelectSuggest(manager.app, search.inputEl); + search.inputEl.addClass('obsidian_douban_template_file_select_input'); + search.inputEl.style.width = '100%'; // @ts-ignore search.setValue(v) // @ts-ignore @@ -95,5 +113,3 @@ export function createFolderSelectionSetting({ }; } - - diff --git a/src/org/wanxp/douban/setting/TemplateVariableSettingsHelper.ts b/src/org/wanxp/douban/setting/TemplateVariableSettingsHelper.ts index 1c874d9..fd5273e 100644 --- a/src/org/wanxp/douban/setting/TemplateVariableSettingsHelper.ts +++ b/src/org/wanxp/douban/setting/TemplateVariableSettingsHelper.ts @@ -1,9 +1,10 @@ import SettingsManager from "./SettingsManager"; import {i18nHelper} from "../../lang/helper"; import {Setting} from "obsidian"; +import DoubanPlugin from "../../main"; export function constructTemplateVariablesUI(containerEl: HTMLElement, manager: SettingsManager) { - containerEl.createEl('h3', { text: i18nHelper.getMessage('1230') }); + // containerEl.createEl('h3', { text: i18nHelper.getMessage('1230') }); containerEl.createEl('p', { text: i18nHelper.getMessage('122003') }); const basicVariablesTable = new DocumentFragment(); diff --git a/src/org/wanxp/douban/setting/model/CreateTemplateSelectParams.ts b/src/org/wanxp/douban/setting/model/CreateTemplateSelectParams.ts index 31290e3..729d2b8 100644 --- a/src/org/wanxp/douban/setting/model/CreateTemplateSelectParams.ts +++ b/src/org/wanxp/douban/setting/model/CreateTemplateSelectParams.ts @@ -3,6 +3,7 @@ import { DoubanPluginSetting } from "./DoubanPluginSetting"; export interface CreateTemplateSelectParams { // @ts-ignore + containerEl: HTMLElement, name:string, desc:string, placeholder:string, diff --git a/src/org/wanxp/douban/setting/model/FileTreeSelectSuggest.ts b/src/org/wanxp/douban/setting/model/FileTreeSelectSuggest.ts new file mode 100644 index 0000000..df453db --- /dev/null +++ b/src/org/wanxp/douban/setting/model/FileTreeSelectSuggest.ts @@ -0,0 +1,79 @@ +import {TAbstractFile, TFile, TFolder} from "obsidian"; +import {TextInputSuggest} from "./TextInputSuggest"; + +export class FileTreeSelectSuggest extends TextInputSuggest { + parentPath: string = "/"; + + getSuggestions(inputStr: string): TAbstractFile[] { + const files: TAbstractFile[] = []; + + if (inputStr.length == 0 || inputStr.trim().length == 0 || inputStr.trim() == '/') { + this.searchFiles(this.app.vault.getRoot(), "", files); + return files; + } + let parentSearchPath:string = null; + let currentName:string = null; + + try { + const testFile = this.app.vault.getAbstractFileByPath(inputStr.trim()) + if (testFile) { + if (testFile instanceof TFile && testFile.name.endsWith(".md")) { + files.push(testFile); + return files; + } + if (testFile instanceof TFolder) { + parentSearchPath = inputStr.trim(); + currentName = ""; + } + } + }catch (e) { + + } + if (parentSearchPath == null) { + parentSearchPath = inputStr.lastIndexOf("/") > 0 ? inputStr.substring(0, inputStr.lastIndexOf("/")) : "/"; + currentName = inputStr.lastIndexOf("/") > 0 ? inputStr.substring(inputStr.lastIndexOf("/") + 1) : inputStr; + currentName = currentName.trim(); + } + if (currentName == null) { + currentName = ""; + } + const root = this.app.vault.getAbstractFileByPath(parentSearchPath) as TFolder; + if (!root) { + return []; + } + const name = currentName.toLowerCase(); + if (root) { + this.searchFiles(root, name, files); + } + + return files; + } + + searchFiles(folder: TFolder, name: string, files: TAbstractFile[]): void { + folder.children.forEach((file: TAbstractFile) => { + if (file.name.toLowerCase().contains(name)) { + files.push(file); + } + }); + } + + renderSuggestion(file: TAbstractFile, el: HTMLElement): void { + el.setText(file.path); + } + + selectSuggestion(file: TAbstractFile): void { + this.inputEl.value = file.path; + this.parentPath = file.path; + // this.inputEl.addEventListener("change", () => { + // this.onInputChanged() + // }) + if (file instanceof TFolder) { + this.inputEl.value += "/"; + this.inputEl.trigger("input"); + }else { + this.close(); + } + + + } +} \ No newline at end of file diff --git a/src/org/wanxp/douban/setting/model/FolderTreeSelectSuggest.ts b/src/org/wanxp/douban/setting/model/FolderTreeSelectSuggest.ts new file mode 100644 index 0000000..e713c65 --- /dev/null +++ b/src/org/wanxp/douban/setting/model/FolderTreeSelectSuggest.ts @@ -0,0 +1,78 @@ +import {TAbstractFile, TFile, TFolder} from "obsidian"; +import {TextInputSuggest} from "./TextInputSuggest"; + +export class FolderTreeSelectSuggest extends TextInputSuggest { + parentPath: string = "/"; + + getSuggestions(inputStr: string): TAbstractFile[] { + const files: TAbstractFile[] = []; + + if (inputStr.length == 0 || inputStr.trim().length == 0 || inputStr.trim() == '/') { + this.searchFiles(this.app.vault.getRoot(), "", files); + return files; + } + let parentSearchPath:string = null; + let currentName:string = null; + + try { + const testFile = this.app.vault.getAbstractFileByPath(inputStr.trim()) + if (testFile) { + if (testFile instanceof TFile) { + return files; + } + if (testFile instanceof TFolder) { + parentSearchPath = inputStr.trim(); + currentName = ""; + } + } + }catch (e) { + + } + if (parentSearchPath == null) { + parentSearchPath = inputStr.lastIndexOf("/") > 0 ? inputStr.substring(0, inputStr.lastIndexOf("/")) : "/"; + currentName = inputStr.lastIndexOf("/") > 0 ? inputStr.substring(inputStr.lastIndexOf("/") + 1) : inputStr; + currentName = currentName.trim(); + } + if (currentName == null) { + currentName = ""; + } + const root = this.app.vault.getAbstractFileByPath(parentSearchPath) as TFolder; + if (!root) { + return []; + } + const name = currentName.toLowerCase(); + if (root) { + this.searchFiles(root, name, files); + } + + return files; + } + + searchFiles(folder: TFolder, name: string, files: TAbstractFile[]): void { + folder.children.filter(f => f instanceof TFolder).forEach((file: TAbstractFile) => { + if (file.name.toLowerCase().contains(name)) { + files.push(file); + } + }); + } + + renderSuggestion(file: TAbstractFile, el: HTMLElement): void { + el.setText(file.path); + } + + selectSuggestion(file: TAbstractFile): void { + this.inputEl.value = file.path; + this.parentPath = file.path; + // this.inputEl.addEventListener("change", () => { + // this.onInputChanged() + // }) + if (file instanceof TFolder) { + this.inputEl.value += "/"; + this.inputEl.trigger("input"); + }else { + this.close(); + } + + + } +} \ No newline at end of file diff --git a/src/org/wanxp/lang/locale/en.ts b/src/org/wanxp/lang/locale/en.ts index c00b8e5..452e990 100644 --- a/src/org/wanxp/lang/locale/en.ts +++ b/src/org/wanxp/lang/locale/en.ts @@ -100,13 +100,14 @@ PS: This file could be delete if you want to. '100132': `Load Douban Login Page Failed`, - '1210': `Basic Setting`, - '1203': `Template Setting`, - '1220': `Output Setting`, - '1230': `Usable Variables`, - '1204': `Set template file path. If keep empty, it will use the default template file to create file. All the usable variables at the end.👇`, + '1210': `Basic`, + '1203': `Template`, + '1220': `Output`, + '1230': `Description`, + '1260': `Login`, + '1204': `Set template file path. The template file will be used when creating new notes . If keep empty, it will use the default template file to create file. All the usable variables at tab "Description" and "Custom Variables"`, '1205': `🧡Tip: You can click the 'Copy' button to copy default template content, then create and paste to your own template file. After that, back to select the file. `, - '1250': `Advanced Setting`, + '1250': `Advanced`, '1252': `Some Debug or Other Settings`, '1251': `☢The Advanced Setting only could be changed after you know what you are doing`, @@ -139,18 +140,18 @@ PS: This file could be delete if you want to. '121101': `Template File`, '121102': `This template will be used when creating new notes. If keep empty, it will use default template`, - '120101': `Movie Template File`, + '120101': `Movie`, '120102': `This template will be used when creating new notes for Movie from Obsidian-Douban.`, '120103': `Available template variables are :`, '120104': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, '120105': `{{url}}, {{desc}}, {{datePublished}}, {{genre}}, `, '120106': `{{originalTitle}},{{director}}, {{author}},`, '120107': ` {{actor}}`, - '120110': `Movie Template File`, + '120110': `Movie`, - '120201': `Book Template File`, + '120201': `Book`, '120202': `This template will be used when creating new notes for Movie from Obsidian-Douban. `, '120203': `Available Book template variables are :`, '120204': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, @@ -159,7 +160,7 @@ PS: This file could be delete if you want to. '120207': `{{translator}}, {{isbn}}, {{price}}, {{totalPage}}`, '120208': `{{series}}, {{binding}}, {{menu}}`, - '120301': `Music Template File`, + '120301': `Music`, '120302': `This template will be used when creating new notes for Music from Obsidian-Douban.`, '120303': `Available Music template variables are :`, '120304': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, @@ -167,7 +168,7 @@ PS: This file could be delete if you want to. '120306': `{{actor}}, {{medium}}, {{albumType}},`, '120307': `{{barcode}}, {{records}}`, - '120401': `Article Template File`, + '120401': `Article`, '120402': `This template will be used when creating new notes for Article from Obsidian-Douban.`, '120403': `Available Article template variables are :`, '120404': `{{id}}, {{title}}, {{type}}, {{image}},`, @@ -175,14 +176,14 @@ PS: This file could be delete if you want to. '120406': `{{author}}, {{authorUrl}}, {{content}}`, '120407': `{{timePublished}}`, - '121301': `Game Template File`, + '121301': `Game`, '121302': `This template will be used when creating new notes for Game from Obsidian-Douban.`, '121303': `Available Game template variables are :`, '121304': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, '121305': `{{url}}, {{desc}}, {{publisher}}, {{datePublished}}`, '121306': `{{genre}}, {{aliases}}, {{developer}}, {{platform}}`, - '121801': `Teleplay Template File`, + '121801': `Teleplay`, '121802': `This template will be used when creating new notes for Teleplay from Obsidian-Douban.`, '120501': `Date Format`, @@ -193,7 +194,7 @@ PS: This file could be delete if you want to. '120506': `For more syntax, refer to`, '120507': `Your current syntax looks like this`, '120508': `format reference`, - '120601': `Array Spilt String`, + '120601': `Array`, '120602': `string to join between array type, start、end string for array, such as authors, actors. support \n (enter)`, '120701': `Douban Request Headers`, @@ -272,6 +273,21 @@ PS: This file could be delete if you want to. '125033': `Are you sure you want to perform this operation?`, + "125034": `Export Settings`, + "125035": `Export current plugin all settings to a local file, including all settings, sync records cache, and login status`, + "125047": `Choose Folder..`, + "125036": `Import Settings`, + "125037": `Import a previously backed up settings file, which will cover all current settings, sync records cache, and login status. For safety, it is recommended to backup the current settings before attempting to import`, + "125038": `Import Settings File`, + "125039": `Select File..`, + "125040": `Import`, + "125041": `Settings Import Successful`, + "125042": `Settings Import Failed`, + "125043": `Settings File Import Failed, please check if the file is correct`, + "125044": `Settings File Import Successful`, + "125045": `Settings File Import Successful, please reload the page`, + "125046": `Are you sure you import the settings file? Please make sure you have export settings before import config file. Note: Importing the settings file will **cover** all current settings, sync records cache, and login status`, + //error '130101': `Fetch Data Error, {0}`, '140101': `Not support for current type. You can add Issues at Github:Wanxp/obsidian-douban`, diff --git a/src/org/wanxp/lang/locale/zh-cn.ts b/src/org/wanxp/lang/locale/zh-cn.ts index eed73bf..f13577c 100644 --- a/src/org/wanxp/lang/locale/zh-cn.ts +++ b/src/org/wanxp/lang/locale/zh-cn.ts @@ -102,17 +102,18 @@ export default { '120005': `所跳转的网页地址即是搜索地址,`, '120006': `将网页地址复制到当前输入框即可,`, - '1210': `基础配置`, - '1203': `模板配置`, - '1220': `输出配置`, - '1230': `可用参数`, + '1210': `基础`, + '1203': `模板`, + '1220': `输出`, + '1230': `字段`, + '1260': `登录`, - '1204': `配置对应类型的模板文件, 如果为空则使用默认模板. 模板可使用的参数列举在最下面.👇 `, + '1204': `配置对应类型的模板文件, 如果为空则使用默认模板. 模板可使用的参数在页签'字段'和'自定义字段'中查看`, '1205': `🧡提示: 建议点击右侧'复制'默认模板按钮, 然后在新建的文件中粘贴修改模板, 最后回到此处选择对应模板. `, - '1240': `自定义属性`, + '1240': `自定义字段`, '1241': `自定义参数,值本身也支持使用参数,如myTitle:《{{title}}》。在模板中使用参数时请用'{{}}'包裹, 举例: 参数myType, 则使用时为{{myType}}. `, '1242': `添加自定义参数, 参数可用于模板中或者文件名中. `, - '1250': `高级设置`, + '1250': `高级`, '1252': `一些运行时的高级配置,如开启debug模式`, '1251': `☢高级设置只有当你知道修改此设置之后的影响才允许修改, 正常情况下请保持默认`, @@ -130,6 +131,20 @@ export default { '125033': `确认要执行此操作吗?`, + "125034": `导出配置`, + "125035": `导出当前插件的所有配置到一个本地文件中,包括所有设置、同步记录的缓存、登录状态`, + "125047": `选择路径..`, + "125036": `导入配置`, + "125037": `导入一个之前导出的配置文件,将会覆盖当前所有设置、同步记录的缓存、登录状态。为了安全起见,建议先导出当前配置再尝试导入`, + "125038": `导入配置文件`, + "125039": `选择文件..`, + "125040": `导入`, + "125041": `导入配置成功`, + "125042": `导入配置失败`, + "125043": `导入配置文件失败,请检查文件是否正确`, + "125044": `导入配置文件成功`, + "125045": `导入配置文件成功,请重新加载页面`, + "125046": `导入配置文件,注意先导出配置备份,然后才导入配置文件`, '124101': `新增`, '124108': `新增一个自定义参数`, @@ -143,7 +158,7 @@ export default { '121101': `模板文件`, '121102': `如果为空, 笔记将会会使用默认模板`, - '120101': `电影模板文件`, + '120101': `电影`, '120102': `导入电影所使用的模板, 请输入并选择对应的文件路径`, '120103': `支持以下参数名称 :`, '120104': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, @@ -151,7 +166,7 @@ export default { '120106': `{{originalTitle}},{{director}}, {{author}},`, '120107': ` {{actor}}`, - '120201': `书籍模板文件`, + '120201': `书籍`, '120202': `导入书籍所使用的模板, 请输入并选择对应的文件路径`, '120203': `支持以下参数名称 :`, '120204': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, @@ -160,7 +175,7 @@ export default { '120207': `{{translator}}, {{isbn}}, {{price}}, {{totalPage}}`, '120208': `{{series}}, {{binding}}, {{menu}}`, - '120301': `音乐模板文件`, + '120301': `音乐`, '120302': `导入音乐所使用的模板, 请输入并选择对应的文件路径`, '120303': `支持以下参数名称 :`, '120304': `{{id}}, {{title}}, {{type}}, {{image}},`, @@ -168,7 +183,7 @@ export default { '120306': `{{genre}}, {{actor}}, {{medium}}, {{albumType}},`, '120307': `{{barcode}}, {{records}}`, - '120401': `日记模板文件`, + '120401': `日记`, '120402': `导入日记所使用的模板, 请输入并选择对应的文件路径`, '120403': `支持以下参数名称 :`, '120404': `{{id}}, {{title}}, {{type}}, {{image}},`, @@ -176,7 +191,7 @@ export default { '120406': `{{author}}, {{authorUrl}}, {{content}}`, '120407': `{{timePublished}}`, - '121301': `游戏模板文件`, + '121301': `游戏`, '121302': `导入游戏所使用的模板, 请输入并选择对应的文件路径`, '121303': `支持以下参数名称 :`, '121304': `{{id}}, {{title}}, {{type}}, {{score}}, {{image}},`, @@ -184,7 +199,7 @@ export default { '121306': `{{genre}}, {{aliases}}, {{developer}}, {{platform}}`, - '121801': `电视剧模板文件`, + '121801': `电视剧`, '121802': `导入电视剧所使用的模板, 请输入并选择对应的文件路径`, @@ -195,9 +210,9 @@ export default { '120506': `详细介绍请参考`, '120507': `时间参数时间格式预览`, '120508': `格式参考`, - '120601': `数组显示形式`, + '120601': `数组显示`, '120602': `当模板中的变量存在数组, 则需要设定数组元素中的分割符号以及起始与结束符号, 比如演员列表, - 支持转义字符\\n(回车)。并且同时支持多种方式输出内容,显示更多配置可点击右侧[>>]展开或点击[+]新增不同输出形式,且支持输出结果预览。`, + 支持转义字符\\n(回车)。并且同时支持多种方式输出内容,点击[+]新增不同输出形式,预览效果在下方`, '124109': `首:`, '124110': `元素首:`, '124111': `分隔符:`, diff --git a/src/org/wanxp/main.ts b/src/org/wanxp/main.ts index f97c603..078b53e 100644 --- a/src/org/wanxp/main.ts +++ b/src/org/wanxp/main.ts @@ -224,16 +224,10 @@ export default class DoubanPlugin extends Plugin { }); this.settingsManager = new SettingsManager(app, this); - this.fetchOnlineData(this.settingsManager); + // this.fetchOnlineData(this.settingsManager); this.userComponent = new UserComponent(this.settingsManager); this.netFileHandler = new NetFileHandler(this.fileHandler); - if (this.userComponent.needLogin()) { - try { - await this.userComponent.login(); - }catch (e) { - log.debug(i18nHelper.getMessage('100101')); - } - } + this.settingTab = new DoubanSettingTab(this.app, this); this.addSettingTab(this.settingTab); this.statusHolder = new GlobalStatusHolder(this.app, this); @@ -322,22 +316,5 @@ export default class DoubanPlugin extends Plugin { syncConfig.dataFileNamePath = syncConfig.dataFileNamePath ? syncConfig.dataFileNamePath : DEFAULT_SETTINGS.dataFileNamePath; } - private fetchOnlineData(settingsManager: SettingsManager) { - // const gistId: string = this.settings.onlineSettingsGistId??DEFAULT_SETTINGS.onlineSettingsGistId; - // const fileName: string = this.settings.onlineSettingsFileName??DEFAULT_SETTINGS.onlineSettingsFileName; - const gistId: string = DEFAULT_SETTINGS.onlineSettingsGistId; - const fileName: string = DEFAULT_SETTINGS.onlineSettingsFileName; - GithubUtil.getGistsData(gistId, fileName) - .then(data => { - this.onlineData = JSON.parse(data); - this.fillOnlineData(this.onlineData, settingsManager); - }) - } - - private fillOnlineData(onlineData: DoubanPluginOnlineData, settingsManager: SettingsManager) { - if (onlineData.settings) { - settingsManager.onlineSettings = onlineData.settings; - } - } } diff --git a/src/org/wanxp/utils/TimeUtil.ts b/src/org/wanxp/utils/TimeUtil.ts index 7f3e416..348b04f 100644 --- a/src/org/wanxp/utils/TimeUtil.ts +++ b/src/org/wanxp/utils/TimeUtil.ts @@ -62,6 +62,31 @@ export default class TimeUtil { return message; } + /** + * 格式化日期 + * 如:formatDate(new Date(), 'yyyy-MM-dd HH:mm:ss') => 2021-01-01 12:00:00 + * @param date + * @param format + */ + public static formatDate(date:Date, format: string = 'yyyy-MM-dd HH:mm:ss'):string { + + const year = date.getFullYear() + const month = date.getMonth() + 1 + const day = date.getDate() + const hour = date.getHours() + const minute = date.getMinutes() + const second = date.getSeconds() + const formatMap: { [key: string]: any } = { + yyyy: year.toString(), + MM: month.toString().padStart(2, '0'), + dd: day.toString().padStart(2, '0'), + HH: hour.toString().padStart(2, '0'), + mm: minute.toString().padStart(2, '0'), + ss: second.toString().padStart(2, '0') + } + return format.replace(/yyyy|MM|dd|HH|mm|ss/g, (match) => formatMap[match]) + } + } diff --git a/styles.css b/styles.css index 25451c2..d0c620b 100644 --- a/styles.css +++ b/styles.css @@ -107,6 +107,62 @@ } +/* Add this CSS to your stylesheet */ +.obsidian_douban_settings_tab_container { + display: flex; + flex-direction: column; +} + +.obsidian_douban_settings_tab_headers { + display: flex; + /*border-bottom: 1px solid #ccc;*/ +} + +.obsidian_douban_settings_tab_header { + padding: 10px; + cursor: pointer; + /*border: 1px solid #ccc;*/ + border-bottom: none; + margin-right: 5px; +} + + + +.obsidian_douban_settings_tab_contents { + display: flex; + flex-direction: column; +} + +.obsidian_douban_settings_tab_content { + display: none; + padding: 10px; + /*border: 1px solid #ccc;*/ +} + +.obsidian_douban_settings_tab_header.active { + background-color: #282828; + font-weight: bold; + border: 1px solid #323232; + border-radius: 8px 8px 0 0; /* Rounded corners for the top */ +} + +.obsidian_douban_settings_tab_content.active { + background-color: #282828; + display: block; + padding: 10px; + border: 1px solid #323232; + border-radius: 0 8px 8px 8px; /* Rounded corners for the bottom */ +} + +.obsidian_douban_template_file_select { + width: 100%; +} + + +.setting-item-control.obsidian_douban_template_file_select > div.search-input-container { + width: 100%; +} +