downloadMessage method

Future<V2TimCallback> downloadMessage({
  1. V2TimMessage? message,
  2. String? msgID,
  3. required int imageType,
  4. required bool isSnapshot,
  5. String? downloadPath,
  6. void onDownloadFinished(
    1. V2TimMessage message
    )?,
})

Implementation

Future<V2TimCallback> downloadMessage({
  V2TimMessage? message,
  String? msgID,
  required int imageType,
  required bool isSnapshot,
  String? downloadPath,
  void Function(V2TimMessage message)? onDownloadFinished,
}) async {
  if (!TIMManager.instance.isInitSDK()) {
    return V2TimCallback(code: TIMErrCode.ERR_SDK_NOT_INITIALIZED.value, desc: "sdk not init");
  }

  final downloadKey = '$msgID-$imageType-$isSnapshot';
  if (_downloadingMessageSet.contains(downloadKey)) {
    print("message ID: $msgID, imageType: $imageType, isSnapshot: $isSnapshot is downloading");
    return V2TimCallback(code: TIMErrCode.ERR_INVALID_PARAMETERS.value, desc: 'message is downloading');
  }

  if (message == null) {
    if (msgID == null) {
      return V2TimCallback(code: TIMErrCode.ERR_INVALID_PARAMETERS.value, desc: 'message and msgID are both empty');
    } else {
      V2TimValueCallback<List<V2TimMessage>> findResult = await findMessages(messageIDList: [msgID]);
      if (findResult.code != TIMErrCode.ERR_SUCC.value) {
        print("downloadMessage, find message failed");
        return V2TimCallback(code: findResult.code, desc: findResult.desc);
      }

      List<V2TimMessage> msgList = findResult.data!;
      if (msgList.isEmpty) {
        print("downloadMessage, message not found");
        return V2TimCallback(code: TIMErrCode.ERR_INVALID_PARAMETERS.value, desc: "message not found");
      }

      message = msgList[0];
    }
  }

  msgID = message.msgID ?? "";

  if (!{
    MessageElemType.V2TIM_ELEM_TYPE_IMAGE,
    MessageElemType.V2TIM_ELEM_TYPE_VIDEO,
    MessageElemType.V2TIM_ELEM_TYPE_SOUND,
    MessageElemType.V2TIM_ELEM_TYPE_FILE
  }.contains(message.elemType)) {
    print("downloadMessage, message does not support downloading");
    return V2TimCallback(code: TIMErrCode.ERR_INVALID_PARAMETERS.value, desc: "message does not support downloading");
  }

  V2TimMessageDownloadElemParam downloadParam =
      V2TimMessageDownloadElemParam(message: message, imageType: imageType, isSnapshot: isSnapshot);
  if (downloadParam.downloadUrl.isEmpty || downloadParam.fileUUID.isEmpty) {
    print("downloadMessage, message missing necessary download info");
    return V2TimCallback(
        code: TIMErrCode.ERR_INVALID_PARAMETERS.value, desc: "message missing necessary download info");
  }

  String adjustDownloadPath = downloadPath ??
      _getDefaultCachePath(
          message: message, imageType: imageType, isSnapshot: isSnapshot, downloadParam: downloadParam);
  if (File(adjustDownloadPath).existsSync()) {
    return V2TimCallback(code: TIMErrCode.ERR_SUCC.value, desc: "file: $adjustDownloadPath already exists!");
  }

  String userData = Tools.generateUserData('downloadMessage');
  Completer<V2TimCallback> completer = Completer();
  void handleApiCallback(Map jsonResult) {
    V2TimValueCallback<dynamic> result = V2TimValueCallback<dynamic>.fromJson(jsonResult);
    if (result.desc == 'downloading') {
      Map<String, dynamic> processInfo = result.data ?? {};
      if (processInfo.isNotEmpty) {
        int currentSize = processInfo['msg_download_elem_result_current_size'] ?? 0;
        int totalSize = processInfo['msg_download_elem_result_total_size'] ?? 0;

        V2TimMessageDownloadProgress downloadProgress = V2TimMessageDownloadProgress(
          isFinish: currentSize > 0 && currentSize == totalSize,
          isError: false,
          msgID: msgID!,
          currentSize: currentSize,
          totalSize: totalSize,
          type: imageType,
          isSnapshot: isSnapshot,
          path: adjustDownloadPath,
          errorCode: result.code,
          errorDesc: result.desc,
        );

        // 下载进度回调
        _advancedMessageListener.onMessageDownloadProgressCallback(downloadProgress);
      }
    } else {
      // 下载完成回调,更新本地路径,方便调用者直接使用 message 对象刷新界面
      if (onDownloadFinished != null) {
        if (message!.elemType == MessageElemType.V2TIM_ELEM_TYPE_IMAGE) {
          for (V2TimImage? image in message.imageElem?.imageList ?? []) {
            if (image == null) {
              continue;
            }

            if (imageType == V2TIM_IMAGE_TYPE.V2TIM_IMAGE_TYPE_ORIGIN ||
                imageType == V2TIM_IMAGE_TYPE.V2TIM_IMAGE_TYPE_THUMB ||
                imageType == V2TIM_IMAGE_TYPE.V2TIM_IMAGE_TYPE_LARGE) {
              image.localUrl = adjustDownloadPath;
              break;
            } else {
              print("downloadMessage, imageType: $imageType error");
              break;
            }
          }
        } else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_VIDEO) {
          if (isSnapshot) {
            message.videoElem?.localSnapshotUrl = adjustDownloadPath;
          } else {
            message.videoElem?.localVideoUrl = adjustDownloadPath;
          }
        } else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_SOUND) {
          message.soundElem?.localUrl = adjustDownloadPath;
        } else if (message.elemType == MessageElemType.V2TIM_ELEM_TYPE_FILE) {
          message.fileElem?.localUrl = adjustDownloadPath;
        } else {
          print("downloadMessage, message.elemType: ${message.elemType} error");
        }

        onDownloadFinished(message);
      }

      // 下载完成回调
      _downloadingMessageSet.remove(downloadKey);

      completer.complete(V2TimCallback(code: result.code, desc: result.desc));
    }
  }

  NativeLibraryManager.timApiValueCallback2Future(userData, handleApiCallback);

  _downloadingMessageSet.add(downloadKey);

  Pointer<Char> pDownloadParam = Tools.string2PointerChar(json.encode(downloadParam.toJson()));
  Pointer<Char> pDownloadPath = Tools.string2PointerChar(adjustDownloadPath);
  Pointer<Void> pUserData = Tools.string2PointerVoid(userData);
  NativeLibraryManager.bindings.DartDownloadElemToPath(pDownloadParam, pDownloadPath, pUserData);

  return completer.future;
}