Valo Documentation
首頁
開發設置
專案結構
登入前單元
登入後單元
聊天對話單元
聊天系統
群組系統
認證
部署
故障排除
首頁
開發設置
專案結構
登入前單元
登入後單元
聊天對話單元
聊天系統
群組系統
認證
部署
故障排除
  • 專案文檔

    • 開發環境設置指南
    • 專案資料夾結構說明
    • - 聊天功能核心
    • - 群組目錄
    • 身份驗證
    • 登入前的單元
    • 登入後的單元
    • 聊天對話單元
    • 部署指南
    • 常見問題排解
    • 專案故事
    • 最初的那些痛

聊天對話單元

主要參考檔案: ValoChat

我們能觀察到以下區段,了解個別資料做什麼職責,其他幾乎是 UI 上的細節:

  • ValoChatComposerProvider: 對話的底部的共用資料。
    • ex: 媒體面板、目前輸入訊息文字、訊息檔案、回覆訊息...等
  • ValoChatSearchProvider: 針對 對話搜尋,集中的共用資料。
    • ex: 是否已切換搜尋模式、目前輸入搜尋文字、搜尋後的結果
  • ValoChatGroupMessageReadCountProvider: 針對整個對話,所以的已讀數量的 共用資料。
    • 當時後續疊加的功能,需要一個地方去 熱更新 數量,拉出來獨立做管理較方便。
    • 群組已讀數量、好友已讀,先參考 Agora Message Receipts
      • 進入聊天對話時,需要將每則訊息 已讀數量 準備好。
      • 進入聊天對話後,開始監聽 Agora 已讀事件,熱更新數量。
  • ValoChatResendProvider: 針對整個對話,失敗訊息的 共用資料。
    • 當時後續疊加的功能,沒想太多就拉出來。
      • 進入聊天對話時,將失敗訊息保存起來
      • 該則訊息重送後,會轉交由 ChatClient.getInstance.chatManager.addMessageEvent:onSuccess,成功後,會將該筆失敗訊息刪除。
  • ForeceMessageIdProvider: 紀錄 目前使用者 對哪則訊息長按,要給 1-3 單元使用的 共用資料。
  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: [
        Provider.value(value: conversation),
        ChangeNotifierProvider(create: (context) => ValoChatComposerProvider()),
        ChangeNotifierProvider(create: (context) => ValoChatSearchProvider()),
        ChangeNotifierProvider(create: (context) => ValoChatGroupMessageReadCountProvider()),
        ChangeNotifierProvider(create: (context) => ValoChatResendProvider()),
        ChangeNotifierProvider(create: (context) => ForeceMessageIdProvider()),
      ],

1. 訊息類別(參考:Agora Message)

1-1. 加入群組

ChatCustomMessage(event:group_invite)

  • 邀請人 inviter_user_id
  • 群名稱 group_name

對方如何擁有 加入群組訊息:

  • 我/建立群組時,邀請好友
  • 我/群組聊天/右上more/邀請好友

提示

因為 valo 為匿名群組,彼此並不會知道,是否在群組內,邀請好友時,會統一送出,是否加入/已加入在對方的對話訊息中各自判斷。

1-2. 一般訊息

文字、檔案、圖片、影片 參考檔案列:

  • valo_chat.dart:
    • chat_ui.Builders 會有各項訊息的元件。
    • agora.ChatClient.getInstance.chatManager.addMessageEvent
      • 監聽 我自己送出的訊息
        • 是否成功、失敗
        • 成功,右訊息狀態 'V'
        • 失敗,右訊息狀態 '!'(紅),並且 長按(onMessageLongPress) 顯示 Resend

1-3. 回覆、重送、複製訊息

長按(onMessageLongPress) 叫出

  • ValoChatMessageActionPanelManager:
    • 可以理解為 面板管理員,根據這則訊息,顯示需要顯示的項目
      • ex: 回覆、重送、複製
  • 目前複製功能尚未實作。

存在的問題

原因: 消息面板,我是使用全域漂浮定位

  • 只能抓到 距離頂部有多少
  • 無法預先知道該元素多高
  • 無法控制 層級(類似前端的 z-index)

造成目前現象:

  1. 只能定在 該訊息的 左上或右上
  2. 會浮在整個 APP最上層
  3. 如果 有時間標籤 連他的高,也會被算進去

處理方式:

  1. 需要深入尋找其他套件,或是研究、熟悉 Flutter 元件去製造創新元件
  2. 同 1
  3. 在 show 時,需要多加更精細的判斷,看這則是不是有 被掛上 時間標籤,有的話減去固定高度

2. 上傳媒體

2-1. 相機模式

程式碼: media_service.dart::_CameraScreen

在 上傳媒體面板中的相機功能。

  • 單點純拍照
  • 長按錄影,直到手指放開為止

如何判別 純拍照、長按錄影?

onPointerDown: 點下去紀錄開始時間。

  • 此時給一個 倒數者(200 毫秒)
    • 到點,就切換成錄影模式。
    • 還沒到,會被 onPointerUp 攔截掉注銷。

onPointerUp: 錄影結束 or 純拍照。

過往

最過往是使用 image_picker 中的 camera 模式,但它不支援 錄影。

後面在 影片訊息開放後,相機也需要開放錄影,才比較符合需求,而尋覓了需多套件,參考競品,發現很多人家的 相機頁面,其實很多自己實現居多,例如 ig line 有很多濾鏡、人像辨識...等,未來這塊能尋覓 新套件 將這段替換掉,當時尋覓的新套件功能太重,設定太複雜而選擇自做。

2-2. 相簿上傳

程式碼:media_service.dart::pickMedia

  • IOS 使用 image_picker 打開 IOS 相簿。
  • Android 平台,使用 file_picker 選取圖片、影片,中間的檔案類型過濾,套件中有說明如何過濾,自行實現。

過往

image_picker 在 Android 平台支援度很差,所以 Android 平台,使用 file_picker。

2-3. 檔案上傳

程式碼:media_service.dart::pickDocument

使用 file_picker 選取圖片、影片,中間的檔案類型過濾,套件中有說明如何過濾,自行實現。

Prev
登入後的單元
Next
部署指南