chore: upgrade watch-fs plugin

This commit is contained in:
tiddlygit-test 2020-08-13 00:08:55 +08:00
parent 5d9f8ead1d
commit ac41266982
6 changed files with 88 additions and 19 deletions

View file

@ -8,7 +8,7 @@
This file is modified based on $:/plugins/OokTech/Bob/FileSystemMonitor.js This file is modified based on $:/plugins/OokTech/Bob/FileSystemMonitor.js
\ */ \ */
const isNonTiddlerFiles = filePath => filePath.endsWith('.DS_Store'); const isNotNonTiddlerFiles = (filePath) => !filePath.endsWith('.DS_Store') && !filePath.includes('.git');
function FileSystemMonitor() { function FileSystemMonitor() {
const isDebug = false; const isDebug = false;
@ -21,6 +21,8 @@ function FileSystemMonitor() {
// this allow us to test this module in nodejs directly without "ReferenceError: $tw is not defined" // this allow us to test this module in nodejs directly without "ReferenceError: $tw is not defined"
const $tw = this.$tw || { node: true }; const $tw = this.$tw || { node: true };
// init our namespace for communication
$tw.wiki.watchFs = {};
// folder to watch // folder to watch
// non-tiddler files that needs to be ignored // non-tiddler files that needs to be ignored
@ -29,7 +31,9 @@ function FileSystemMonitor() {
const fs = require('fs'); const fs = require('fs');
const path = require('path'); const path = require('path');
const watchPathBase = path.resolve($tw.boot.wikiInfo?.config?.watchFolder || $tw.boot.wikiTiddlersPath || './tiddlers'); const watchPathBase = path.resolve(
$tw.boot.wikiInfo?.config?.watchFolder || $tw.boot.wikiTiddlersPath || './tiddlers'
);
debugLog(`watchPathBase`, JSON.stringify(watchPathBase, undefined, ' ')); debugLog(`watchPathBase`, JSON.stringify(watchPathBase, undefined, ' '));
/** /**
@ -55,6 +59,7 @@ function FileSystemMonitor() {
* } * }
*/ */
const inverseFilesIndex = {}; const inverseFilesIndex = {};
$tw.wiki.watchFs.inverseFilesIndex = inverseFilesIndex;
// initialize the inverse index // initialize the inverse index
for (const tiddlerTitle in initialLoadedFiles) { for (const tiddlerTitle in initialLoadedFiles) {
if ({}.hasOwnProperty.call(initialLoadedFiles, tiddlerTitle)) { if ({}.hasOwnProperty.call(initialLoadedFiles, tiddlerTitle)) {
@ -72,8 +77,8 @@ function FileSystemMonitor() {
delete inverseFilesIndex[filePath]; delete inverseFilesIndex[filePath];
} }
}; };
const filePathExistsInIndex = filePath => !!inverseFilesIndex[filePath]; const filePathExistsInIndex = (filePath) => !!inverseFilesIndex[filePath];
const getTitleByPath = filePath => { const getTitleByPath = (filePath) => {
try { try {
return inverseFilesIndex[filePath].tiddlerTitle; return inverseFilesIndex[filePath].tiddlerTitle;
} catch { } catch {
@ -87,7 +92,7 @@ function FileSystemMonitor() {
* we need to get old tiddler path by its name * we need to get old tiddler path by its name
* @param {string} title * @param {string} title
*/ */
const getPathByTitle = title => { const getPathByTitle = (title) => {
try { try {
for (const filePath in inverseFilesIndex) { for (const filePath in inverseFilesIndex) {
if (inverseFilesIndex[filePath].title === title || inverseFilesIndex[filePath].title === `${title}.tid`) { if (inverseFilesIndex[filePath].title === title || inverseFilesIndex[filePath].title === `${title}.tid`) {
@ -109,6 +114,20 @@ function FileSystemMonitor() {
*/ */
const lockedFiles = new Set(); const lockedFiles = new Set();
// every time a file changed, refresh the count down timer, so only when disk get stable after a while, will we sync to the browser
$tw.wiki.watchFs.canSync = false;
const debounceInterval = 4 * 1000;
let syncTimeoutHandler = undefined;
const refreshCanSyncState = () => {
$tw.wiki.watchFs.canSync = false;
debugLog(`canSync is now ${$tw.wiki.watchFs.canSync}`);
clearTimeout(syncTimeoutHandler);
syncTimeoutHandler = setTimeout(() => {
$tw.wiki.watchFs.canSync = true;
debugLog(`canSync is now ${$tw.wiki.watchFs.canSync}`);
}, debounceInterval);
};
/** /**
* This watches for changes to a folder and updates the wiki when anything changes in the folder. * This watches for changes to a folder and updates the wiki when anything changes in the folder.
* *
@ -127,11 +146,6 @@ function FileSystemMonitor() {
const fileRelativePath = path.relative(watchPathBase, filePath); const fileRelativePath = path.relative(watchPathBase, filePath);
const fileAbsolutePath = path.join(watchPathBase, fileRelativePath); const fileAbsolutePath = path.join(watchPathBase, fileRelativePath);
debugLog(`${fileRelativePath} ${changeType}`); debugLog(`${fileRelativePath} ${changeType}`);
// ignore some cases
if (isNonTiddlerFiles(fileRelativePath)) {
debugLog(`${fileRelativePath} ignored due to isNonTiddlerFiles`);
return;
}
if (lockedFiles.has(fileRelativePath)) { if (lockedFiles.has(fileRelativePath)) {
debugLog(`${fileRelativePath} ignored due to mutex lock`); debugLog(`${fileRelativePath} ignored due to mutex lock`);
// release lock as we have already finished our job // release lock as we have already finished our job
@ -155,15 +169,15 @@ function FileSystemMonitor() {
* "hasMetaFile": false * "hasMetaFile": false
* } * }
*/ */
const [tiddlersDescriptor] = $tw.loadTiddlersFromPath(fileAbsolutePath); const tiddlersDescriptor = $tw.loadTiddlersFromFile(fileAbsolutePath, { title: fileAbsolutePath });
debugLog(`tiddlersDescriptor`, JSON.stringify(tiddlersDescriptor, undefined, ' ')); debugLog(`tiddlersDescriptor`, JSON.stringify(tiddlersDescriptor, undefined, ' '));
const { tiddlers, ...fileDescriptor } = tiddlersDescriptor; const { tiddlers, ...fileDescriptor } = tiddlersDescriptor;
// if user is using git or VSCode to create new file in the disk, that is not yet exist in the wiki // if user is using git or VSCode to create new file in the disk, that is not yet exist in the wiki
// but maybe our index is not updated, or maybe user is modify a system tiddler, we need to check each case // but maybe our index is not updated, or maybe user is modify a system tiddler, we need to check each case
if (!filePathExistsInIndex(fileRelativePath) || !fileDescriptor.tiddlerTitle) { if (!filePathExistsInIndex(fileRelativePath)) {
tiddlers.forEach(tiddler => { tiddlers.forEach((tiddler) => {
// check whether we are rename an existed tiddler // check whether we are rename an existed tiddler
debugLog('getting tiddler.title', tiddler.title); debugLog('getting new tiddler.title', tiddler.title);
const existedWikiRecord = $tw.wiki.getTiddler(tiddler.title); const existedWikiRecord = $tw.wiki.getTiddler(tiddler.title);
if (existedWikiRecord && deepEqual(tiddler, existedWikiRecord.fields)) { if (existedWikiRecord && deepEqual(tiddler, existedWikiRecord.fields)) {
// because disk file and wiki tiddler is identical, so this file creation is triggered by wiki. // because disk file and wiki tiddler is identical, so this file creation is triggered by wiki.
@ -192,13 +206,18 @@ function FileSystemMonitor() {
// if it already existed in the wiki, this change might 1. due to our last call to `$tw.syncadaptor.wiki.addTiddler`; 2. due to user change in git or VSCode // if it already existed in the wiki, this change might 1. due to our last call to `$tw.syncadaptor.wiki.addTiddler`; 2. due to user change in git or VSCode
// so we have to check whether tiddler in the disk is identical to the one in the wiki, if so, we ignore it in the case 1. // so we have to check whether tiddler in the disk is identical to the one in the wiki, if so, we ignore it in the case 1.
tiddlers tiddlers
.filter(tiddler => { .filter((tiddler) => {
debugLog('updating existed tiddler', tiddler.title); debugLog('updating existed tiddler', tiddler.title);
const { fields: tiddlerInWiki } = $tw.wiki.getTiddler(tiddler.title); const { fields: tiddlerInWiki } = $tw.wiki.getTiddler(tiddler.title);
return !deepEqual(tiddler, tiddlerInWiki); if (deepEqual(tiddler, tiddlerInWiki)) {
debugLog('Ignore update due to change from the Browser', tiddler.title);
return false;
}
debugLog('Saving updated', tiddler.title);
return true;
}) })
// then we update wiki with each newly created tiddler // then we update wiki with each newly created tiddler
.forEach(tiddler => { .forEach((tiddler) => {
$tw.syncadaptor.wiki.addTiddler(tiddler); $tw.syncadaptor.wiki.addTiddler(tiddler);
}); });
} }
@ -243,10 +262,12 @@ function FileSystemMonitor() {
}); });
} }
} }
refreshCanSyncState();
}; };
// use node-watch // use node-watch
const watch = require('./watch'); const watch = require('./watch');
const watcher = watch(watchPathBase, { recursive: true, delay: 200 }, listener); const watcher = watch(watchPathBase, { recursive: true, delay: 200, filter: isNotNonTiddlerFiles }, listener);
} }
FileSystemMonitor(); FileSystemMonitor();

View file

@ -1,4 +1,4 @@
title: $:/config/SyncPollingInterval title: $:/config/SyncPollingInterval
type: text/vnd.tiddlywiki type: text/vnd.tiddlywiki
1000 32140800000

View file

@ -0,0 +1,21 @@
/*\
title: $:/plugins/linonetwo/watch-fs/get-can-sync.js
type: application/javascript
module-type: route
GET /watch-fs-can-sync
\*/
(function () {
exports.method = 'GET';
exports.aaa = 'bbb';
// route should start with something https://github.com/Jermolene/TiddlyWiki5/issues/4807
exports.path = /^\/linonetwo\/watch-fs-can-sync$/;
exports.handler = function handler(request, response, state) {
response.writeHead(200, { 'Content-Type': 'application/json' });
const { canSync } = state.wiki.watchFs;
// DEBUG: console
console.log(`canSync`, canSync);
response.end(JSON.stringify(canSync), 'utf8');
};
})();

View file

@ -0,0 +1,4 @@
creator: LinOnetwo
title: $:/plugins/linonetwo/watch-fs/get-can-sync.js
type: application/javascript
module-type: route

View file

@ -0,0 +1,17 @@
<script type="application/javascript">
const checkCanSyncInterval = 1000; // ms
// after we sync, set this to false
let deSync = false;
setInterval(async function checkCanSync() {
// debounced sync indicator, will be true if there is no change in the disc for several seconds
const canSync = (await fetch('/linonetwo/watch-fs-can-sync').then((response) => response.text())) === 'true';
if (!deSync && !canSync) {
// we have previously synced, and server have changes that is not debounced yet
deSync = true;
}
if (canSync && deSync) {
$tw.syncer.syncFromServer();
deSync = false;
}
}, checkCanSyncInterval);
</script>

View file

@ -0,0 +1,6 @@
created: 20200411065413157
modified: 20200414150804034
creator: LinOnetwo
tags: $:/tags/RawMarkup
title: $:/plugins/linonetwo/copy-on-select/copy-on-select.html
type: text/html