チャットは Korat の他のすべてが寄りかかっている部分です。友だちが自分のテーブルに呼べば、招待はチャットのカードとして届きます。誰かが投稿を共有すれば、開けるカードになって落ちてきます。出会い機能で互いに「いいね」した瞬間、それは本物の会話になります。メッセージの着地点が一つだから、見る場所も一つで済む。そしてメッセージ機能は一つのことだけをきちんとやればよくなります——二人のあいだの一本のスレッドを、他のアプリに行かなくて済むだけの添付の種類とともに。
二人、一本のスレッド
Korat のチャットは1対1のみです。ダイレクトなスレッドに入れるのはちょうど二人で、三人目を加える方法はありません。三人以上の会話は別の二か所で起き、そのどちらもこのメッセンジャーではありません。ひとつはグループの投稿です。グループの投稿はグループ ID を持った普通の投稿なので、フィードのコメント・@メンション・通知の仕組みをそのまま受け継ぎ、返信がぶら下がり、検索でき、残ります。もうひとつは、グループとスポーツクラブが持てるサブルームです。グループの中に並ぶ Discord 風のテキストチャンネルで、独自のテーブルと独自の権限の上に建っており、ダイレクトなスレッドよりできることはかなり少なくなります。その限界は下にすべて書いてあります。チャットに見えてチャットではない部屋は、部屋がないことより悪いからです。
1対1が引き換えに得たのは深さです。特定のメッセージを引用して返信する、送信後に編集する、送信を取り消す、大事な一通をスレッドの先頭に固定する。よく使う6つの絵文字で素早く反応することも、30個の絵文字バーを開くこともできます。入力中の表示と既読の状態は、想像どおりに動きます。
一通のメッセージに入れられるもの
テキストのほかに、画像、任意のファイル、そして音声メッセージ——端末の MediaRecorder で M4A コンテナの AAC として録音し、吹き出しの中で再生します。位置情報も送れます。加えて、アプリの他の部分が発行するシステムカードがあります。共有された投稿、飲食店のテーブルへの招待、そして一度かかった通話の記録です。
新しいメッセージは相手の端末にプッシュ通知を出します——1対1のメッセージも店の受信箱も同じです。届くのは失効していない端末だけで、その部屋を開けばその部屋の通知は消えます。メッセージを生み出しているのに誰にも知らされないチャットは、静かなのではなく壊れています。並べて言っておくべき制約は、ウェブ版にプッシュはないことです。ブラウザで話しているなら、メッセージはタブを開いたときに見え、届いたときには見えません。
通話記録のカードは、聞こえるより重要です。鳴って出られなかった通話は、そのままでは見えません——あとでアプリを開いても、何かが起きたことを伝えるものが何もない。通話をスレッドに書き込めば、ある関係の履歴はスクロールできる一本のリストになります。会話がこちら、通話履歴があちら、ではなく。
通話は、両方が扉を開けてから
音声・ビデオ通話はアプリ内のマネージャー経由で本物の WebRTC 上を走ります。ミュート、カメラオフ、カメラ切り替え、全画面の着信画面、バックグラウンド時の着信通知。特徴的なのはその手前にある関門です。通話の許可は双方向で、会話ごとに独立しています。 一本のスレッドでは、二人がそれぞれ自分の側の鍵を開けるまで通話ボタンが現れません。それまでは、どちらからも鳴らせません。
これは「鳴らすことはアプリにできる最も侵入的な行為だ」という事実への正面からの答えです。出会い機能や店舗ページであなたを見つけた見知らぬ相手は、無視できるメッセージを送ることはできます。しかし、あなたが明確に同意しないかぎり、午前2時にあなたの電話を鳴らすことはできません。許可は会話ごとなので、一人に開けたことは他の誰にも影響しません。しかも、設定の奥に埋もれたスイッチではなく、自分で開ける鍵です。
二つの正直な限界。 ダイレクトメッセージは1対1のみです——スレッドをグループに変えることはできず、このページで説明しているメッセンジャーに複数人版はありません。実在するのはグループとクラブが持つサブルームで、これは別のテーブルの上に建つ、より薄い仕組みです。送信と自分の投稿の削除ができるプレーンテキストだけで、メッセージの編集も、特定のメッセージへの返信も、リアクションも、写真・ファイル・音声メッセージの添付も、通話もできません。このページのどこも、サブルームの説明として読まれるべきではありません。
通話はエンドツーエンド暗号化されておらず、TURN サーバーもありません。 双方のネットワークが直接届く場合はメディアが P2P で流れますが、中継サーバーがないため、携帯キャリアと厳しい NAT のある組み合わせでは接続できません。通話がつながらないときの原因はたいていこれで、アプリのバグではなく、まだ立てていないインフラです。
オンライン表示は心拍であって、常時接続ではありません
Korat の緑の点は、具体的に一つのことだけを意味します。その人のクライアントが過去90秒以内に last_seen のタイムスタンプを書いた、ということです。持続的な接続ではなく一定間隔のポーリングなので、電池には優しく、そのぶん粗い。40秒前にアプリを閉じた人はまだオンラインに見えますし、トンネルに入った人はどこへも行かないうちに暗くなります。
これを「オンライン」ではなく心拍と呼ぶのは、オンライン表示がもっとも証拠として読まれやすいからです——メッセージを読んだ証拠、わざと返さない証拠。90秒のポーリング窓は、その重さを支えられません。
目当ての会話を見つける
長いチャットリストを使える状態に保っているのは二つの機能です。一つめはチャット別名。どの会話でも、自分が実際にその人を呼んでいる名前に変えられて、その名前は自分にしか見えません。フィードにもグループにもコメントにも相手のプロフィールにも漏れません。あなたが「大家さん」で保存した相手は、どこでも本人が書いた表示名のままです。Korat の他の場所の名前はプロフィールから都度解決されます。一箇所での改名が別の場所とずれないようにするためです。
二つめはラベル。自分で作る色付きのタグで、所属も作成・編集・削除もすべて自分の手にあり、そのままチャットリストのフィルターとして働きます。隣には未読・公式アカウント・出会い由来という組み込みのフィルターが並びます。検索は会話名と最後のメッセージの両方にかかるので、うろ覚えの一文で十分にたどり着けます。会話は上部に固定、既読にする、削除ができます。
サーバーから何が見えるのか、相手に対して何ができるのか
メッセージはサーバー側に平文で保存され、行レベルセキュリティのポリシーが一つの会話の行をその二人の参加者に限定しています。Korat のチャット・通話・ファイルにエンドツーエンド暗号化はなく、マネージドデータベースが備えるもの以外にアプリケーション層の保存時暗号化もありません。話す内容にそれが必要なら、そのために作られた道具を使ってください——安心させる一言よりも、脅威モデルを正確に書くほうがあなたの役に立ちます。
人の側については、スレッドからでもプロフィールからでもブロックでき、相手のチャットと投稿が隠れ、同時に出会い機能のデッキからも消えます。通報もできます。ブロックは一度の操作でアプリのすべての面に効き、画面ごとに繰り返す必要はありません。
スレッドに届くカードにはそれぞれ出どころがあります。友人に呼ばれた席は飲食の同じ卓であり、流れてきた投稿はフィードのその一件です。
お客さまからお店へのメッセージも同じ仕組みで届きますが、店側が読むのはビジネスコンソールの受信箱です。デジタル名刺を読み取ったあとにそのまま話しかける先も、ここに戻ってきます。