フィードは Korat の投稿という一つのオブジェクトが最もよく見える場所です。グループも、店舗ページも、ストーリーも、共有も——Korat のほとんどは4つの並行したシステムではなく、一つの投稿の行の上に建っています。グループ投稿はグループ ID を持った普通の投稿。店舗ページの投稿はビジネス ID を持った普通の投稿。この判断のおかげで、リアクション・コメント・@メンション・通知がどこでも同じように動き、片方を直せば全部が同時に直ります。このページは実質、アプリの残り全部を作っている素材の説明です。
投稿の4つの書き方
投稿はただのテキストにも、灰色の段落では埋もれてしまう短い一行のための色背景つきテキストにも、枚数に応じて組み替わる X 風グリッドの最大4枚の画像にもできます。自分として出すことも、管理している店舗ページとして出すこともでき、メインのフィードではなくグループに投稿することもできます。
投稿にはそれぞれ公開範囲——公開か友だち——が付いており、送信した瞬間に凍結されるのではなく、後から変更できます。人は読み手を絶えず見誤ります。友だち向けに書いたものが実は全員に見せる価値があったり、その逆が1時間後にはっきりしたりする。唯一の例外は店舗ページとして出した投稿で、これは常に公開です。一部の客にしか見えない店の投稿は、問い合わせを生むだけだからです。
投稿もコメントもストーリーも、決まった一覧から理由を選んで通報できます。通報はサーバーの権限ではなく*あなた自身*の権限で走る関数を通るので、見られない投稿と存在しない投稿はまったく同じ答えを返します——通報ボタンが「見る権限のない内容が存在するか」を探る道具になることは決してありません。回数の制限はアプリではなくデータベースで強制されます。自分の投稿は公開後に編集でき、削除もできます。コメントは実在のハンドルに解決される @メンションに対応しているので、メンションはたまたまアットマークで始まる文字列ではなく人へのリンクになり、その人に通知が届きます。
6種類のリアクション、一人ひとつ
リアクションは6種類——👍 ❤️ 😄 😮 😢 😡——で、一つの投稿につき一人ひとつです。同じものをもう一度押すと外れ、別のものを押すと移ります。連打で膨らませられるカウントも、いいねとリアクションを別々に帳尻合わせする処理もありません。
1種類ではなく6種類なのは、悪い知らせに対する「いいね」が曖昧だからです。30種類にしないのは、めったに使われないリアクションの長い尾がカウントを読めなくするからです。同意と共感と怒りを区別するには6つで足ります。それが実際に必要な区別です。
フィードは並べ替えられていて、その基準は書き出されています
メインのフィードは厳密な新着順ではありません。アプリのソースの一つのファイル data/Ranking.kt にあるランキング関数で並び、その重みはすべて、友だち提案・出会い・検索の重みと並んでプロジェクトのコアアルゴリズム文書に記録されています。重みが変われば、その文書も一緒に変わります。
これをわざわざ書くのは、「アルゴリズム」がふつうソーシャル製品の誰も説明したがらない部分だからです。ランキングとは誰かが選んだ数字の集合であり、それを一箇所に書き出すことが、議論できるランキングとブラックボックスの違いです。グループ投稿はそのパイプラインのちょうど一箇所でメインのフィードから除かれます——投稿はそのグループのものであり、そこに留まります。
アルバム、そして写真の行き先
写真はそれ自体の公開範囲——公開・友だち・非公開——を持つアルバムに整理され、その写真を使った投稿とは独立しています。各アルバムにはカバー写真があり、名前の変更も削除もできます。プロフィール写真・カバー写真・投稿画像という3つの既定アルバムが最初から存在するので、投稿に写真を上げても、見えない場所に写真ライブラリの二つめの複製が静かに作られることはありません。
非公開アルバムが非公開であるというのは、Korat の画面が他人に見せない、という意味です。暗号的な意味での非公開ではありません。そこが正直に書くべきところです。
アップロードされたメディアは URL を知っていれば誰でも読めます。 Korat は署名付き URL も非公開バケットも使っていません。画像の直接 URL を持っている人は、その投稿やアルバムに設定された公開範囲に関係なくファイルを開けます。公開範囲が制御するのはアプリの中で誰に見えるかであって、誰がファイルを取得できるかではありません。
Korat のどこにもエンドツーエンド暗号化はなく、アプリケーション層の保存時暗号化もありません。アップロードした写真は、アドレスを入手した人なら誰でも到達しうるものとして扱い、そうなったら困るものは上げないでください。
共有と、何も語らないリンク
共有できるものは、チャットにカードとして、自分のフィードに、ストーリーに、あるいは Android の共有シートから端末上の任意のアプリへ送れます。さらに koratland.com の共有リンクにもできます——koratland.com/s/<token> という形の URL で、トークンはランダムな14文字です。投稿・プロフィール・ビジネス・ストーリーがこの方法で共有できます。
トークンが不透明なのは意図的です。誰かが開くと、サーバーは2つのことだけを返す関数で解決します。対象の種類と、どの対象か。共有したのが誰かも、何回クリックされたかも決して返しません。クリック計上は逆向きに動きます。別の関数がクリックを記録し、その下のテーブルには誰に対しても INSERT 権限が意図的に用意されていません。だから訪問者はカウンターを増やせても、それ以外を書き込むことはできません。グループチャットに貼ったリンクは、受け取った人にあなたの共有履歴について何も伝えません。
消えるストーリーと、消えない閲覧者リスト
ストーリーは写真か色背景のテキストで、埋め込みフォントを選び、キャンバスのどこにでも文字を置き、文字色を決められます。公開範囲は投稿と同じ公開か友だちの2択で、時間が経てば自分で消えます。その前に自分で削除することもできます。
ストーリーの持ち主には閲覧者リストが届きます。数ではなく、開いた実際の人たちです。数は「見られた」ことを伝えますが、リストは「誰に」を伝えます。それが知りたかったことであり、同時に、見ることが匿名ではないと全員に明らかにします。健康モジュールの活動も、選んだ背景の上にキャプションを載せてストーリーに共有できます。同じストーリーのオブジェクトに、違う中身を注いだだけです。
走った記録や自転車の記録は仲間と同じ順位表に並びます。それがスポーツクラブで、投稿を特定の一人にだけ送ればチャットの中のカードになります。
名前の横のバッジが何を根拠に出るのか、そしてなぜ「認証済み」とは決して書かないのかは信頼と安全に書いてあります。店舗アカウントとして投稿・返信する側はビジネスコンソールです。