generated at
zeroconf-watch
結論hata6502
Scrapboxに通知機能は不要。
思考に集中できなくなる。
好きなScrapboxプロジェクトは手動で巡回してるでしょう。


scrapbox-lazy-watchとは異なるアプローチで通知機能を作る。
ユーザーにパラメーター弄りをさせず、開発者の責務でいい感じの通知機能を作れないか?


ページ単位ではなくセクション単位であれば、通知の精度が高いのではないか。
Scrapboxページには、目に見えないセクションの区切りがある。
しかし、/villagepump/豆知識のようなページで通知地獄になりそうだ。

インデントを使う?
だいたい返信をするときはインデントを使うでしょう。
そうですね。(このように)
インデントが深くなっていくのではないか。
メールのRe:Re:Re...のように。
これは大変だから、いいところでインデントをリセットしますね。(これは通知が飛ぶ)
リセットしました。(これは通知が飛ばない)

通知は各自が作るべきではないか、他の人にコミュニケーションの負担をさせない仕組みは必要だ。
「ToではなくCCを使え」とか「@付けてメンション飛ばせ」とか。
「FF外から失礼します」とか「巻き込みするな」とか。
こんなことにならない仕組みは作れるのだろうか……

もしも通知地獄になる場合hata6502
通知は大事です
私はきらい
そんなことが
そんなってなんのこと?
通知地獄のことです。
地獄と言う表現はどうなの。
……
通知機能以前に不健全な感じ。


通知機能は難しい。
世の中のあらゆる俗に結びついて、頭おかしくなりそう。ムギーー!!hata6502hata6502hata6502

難しい機能だから、UserScriptで個人的に実験するのが楽しいのか。
とりあえず実験してみるか。


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)); };