diff --git a/src/org/wanxp/constant/Constsant.ts b/src/org/wanxp/constant/Constsant.ts index 5395a8f..ec0e23b 100644 --- a/src/org/wanxp/constant/Constsant.ts +++ b/src/org/wanxp/constant/Constsant.ts @@ -5,11 +5,52 @@ import {i18nHelper} from "../lang/helper"; */ export const BasicConst = { YAML_FRONT_MATTER_SYMBOL: '---', + /** + * 状态栏显示毫秒数 + */ CLEAN_STATUS_BAR_DELAY: 5000, - CALL_DOUBAN_DELAY: 3000, - CALL_DOUBAN_DELAY_RANGE: 3000, + /** + * 请求豆瓣周期(多少秒一次) + */ + CALL_DOUBAN_DELAY: 4000, + /** + * 请求豆瓣周期(多少秒一次) + */ + CALL_DOUBAN_DELAY_RANGE: 4000, + /** + * 多少条后同步速率变慢,防止403 + */ + SLOW_SIZE: 200, + + /** + * 请求豆瓣周期(多少秒一次) 慢速模式 + */ + CALL_DOUBAN_DELAY_SLOW: 10000, + /** + * 请求豆瓣周期(多少秒一次) + */ + CALL_DOUBAN_DELAY_RANGE_SLOW: 5000, + } +/** + * 预估程序处理时间长度 + * @private + */ +export const ESTIMATE_TIME_PER:number = 2000; + +/** + * 预估每次请求+处理时间长度(慢速模式) + * @private + */ +export const ESTIMATE_TIME_PER_WITH_REQUEST_SLOW:number = ESTIMATE_TIME_PER + BasicConst.CALL_DOUBAN_DELAY_SLOW + BasicConst.CALL_DOUBAN_DELAY_RANGE_SLOW / 2; + +/** + * 预估每次请求+处理时间长度(正常模式) + * @private + */ +export const ESTIMATE_TIME_PER_WITH_REQUEST:number = ESTIMATE_TIME_PER + BasicConst.CALL_DOUBAN_DELAY + BasicConst.CALL_DOUBAN_DELAY_RANGE / 2; + /** * 模板类型 */ @@ -93,9 +134,17 @@ export const SyncTypeRecords: { [key in SyncType]: string } = { [SyncType.music]: i18nHelper.getMessage('504106'), } - +/** + * 同步豆瓣每页的大小 + */ export const PAGE_SIZE:number = 30; +/** + * 多少条后同步速率变慢,防止403 + */ + + + /** * 动作 */ @@ -111,5 +160,8 @@ export enum SyncItemStatus { replace= 'replace', create= 'create', fail= 'fail', + unHandle='unHandle', } + + diff --git a/src/org/wanxp/constant/DefaultSettings.ts b/src/org/wanxp/constant/DefaultSettings.ts index b6e0711..9d77ba0 100644 --- a/src/org/wanxp/constant/DefaultSettings.ts +++ b/src/org/wanxp/constant/DefaultSettings.ts @@ -30,5 +30,5 @@ export const DEFAULT_SETTINGS: DoubanPluginSetting = { loginCookiesContent: '', cacheImage: true, attachmentPath: 'assets', - syncHandledData: new Map(), + syncHandledDataArray: [], } diff --git a/src/org/wanxp/douban/component/DoubanSyncModal.ts b/src/org/wanxp/douban/component/DoubanSyncModal.ts index 2fcb160..7aba4ae 100644 --- a/src/org/wanxp/douban/component/DoubanSyncModal.ts +++ b/src/org/wanxp/douban/component/DoubanSyncModal.ts @@ -20,6 +20,7 @@ import {DEFAULT_SETTINGS} from "../../constant/DefaultSettings"; import {createFileSelectionSetting} from "../setting/TemplateSettingHelper"; import {FileSuggest} from "../setting/model/FileSuggest"; import {getDefaultTemplateContent} from "../../constant/DefaultTemplateContent"; +import TimeUtil from "../../utils/TimeUtil"; export class DoubanSyncModal extends Modal { plugin: DoubanPlugin; @@ -90,7 +91,7 @@ export class DoubanSyncModal extends Modal { if (!this.plugin.statusHolder.syncStarted) { progress.innerHTML = `

- ${syncStatus.getHandle()}/${syncStatus.getTotal()}:${i18nHelper.getMessage('110036')} + ${syncStatus.getHasHandle()}/${syncStatus.getTotal()}:${i18nHelper.getMessage('110036')}

` backgroundButton.setDisabled(true); stopButton.setButtonText(i18nHelper.getMessage('110036')) @@ -98,7 +99,8 @@ export class DoubanSyncModal extends Modal { } progress.innerHTML = `

- ${syncStatus.getHandle()}/${syncStatus.getTotal()} + ${syncStatus.getTotal() == 0 ? i18nHelper.getMessage('110043') : syncStatus.getHasHandle() + '/' + syncStatus.getTotal()} +${syncStatus.getHandle() == 0? '...' : i18nHelper.getMessage('110042') + ':' + TimeUtil.estimateTimeMsg(syncStatus.getNeedHandled()-syncStatus.getHandle(), syncStatus.getOverSize())}

`} private showSyncConfig(contentEl: HTMLElement) { @@ -199,6 +201,7 @@ export class DoubanSyncModal extends Modal { .setValue(config.syncType) .onChange((value) => { config.syncType = value; + config.templateFile = this.getDefaultTemplatePath(value); this.openScopeDropdown(scopeSelections, config, disable); this.showTemplateFileSelectionSetting(templateFile, config, disable); }); @@ -207,6 +210,23 @@ export class DoubanSyncModal extends Modal { this.showTemplateFileSelectionSetting(templateFile, config, disable); } + private getDefaultTemplatePath(value: string) { + let result:string = ""; + const {settings} = this.plugin; + switch (value) { + case SyncType.movie: + result = (settings.movieTemplateFile == '' || settings.movieTemplateFile == null) ? DEFAULT_SETTINGS.movieTemplateFile : settings.movieTemplateFile + break; + case SyncType.book: + result = (settings.bookTemplateFile == '' || settings.bookTemplateFile == null) ? DEFAULT_SETTINGS.bookTemplateFile : settings.bookTemplateFile + break; + case SyncType.music: + result = (settings.musicTemplateFile == '' || settings.musicTemplateFile == null) ? DEFAULT_SETTINGS.musicTemplateFile : settings.musicTemplateFile + break; + } + return result; + } + private showScopeDropdown(containerEl:HTMLDivElement, scopeSelections: Record, config: SyncConfig, disable:boolean) { containerEl.empty(); new Setting(containerEl) diff --git a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts index b959367..c7ca688 100644 --- a/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts +++ b/src/org/wanxp/douban/data/handler/DoubanAbstractLoadHandler.ts @@ -160,10 +160,9 @@ export default abstract class DoubanAbstractLoadHandler log.error(i18nHelper.getMessage('130101', e.toString()), e); if (url) { let id = StringUtil.analyzeIdByUrl(url); - context.syncStatusHolder?context.syncStatusHolder.syncFail(id, ''):null; + context.syncStatusHolder?context.syncStatusHolder.syncStatus.fail(id, ''):null; }else { - context.syncStatusHolder?context.syncStatusHolder.syncHandled(1):null; - + context.syncStatusHolder?context.syncStatusHolder.syncStatus.handled(1):null; } }); ; diff --git a/src/org/wanxp/douban/data/model/SubjectListItem.ts b/src/org/wanxp/douban/data/model/SubjectListItem.ts index 797b990..8c9bea2 100644 --- a/src/org/wanxp/douban/data/model/SubjectListItem.ts +++ b/src/org/wanxp/douban/data/model/SubjectListItem.ts @@ -1,4 +1,5 @@ export interface SubjectListItem { id:string; url:string; + title:string; } diff --git a/src/org/wanxp/douban/model/GlobalStatusHolder.ts b/src/org/wanxp/douban/model/GlobalStatusHolder.ts index 5ff54de..212cb95 100644 --- a/src/org/wanxp/douban/model/GlobalStatusHolder.ts +++ b/src/org/wanxp/douban/model/GlobalStatusHolder.ts @@ -5,8 +5,7 @@ import { SyncTypeRecords} from "../../constant/Constsant"; import {DoubanSubjectState} from "../../constant/DoubanUserState"; import SyncStatusHolder from "../sync/model/SyncStatusHolder"; import DoubanPlugin from "../../main"; -import {HandleKey} from "../sync/model/HandledKey"; -import {HandleValue} from "../sync/model/HandleValue"; +import {SyncHandledData} from "../setting/model/SyncHandledData"; export default class GlobalStatusHolder { public syncStatus:SyncStatusHolder; @@ -48,64 +47,23 @@ export default class GlobalStatusHolder { return this.syncStarted; } - public syncReplace(id:string, title:string) { - this.syncStatus.replace(id, title); + public async initHandledData() { + this.syncStatus.initSyncHandledData(this._plugin.settings.syncHandledDataArray); } - public syncExists(id:string, title:string) { - this.syncStatus.exists(id, title); - } - - public syncCreate(id:string, title:string) { - this.syncStatus.create(id, title); - } - - public syncFail(id:string, title:string) { - this.syncStatus.fail(id, title); - } - - public putSyncHandledData(handledData:Map>) { - this.syncStatus.handledData = handledData; - } - - public initSyncHandledData() { - this.putSyncHandledData(this._plugin.settings.syncHandledData); - const incrementalUpdate:boolean = this.syncStatus.syncConfig.incrementalUpdate; - if (incrementalUpdate == false) { - this.syncStatus.resetSyncHandledSet(); - } - } - - public setTotal(total:number) { - this.syncStatus.setTotal(total); - } - - syncHandled(num:number) { - this.syncStatus.handled(num); - } - - syncTotalNum(num:number) { - this.syncStatus.setTotal(num); - } - - getSyncTotal():number { - return this.syncStatus.getTotal(); - } - - getSyncHandle():number { - return this.syncStatus.getHandle(); - } - - private async saveHandledData() { + public async saveHandledData() { if(!this.syncStatus || !this.syncStatus.handledData) { return; } - this._plugin.settings.syncHandledData = this.syncStatus.handledData; + const data:SyncHandledData[] = []; + this.syncStatus.handledData.forEach((value, key) => { + data.push({key: key, value: Array.from(value)}); + }) + this._plugin.settings.syncHandledDataArray = data; await this._plugin.saveSettings(); - } - shouldSync(id: string) { - return this.syncStatus.shouldSync(id); + public async onunload() { + await this.saveHandledData(); } } diff --git a/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts b/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts index 794255f..4a862c1 100644 --- a/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts +++ b/src/org/wanxp/douban/setting/model/DoubanPluginSetting.ts @@ -1,7 +1,5 @@ import {CustomProperty} from "./CustomProperty"; -import {SyncConfig} from "../../sync/model/SyncConfig"; -import {HandleKey} from "../../sync/model/HandledKey"; -import {HandleValue} from "../../sync/model/HandleValue"; +import {SyncHandledData} from "./SyncHandledData"; export interface DoubanPluginSetting { movieTemplateFile: string, @@ -24,5 +22,5 @@ export interface DoubanPluginSetting { loginCookiesContent: string, cacheImage: boolean, attachmentPath: string, - syncHandledData?:Map>, + syncHandledDataArray: SyncHandledData[], } diff --git a/src/org/wanxp/douban/setting/model/SyncHandledData.ts b/src/org/wanxp/douban/setting/model/SyncHandledData.ts new file mode 100644 index 0000000..c1881a3 --- /dev/null +++ b/src/org/wanxp/douban/setting/model/SyncHandledData.ts @@ -0,0 +1,4 @@ +export interface SyncHandledData { + key:string; + value:string[]; +} diff --git a/src/org/wanxp/douban/sync/handler/DoubanAbstractSyncHandler.ts b/src/org/wanxp/douban/sync/handler/DoubanAbstractSyncHandler.ts index 35e9f37..335c0e7 100644 --- a/src/org/wanxp/douban/sync/handler/DoubanAbstractSyncHandler.ts +++ b/src/org/wanxp/douban/sync/handler/DoubanAbstractSyncHandler.ts @@ -65,14 +65,19 @@ export abstract class DoubanAbstractSyncHandler implem if (!items || items.length == 0) { return ; } - context.syncStatusHolder.setTotal(items.length); + const {syncStatus} = context.syncStatusHolder; + syncStatus.totalNum(items.length); + const needHandled:number = items.filter(item => syncStatus.shouldSync(item.id)).length; + syncStatus.setNeedHandled(needHandled); for (const item of items) { - await sleepRange(BasicConst.CALL_DOUBAN_DELAY, BasicConst.CALL_DOUBAN_DELAY + BasicConst.CALL_DOUBAN_DELAY_RANGE); if (!context.plugin.statusHolder.syncing()) { return; } - if(context.syncStatusHolder.shouldSync(item.id)) { + if(syncStatus.shouldSync(item.id)) { await this.doubanSubjectLoadHandler.handle(item.url, context); + await sleepRange(BasicConst.CALL_DOUBAN_DELAY, BasicConst.CALL_DOUBAN_DELAY + BasicConst.CALL_DOUBAN_DELAY_RANGE); + }else { + syncStatus.unHandle(item.id, item.title); } } } diff --git a/src/org/wanxp/douban/sync/handler/SyncHandler.ts b/src/org/wanxp/douban/sync/handler/SyncHandler.ts index e586328..10a64c6 100644 --- a/src/org/wanxp/douban/sync/handler/SyncHandler.ts +++ b/src/org/wanxp/douban/sync/handler/SyncHandler.ts @@ -48,24 +48,35 @@ export default class SyncHandler { async showResult() { const {syncStatusHolder} = this.context; - const {statusHandleMap} = syncStatusHolder.syncStatus; - const {syncResultMap} = syncStatusHolder.syncStatus; - let summary:string = `${i18nHelper.getMessage('syncall')}: ${syncStatusHolder.getSyncTotal()} + const {syncStatus} = syncStatusHolder; + const {statusHandleMap} = syncStatus; + const {syncResultMap} = syncStatus; + let summary:string + = `${i18nHelper.getMessage('110053', i18nHelper.getMessage('110050'), i18nHelper.getMessage('110051'), i18nHelper.getMessage('110052'))} +|-----|----|----------------------------------| +`; + summary += `${i18nHelper.getMessage('110053', i18nHelper.getMessage('syncall'), syncStatus.getTotal(), i18nHelper.getMessage('syncall_desc'))} `; for (const [key, value] of statusHandleMap) { // @ts-ignore - summary+= `${i18nHelper.getMessage(key)}: ${value} + summary+= `${i18nHelper.getMessage('110053', i18nHelper.getMessage(key), value, i18nHelper.getMessage(key + '_desc'))} `; } + summary += `${i18nHelper.getMessage('110053', i18nHelper.getMessage('notsync'), syncStatus.getTotal()-syncStatus.getHasHandle(), i18nHelper.getMessage('notsync_desc'))} +`; let details:string = ''; for (const [key, value] of syncResultMap) { - // @ts-ignore - details+= `${value.id}-[[${value.title}]]: ${i18nHelper.getMessage(value.status)} + if (value.status == 'unHandle') { + // @ts-ignore + details+= `${value.id}- ${value.title} : ${i18nHelper.getMessage(value.status)} `; - } - summary+= `${i18nHelper.getMessage('notsync')}: ${syncStatusHolder.getSyncTotal() - syncStatusHolder.getSyncHandle()} -` + }else { + // @ts-ignore + details+= `${value.id}-[[${value.title}]]: ${i18nHelper.getMessage(value.status)} +`; + } + } const result : string = i18nHelper.getMessage('110037', summary, details); const resultFileName = `${i18nHelper.getMessage('110038')}_${moment(new Date()).format('YYYYMMDDHHmmss')}` await this.plugin.fileHandler.createNewNoteWithData(`${this.syncConfig.dataFilePath}/${resultFileName}`, result, true); diff --git a/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts b/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts index b9a19ce..1867868 100644 --- a/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts +++ b/src/org/wanxp/douban/sync/handler/list/DoubanAbstractListHandler.ts @@ -75,9 +75,10 @@ export default abstract class DoubanAbstractListHandler implements DoubanListHan .map((i: any) => { const item = dataHtml(i); const linkValue:string = item.find('div.title > a').attr('href'); + const titleValue:string = item.find('div.title > a').text().trim(); let idPattern = /(\d){5,10}/g; let ececResult = idPattern.exec(linkValue); - return ececResult?{id: ececResult[0], url: linkValue}:null; + return ececResult?{id: ececResult[0], url: linkValue, title: titleValue}:null; // return linkValue; }) } diff --git a/src/org/wanxp/douban/sync/model/GlobalSyncStatusHolder.ts b/src/org/wanxp/douban/sync/model/GlobalSyncStatusHolder.ts deleted file mode 100644 index 686e9c1..0000000 --- a/src/org/wanxp/douban/sync/model/GlobalSyncStatusHolder.ts +++ /dev/null @@ -1,30 +0,0 @@ -import {SyncConfig} from "./SyncConfig"; -import {SyncItemStatus} from "../../../constant/Constsant"; - -export default class GlobalSyncStatusHolder { - public syncConfig: SyncConfig; - private total:number; - private handle:number; - - constructor(syncConfig: SyncConfig) { - this.syncConfig = syncConfig; - this.total = 0; - this.handle = 0; - } - - handled(num:number) { - this.handle = this.handle + num; - } - - totalNum(num:number) { - this.total = num ; - } - - getTotal():number { - return this.total; - } - - getHandle():number { - return this.handle; - } -} diff --git a/src/org/wanxp/douban/sync/model/HandleValue.ts b/src/org/wanxp/douban/sync/model/HandleValue.ts deleted file mode 100644 index 766bc3b..0000000 --- a/src/org/wanxp/douban/sync/model/HandleValue.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface HandleValue { - v: string; -} diff --git a/src/org/wanxp/douban/sync/model/HandledKey.ts b/src/org/wanxp/douban/sync/model/HandledKey.ts deleted file mode 100644 index ca2a578..0000000 --- a/src/org/wanxp/douban/sync/model/HandledKey.ts +++ /dev/null @@ -1,3 +0,0 @@ -export interface HandleKey { - k: string; -} diff --git a/src/org/wanxp/douban/sync/model/SyncStatusHolder.ts b/src/org/wanxp/douban/sync/model/SyncStatusHolder.ts index 14226dc..5d7c0cf 100644 --- a/src/org/wanxp/douban/sync/model/SyncStatusHolder.ts +++ b/src/org/wanxp/douban/sync/model/SyncStatusHolder.ts @@ -1,25 +1,67 @@ import {SyncConfig} from "./SyncConfig"; -import GlobalSyncStatusHolder from "./GlobalSyncStatusHolder"; import {SyncItemResult} from "./SyncItemResult"; -import {SyncItemStatus} from "../../../constant/Constsant"; -import {HandleKey} from "./HandledKey"; -import {HandleValue} from "./HandleValue"; +import {BasicConst, SyncItemStatus} from "../../../constant/Constsant"; +import {SyncHandledData} from "../../setting/model/SyncHandledData"; -export default class SyncStatusHolder extends GlobalSyncStatusHolder{ +export default class SyncStatusHolder { - public handledData: Map>; + public handledData: Map>; public syncResultMap: Map = new Map(); public statusHandleMap: Map = new Map([ [SyncItemStatus.exists, 0], [SyncItemStatus.replace, 0], [SyncItemStatus.create, 0], [SyncItemStatus.fail, 0], -]); + [SyncItemStatus.unHandle, 0], + ]); + + private key: string; + + public syncConfig: SyncConfig; + private total:number; + private handle:number; + private needHandled:number; constructor(syncConfig: SyncConfig) { - super(syncConfig) + this.syncConfig = syncConfig; + this.total = 0; + this.handle = 0; + this.needHandled = 0; + this.key =this.getKey(syncConfig); } + handled(num:number) { + this.handle = this.handle + num; + } + + totalNum(num:number) { + this.total = num ; + } + + getTotal():number { + return this.total; + } + + getHandle():number { + return this.handle; + } + + /** + * 已处理总数,包含已经存在不需要同步的部分 + */ + getHasHandle():number { + return this.handle; + } + + setNeedHandled(needHandled:number) { + this.needHandled = needHandled; + } + + getNeedHandled():number { + return this.needHandled; + } + + public replace(id:string, title:string) { this.putToHandled(id, title); this.updateResult(id, title, SyncItemStatus.replace); @@ -30,6 +72,11 @@ export default class SyncStatusHolder extends GlobalSyncStatusHolder{ this.updateResult(id, title, SyncItemStatus.exists); } + public unHandle(id:string, title:string) { + this.updateResult(id, title, SyncItemStatus.unHandle); + } + + public create(id:string, title:string) { this.putToHandled(id, title); this.updateResult(id, title, SyncItemStatus.create); @@ -42,37 +89,76 @@ export default class SyncStatusHolder extends GlobalSyncStatusHolder{ private updateResult(id:string, title:string, status:SyncItemStatus) { this.syncResultMap.set(id, {id: id,title:title,status:status}); this.statusHandleMap.set(status, this.statusHandleMap.get(status) + 1); - super.handled(1); + this.handled(1); } public setTotal(total:number) { - super.totalNum(total); + this.totalNum(total); } private putToHandled(id: string, title: string) { if (!this.handledData) { - this.handledData = new Map>(); + this.handledData = new Map>(); } - const key = {k: this.syncConfig.dataFilePath} + const {key} = this; if (!this.handledData.has(key)) { - this.handledData.set(key, new Set()); - } - this.handledData.get(key).add({v:id}) - } - - resetSyncHandledSet() { - if (!this.handledData) { - return; - } - const key = {k: this.syncConfig.dataFilePath} - if (this.handledData.has(key)) { - this.handledData.set(key, new Set()); + this.handledData.set(key, new Set()); } + this.handledData.get(key).add(id) } shouldSync(id: string) { - const key = {k: this.syncConfig.dataFilePath} - return !this.handledData.get(key).has({v:id}); + return this.handledData.get(this.key)?!this.handledData.get(this.key).has(id):true; } + + getKey(syncConfig: SyncConfig):string { + const type:string = syncConfig.syncType ? syncConfig.syncType : ''; + const scope:string = syncConfig.scope ? syncConfig.scope : ''; + const path:string = syncConfig.dataFilePath ? syncConfig.dataFilePath : ''; + return `${path}+${type}+${scope}`; + } + + getOverSize():boolean { + return this.getNeedHandled() > BasicConst.SLOW_SIZE; + } + + public initSyncHandledData(data:SyncHandledData[]) { + this.handledData = new Map>(); + const {handledData} = this; + data.forEach((d) => { + handledData.set(d.key,new Set(d.value)); + }) + if (!this.syncConfig.incrementalUpdate) { + this.resetSyncHandledData(); + } + this.resetTypeOtherSyncHandledData(); + } + + public resetSyncHandledData() { + return this.handledData.set(this.key, new Set()); + } + + public resetTypeOtherSyncHandledData() { + this.handledData.forEach((value, key) => { + if (this.needClearByKey(this.key, key)) { + value.clear(); + } + }); + } + + private needClearByKey(handleKey:string, savedKey:string):boolean { + if (handleKey == savedKey) { + return false; + } + let handledKeys = handleKey.split('+'); + let savedKeys = savedKey.split('+'); + handledKeys = handledKeys??['']; + savedKeys = savedKeys??['']; + if (handledKeys[0] == savedKeys[0]) { + return true; + } + return false; + } + } diff --git a/src/org/wanxp/lang/locale/en.ts b/src/org/wanxp/lang/locale/en.ts index fdffddd..45b1b0c 100644 --- a/src/org/wanxp/lang/locale/en.ts +++ b/src/org/wanxp/lang/locale/en.ts @@ -35,15 +35,31 @@ PS: This file could be delete if you want to. '110038': `DoubanSyncResult`, '110039': `SyncNotSync:`, '110040': `Only sync that haven't been synced yet. if not enabled, will sync all the subject'`, - '110041': `If`, + '110041': `IncrementalSync`, + '110042': `EstimateTime`, + '110043': `Loading Menu`, + '110050': `Type`, + '110051': `Number`, + '110052': `Description`, 'exists':`[exists]`, + 'unHandle':`[unHandle]`, 'replace':`[replace]`, 'create':`[create]`, 'fail':`[fail]`, - 'notsync':`[notSync]`, 'syncall':`[summary]`, + 'notsync':`[notsync]`, + + 'unHandle_desc':`unHandle`, + 'exists_desc': `exists`, + 'replace_desc': `replace`, + 'create_desc': `create`, + 'fail_desc': `fail`, + 'notsync_desc': `notsync`, + 'syncall_desc': `syncall`, + + '110053':`|{0}|{1}|{2}|`, //DoubanSettingTab '1201': `Obsidian Douban`, @@ -495,4 +511,9 @@ PS: This file could be delete if you want to. 'NOTE': `note`, 'GAME': `game`, 'TELEPLAY': `teleplay`, + + 'DAY': `D`, + 'HOUR': `H`, + 'MINUTE': `m`, + 'SECOND': `S`, } diff --git a/src/org/wanxp/lang/locale/zh-cn.ts b/src/org/wanxp/lang/locale/zh-cn.ts index 1f52f4c..73bf4ad 100644 --- a/src/org/wanxp/lang/locale/zh-cn.ts +++ b/src/org/wanxp/lang/locale/zh-cn.ts @@ -38,13 +38,28 @@ export default { '110039': `增量同步:`, '110040': `仅同步上面'笔记存放位置'目录中最近新增/同步失败/未同步的部分,不同步已同步的内容.若关闭则会全量同步.增量同步会更快,适合之前同步中途失败停止或最近有豆瓣新增了内容,全量同步适合修改了模板或修改了存放路径情况下进行.`, '110041': `使用增量`, + '110042': `预计处理时间`, + '110043': `同步目录加载中`, - 'exists':`[未替换]`, - 'replace':`[已替换]`, - 'create':`[已创建]`, - 'fail':`[失败]`, - 'notsync':`[未进行]`, - 'syncall':`[总数]`, + '110050': `类型`, + '110051': `数量`, + '110052': `说明`, + + 'unHandle':`[已忽略]`, + 'exists': `[未替换]`, + 'replace': `[已替换]`, + 'create': `[已创建]`, + 'fail': `[已失败]`, + 'syncall': `[总数]`, + 'notsync': `[未进行]`, + + 'unHandle_desc':`增量同步上次已进行,这次无需处理`, + 'exists_desc': `已经存在的同名文档,这次无需同步`, + 'replace_desc': `已经存在的同名文档,这次已被替换`, + 'create_desc': `之前不存在的文档,这次直接新增`, + 'fail_desc': `处理过程钟出现错误,未能成功`, + 'notsync_desc': `因异常中断或提前终止导致还未处理`, + 'syncall_desc': `您此次同步条件在豆瓣中的条目总数`, '110201': `{0} 文件已经存在.`, '110202': `{0} 模板文件无法读取`, @@ -506,5 +521,9 @@ export default { 'GAME': `游戏`, 'TELEPLAY': `电视剧`, + 'DAY': `天`, + 'HOUR': `时`, + 'MINUTE': `分`, + 'SECOND': `秒`, } diff --git a/src/org/wanxp/main.ts b/src/org/wanxp/main.ts index 5f26704..9277ed1 100644 --- a/src/org/wanxp/main.ts +++ b/src/org/wanxp/main.ts @@ -22,7 +22,6 @@ import {DoubanSyncModal} from "./douban/component/DoubanSyncModal"; import SyncHandler from "./douban/sync/handler/SyncHandler"; import {SyncConfig} from "./douban/sync/model/SyncConfig"; import GlobalStatusHolder from "./douban/model/GlobalStatusHolder"; -import SyncStatusHolder from "./douban/sync/model/SyncStatusHolder"; export default class DoubanPlugin extends Plugin { public settings: DoubanPluginSetting; @@ -36,7 +35,7 @@ export default class DoubanPlugin extends Plugin { async putToObsidian(context: HandleContext, extract: DoubanSubject) { - const {syncStatusHolder} = context; + const {syncStatus} = context.syncStatusHolder; try { if (!extract) { @@ -44,7 +43,7 @@ export default class DoubanPlugin extends Plugin { return; } if (Action.Sync == context.action) { - this.showStatus(i18nHelper.getMessage('140207', syncStatusHolder.getSyncHandle(), syncStatusHolder.getSyncTotal(), extract.title)); + this.showStatus(i18nHelper.getMessage('140207', syncStatus.getHasHandle(), syncStatus.getTotal(), extract.title)); }else { this.showStatus(i18nHelper.getMessage('140204', extract.title)); } @@ -53,13 +52,13 @@ export default class DoubanPlugin extends Plugin { await this.putContentToObsidian(context, result); } if (Action.Sync == context.action) { - this.showStatus(i18nHelper.getMessage('140208', syncStatusHolder.getSyncHandle(), syncStatusHolder.getSyncTotal(), extract.title)); + this.showStatus(i18nHelper.getMessage('140208', syncStatus.getHasHandle(), syncStatus.getTotal(), extract.title)); }else { this.showStatus(i18nHelper.getMessage('140205', extract.title)); } } catch (e) { log.error(i18nHelper.getMessage('140206', e.message), e); - syncStatusHolder!=null?syncStatusHolder.syncFail(extract.id, extract.title):null; + syncStatus!=null?syncStatus.fail(extract.id, extract.title):null; } finally { this.clearStatusBarDelay(); } @@ -89,20 +88,20 @@ export default class DoubanPlugin extends Plugin { } filePath = filePath?filePath:DEFAULT_SETTINGS.dataFilePath; filePath = FileUtil.join(filePath, result.fileName); - const {syncStatusHolder} = context; + const {syncStatus} = context.syncStatusHolder; const {subject} = result; const {content} = result; if (Action.Sync == context.action) { if (context.syncStatusHolder.syncStatus.syncConfig.force) { const exists:boolean = await this.fileHandler.createOrReplaceNewNoteWithData(filePath, content, context.showAfterCreate); if (exists) { - syncStatusHolder != null ? syncStatusHolder.syncReplace(subject.id, subject.title):null; + syncStatus != null ? syncStatus.replace(subject.id, subject.title):null; }else { - syncStatusHolder != null ?syncStatusHolder.syncCreate(subject.id, subject.title):null; + syncStatus != null ?syncStatus.create(subject.id, subject.title):null; } }else { const created:boolean = await this.fileHandler.createNewNoteWithData(filePath, content, context.showAfterCreate, false); - created ?syncStatusHolder.syncCreate(subject.id, subject.title):syncStatusHolder.syncExists(subject.id, subject.title); + created ?syncStatus.create(subject.id, subject.title):syncStatus.exists(subject.id, subject.title); } }else { await this.fileHandler.createNewNoteWithData(filePath, content, context.showAfterCreate); @@ -224,6 +223,13 @@ export default class DoubanPlugin extends Plugin { } + async onunload() { + if (this.statusHolder.syncStatus) { + await this.statusHolder.onunload(); + } + } + + @@ -252,8 +258,7 @@ export default class DoubanPlugin extends Plugin { // @ts-ignore new Notice(i18nHelper.getMessage('140301', SyncTypeRecords[syncConfig.syncType])); this.initSyncDefaultSettings(syncConfig); - context.syncStatusHolder.initSyncHandledData(); - + context.syncStatusHolder.initHandledData(); // @ts-ignore this.showStatus(i18nHelper.getMessage('140203', SyncTypeRecords[syncConfig.syncType])); const syncHandler = new SyncHandler(this.app, this, syncConfig, context); diff --git a/src/org/wanxp/utils/TimeUtil.ts b/src/org/wanxp/utils/TimeUtil.ts index c77eebe..fb5d5c1 100644 --- a/src/org/wanxp/utils/TimeUtil.ts +++ b/src/org/wanxp/utils/TimeUtil.ts @@ -1,9 +1,72 @@ import NumberUtil from "./NumberUtil"; import {log} from "./Logutil"; +import {BasicConst, ESTIMATE_TIME_PER_WITH_REQUEST, ESTIMATE_TIME_PER_WITH_REQUEST_SLOW} from "../constant/Constsant"; +import {moment} from "obsidian"; +import {Moment} from "moment"; +import {i18nHelper} from "../lang/helper"; export default class TimeUtil { + /** + * 计算预估需要的时间 + * @param needHandled 需要处理的数量 + * @param overSlowSize 是否超过慢速长度的阈值 + * @return 需要耗费的毫秒数 + */ + public static estimateTime(needHandled:number, overSlowSize:boolean):number { + if (needHandled <= 0) { + return 0; + } + let times = 0; + if (overSlowSize) { + if (needHandled <= BasicConst.SLOW_SIZE) { + times = ESTIMATE_TIME_PER_WITH_REQUEST * needHandled; + }else { + times = ESTIMATE_TIME_PER_WITH_REQUEST * BasicConst.SLOW_SIZE + ESTIMATE_TIME_PER_WITH_REQUEST_SLOW * Math.max(needHandled - BasicConst.SLOW_SIZE, 0); + } + }else { + times = ESTIMATE_TIME_PER_WITH_REQUEST * needHandled; + } + return times; + } + + public static estimateTimeMsg(needHandled:number, overSlowSize:boolean):string { + const times:number = this.estimateTime(needHandled, overSlowSize); + if (times <= 0) { + return 0+i18nHelper.getMessage('SECOND'); + } + return this.formatDuring(times); + } + + public static formatDuring(mss:number):string { + let show:boolean = false; + let message:string = ""; + const days = Math.floor(mss / (1000 * 60 * 60 * 24)); + const hours = Math.floor((mss % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((mss % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((mss % (1000 * 60)) / 1000); + + if (days > 0) { + show = true; + message += days + i18nHelper.getMessage("DAY"); + } + if (hours > 0 || show) { + show = true; + message += hours + i18nHelper.getMessage("HOUR"); + } + if (minutes > 0 || show) { + show = true; + message += minutes + i18nHelper.getMessage("MINUTE"); + } + if (seconds > 0 || show) { + message += seconds + i18nHelper.getMessage("SECOND"); + } + return message; + } + + + }