zeroconf-watch
結論
Scrapboxに通知機能は不要。
思考に集中できなくなる。
好きなScrapboxプロジェクトは手動で巡回してるでしょう。
ユーザーにパラメーター弄りをさせず、開発者の責務でいい感じの通知機能を作れないか?
ページ単位ではなくセクション単位であれば、通知の精度が高いのではないか。
Scrapboxページには、目に見えないセクションの区切りがある。
インデントを使う?
だいたい返信をするときはインデントを使うでしょう。
そうですね。(このように)
インデントが深くなっていくのではないか。
メールのRe:Re:Re...のように。
これは大変だから、いいところでインデントをリセットしますね。(これは通知が飛ぶ)
リセットしました。(これは通知が飛ばない)
「ToではなくCCを使え」とか「@付けてメンション飛ばせ」とか。
「FF外から失礼します」とか「巻き込みするな」とか。
こんなことにならない仕組みは作れるのだろうか……
もしも通知地獄になる場合
通知は大事です
私はきらい
そんなことが
そんなってなんのこと?
通知地獄のことです。
地獄と言う表現はどうなの。
……
通知機能以前に不健全な感じ。
通知機能は難しい。
とりあえず実験してみるか。
TODO
ページごとにcheckedDateを記録する?
意外と現実的にlocalStorageで収まるサイズかも。
たくさんタブを開こうとするとChromeにブロックされる。
安全仕様ではあるが、その分の通知は消えてしまう。
index.js export const runZeroconfWatch = async () => {
const nowUNIXTime = Math.floor(new Date().getTime() / 1000);
const projectName = scrapbox.Project.name;
const userResponse = await fetch("/api/users/me");
const user = await userResponse.json();
const checkedKey = `zeroconf-watch-checked-${user.name}-${projectName}`;
const checkedUNIXTime = Number(
localStorage.getItem(checkedKey) ?? String(nowUNIXTime)
);
const pagesResponse = await fetch(`/api/pages/${projectName}?limit=1000`);
const pages = await pagesResponse.json();
const streamResponse = await fetch(`/api/stream/${projectName}`);
const stream = await streamResponse.json();
[...new Set(stream.pages.flatMap((page) => {
const pageSummary = pages.pages.find((pageSummary) => pageSummary.id === page.id);
const scopes = [
page.title,
...pageSummary?.descriptions ?? []
].join("\n").includes(user.name)
? [{ indentDepth: -1 }]
: [];
return page.lines.flatMap((line) => {
const { userId } = line;
const indentDepth = [...line.text.match(/^(\s*)/)[1]].length;
if (scopes.length >= 1) {
const currentScope = scopes[scopes.length - 1];
if (
currentScope.indentDepth - (currentScope.userId === userId ? 1 : 0) >= indentDepth
) {
scopes.pop();
}
}
if (line.text.includes(user.name)) {
scopes.push({
id: line.id,
indentDepth,
userId
});
}
if (scopes.length < 1 || line.updated < checkedUNIXTime || userId === user.id) {
return [];
}
const { id } = scopes[scopes.length - 1];
return [ `/${projectName}/${encodeURIComponent(page.title)}${id ? `#${id}` : ''}` ];
});
}))].forEach((url) => open(url));
localStorage.setItem(checkedKey, String(nowUNIXTime));
};