fluffychat/lib/pages/add_story/add_story.dart

309 lines
8.6 KiB
Dart
Raw Permalink Normal View History

2021-12-24 14:18:09 +01:00
import 'dart:io';
2022-02-20 10:24:23 +01:00
import 'dart:math';
2021-12-24 14:18:09 +01:00
import 'package:flutter/material.dart';
import 'package:file_picker_cross/file_picker_cross.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart';
import 'package:video_player/video_player.dart';
import 'package:vrouter/vrouter.dart';
import 'package:fluffychat/pages/add_story/add_story_view.dart';
import 'package:fluffychat/pages/add_story/invite_story_page.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart';
2022-01-19 08:30:43 +01:00
import 'package:fluffychat/utils/resize_image.dart';
2022-03-06 11:39:31 +01:00
import 'package:fluffychat/utils/story_theme_data.dart';
2021-12-24 14:18:09 +01:00
import 'package:fluffychat/utils/string_color.dart';
import 'package:fluffychat/widgets/matrix.dart';
import '../../utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
class AddStoryPage extends StatefulWidget {
const AddStoryPage({Key? key}) : super(key: key);
@override
AddStoryController createState() => AddStoryController();
}
class AddStoryController extends State<AddStoryPage> {
final TextEditingController controller = TextEditingController();
2022-02-11 22:50:20 +01:00
final FocusNode focusNode = FocusNode();
2021-12-24 14:18:09 +01:00
late Color backgroundColor;
late Color backgroundColorDark;
MatrixImageFile? image;
MatrixVideoFile? video;
2021-12-24 14:18:09 +01:00
VideoPlayerController? videoPlayerController;
bool get hasMedia => image != null || video != null;
bool hasText = false;
2022-02-11 22:50:20 +01:00
bool textFieldHasFocus = false;
2022-02-20 10:24:23 +01:00
BoxFit fit = BoxFit.contain;
2022-02-20 10:24:23 +01:00
int alignmentX = 0;
int alignmentY = 0;
void toggleBoxFit() {
if (fit == BoxFit.contain) {
setState(() {
fit = BoxFit.cover;
});
} else {
setState(() {
2022-02-20 10:24:23 +01:00
fit = BoxFit.contain;
});
}
}
void updateHasText(String text) {
if (hasText != text.isNotEmpty) {
setState(() {
hasText = text.isNotEmpty;
});
}
}
2021-12-24 14:18:09 +01:00
void importMedia() async {
2022-01-15 12:01:14 +01:00
final picked = await FilePickerCross.importFromStorage(
type: FileTypeCross.image,
2021-12-24 14:18:09 +01:00
);
final fileName = picked.fileName;
if (fileName == null) return;
final matrixFile = MatrixImageFile(
bytes: picked.toUint8List(),
name: fileName,
);
2021-12-24 14:18:09 +01:00
setState(() {
image = matrixFile;
2021-12-24 14:18:09 +01:00
});
}
void capturePhoto() async {
final picked = await ImagePicker().pickImage(
source: ImageSource.camera,
);
if (picked == null) return;
final matrixFile = await showFutureLoadingDialog(
2022-02-20 10:24:23 +01:00
context: context,
future: () async {
final bytes = await picked.readAsBytes();
return MatrixImageFile(
2022-02-20 10:24:23 +01:00
bytes: bytes,
name: picked.name,
);
});
2021-12-24 14:18:09 +01:00
setState(() {
image = matrixFile.result;
2022-02-20 10:24:23 +01:00
});
}
void updateColor() {
final rand = Random().nextInt(1000).toString();
setState(() {
backgroundColor = rand.color;
backgroundColorDark = rand.darkColor;
2021-12-24 14:18:09 +01:00
});
}
void captureVideo() async {
final picked = await ImagePicker().pickVideo(
source: ImageSource.camera,
);
if (picked == null) return;
final bytes = await picked.readAsBytes();
setState(() {
video = MatrixVideoFile(bytes: bytes, name: picked.name);
2021-12-24 14:18:09 +01:00
videoPlayerController = VideoPlayerController.file(File(picked.path))
..setLooping(true);
});
}
void reset() => setState(() {
image = video = null;
2022-03-06 11:39:31 +01:00
alignmentX = alignmentY = 0;
controller.clear();
});
2021-12-24 14:18:09 +01:00
void postStory() async {
2022-01-19 08:30:43 +01:00
if (video == null && image == null && controller.text.isEmpty) return;
2021-12-24 14:18:09 +01:00
final client = Matrix.of(context).client;
2021-12-25 08:56:35 +01:00
var storiesRoom = await client.getStoriesRoom(context);
2021-12-24 14:18:09 +01:00
// Invite contacts if necessary
final undecided = await showFutureLoadingDialog(
context: context,
future: () => client.getUndecidedContactsForStories(storiesRoom),
);
final result = undecided.result;
if (result == null) return;
if (result.isNotEmpty) {
final created = await showDialog<bool>(
context: context,
useRootNavigator: false,
builder: (context) => InviteStoryPage(storiesRoom: storiesRoom),
);
if (created != true) return;
2021-12-25 08:56:35 +01:00
storiesRoom ??= await client.getStoriesRoom(context);
2021-12-24 14:18:09 +01:00
}
// Post story
final postResult = await showFutureLoadingDialog(
context: context,
future: () async {
if (storiesRoom == null) throw ('Stories room is null');
2022-01-19 08:30:43 +01:00
var video = this.video?.detectFileType;
2021-12-24 14:18:09 +01:00
if (video != null) {
2022-01-19 08:30:43 +01:00
video = await video.resizeVideo();
final thumbnail = await video.getVideoThumbnail();
await storiesRoom.sendFileEvent(
2022-01-19 08:30:43 +01:00
video,
2022-02-20 10:24:23 +01:00
extraContent: {
'body': controller.text,
StoryThemeData.contentKey: StoryThemeData(
fit: fit,
alignmentX: alignmentX,
alignmentY: alignmentY,
).toJson(),
},
thumbnail: thumbnail,
2021-12-24 14:18:09 +01:00
);
return;
}
final image = this.image;
2021-12-24 14:18:09 +01:00
if (image != null) {
await storiesRoom.sendFileEvent(
2022-01-19 08:30:43 +01:00
image,
2022-02-20 10:24:23 +01:00
extraContent: {
'body': controller.text,
StoryThemeData.contentKey: StoryThemeData(
fit: fit,
alignmentX: alignmentX,
alignmentY: alignmentY,
).toJson(),
},
2021-12-24 14:18:09 +01:00
);
return;
}
2022-02-20 10:24:23 +01:00
await storiesRoom.sendEvent(<String, dynamic>{
'msgtype': MessageTypes.Text,
'body': controller.text,
StoryThemeData.contentKey: StoryThemeData(
color1: backgroundColor,
color2: backgroundColorDark,
fit: fit,
alignmentX: alignmentX,
alignmentY: alignmentY,
).toJson(),
});
2021-12-24 14:18:09 +01:00
},
);
if (postResult.error == null) {
2021-12-28 19:30:19 +01:00
VRouter.of(context).pop();
2021-12-24 14:18:09 +01:00
}
}
2022-02-20 10:24:23 +01:00
void onVerticalDragUpdate(DragUpdateDetails details) {
final delta = details.primaryDelta;
if (delta == null) return;
if (delta > 0 && alignmentY < 100) {
setState(() {
alignmentY += 1;
});
} else if (delta < 0 && alignmentY > -100) {
setState(() {
alignmentY -= 1;
});
}
}
void onHorizontalDragUpdate(DragUpdateDetails details) {
final delta = details.primaryDelta;
if (delta == null) return;
if (delta > 0 && alignmentX < 100) {
setState(() {
alignmentX += 1;
});
} else if (delta < 0 && alignmentX > -100) {
setState(() {
alignmentX -= 1;
});
}
}
2021-12-24 14:18:09 +01:00
@override
void initState() {
super.initState();
2022-02-20 10:24:23 +01:00
final rand = Random().nextInt(1000).toString();
backgroundColor = rand.color;
backgroundColorDark = rand.darkColor;
2022-02-11 22:50:20 +01:00
focusNode.addListener(() {
if (textFieldHasFocus != focusNode.hasFocus) {
setState(() {
textFieldHasFocus = focusNode.hasFocus;
});
}
});
2021-12-25 18:47:36 +01:00
final shareContent = Matrix.of(context).shareContent;
if (shareContent != null) {
2022-02-06 17:24:09 +01:00
controller.text = shareContent.tryGet<String>('body') ?? '';
final shareFile = shareContent.tryGet<MatrixFile>('file')?.detectFileType;
if (shareFile is MatrixImageFile) {
2022-02-06 17:24:09 +01:00
setState(() {
image = shareFile;
});
} else if (shareFile is MatrixVideoFile) {
setState(() {
video = shareFile;
});
}
final msgType = shareContent.tryGet<String>('msgtype');
if (msgType == MessageTypes.Image) {
2021-12-25 18:47:36 +01:00
Event(
content: shareContent,
type: EventTypes.Message,
room: Room(id: '!tmproom', client: Matrix.of(context).client),
eventId: 'tmpevent',
senderId: '@tmpsender:example',
originServerTs: DateTime.now(),
).downloadAndDecryptAttachment().then((file) {
setState(() {
2022-02-06 17:24:09 +01:00
image = file.detectFileType as MatrixImageFile;
2021-12-25 18:47:36 +01:00
});
});
2022-02-06 17:24:09 +01:00
} else if (msgType == MessageTypes.Video) {
2021-12-25 18:47:36 +01:00
Event(
content: shareContent,
type: EventTypes.Message,
room: Room(id: '!tmproom', client: Matrix.of(context).client),
eventId: 'tmpevent',
senderId: '@tmpsender:example',
originServerTs: DateTime.now(),
).downloadAndDecryptAttachment().then((file) {
setState(() {
2022-02-06 17:24:09 +01:00
video = file.detectFileType as MatrixVideoFile;
2021-12-25 18:47:36 +01:00
});
});
}
Matrix.of(context).shareContent = null;
}
2021-12-24 14:18:09 +01:00
}
2022-01-15 12:01:14 +01:00
@override
void dispose() {
videoPlayerController?.dispose();
super.dispose();
}
2021-12-24 14:18:09 +01:00
@override
Widget build(BuildContext context) => AddStoryView(this);
}