Files
zh-chat-flutter/lib/controllers/publish_controller.dart
2022-10-20 16:08:27 +08:00

150 lines
4.8 KiB
Dart

import 'package:chat/controllers/moment_controller.dart';
import 'package:chat/models/upload_model.dart';
import 'package:chat/routes/moments_routes.dart';
import 'package:chat/providers/moment_provider.dart';
import 'package:chat/utils/ui_tools.dart';
import 'package:chat/views/moments/publish/widgets/delete_dialog.dart';
import 'package:flutter/material.dart';
import 'package:flutter_easyloading/flutter_easyloading.dart';
import 'package:get/get.dart';
import 'package:tuple/tuple.dart';
import 'package:wechat_assets_picker/wechat_assets_picker.dart';
class PublishController extends GetxController {
static PublishController get to => Get.find<PublishController>();
static const fileMaxLength = 9;
/// 发布"发现"的文件列表
final publishFileList = <AssetEntity>[].obs;
/// 已上传的文件获得的url
///
/// [Tuple(hashCode, UploadModel)]
final uploadedFileList = <Tuple2<int, UploadModel?>>[];
/// preview页显示的下标
final publistFileIndex = 0.obs;
/// 发布的文本内容
final publishContent = ''.obs;
/// 退出确认
Future<bool> exitConfirmation() async {
if (publishFileList.isEmpty && publishContent.isEmpty) return true;
final result = await Get.defaultDialog<bool?>(
title: '确认',
middleText: '退出后将不会保存内容',
onConfirm: () {
Get.back(result: true);
},
);
return result == true;
}
Future<void> publish() async {
FocusScope.of(Get.context!).requestFocus(FocusNode());
EasyLoading.show(status: '上传中', maskType: EasyLoadingMaskType.black);
final result = await uploadAllFile();
if (!result) return;
final res = await MomentProvider.publishMoment(
description: publishContent.value,
pictures: uploadedFileList.map((e) => e.item2!.url).toList(),
);
EasyLoading.dismiss();
if (res != null) {
UiTools.toast('发表成功');
Get.back();
MomentController.to.refreshList();
}
}
Future<bool> uploadAllFile() async {
try {
for (var i = 0; i < publishFileList.length; i++) {
final file = publishFileList[i];
final exists = uploadedFileList.any(
(e) => (e.item1 == file.hashCode && e.item2?.url != null),
);
if (!exists) {
final res = await MomentProvider.uploadFile((await file.file)!.path);
if (res == null) throw Exception('上传失败');
for (var index = 0; index < uploadedFileList.length; index++) {
final uploaded = uploadedFileList[index];
if (uploaded.item1 == file.hashCode) {
uploadedFileList[index] = uploaded.withItem2(res);
}
}
}
}
return true;
} catch (e) {
UiTools.toast('上传失败');
return false;
}
}
Future<void> deleteImageOrVideo(int index) async {
final result = await Get.dialog<bool?>(const PublishDeleteDialog());
if (result == true) {
removeFileByIndex(index);
}
}
/// 选择文件并添加到[publishFileList]里
Future<void> pickImageOrVideo() async {
FocusScope.of(Get.context!).requestFocus(FocusNode());
final result = await AssetPicker.pickAssets(
Get.context!,
pickerConfig: AssetPickerConfig(
maxAssets: fileMaxLength - publishFileList.length,
),
);
if (result == null) return;
bool videoAlreadyExists =
publishFileList.any((e) => e.type == AssetType.video);
final list = result.where(
(e) {
if (e.type == AssetType.image) return true;
if (videoAlreadyExists) return false;
final authorized = e.videoDuration.inSeconds <= 30;
if (authorized) videoAlreadyExists = true;
return authorized;
},
).toList();
if (videoAlreadyExists && list.length != result.length) {
UiTools.toast('最多能选择一个视频, 且视频时长不能超过30秒');
} else if (list.length != result.length) {
UiTools.toast('视频时长不能超过30秒');
}
// ignore: todo
// TODO: 限制视频或者图片大小
publishFileList.addAll(list);
list.asMap().forEach((index, file) {
uploadedFileList.add(Tuple2(file.hashCode, null));
});
}
/// preview[publishFileList]里的文件
void previewFiles(int index) {
FocusScope.of(Get.context!).requestFocus(FocusNode());
publistFileIndex.value = index;
Get.toNamed(MomentsRoutes.publishPreview);
}
/// 按index删除file
void removeFileByIndex(int index) {
uploadedFileList.removeAt(index);
publishFileList.removeAt(index);
if (publishFileList.isEmpty &&
Get.currentRoute == MomentsRoutes.publishPreview) Get.back();
if (publistFileIndex.value >= publishFileList.length) {
publistFileIndex.value = publishFileList.length - 1;
}
}
/// 删除preview当前显示的file
void removeFileByCurrentIndex() {
removeFileByIndex(publistFileIndex.value);
}
}