Korat
功能

一對一訊息,和瀏覽器裡的通話

Korat 的訊息模組刻意做得很窄:兩個人,一條會話。應用裡其餘的一切——別人邀你入座的餐桌、分享過來的帖子、約會里的配對——都以卡片的形式落進這條會話裡,可以直接操作。

聊天是 Korat 其他部分共同依賴的那一塊。朋友邀你上他那桌,邀請是一張聊天卡片;有人分享一條帖子,它落下來就是一張能點開的卡片;約會裡兩個人互相喜歡的瞬間,就變成一段真實的對話。因為訊息只有一個落點,你也就只有一個地方要看,而訊息模組只需要把一件事做好:兩個人之間的一條會話,附件種類足夠多到你不必換應用。

兩個人,一條會話

Korat 的聊天只有一對一:一條私聊里正好兩個人,沒有任何辦法拉進第三個人。多人對話發生在另外兩個地方,而它們都不是這個訊息模組。群組用帖子來承載:群組帖子帶著一個群 id,因此直接繼承了資訊流那一套評論、@提及和通知——有回覆層級、可搜尋、長期留存。此外,群組和運動俱樂部都可以有子房間:列在群組內部的 Discord 式文字頻道,建在自己的表和自己的權限上,能做的事比一條私聊少得多。下面把限制寫全了,因為一個看起來像聊天、實際不是的房間,比沒有這個房間更糟。

一對一換來的是深度。你可以引用某條訊息回覆、發出後再編輯、撤回、把重要的一條置頂,也可以用六個常用表情快速回應,或展開三十個表情的長條。正在輸入的提示和已讀狀態都按你預期的方式工作。

一條訊息裡能裝什麼

文字之外還有圖片、任意檔案,以及語音訊息——用裝置自帶的 MediaRecorder 錄成 M4A 容器裡的 AAC,在氣泡裡直接播放。也可以傳送位置。此外還有應用其他部分鑄出來的系統卡片:分享的帖子、餐桌邀請、以及一次通話的記錄。

新訊息會給對方的裝置推送通知——一對一訊息和商家收件箱都一樣。它只送到沒有被吊銷的裝置上,而開啟那個會話就會清掉那個會話的通知。一個產生了訊息卻沒人被告知的聊天不是安靜,是壞了。必須一起說的限制是:網頁版沒有推送。如果你在瀏覽器裡聊天,你會在開啟標籤頁的時候看見訊息,而不是它到達的時候。

通話記錄卡片比聽上去重要。一通響過又沒接的電話本來是看不見的:你事後開啟應用,沒有任何東西告訴你發生過什麼。把通話寫進會話,就意味著一段關係的歷史是一條可以往上滾的列表,而不是對話在一處、通話記錄在另一處。

通話要兩邊都開了鎖才出現

語音和視訊通話跑在真實的 WebRTC 上,支援靜音、關攝像頭、切換前後置、全屏來電介面,以及應用在後臺時的來電通知。特別的是它前面那道門:通話許可是雙向的,且按會話獨立。一條會話裡,只有雙方都在自己這側開了鎖,通話按鈕才會出現;在那之前誰都打不通誰。

這是對“響鈴是一個應用能做的最具侵入性的事”這一事實的正面回應。一個從約會或店鋪頁找到你的陌生人可以發訊息,你可以不理;但除非你明確同意,他不能在凌晨兩點讓你的手機響起來。許可按會話計算,所以對一個人開鎖不代表對任何別人開鎖;而且它是一把你去開的鎖,不是藏在偏好設定深處的一個開關。

兩條誠實的限制。私聊只有一對一——一條會話無法變成群組,本頁描述的這個訊息模組沒有多人版本。真正存在的是群組和俱樂部自帶的子房間,它是另一套更薄的系統,建在不同的表上:純文字,能發、能刪自己發的,但不能編輯訊息、不能針對某條訊息回覆、不能用表情回應、不能發圖片、檔案或語音訊息,也不能從房間裡發起通話。本頁任何內容都不應被讀成對子房間的描述。

通話沒有端到端加密,也沒有 TURN 伺服器。在兩端網路能直接互通時媒體走點對點;但沒有中繼伺服器,某些運營商網路與嚴格 NAT 的組合就是連不上。通話建立不起來,通常就是這個原因——那是一塊我們還沒搭起來的基礎設施,不是應用裡的 bug。

線上狀態是心跳,不是長連線

Korat 裡的綠點只表示一件具體的事:那個人的客戶端在過去九十秒內寫過一次 last_seen 時間戳。它是按間隔輪詢,不是持久連線,所以省電,也因此很粗。四十秒前剛關掉應用的人看起來還線上;進了隧道的人還沒走遠就先暗了下去。

我們叫它心跳而不是“線上”,是因為線上狀態最容易被當成證據——證明訊息被看到了,證明對方在故意不回。九十秒的輪詢視窗撐不起這個分量。

找到你要的那條會話,以及怎麼處理一個人

兩個功能在維持長會話列表的可用性。第一個是會話備註名:把任意會話改成你實際對這個人的稱呼,而這個名字只有你看得見。它絕不會漏進資訊流、群組、評論或對方的資料頁——你存成“房東”的那個人,在所有地方顯示的仍是他自己寫的名字。Korat 裡其他地方的名字都是從資料頁實時解析的,正是為了讓一處改名不會與另一處失同步。

第二個是標籤:你自己建立的彩色標籤,成員由你控制,可增可改可刪,同時充當會話列表的篩選器,旁邊還有未讀、官方帳號和來自約會這三個內建篩選。搜尋同時覆蓋會話名和最後一條訊息,所以記得半句話就夠找回一條會話。會話可以置頂、標為已讀或刪除。

服務端能看到什麼,以及你能對一個人做什麼

訊息以明文存在服務端,由行級安全策略把一條會話的行限制在兩位參與者之內。Korat 的聊天、通話和檔案都沒有端到端加密,除託管資料庫自帶的部分外也沒有應用層靜態加密。如果你要談的事情需要這些,請換一個為此而生的工具——準確描述我們的威脅模型,比一句安撫的話對你更有用。

至於人這一側:你可以從會話裡或資料頁拉黑某人,這會同時隱藏他的會話與帖子,並把他從你的約會卡片堆裡移除,你也可以舉報某個使用者。拉黑是一個動作,在應用的每個角落生效,不需要你逐個介面重複。

落進會話裡的那些卡片各有來處:朋友邀你上他那桌,那張桌子來自點餐;有人分享一條帖子,它就是動態裡的那一條。

顧客發給店鋪的訊息走的也是這套會話,只是店家那一側讀到的是商家控制檯裡的收件箱;掃一張數字名片之後要不要直接說話,同樣回到這裡。

常見問題

Korat 有群聊嗎?

訊息模組裡沒有。一條私聊只有一對一,拉不進第三個人。多人交流在群組裡:一是帖子,支援評論、@提及和通知;二是群組自帶的子房間——列在群組內部的 Discord 式文字頻道,運動俱樂部也有。

那些子房間和私聊是兩套系統,能做的事少得多:純文字,能發、能刪自己發的,但不能編輯、不能針對某條訊息回覆、不能用表情回應、不能發附件或語音訊息,也不能通話。

Korat 的訊息是端到端加密的嗎?

不是。訊息、檔案和通話都沒有端到端加密。聊天記錄存在服務端,由行級安全策略把每條會話限制在兩位參與者之內。

除託管資料庫自帶的部分外,沒有應用層的靜態加密。

為什麼我在某條會話裡看不到通話按鈕?

通話許可是雙向的,且按會話獨立。只有當雙方都在那條具體會話裡開了通話鎖,語音和影片按鈕才會出現。

對一個人開鎖,不會對任何其他人開鎖。

我的視訊通話連不上,是哪裡出了問題?

目前還沒有 TURN 中繼伺服器,通話依賴兩臺裝置能夠直接互相到達。某些行動網路與嚴格 NAT 的組合做不到這一點,通話就建立不起來。

兩臺裝置在同一個 Wi-Fi 下,或者在允許點對點直連的網路裡,通常就能打通。

我給一條會話改了名字,對方會看到新名字嗎?

不會。會話備註名只屬於你。對方真實的顯示名對所有人照舊出現,包括資訊流、評論和群組裡。

Korat 各處的名字都是從資料頁實時解析的,所以備註名不可能漏進內容裡。

開一段對話

Korat 免費,安卓和瀏覽器都能用,聊天在兩邊表現一致。