mirror of
https://github.com/Wanxp/obsidian-douban.git
synced 2026-04-04 16:48:44 +08:00
add function sync breakpoint resume
This commit is contained in:
parent
594cd3a40b
commit
36b35db78d
@ -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',
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@ -30,5 +30,5 @@ export const DEFAULT_SETTINGS: DoubanPluginSetting = {
|
||||
loginCookiesContent: '',
|
||||
cacheImage: true,
|
||||
attachmentPath: 'assets',
|
||||
syncHandledData: new Map(),
|
||||
syncHandledDataArray: [],
|
||||
}
|
||||
|
||||
@ -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 = `<p>
|
||||
<label for="file">${i18nHelper.getMessage('110033')}</label>
|
||||
<progress class="obsidian_douban_sync_slider" max="${syncStatus.getTotal() == 0 ? 1:syncStatus.getTotal()}" value="${syncStatus.getHandle()}"> </progress> <span> ${syncStatus.getHandle()}/${syncStatus.getTotal()}:${i18nHelper.getMessage('110036')} </span>
|
||||
<progress class="obsidian_douban_sync_slider" max="${syncStatus.getTotal() == 0 ? 1:syncStatus.getTotal()}" value="${syncStatus.getHasHandle()}"> </progress> <span> ${syncStatus.getHasHandle()}/${syncStatus.getTotal()}:${i18nHelper.getMessage('110036')} </span>
|
||||
</p>`
|
||||
backgroundButton.setDisabled(true);
|
||||
stopButton.setButtonText(i18nHelper.getMessage('110036'))
|
||||
@ -98,7 +99,8 @@ export class DoubanSyncModal extends Modal {
|
||||
}
|
||||
progress.innerHTML = `<p>
|
||||
<label for="file">${i18nHelper.getMessage('110033')}</label>
|
||||
<progress class="obsidian_douban_sync_slider" max="${syncStatus.getTotal() == 0 ? 1:syncStatus.getTotal()}" value="${syncStatus.getHandle()}"> </progress> <span> ${syncStatus.getHandle()}/${syncStatus.getTotal()} </span>
|
||||
<progress class="obsidian_douban_sync_slider" max="${syncStatus.getTotal() == 0 ? 1:syncStatus.getTotal()}" value="${syncStatus.getHasHandle()}"> </progress> <span> ${syncStatus.getTotal() == 0 ? i18nHelper.getMessage('110043') : syncStatus.getHasHandle() + '/' + syncStatus.getTotal()}
|
||||
${syncStatus.getHandle() == 0? '...' : i18nHelper.getMessage('110042') + ':' + TimeUtil.estimateTimeMsg(syncStatus.getNeedHandled()-syncStatus.getHandle(), syncStatus.getOverSize())} </span>
|
||||
</p>`}
|
||||
|
||||
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<string, string>, config: SyncConfig, disable:boolean) {
|
||||
containerEl.empty();
|
||||
new Setting(containerEl)
|
||||
|
||||
@ -160,10 +160,9 @@ export default abstract class DoubanAbstractLoadHandler<T extends DoubanSubject>
|
||||
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;
|
||||
}
|
||||
});
|
||||
;
|
||||
|
||||
@ -1,4 +1,5 @@
|
||||
export interface SubjectListItem {
|
||||
id:string;
|
||||
url:string;
|
||||
title:string;
|
||||
}
|
||||
|
||||
@ -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<HandleKey, Set<HandleValue>>) {
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
@ -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<HandleKey, Set<HandleValue>>,
|
||||
syncHandledDataArray: SyncHandledData[],
|
||||
}
|
||||
|
||||
4
src/org/wanxp/douban/setting/model/SyncHandledData.ts
Normal file
4
src/org/wanxp/douban/setting/model/SyncHandledData.ts
Normal file
@ -0,0 +1,4 @@
|
||||
export interface SyncHandledData {
|
||||
key:string;
|
||||
value:string[];
|
||||
}
|
||||
@ -65,14 +65,19 @@ export abstract class DoubanAbstractSyncHandler<T extends DoubanSubject> 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -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) {
|
||||
if (value.status == 'unHandle') {
|
||||
// @ts-ignore
|
||||
details+= `${value.id}- ${value.title} : ${i18nHelper.getMessage(value.status)}
|
||||
`;
|
||||
}else {
|
||||
// @ts-ignore
|
||||
details+= `${value.id}-[[${value.title}]]: ${i18nHelper.getMessage(value.status)}
|
||||
`;
|
||||
}
|
||||
summary+= `${i18nHelper.getMessage('notsync')}: ${syncStatusHolder.getSyncTotal() - syncStatusHolder.getSyncHandle()}
|
||||
`
|
||||
|
||||
}
|
||||
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);
|
||||
|
||||
@ -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;
|
||||
})
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
export interface HandleValue {
|
||||
v: string;
|
||||
}
|
||||
@ -1,3 +0,0 @@
|
||||
export interface HandleKey {
|
||||
k: string;
|
||||
}
|
||||
@ -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<HandleKey, Set<HandleValue>>;
|
||||
public handledData: Map<string, Set<string>>;
|
||||
public syncResultMap: Map<string, SyncItemResult> = new Map();
|
||||
public statusHandleMap: Map<SyncItemStatus, number> = 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<HandleKey, Set<HandleValue>>();
|
||||
this.handledData = new Map<string, Set<string>>();
|
||||
}
|
||||
const key = {k: this.syncConfig.dataFilePath}
|
||||
const {key} = this;
|
||||
if (!this.handledData.has(key)) {
|
||||
this.handledData.set(key, new Set<HandleValue>());
|
||||
}
|
||||
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<HandleValue>());
|
||||
this.handledData.set(key, new Set<string>());
|
||||
}
|
||||
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<string, Set<string>>();
|
||||
const {handledData} = this;
|
||||
data.forEach((d) => {
|
||||
handledData.set(d.key,new Set<string>(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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -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`,
|
||||
}
|
||||
|
||||
@ -38,13 +38,28 @@ export default {
|
||||
'110039': `增量同步:`,
|
||||
'110040': `仅同步上面'笔记存放位置'目录中最近新增/同步失败/未同步的部分,不同步已同步的内容.若关闭则会全量同步.增量同步会更快,适合之前同步中途失败停止或最近有豆瓣新增了内容,全量同步适合修改了模板或修改了存放路径情况下进行.`,
|
||||
'110041': `使用增量`,
|
||||
'110042': `预计处理时间`,
|
||||
'110043': `同步目录加载中`,
|
||||
|
||||
'110050': `类型`,
|
||||
'110051': `数量`,
|
||||
'110052': `说明`,
|
||||
|
||||
'unHandle':`[已忽略]`,
|
||||
'exists': `[未替换]`,
|
||||
'replace': `[已替换]`,
|
||||
'create': `[已创建]`,
|
||||
'fail':`[失败]`,
|
||||
'notsync':`[未进行]`,
|
||||
'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': `秒`,
|
||||
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
Loading…
Reference in New Issue
Block a user