ATProtocolのRustライブラリを作っている 活動の続きとして、ライブラリの動作確認も兼ねてDesktop Applicationを作ってみることにした。
Tauri
RustでDesktop Application作成、といえば今もっとも普及しているのがTauriだろう。
ステータスとしてはMobile Application対応を含む v2のリリースに向けてBeta versionが公開されている、という状態のようだ。
Tarium
で、AT ProtocolのためのRustライブラリである ATrium をバックエンドで使ったTauri製のBluesky Client、ということで「Tarium」という名前にした。
Frontend
フロントエンドは各プラットフォームでのWebView上で動くわけで、結局HTMLやJavaScriptで用意することになる。 気合いでFull Rustで実装しようとすれば Yew などで構築することもできるようだったが、自分はまだ使ったことがなく学習が大変そうだったので、結局 Vite + React でTypeScriptで書くことにした。あとは React Router と Tailwind。
Backend
普通にWeb Applicationが作れるので、Bluesky Clientとしてはatproto
公式のTypeScriptライブラリを使ってフロントエンドで完結するものも作れてしまう。
しかし自分の目的としては ATrium
の動作確認なので、意地でもAT Protocolの処理はバックエンドにやらせることにしている。
結局バックエンドは command
を介してフロントエンドからのXRPC Requestをproxyするだけ、になってしまいがちで 何のためにRustバックエンドが存在しているんだ… という感じにはなってしまうけど。
一応役割としては内部のStateとしてAtpAgent
を持ってSession管理などをしている、くらい。単にproxyするだけだと悔しいので、feedの取得などはバックグラウンドタスクで定期的に実行して新しく表示すべきものをEventのemit
によってフロントエンドに通知する、という方式にしている。まぁそれもフロントエンドでsetInterval
で実装するのとたいして変わらないんだろうけど…。
今のところPWAと比較して「Native Appならでは」というのはあまり無く、ようやくデスクトップ通知ができるようになった、くらいか? 今後はもしかしたらショートカットキーを使った操作などが実装できるとNativeならでは感がでるかもしれない。
型定義生成
ということで結局は書くコードの大半はTypeScriptになる。 そしてデータはバックエンドから取得するが IPC を介して結局JSONでやりとりすることになるので、Lexiconに沿った型にmappingさせて表示に使うにはどうしても型定義が必要になる。
最新のLexiconから対応する型定義などを生成したものが @atproto/api
パッケージなどに含まれていて、公式appや他の多くのWeb Clientなどではこれを使っているはず。
Tariumのフロントエンドでもこれを素直に使えば良いが、この api
パッケージにはXRPCのためのClient機能なども含まれていて、折角バックエンドでXRPC処理するようにしているのに本末転倒、というか「負けた」感じになってしまう…。
なので、意地でも @atproto/api
は使わずに必要な型定義だけを得たい!ということで この api
のためのコードを生成している @atproto/lex-cli
をハックして必要なものだけを生成して使う、ということをした。
https://github.com/sugyan/tarium/tree/main/gen-types
現在の状況
v0.0.8
で、FollowingのタイムラインとCustom Feeds、あと通知がようやく表示できるようになって あとはテキストのみの単純な投稿ならできる、というくらい。まだまだ足りない機能だらけではあるが ちょっとずつ使えるようになってきている、とは思う。
自分が満足いくところまでは頑張って機能実装していくつもり。
実際、ここまで実装する過程でATriumがgetPreferences
を正しく取得できないバグに気付いたりできたので、当初の目的としては正しく達成できている。