兩個人以上的對話在 Korat 裡發生在群組,因為聊天本身只有一對一。它有兩種形態。大部分是帖子:群組帖子就是 posts 表裡一行帶著社群 id 的普通記錄,所以評論、提及、通知和搜尋都原封不動地成立,不必並行再建一遍。此外,群組還可以有子房間——列在群組內部的 Discord 式文字頻道,有自己的權限和自己的已讀狀態。子房間是刻意做薄的,下面的提示框寫明瞭薄到什麼程度。
群組帖子就是帶地址的資訊流帖子
這是理解 Korat 群組最要緊的一件事。你往群裡發帖時,建立的和你發在自己資訊流上的是完全同一個物件:同樣的表情回應、同樣的評論、同樣能解析到真實帳號的 @提及、同樣的編輯與刪除、同樣的通知管線。不存在一套缺胳膊少腿的二等群評論系統。
群 id 唯一改變的是帖子出現在哪裡。群組帖子在程式碼裡恰好一個位置被過濾出主資訊流,因此留在群內,不會滲進每一個恰好和某個成員是好友的人的時間線。一個位置、一條過濾規則,也是行為一致的原因——不存在第二條排除規則在別處慢慢與第一條產生分歧。
實際的回報是:Korat 的群組一上來就和資訊流一樣強,改進同時落在兩邊。代價寫在下面,也很直白:群組的子房間不是訊息模組,群組耐久的那一半是它的帖子板。
群組的子房間不是訊息模組。私聊只有一對一,也無法變成群組。群組的子房間只承載純文字,能發、能刪自己發的——不能編輯訊息、不能針對某條訊息回覆、不能用表情回應、不能發圖片、檔案或語音訊息,也不能通話。
所以五個人實時你來我往是可以的,在子房間裡,用純文字。做不到的是讓這種你來我往帶上私聊才有的附件、表情回應和通話。群組耐久、可搜尋、可評論的那一半是它的帖子板,帶真實角色和真實入群流程。
公開與封閉,以及封閉到底意味著什麼
建立群組時你要設定名稱、簡介、分類、公開或封閉的隱私設定,以及一段群規。群規欄位不是裝飾:一個沒有寫下規則的群最終還是會有規則,由當天負責管理的那個人臨時發明,而成員是透過違反它才知道有這麼一條。
封閉群使用入群申請:有人提出申請,群主或管理員批准或拒絕;申請人也可以撤回待處理的申請,而不是卡在一個不會到來的決定上。兩側都會收到通知——管理員收到申請到達,申請人收到批准結果。申請石沉大海是所有群組系統最常見的失敗,而批准時發一條通知是最便宜的修法。
群的狀態在你點之前就擺出來,而不是點完才知道:封閉群的卡片上帶一把鎖,所以“加入”和“申請加入”的差別在你還在猶豫時就看得見——按鈕絕不能承諾下一屏會拒絕的事。
四個分割槽,而不是一個列表加徽章
群組頁被拆成帶計數的標題分割槽,而不是用一個小徽章去表達你和這個群的關係:我管理的群、我加入的群、待處理申請和發現,另加一個橫跨全部的搜尋。
它最初只是一個“我的群組”列表,後來重做了,因為這四行意思完全不同。你擁有的群有設定,還有一個等著你的申請佇列;你只是提交過申請的群什麼都還沒有。把它們分進帶計數的標題分割槽,一眼就能回答“有沒有需要我處理的事”,而埋在第三十行的一個徽章回答不了。
角色,以及把群交出去
有三種角色——群主、管理員和成員——以徽章形式顯示在名字旁邊。群主或管理員可以改變成員角色、移除成員、編輯群設定或刪除群。還有群主轉讓,它比聽上去重要:一個群主已經不再用這個應用、又交不出鑰匙的群,會帶著一屏鎖死的設定慢慢死掉。
Korat 的規矩是:後端會拒絕的動作,介面上就不該提供。群主看不到“退出群組”這一項,因為退出會讓群變成孤兒;想脫身的群主的路徑是先轉讓。破壞性操作——刪除群、移除成員——都在確認框後面,而確認框會同時明說什麼*不會*發生,因為人們猶豫,多半是因為預設設想了最壞的結果。
對應決定的通知
群組發四種通知,每一種都對應一個有人需要知道點什麼的時刻:你所在群裡的新帖子、送到管理員那裡的入群申請、你的申請被批准,以及你的角色變更。
第一種早期是缺失的,結果是群看起來像被廢棄了——成員根本無從得知有人發過東西。同樣的失敗模式後來又在店鋪訂單上出現了一次。一個產出內容卻不告訴任何人的功能不是安靜,是壞的。
把群分享出去
群可以透過 Korat 其餘部分共用的那套不透明連結分享出去:一條 koratland.com/s/<token> 形式的 URL,令牌是 14 位隨機字元,在應用內解析。解析器只返回令牌指向的物件型別和具體是哪一個;它從不透露是誰建立的分享,也不透露被開啟過多少次。所以一條公開張貼的招募連結,不攜帶任何關於張貼者的資訊。
群裡發的帖子本身就是動態裡的帖子,只是多帶一個群 id;要帶成員排行榜的跑團或球隊,用運動俱樂部——兩者的子房間是同一套,差別在排行榜。