ScrapBubble
takker.iconが作ってるやつ
https://gyazo.com/d81a7a2fa6fa793a3990031cf075d6a8
リンクを吹き出し表示する + リンクホバーでページの内容を表示する、を組み合わせたもの
表示されているページのリンクをホバーでさらに先のページまで見れる
しかも他プロジェクトのリンクにも飛べる
0.2.0では飛べるプロジェクトをホワイトリスト方式で制限しましたtakker.icon
-.icon
Reactの概要を理解したので、改めてコード読んだ上で最新版を導入しようかな
理解した上で導入しておきたい
ちなみにReactとは型定義が若干異なりますtakker.icon
ReactではなくPreactを使っている
型定義以外はほぼ一緒です
思ったよりでかかったw
directoryで階層構造を作るのをやめたらこうなったtakker.icon
だいたい1ファイル1関数で書いているので、ファイルサイズはそんなに大きくないはずです
なるほどblu3mo.icon
そもそもScrapboxのhoverとかのイベントをどう拾ってるんだ?
handlePointerEnterで呼ばれるコードが見つからない
usePromiseSettledAnytimesが理解できないな
あ〜、わかったかも
waitPointerEnterはPromiseを返す
そのPromiseをresolveさせる関数は、usePromiseSettledAnytimesのresstateが持つ
その上で、そのresstateはhandlePointerEnterに代入される
だから、
handlePointerEnterを呼ぶ
-> waitPointerEnterというPromiseがresolveされる
-> await waitPointerEnterで止められてた処理が再開する
ってことか
そんでもって、waitPointerEnterでせきとめられるループがずっと回っていると
なぜevent = await waitPointerEnter();ができる?
handlePointerEnterの引数にeventを持たせておけば、Promise.resolve(event)ということになる
Promise.resolveの引数はconst x = await Promise()で代入できる
なるほど〜〜blu3mo.icon
仕組みは理解blu3mo.icon
不思議な実装だな
ループのせき止めを解除する形でEventに反応するのはなぜ?
Promiseを挟むのはなぜ?
今回このような実装をするメリットはほとんど有りませんtakker.icon
一応一点だけ利点っぽいものがあります
ループが一度に一つしか実行されない
event = await waitPointerEnter();以降のループを処理している間にきたpointerenterは全て無視される
普通にaddEventListener("pointerenter", async (e) => {/*...*/})としてしまうと、以前のcallbackが実行し終わる前に次のcallbackが実行し始めるかもしれない
ただこのprogramでこんな保証を取る必要があるかというと疑問だったりする……
なるほど🙏blu3mo.icon
このあたりを参照takker.icon
-.icon
ReactみたいなのをUserScriptで動かしているという理解でいいのかな ですですtakker.icon
軽量版ReactのPreactをUserScriptにぶちこんでいます 無印のScrapBubbleの方は、この辺も自力で実装してて辛かった
Scrapboxの各要素(コードブロックとかGyazo表示とか動画表示とか)を全部自力で再実装している..?
自力ですねtakker.icon
JSXっぽいやつで簡単にUIを構築できるのでそんなに難しいことじゃないです
CSSの調節がちょっと面倒かも
それ以前に混入してたら……どうしようもない
なるほど!!blu3mo.icon
(至れり尽くせり、すごい)
今の所特にスマホ/iPadで使いたいとは感じていないので、TamperMonkeyでメインPCに導入した
どんなプロジェクトでも動くように改変した(自分のプロジェクト除外判定を省いた)