mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 16:28:40 +00:00
fix #183
This commit is contained in:
parent
e7b48ecf63
commit
25d2edf89e
4 changed files with 75 additions and 23 deletions
|
|
@ -91,11 +91,6 @@ Future retryMediaUpload({int maxRetries = 3}) async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (maxRetries == 0) return;
|
|
||||||
// retry upload
|
|
||||||
// Future.delayed(const Duration(milliseconds: 1000), () {
|
|
||||||
// retryMediaUpload(maxRetries: maxRetries - 1);
|
|
||||||
// });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int?> initMediaUpload() async {
|
Future<int?> initMediaUpload() async {
|
||||||
|
|
@ -576,7 +571,7 @@ Future<void> deleteMediaFile(int mediaUploadId, String type) async {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<String> getMediaFilePath(int mediaId, String type) async {
|
Future<String> getMediaFilePath(dynamic mediaId, String type) async {
|
||||||
final basedir = await getApplicationSupportDirectory();
|
final basedir = await getApplicationSupportDirectory();
|
||||||
final mediaSendDir = Directory(join(basedir.path, 'media', type));
|
final mediaSendDir = Directory(join(basedir.path, 'media', type));
|
||||||
if (!await mediaSendDir.exists()) {
|
if (!await mediaSendDir.exists()) {
|
||||||
|
|
@ -585,6 +580,15 @@ Future<String> getMediaFilePath(int mediaId, String type) async {
|
||||||
return join(mediaSendDir.path, '$mediaId');
|
return join(mediaSendDir.path, '$mediaId');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<String> getMediaBaseFilePath(String type) async {
|
||||||
|
final basedir = await getApplicationSupportDirectory();
|
||||||
|
final mediaSendDir = Directory(join(basedir.path, 'media', type));
|
||||||
|
if (!await mediaSendDir.exists()) {
|
||||||
|
await mediaSendDir.create(recursive: true);
|
||||||
|
}
|
||||||
|
return mediaSendDir.path;
|
||||||
|
}
|
||||||
|
|
||||||
/// combines two utf8 list
|
/// combines two utf8 list
|
||||||
Uint8List combineUint8Lists(Uint8List list1, Uint8List list2) {
|
Uint8List combineUint8Lists(Uint8List list1, Uint8List list2) {
|
||||||
final combinedLength = 4 + list1.length + list2.length;
|
final combinedLength = 4 + list1.length + list2.length;
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,9 @@
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
import 'dart:math';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||||
|
import 'package:path/path.dart';
|
||||||
|
import 'package:twonly/src/providers/api/media_send.dart';
|
||||||
import 'dart:typed_data';
|
import 'dart:typed_data';
|
||||||
|
|
||||||
import 'package:twonly/src/utils/misc.dart';
|
import 'package:twonly/src/utils/misc.dart';
|
||||||
|
|
@ -9,11 +12,13 @@ class SaveToGalleryButton extends StatefulWidget {
|
||||||
final Future<Uint8List?> Function() getMergedImage;
|
final Future<Uint8List?> Function() getMergedImage;
|
||||||
final String? sendNextMediaToUserName;
|
final String? sendNextMediaToUserName;
|
||||||
final File? videoFilePath;
|
final File? videoFilePath;
|
||||||
|
final int? mediaUploadId;
|
||||||
|
|
||||||
const SaveToGalleryButton(
|
const SaveToGalleryButton(
|
||||||
{super.key,
|
{super.key,
|
||||||
required this.getMergedImage,
|
required this.getMergedImage,
|
||||||
this.sendNextMediaToUserName,
|
this.sendNextMediaToUserName,
|
||||||
|
this.mediaUploadId,
|
||||||
this.videoFilePath});
|
this.videoFilePath});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -41,12 +46,26 @@ class SaveToGalleryButtonState extends State<SaveToGalleryButton> {
|
||||||
});
|
});
|
||||||
|
|
||||||
String? res;
|
String? res;
|
||||||
|
String memoryPath = await getMediaBaseFilePath("memories");
|
||||||
|
|
||||||
|
if (widget.mediaUploadId != null) {
|
||||||
|
memoryPath = join(memoryPath, "${widget.mediaUploadId!}");
|
||||||
|
} else {
|
||||||
|
final Random random = Random();
|
||||||
|
String token = uint8ListToHex(
|
||||||
|
List<int>.generate(32, (i) => random.nextInt(256)));
|
||||||
|
memoryPath = join(memoryPath, token);
|
||||||
|
}
|
||||||
|
|
||||||
if (widget.videoFilePath != null) {
|
if (widget.videoFilePath != null) {
|
||||||
|
memoryPath += ".mp4";
|
||||||
|
await File(widget.videoFilePath!.path).copy(memoryPath);
|
||||||
res = await saveVideoToGallery(widget.videoFilePath!.path);
|
res = await saveVideoToGallery(widget.videoFilePath!.path);
|
||||||
} else {
|
} else {
|
||||||
|
memoryPath += ".png";
|
||||||
Uint8List? imageBytes = await widget.getMergedImage();
|
Uint8List? imageBytes = await widget.getMergedImage();
|
||||||
if (imageBytes == null || !context.mounted) return;
|
if (imageBytes == null || !context.mounted) return;
|
||||||
|
await File(memoryPath).writeAsBytes(imageBytes);
|
||||||
res = await saveImageToGallery(imageBytes);
|
res = await saveImageToGallery(imageBytes);
|
||||||
}
|
}
|
||||||
if (res == null) {
|
if (res == null) {
|
||||||
|
|
|
||||||
|
|
@ -535,6 +535,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||||
children: [
|
children: [
|
||||||
SaveToGalleryButton(
|
SaveToGalleryButton(
|
||||||
getMergedImage: getMergedImage,
|
getMergedImage: getMergedImage,
|
||||||
|
mediaUploadId: mediaUploadId,
|
||||||
videoFilePath: widget.videoFilePath,
|
videoFilePath: widget.videoFilePath,
|
||||||
sendNextMediaToUserName: sendNextMediaToUserName,
|
sendNextMediaToUserName: sendNextMediaToUserName,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ class GalleryItem {
|
||||||
this.imagePath,
|
this.imagePath,
|
||||||
this.videoPath,
|
this.videoPath,
|
||||||
});
|
});
|
||||||
final int id;
|
final String id;
|
||||||
final List<Message> messages;
|
final List<Message> messages;
|
||||||
final DateTime date;
|
final DateTime date;
|
||||||
final File? imagePath;
|
final File? imagePath;
|
||||||
|
|
@ -135,6 +135,40 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
||||||
initAsync();
|
initAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<GalleryItem>> loadMemoriesDirectory() async {
|
||||||
|
final directoryPath = await send.getMediaBaseFilePath("memories");
|
||||||
|
final directory = Directory(directoryPath);
|
||||||
|
|
||||||
|
List<GalleryItem> items = [];
|
||||||
|
if (await directory.exists()) {
|
||||||
|
final files = directory.listSync();
|
||||||
|
|
||||||
|
for (var file in files) {
|
||||||
|
if (file is File) {
|
||||||
|
final fileName = file.uri.pathSegments.last;
|
||||||
|
File? imagePath;
|
||||||
|
File? videoPath;
|
||||||
|
if (fileName.contains(".png")) {
|
||||||
|
imagePath = file;
|
||||||
|
} else if (fileName.contains(".mp4")) {
|
||||||
|
videoPath = file;
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
final creationDate = await file.lastModified();
|
||||||
|
items.add(GalleryItem(
|
||||||
|
id: fileName,
|
||||||
|
messages: [],
|
||||||
|
date: creationDate,
|
||||||
|
imagePath: imagePath,
|
||||||
|
videoPath: videoPath,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return items;
|
||||||
|
}
|
||||||
|
|
||||||
Future initAsync() async {
|
Future initAsync() async {
|
||||||
List<Message> storedMediaFiles =
|
List<Message> storedMediaFiles =
|
||||||
await twonlyDatabase.messagesDao.getAllStoredMediaFiles();
|
await twonlyDatabase.messagesDao.getAllStoredMediaFiles();
|
||||||
|
|
@ -160,7 +194,7 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
||||||
.putIfAbsent(
|
.putIfAbsent(
|
||||||
id,
|
id,
|
||||||
() => GalleryItem(
|
() => GalleryItem(
|
||||||
id: id,
|
id: id.toString(),
|
||||||
messages: [],
|
messages: [],
|
||||||
date: message.sendAt,
|
date: message.sendAt,
|
||||||
imagePath: imagePath,
|
imagePath: imagePath,
|
||||||
|
|
@ -174,7 +208,9 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
||||||
months = [];
|
months = [];
|
||||||
|
|
||||||
String lastMonth = "";
|
String lastMonth = "";
|
||||||
galleryItems = items.values.toList();
|
galleryItems = await loadMemoriesDirectory();
|
||||||
|
galleryItems += items.values.toList();
|
||||||
|
galleryItems.sort((a, b) => b.date.compareTo(a.date));
|
||||||
for (var i = 0; i < galleryItems.length; i++) {
|
for (var i = 0; i < galleryItems.length; i++) {
|
||||||
String month = DateFormat('MMMM yyyy').format(galleryItems[i].date);
|
String month = DateFormat('MMMM yyyy').format(galleryItems[i].date);
|
||||||
if (lastMonth != month) {
|
if (lastMonth != month) {
|
||||||
|
|
@ -232,9 +268,9 @@ class GalleryMainViewState extends State<GalleryMainView> {
|
||||||
MaterialPageRoute(
|
MaterialPageRoute(
|
||||||
builder: (context) => GalleryPhotoViewWrapper(
|
builder: (context) => GalleryPhotoViewWrapper(
|
||||||
galleryItems: galleryItems,
|
galleryItems: galleryItems,
|
||||||
backgroundDecoration: const BoxDecoration(
|
// backgroundDecoration: const BoxDecoration(
|
||||||
color: Colors.black,
|
// color: Colors.black,
|
||||||
),
|
// ),
|
||||||
initialIndex: index,
|
initialIndex: index,
|
||||||
scrollDirection: verticalGallery ? Axis.vertical : Axis.horizontal,
|
scrollDirection: verticalGallery ? Axis.vertical : Axis.horizontal,
|
||||||
),
|
),
|
||||||
|
|
@ -298,12 +334,10 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||||
FilledButton.icon(
|
FilledButton.icon(
|
||||||
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
|
icon: FaIcon(FontAwesomeIcons.solidPaperPlane),
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
await Navigator.push(
|
Navigator.push(
|
||||||
context,
|
context,
|
||||||
PageRouteBuilder(
|
MaterialPageRoute(
|
||||||
opaque: false,
|
builder: (context) => ShareImageEditorView(
|
||||||
pageBuilder: (context, a1, a2) =>
|
|
||||||
ShareImageEditorView(
|
|
||||||
videoFilePath:
|
videoFilePath:
|
||||||
widget.galleryItems[currentIndex].videoPath,
|
widget.galleryItems[currentIndex].videoPath,
|
||||||
imageBytes: widget
|
imageBytes: widget
|
||||||
|
|
@ -312,12 +346,6 @@ class _GalleryPhotoViewWrapperState extends State<GalleryPhotoViewWrapper> {
|
||||||
mirrorVideo: false,
|
mirrorVideo: false,
|
||||||
useHighQuality: true,
|
useHighQuality: true,
|
||||||
),
|
),
|
||||||
transitionsBuilder:
|
|
||||||
(context, animation, secondaryAnimation, child) {
|
|
||||||
return child;
|
|
||||||
},
|
|
||||||
transitionDuration: Duration.zero,
|
|
||||||
reverseTransitionDuration: Duration.zero,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue