ディスプレイを新調したらWhalebirdに満足できなくなったので新しくFediverseクライアントを作っている

この記事はFediverse (2) Advent Calendar 2022の7日目です.

最近34インチのウルトラワイドディスプレイを買ったんだけど,これによって俺の作業スペースは格段に広がった.Emacsは常時3分割or4分割だし,1ワークスペースにブラウザとターミナルを表示するのは普通.むしろ1アプリで1ワークスペースを専有させるものはほとんどなくなった.と同時に,Whalebirdの情報密度をもっと濃くしたくなった.

Whalebirdは当初からシングルカラムのMastodonクライアントだ.ただし最近はいくつか不満な点があって,

  1. 画面幅が3440x1440なので画面に対して表示される情報量が少ない
  2. 他のサーバや他のTLを開くときにいちいち読み込みが走るのが面倒
  3. (これは日本人だけかもしれんが)そもそもみんなそんなに長いポスト,してないんだわ.みんな「ゆれ」とかしか投稿しないのに,この横幅いらなくね?

というわけでマルチカラムのクライアントが欲しくなった.

Whalebirdをマルチカラム化することも考えたが,

  1. 現状のコードベースをきれいにしたいところがかなりある
  2. Vue.jsをもうあまり書きたくない
  3. そもそもマルチカラムに耐えうる設計じゃない

と思ったので新しく作ることになった.

はい,こんな感じです.

リポジトリはこれ.

github.com

機能面でいうと,

  1. 認証せずにサーバを追加できる.この場合見られるTLはpublicとlocalのみで,リアクションもできない.が,TLを覗くだけということができるようになる
  2. 投稿するアカウントを選択できる.ただしリプライ時にここをどうするかは検討中
  3. Mastodon/Pleromaには対応済み.Misskeyどうするかね?
  4. あとは普通のマルチカラムクライアントの機能……はまだ全然足りてないが

今後実装したいもので,優先度の高いものはissueにしているが

github.com

ここに書いていないものだと

  • RT, fav等のリアクション時に,どのアカウントで行うかを選択できるようにしたい……?できるのか?
  • 通知件数をmarkerから読むようにしたら未読件数を表示できる……?かなぁ?
  • サーバ/アカウントごとの通知に一発で飛べるようにしたい
  • アイコンほしい

WhalebirdはElectronで作っていたが,実はこいつはtauriで動いている.だからたぶんWhalebirdより軽いんじゃないかな,計測してないけど.メインプロセスはそりゃー軽いだろうが,レンダリング部分は正直何をレンダリングしているか(=TLに今何が表示されているか)に強く依存するので,何を比較したらいいのかよくわからん.同じTLを表示するだけならtauriのほうが軽いんじゃないかね.ただ,そもそもシングルカラムとマルチカラムでは同時に表示されるTLの数も違うので,比較するのに意味があるのかわからん.原理的にはfedistarのほうが重くなるはず(今の所TLの数を無限に増やせるので).

で,tauriはメインプロセスをRustで動かすわけだが,このためにmegalodon(Whalebirdのために作ったMastodon/Pleroma/Misskeyのクライアントライブラリ)をRust対応させた.これだけでひと月くらい費やしたけど.

github.com

メインプロセスでFediverse APIを叩くかどうかという疑問もあるのだが,俺は叩くことにした.というか,WebSocketのストリーミングをフロントエンドで維持するのかメインプロセスで維持するのか,どちらが良いか考えた末にメインプロセスでやらせることにした.おそらく多少はこのほうが軽くなるはず. もちろんフロントエンド側でFediverse APIを叩く部分は従来どおりmegalodonを使っている.同じライブラリなのでEntityは互換性をもたせている.そのためバックエンド - フロントエンド間でEntityのやりとりをするときも,そのままEntityを送りつけることができる.

フロントエンドはNext.jsにしている.Reactにしたのは,Vue.jsを書きたくないというのもあるし,周辺ライブラリやエコシステムが豊富だというのもある. 例えばこういうクライアントを作る上で考慮するのはバーチャルスクロールなのだが,SNSのタイムラインを構成するバーチャルスクロールというのはかなり複雑である.

特に上方向にスクロールしてステータスが積み上がるタイプのもの(Slackみたいなやつね)はかなり難しい.巷のinfinity scrollはだいたい下方向にスクロールする(これがデフォルトの挙動).この場合,ある程度下まで来たら追加読み込みをしてエンティティをリストの末尾に追加するだけで良い.ブラウザはエンティティが更新された場合,scrollTopを維持した状態でリストを更新する. しかし,この挙動は逆向きスクロールのときに非常に困る.上方向にスクロールしてエンティティが積み上がるということは,リストの末尾ではなく先頭にエンティティが追加される.となるとscrollTopを維持したままリストを更新したら,見ているエンティティが一気に入れ替わることになる.Slackを想像してもらえればわかりやすいが,これは許容できない.というわけで,上方向にエンティティが積み上がるときにscrollTopを維持せずに,というかスクロール位置を変えずにリストを更新する必要がある. こんなことができるライブラリはVue.jsには存在しない.

しかしReactであればいくつか選択肢があり,

tmegos.hatenablog.jp

この中から用途にあった開発が活発そうなものを選べる. これに限らず様々なライブラリでVueよりReactの方が選択肢が豊富だ.

その上Vue3になってから,そこまでReactに対してメリットがあるような記述でもなくなってしまった.結局hooksを使うReactの二番煎じみたいな状態になっており,これならReactを使うほうが良い.

ちなみにまだバージョンは0.2である.つまり安定版ではない,そんなものは存在しないのである. 少なくとも1.0にならなきゃMac App Storeには出せないわけで,そのくらいのバージョンになったら安定版だと考えてほしい.それまでは思う存分破壊的変更を入れるので,怖いものが見たい人だけがダウンロードしてくれ.そういう意味も込めて,基本的にはgithub releasesでしかバイナリを配布していない.snapcraftとかhomebrewとかMac App Storeとか,そういう「いかにも使ってください」みたいなところにはまだ出していないし,1.0が見えるまでは出すつもりはない. ただし,AURにはすでにある.Arch Linuxユーザなら,多少ぶっ壊れたソフトウェアとか,互換性がまったくないバージョンアップとか配布しても,許してくれるかなというイメージを勝手に持っているので出している.壊れたら消して入れ直してくれ. そしてリリースのchangelogはちゃんと読んでからインストールしてくれ.破壊的変更が入るときにアナウンスは書いているので.

あと,まだ0.2なので足らない機能が盛りだくさんである.そもそも0.1.0リリース時点では,TLが見られるだけで投稿が一切できなかった.今でも上記の通りリプライはできない.アカウント選択をどうするかが悩み中なのでそれが決まり次第ということになる.そういうのは順々に追加していくんで…….

ちなみにバグレーポートはほとんど募集していない.というか,なにか不都合があったとして,それはバグじゃない,未実装なだけだ.ありとあらゆるものは未実装であり,バグっているわけではない.なのでPullRequestは随時募集しております.

Q&A

The DeskとかSengiじゃだめだったの?

俺は俺の作るクライアントでFediverseをやりたいのでだめです.Fediverseがやりたいっていうかむしろクライアントが作りたいんだよ.Twitterはクライアント作らせてくれないし,そういうところが嫌で家出したのだから,Fediverseにきたら自分でクライアントを作りたいんだよ.

とはいえ差別化とかないの?

知らん. ビジネスなら差別化しないとシェアが奪えなくて売上が上がらないかもしれんが,これは無料だ.俺の趣味だ.シェアなんかどうでもいい.差別化なんぞ知るか.俺の好きな機能を好きなように実装させろ.

Whalebirdどうするの?

最初は置き換えることも考えたが,シングルカラムクライアントの需要がある限りは続けます.まぁ更新頻度が下がることはあり得る. ただ,マルチカラムをfedistarで実現できそうなので,Whalebirdはもう少しシンプルにしたいとは思っている.まず,最初に書いたアカウントやTL切替時のローディングはもっと短くできると思っているので,もっとスムーズに切り替えられるようにしたい.その他,結構言われるがまま実装したものもあるなーと思っていて,機能を削りたいとは思っている.

いつ安定版になるの?

わからん. PRを送ってくれると多少その時期が早くなるかもしれない.

Android版とかiOS版とか?

ない. 作る予定もない.というかモバイルでマルチカラムはいらんだろ…….別で開発したほうがいい.

そういえばアイコンもまだない

アイコンをどうしようか考え中なんだけど,俺にはアイコンを描く技術はない.ので誰かに頼まないといけないのだが,あんまりデザイナーの友達もいないので,もし描いてもいいよって方がいたら連絡ください.お金は払います.

@h3poteto@pleroma.io

大事なことなのでもう一度書くと,お金は払います

会社のPCにManjaro i3 Editionを入れた

何度目かわからないLinux環境構築記事です.ちなみに

h3poteto.hatenablog.com

h3poteto.hatenablog.com

このような前例があり,今回もこれらの記事には非常に助けられた.

買ったPC

転職先の会社で好きなPCを選んで良いことになったので,Linuxを入れる前提で「ThinkPad X1 Extreme Gen5」を買った.

本当はFramework を狙っていたんだけど,日本に配送してくれそうな情報が見当たらずに諦めた.System76 も割と良さそうで,こちらは日本配送できるのだが,スペックを上げるとキーボードにテンキーが付属するのが我慢できなかった.ノートPCのキーボードにテンキーは不要だ.

どうせリモートだし,ノートPCを持ち歩くシチュエーションもほとんどない気がしたのでMinisforumあたりも考えたのだが,これについては覚悟が足らなかった.

というわけでThinkPadである.

Manjaro i3 Edition

まずBIOSの設定からSecure Bootを無効化しておく.ちなみにArch LinuxはSecure Bootに対応しているらしいが,Manjaroは今の所対応する予定はない.

forum.manjaro.org

今回は最初からcommunityメンテナンスのi3 editionをダウンロードしてきた.

https://manjaro.org/download/

そしてWindowsを削除して上からManjaroを入れる.Windows11が入っていたらしいがセットアップせずにフォーマットしてManjaroをインストールする.

自分でi3を入れると,かなり簡素なデスクトップが表示され,それをカスタマイズしていく形になるのだが,このi3 editionはそれなりに整った見た目が最初から用意されていた.まぁそれらを削除して全部自分の設定を入れるわけだが.

ちなみにインストールで迷うのは,ハードウェアのドライバを,OSSにするかProprietaryにするかだろう.今回は最初からProprietaryにした.どうせnvidiaドライバを使うのは確定なわけだしnouveauを入れるだけ無駄だ.

GPUの設定

まず,BIOSでグラフィックボードの設定をいじる.デスクトップだとあまり出会わないのだが,ノートPCだとIntelの内蔵GPUと,GeForce両方積んでいるパターンがある.この場合,ハイブリット設定になっている場合があり,これがややこしいのでGeForceのみを使うようにハイブリット設定をオフにしておく.

その上で,

$ sudo mhwd -a pci nonfree 0300

をやる.mhwdが入っていれば,あとはいい感じにnvidiaのドライバセットアップまでやってくれるので楽だ.

$ lspci -k | grep -A 2 -E "(VGA|3D)"
01:00.0 VGA compatible controller: NVIDIA Corporation GA107M [GeForce RTX 3050 Ti Mobile] (rev a1)
        Subsystem: Lenovo Device 22f8
        Kernel driver in use: nvidia

こうなれば良い.

IME

最近はibusをやめてfcitxを使っていたので,fcitxを入れる.ただ,ここでfcitx-mozcを入れてさらにemacs-mozcを入れようとするとドツボにはまった.

ain0204.hatenablog.com

ここに書かれているとおりなのだが,fcitx-mozcとmozcはコンフリクトする.依存関係としてはemacs-mozc -(depend)-> mozc <-(conflict)-> fcitx-mozc という状態になっている.で,巷の記事ではPKGBUILDを修正して

## If you will be using mozc.el on Emacs, uncomment below.
_emacs_mozc="yes"

ビルドすれば良いよという記事は多いし,過去の俺もそのようなことを書いていた.

h3poteto.hatenablog.com

が,最新のemacs-mozcはbazelでビルドされるようになっており,PKBGUILDにこのような変数は存在しない.

というわけで,今の所この2つをコンフリクトせずに入れる方法が謎のままである.

さらに,最近fcitxはWayland対応でfcitx5という新しいバージョンを出している.これは別パッケージになっているので,インストールするのは

$ yay -S fcitx5 fcitx5-im fcitx5-mozc

である.

で,emacs-mozcであるが,入れないことにした.

というかfcitxは

export GTK_IM_MODULE=fcitx
export QT_IM_MODULE=fcitx
export XMODIFIERS=@im=fcitx

こうしておくと普通にemacsでもfcitxのままmozcが使える.なのでわざわざemacs-mozcを入れる必要がない気がして,やめた.

オーディオ関連の設定

ノートPCだと音量調節用のキーが設定されていたりするので,i3の設定に

bindsym XF86AudioRaiseVolume exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ 0 && pactl set-sink-volume @DEFAULT_SINK@ +5% && $refresh_i3status
bindsym XF86AudioLowerVolume exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ 0 && pactl set-sink-volume @DEFAULT_SINK@ -5% && $refresh_i3status
bindsym XF86AudioMute exec --no-startup-id pactl set-sink-mute @DEFAULT_SINK@ toggle && $refresh_i3status

こいうのを追加しておくとそれらのキーが使えるようになる.

pactlは

$ yay -S pulseaudio pavucontrol

として入れておく.

ディスプレイ関連の設定

同じく内蔵ディスプレイの明るさ調節ができるボタンがあったりするので,

bindsym XF86MonBrightnessUp exec xbacklight -inc 10
bindsym XF86MonBrightnessDown exec xbacklight -dec 10

としておく.

xorg-server関連でxbacklightコマンドは入っていると思うが,ない場合は

$ yay -S xorg-xbacklight

しておく.

その他

  • i3のステータスバーはpolybar
  • ファイラーはnemo
  • ターミナルはurxvt
  • ランチャーはulauncher
  • クリップボードはparcellite
  • 通知はdeadd-notification-center

こんな感じ.

Macにも一応yabaiのようなタイル型ウィンドウマネージャーを模したものはあるんだけど,やはりi3wmの使用感には敵わない.

Z Labを退職してoViceに転職します

10月31日にZ Lab株式会社を退職した.

おそらくほとんどの人はZ Labを知らないと思うので説明すると,ヤフーの子会社だ.ただし社員はヤフーの原籍正社員でZ Labに出向という形で雇用されている.つまり退職したのはヤフー株式会社を退職したということになる. ちなみに私の場合は,入社した時点でZ Lab出向だったので,ヤフー社で働いていたことはない.ヤフーのこと,あんまり知らない.

2020年9月入社だったので,2年2ヶ月居たことになる.

続きを読む

flycheckでcredoを実行する

credoというのがある.

github.com

これはElixirの静的解析ツールで,まぁrubocopみたいなものだと思っていただければ良い.これは単なるCLIなのだが,これに違反した場合,違反箇所をエディタ上に表示してほしいと思った.

そこでflycheck-credoというのがある.

github.com

これでcredoを実行して結果をflycheckに連携してくれるので,Emacs上でそれを見ることができるのだ.

しかし,lsp-modeを有効化しているとこれがうまいこと動作しない.実はlsp側が内部でflycheckを実行し,この結果を表示してくれているのだが,flycheck-credoの結果はこのlsp内部から実行されるflycheckにより結果が上書きされてしまう. その結果credoとしてのエラーがflycheckに表示されなくなっている. 試しに一度lsp-modeを無効化した上で,flycheck-credoを入れてみて欲しい.ちゃんと動作するから.

ただ現代においてlspを無効化するのはあまり現実的ではないので,なんとかこの2つに共存していただきたい.

というわけで,

(use-package elixir-mode
  :config
  (add-hook 'elixir-mode-hook
            (lambda ()
              (setq lsp-flycheck-live-reporting nil)
              (setq-local flycheck-check-syntax-automatically '(mode-enabled save))))
  (add-hook 'lsp-after-initialize-hook
            (lambda ()
              (flycheck-add-next-checker 'lsp 'elixir-credo)))

とやることで,これらを同居できる.

まず flycheck-add-next-checkerだが,これをやることで2つのcheckerを併用できる. その上で,lsp-flycheck-live-reporting を無効化することで,elixir-credoの結果が上書きされるのを防いでいる.

Refs: elixirforum.com

Siderが終わるのでlintをreviewdogに移した

このとおりですが,

siderlabs.com

siderがサービス終了するらしいです.

今まで個人プロジェクトでも,会社のプロジェクトでも結構お世話になってきました.使い始めた頃は,まだSideCIという名前で,会社名もアクトキャットという名前だった気がしますが,感慨深い.

とりあえず使えなくなるので,移行します.

続きを読む