*iroi*

mechairoi の Blog

iOS Safari でキーボード表示時にフッターを固定するもう1つの方法

zenn.dev

エディタを作っていると iOS Safari でキーボードを開いたときの挙動は本当に大変ですよね。 この記事では、キーボードを開いたままスクロールしてもフッターを固定できるようなワークアラウンドを最近見つけたので紹介します。 Safari 16 以降が必要。キーボード開閉時に追従が遅れる挙動は改善しません。

デモは https://mechairoi.github.io/ios-safari-virtual-keyboard/iPhoneiOS Simulator でお試しください。

GitHub - mechairoi/ios-safari-virtual-keyboard

Virtual Keyboard の挙動

Virtual Keyboard を開いたときには以下のようなことが起こっていると推測しています。

  • Visual_Viewport_API で取得できる Visual Viewport のサイズがキーボードを除いた領域のサイズまで小さくなります。
  • レイアウトの計算をするときにはキーボード表示前の Visual Viewport が使われます。vh 単位や fixed, sticky 要素の位置などは表示前と変わりません。
  • スクロールしたときに、キーボード表示前の Visual Viewport のうち画面に表示されている位置が変わることがあり、fixed 要素が動いて見えます。
    • Layout Viewport の上に大小二つの Visual Viewport が重なっていてそこから見ている感じです、ややこしいですね。
  • Layout Viewport の下?に謎の余白が追加されます。下にスクロールし続けると余白が表示されます。
  • キーボードと重なる位置にある入力要素をタップしてキーボードを開いたとき、キーボードに隠れないようにするためかスクロールが発生します。
    • また、キーボードを開いている状態で他の入力要素等にフォーカスが移動したときにもスクロールが発生します。

ワークアラウンド

まず画面全体にスクロール可能な要素を表示します。さらにSafari 16 から使えるようになった overscroll-behavior: contain をすることでスワイプやフリック操作による window のスクロールを防ぎます。window がスクロールしなければ固定した要素が動いて見えることはありません。

#root {
  overflow-y: scroll;
  overscroll-behavior: contain;
  width: 100svw;
  height: 100svh;
}

キーボード開閉時などどうしてもスクロールが発生してしまうタイミングでは JavaScript で計算して要素を移動したりするのはこれまでの方法と変わらないです。

ダイアログなど他の要素を画面に固定したいときは position:sticky を使うか、position:fixedposition:absolute で固定した要素の内側もスクロール可能にしてoverscroll-behavior: contain します。overscroll-behavior: contain しないと固定した要素上でスワイプしたときにwindow がスクロールしてしまいます。また選択範囲のすぐ隣にツールバー出すときはコンテンツに対して固定できれば良いので position:relativeposition:absolute が使えます。

他にも以下のような工夫をしてます。

  • コンテンツが少ないときも overscroll-behavior を効かせるために min-height を指定して微妙にスクロールできるようにします。
  • overscroll-behavior-y:contain があると Safari では pull to refresh できなくなってしまいます。キーボードを閉じているときは pull to refresh できるように overscroll-behavior-y:contain はキーボードが開いている間だけ有効にします。
  • maximum-scale=1ツールバーを非表示機能を使ったタイミングで微妙に拡大されてしまうのを防ぎます。指定していても最近のブラウザではピンチアウトで拡大できると思います…
  • キーボードを開いた時にカーソルがヘッダやフッタの下に隠れてしまうことがあるので調整が必要ですが、少し頑張ればなんとかなるでしょう。

この方法でも実現できるUIに制限があり現実的にはある程度妥協することになりそうです。Safariinteractive-widget=resizes-content に対応してくれるとかなり解決する気がするので、なんとかお願いします。

参考文献

SQLiteでLinderaを使った日本語全文検索

これは はてなエンジニアアドベントカレンダー2023 3日目の記事です。

昨日は id:pokutuna さんの

blog.pokutuna.com

でした。私も若い頃に同僚とGitHub上で白熱してしまい観光名所になってしまっていたような気がします。気を付けていきましょう。


さて、この記事では SQLiteでLinderaを使った日本語全文検索をする話を紹介します。

モチベーション

laiso.hatenablog.com

上の記事でも話題になっているように個人開発ではDBのコストは問題です。同様に全文検索したいときにもコストに頭を悩ませているのではないでしょうか?

たとえば Amazon OpenSearch Service は t2.micro でも東京リージョンでは $20.44 /月/台 から 、冗長化には最低で3台必要です。他にもマネージドなDBで全文検索するにもプラグインや拡張が自由に入れられず日本語の検索に向いたトークナイザが使えなかったりと、安価で楽に運用できる方法はあまりありません。

そこで fly.io の LiteFS Cloud なら10GBまでは $5/月/組織です。fly.io の請求は月 $5未満? *1*2 は $0 になるようなので実質無料(?)*3で冗長構成です 。あとはいい感じに全文検索ができるようになれば解決です。Litestream も良さそうですね。

SQLite のカスタムトークナイザ

SQLite には SQLite FTS5 Extension という全文検索用の Extension があり、これを使うとSQL全文検索できます。

CREATE VIRTUAL TABLE email USING fts5(sender, title, body);
SELECT * FROM email WHERE email MATCH ? ORDER BY bm25(fts);

デフォルトではあまり日本語の検索に向いたトークナイザはありませんがカスタムトークナイザを load して使うことができます。

既存の日本語向けのカスタムトークナイザは手元でうまく動かせなかったりしたので、signalapp/Signal-FTS5-Extension を fork してみました。オリジナルでは Unicode Text Segmentation を使ってますが、日本語を検索したいので lindera-morphology/lindera を使うように書き換えていきます。Lindera は Meilisearch などでも使われている Rust で書かれた形態素解析ライブラリです。動詞の活用や漢数字の正規化もやってくれます。

できたら .load してテーブル作成時にtokenizerを指定して使います

.load "./lib/libsignal_tokenizer" "signal_fts5_tokenizer_init"
CREATE VIRTUAL TABLE email USING fts5(sender, title, body, tokenize="signal_tokenizer");

signalapp/Signal-FTS5-Extension のライセンスは AGPL 3.0 なので忘れず公開しましょう。

https://github.com/mechairoi/Signal-FTS5-Extension

デモ

試しに簡単なWebアプリケーションを書いて、fly.ioの一番小さいマシン(shared 1 cpu, 256MB)にデプロイしてみます。

https://wispy-wildflower-1272.fly.dev/

アクセスが無いときは0台にスケールする設定にしているのでコールドスタートは遅いです。 辞書は lindera-ipadic、データセットは日本語 Wikipedia のサブセット(134万件、335MB) を使っていて、DBのファイルサイズは1021 MBになりました。 アプリケーションのソースコードはこちら

https://github.com/mechairoi/litefs-fts-demo

マッチする記事数が多くなるクエリでは少し遅くなりますが、インクリメンタルサーチでも違和感なく使える速度が出ていると思います。


この記事は はてなエンジニア Advent Calendar 2023 3日目の記事でした。 次は id:mizdra さんです。楽しみですね。

*1:https://community.fly.io/t/questions-on-100-billing-discount/11133

*2:先月はダッシュボードでは $5.06 でしたが 100% Discount でした

*3:無料で使うにはインスタンスのストレージがトータル3GBまで、詳しくは https://fly.io/docs/about/pricing/

ghq/fzf で選んだリポジトリに対応する tmux の session を作ったり探したりするスクリプト

gist41201c4579d17253b7bd26e699c6dccb

  1. リポジトリghq | fzf で選ぶ
  2. リポジトリに対応する session が tmux になければ作る
  3. 対応する session が存在する場合はそれを前面に

といったことを行うスクリプトです。

f:id:mechairoi:20171226225115g:plain

session の current directory がリポジトリのルートに設定されるので、別のシェルを使いたいときは tmux new-window などで新しい端末を開けば cd する必要もありません。 作業リポジトリを切り替えたいときも、このスクリプトを起動して選ぶだけで、以前の session があれば記憶とともに蘇ることでしょう。

gist41201c4579d17253b7bd26e699c6dccb

Wikipedia の作り方 / How to make Wikipedia

こんにちは。アプリケーションエンジニアの id:mechairoi です。
この記事は はてなエンジニアアドベントカレンダー2014 の10日目です。
昨日は id:hatz48 さんの Mackerel と fluentd でサービスの状態を可視化する - Hatena Developer Blog でした。


今日は Wikipedia の作り方について紹介します。

完成イメージ

http://en.wikipedia.org/wiki/Logo_of_Wikipedia#mediaviewer/File:Wikipedia-logo-v2.svg

必要なもの

  • プリンタ、 白の塗料、 セロテープ、 やわらかい鉛筆、 はさみ、のり、お休みの日

作り方

なんとたった7ステップで完成です。

1. くっつける

450mmの半球が届くと想像より大きくてテンションがあがってしまいますが落ち着きます。輪っかにしたセロテープで2つの半球を貼りあわせて球にします。あとで剥がすのでさらっと貼るとよいでしょう。

2. 補助線をひく

くっつけた球にやわらかい鉛筆で補助線をひきます。

f:id:mechairoi:20141210014124j:plain

Wikimedia official marks/About the official Marks - Wikimedia Foundation のいろんな方向からみたWikipediaの様子が参考になります。

f:id:mechairoi:20141210114142j:plain

「W」と「И」の間を通っている線(上図の赤線)が赤道だとすると、南極と北極を結ぶ線を等間隔に10本ひいてから、赤道に平行な線を北半球と南半球に3本づつひきましょう。半球のつなぎ目(上図の青線)と赤道を直交させるとよいでしょう。

やわらかいメジャーやIKEAでもらえる紙の定規があると捗ります。

3. 下書き

スチロールカッターで切断する線を下書きします。

f:id:mechairoi:20141210014128j:plain

ステップ2と同じように Wikimedia official marks/About the official Marks - Wikimedia Foundation をみながら手で雑に書いていきます。ついでにピースに対応する文字も書いておきます。リンク先は各方向から見た様子と展開後とで文字の配置が微妙の異なるので嵌らないように気をつけましょう。

もちろんピースが無いところは自由に想像を膨らませて書きます。

4. スチロールカッターで切る

仮止めしたセロテープを剥がし、スチロールカッターで切ります。

f:id:mechairoi:20141210014132j:plain

一定のペースでカッターを動かすとなめらかに仕上がります。下書きから多少ずれても問題ありません。球の中心から出るレーザーで切るようなイメージでカッターを動かすとやりやすいかもしれません。スチロールの厚みでピースの噛み合わせがうまくいかないところもあるので断面の内側を削って調整します。削り過ぎると安定しなくなるのでほどほどに。半球の境界と重なったピースはセロテープでくっつけます。

ここまでくればパズルを組み立てて遊ぶのもよいでしょう。

f:id:mechairoi:20141210014136j:plain

5. 白く塗る

下書きで汚れたピースの表面を塗料で白く塗って綺麗にします。塗る前にピースの裏に対応する文字を書いておくと後で楽です。

f:id:mechairoi:20141210014140j:plain

6. 文字を入れる

Wikimedia official marks/About the official Marks - Wikimedia Foundation にある文字のSVGInkscape とかで適当に並べて印刷します。印刷した文字をはさみで切ってのりで浮かないように貼ります。文字のまわりに白い部分が残ってもほとんど目立たないのでシュッとやるとよいでしょう。

7. 装う

かぶって仮装パーティに向かうもよし、分解してコンパクトなまま持ち込んで現地で組み立てるもよしです。お気に入りのTシャツとコーディネートするのもオススメです。

f:id:mechairoi:20141031105523j:plain

おわりに

はてなでは、パーティを一緒に盛り上げてくれる方やScalaエンジニアも募集しています。

Wikipedia への寄付もお願いします。

Ways to Give - Wikimedia Foundation

明日は id:shimobayashi さんの予定です。よろしくお願いします!

追記

Wikipedia の作り方 - *iroi*

塗装の塗料なにつかったんだろう。ポスカ?

2014/12/10 13:40

最初は

のマット ホワイトつや消しでやってたんですが、量が足りなかったので2年前に使った

の残りを使いました!

emacs から git-browse-remote で GitHub をいい感じにひらく

カーソル位置とかリージョンで選んだ範囲をブラウザで開けるやつです。
C-u つけると --rev になるのがおしゃれポイントです。
以上です。

参考


git-browse-remote 0.1.0 を公開しました & Vim からいい感じに GitHub を開く - 詩と創作・思索のひろば (Poetry, Writing and Contemplation)

emacs


GitHubでの仕事を快適にするコマンドを紹介します - $shibayu36->blog;

と同じような機能です。

Scala use cases at Hatena という発表をしました。#ScalaMatsuri

はてなで最近作っているMackerel


Calling for Beta Testers! Mackerel: A Revolutionary New Kind of Application Performance Management

の開発には Scala を使ってます。
発表では Mackerel で使ってるライブラリとか開発フローとかPerlから変わったこととか紹介しました。
Scala 関係ない話でも大丈夫ですので、まだ会場にいる方はぜひ声をかけてください!


Perl に戻れないとか書いてますが 個人の意見ですのでよろしくおねがいします。