mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-06-25 02:54:07 +00:00
use media id as filename
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
Some checks are pending
Flutter analyze & test / flutter_analyze_and_test (push) Waiting to run
This commit is contained in:
parent
f14a94d639
commit
4c42d55afd
7 changed files with 111 additions and 21 deletions
|
|
@ -1,5 +1,10 @@
|
|||
# Changelog
|
||||
|
||||
## 0.3.3
|
||||
|
||||
- Fix: Multiple UI issues
|
||||
- Fix: Camera initialization issue
|
||||
|
||||
## 0.3.2
|
||||
|
||||
- Fix: Multiple smaller performance and UI issues
|
||||
|
|
|
|||
|
|
@ -33,7 +33,7 @@ import 'package:twonly/src/utils/startup_guard.dart';
|
|||
|
||||
final _initMutex = Mutex();
|
||||
|
||||
/// This function is used to initialized the absolute minimum so it
|
||||
/// This function is used to initialize the absolute minimum so it
|
||||
/// can also be used by the backend without the UI was loaded.
|
||||
Future<bool> twonlyMinimumInitialization() async {
|
||||
Log.info('twonlyMinimumInitialization: called');
|
||||
|
|
|
|||
|
|
@ -314,11 +314,15 @@ class MediaFileService {
|
|||
await tempPath.copy(storedPath.path);
|
||||
if (userService.currentUser.storeMediaFilesInGallery) {
|
||||
if (mediaFile.type == MediaType.video) {
|
||||
await saveVideoToGallery(storedPath.path);
|
||||
await saveVideoToGallery(
|
||||
storedPath.path,
|
||||
name: mediaFile.mediaId,
|
||||
);
|
||||
} else {
|
||||
await saveImageToGallery(
|
||||
storedPath.readAsBytesSync(),
|
||||
createdAt: mediaFile.createdAt,
|
||||
name: mediaFile.mediaId,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'package:gal/gal.dart';
|
|||
import 'package:image/image.dart' as img;
|
||||
import 'package:intl/intl.dart';
|
||||
import 'package:local_auth/local_auth.dart';
|
||||
import 'package:path/path.dart';
|
||||
import 'package:provider/provider.dart';
|
||||
import 'package:twonly/src/localization/generated/app_localizations.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/websocket/error.pb.dart';
|
||||
|
|
@ -36,6 +37,7 @@ extension ShortCutsExtension on BuildContext {
|
|||
Future<String?> saveImageToGallery(
|
||||
Uint8List imageBytes, {
|
||||
DateTime? createdAt,
|
||||
String? name,
|
||||
}) async {
|
||||
var bytesToProcess = imageBytes;
|
||||
|
||||
|
|
@ -75,7 +77,7 @@ Future<String?> saveImageToGallery(
|
|||
await Gal.requestAccess(toAlbum: true);
|
||||
}
|
||||
try {
|
||||
await Gal.putImageBytes(jpgImages, album: 'twonly');
|
||||
await Gal.putImageBytes(jpgImages, album: 'twonly', name: name ?? 'image');
|
||||
return null;
|
||||
} on GalException catch (e) {
|
||||
Log.error(e);
|
||||
|
|
@ -83,17 +85,45 @@ Future<String?> saveImageToGallery(
|
|||
}
|
||||
}
|
||||
|
||||
Future<String?> saveVideoToGallery(String videoPath) async {
|
||||
Future<String?> saveVideoToGallery(
|
||||
String videoPath, {
|
||||
String? name,
|
||||
}) async {
|
||||
final hasAccess = await Gal.hasAccess(toAlbum: true);
|
||||
if (!hasAccess) {
|
||||
await Gal.requestAccess(toAlbum: true);
|
||||
}
|
||||
|
||||
var pathToSave = videoPath;
|
||||
File? tempFile;
|
||||
|
||||
try {
|
||||
await Gal.putVideo(videoPath, album: 'twonly');
|
||||
if (name != null) {
|
||||
final file = File(videoPath);
|
||||
final extension = file.path.split('.').last;
|
||||
final tempDir = Directory.systemTemp;
|
||||
tempFile = File(join(tempDir.path, '$name.$extension'));
|
||||
if (tempFile.existsSync()) {
|
||||
try {
|
||||
tempFile.deleteSync();
|
||||
} catch (_) {}
|
||||
}
|
||||
file.copySync(tempFile.path);
|
||||
pathToSave = tempFile.path;
|
||||
}
|
||||
await Gal.putVideo(pathToSave, album: 'twonly');
|
||||
return null;
|
||||
} on GalException catch (e) {
|
||||
Log.error(e);
|
||||
return e.type.message;
|
||||
} finally {
|
||||
if (tempFile != null && tempFile.existsSync()) {
|
||||
try {
|
||||
tempFile.deleteSync();
|
||||
} catch (e) {
|
||||
Log.error('Failed to delete temp video file: $e');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -310,11 +310,18 @@ class MemoriesViewState extends State<MemoriesView> with AutomaticKeepAliveClien
|
|||
if (item != null) {
|
||||
final media = item.mediaService;
|
||||
if (media.mediaFile.type == MediaType.video) {
|
||||
await saveVideoToGallery(media.storedPath.path);
|
||||
await saveVideoToGallery(
|
||||
media.storedPath.path,
|
||||
name: media.mediaFile.mediaId,
|
||||
);
|
||||
} else if (media.mediaFile.type == MediaType.image ||
|
||||
media.mediaFile.type == MediaType.gif) {
|
||||
final imageBytes = await media.storedPath.readAsBytes();
|
||||
await saveImageToGallery(imageBytes, createdAt: media.mediaFile.createdAt);
|
||||
await saveImageToGallery(
|
||||
imageBytes,
|
||||
createdAt: media.mediaFile.createdAt,
|
||||
name: media.mediaFile.mediaId,
|
||||
);
|
||||
}
|
||||
}
|
||||
setProgress((i + 1) / selectedList.length);
|
||||
|
|
|
|||
|
|
@ -193,11 +193,18 @@ class _SynchronizedImageViewerScreenState
|
|||
|
||||
try {
|
||||
if (item.mediaFile.type == MediaType.video) {
|
||||
await saveVideoToGallery(item.storedPath.path);
|
||||
await saveVideoToGallery(
|
||||
item.storedPath.path,
|
||||
name: item.mediaFile.mediaId,
|
||||
);
|
||||
} else if (item.mediaFile.type == MediaType.image ||
|
||||
item.mediaFile.type == MediaType.gif) {
|
||||
final imageBytes = await item.storedPath.readAsBytes();
|
||||
await saveImageToGallery(imageBytes, createdAt: item.mediaFile.createdAt);
|
||||
await saveImageToGallery(
|
||||
imageBytes,
|
||||
createdAt: item.mediaFile.createdAt,
|
||||
name: item.mediaFile.mediaId,
|
||||
);
|
||||
}
|
||||
if (!mounted) return;
|
||||
showSnackbar(
|
||||
|
|
|
|||
|
|
@ -13,6 +13,7 @@ import 'package:twonly/src/database/tables/mediafiles.table.dart';
|
|||
import 'package:twonly/src/database/twonly.db.dart';
|
||||
import 'package:twonly/src/services/android_photo_picker.service.dart';
|
||||
import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
|
||||
import 'package:twonly/src/utils/log.dart';
|
||||
import 'package:twonly/src/utils/misc.dart' show ShortCutsExtension, sha256File;
|
||||
import 'package:twonly/src/visual/components/selectable_thumbnail.comp.dart';
|
||||
import 'package:twonly/src/visual/components/snackbar.dart';
|
||||
|
|
@ -84,8 +85,8 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
|
||||
final hash = Uint8List.fromList(sha256.convert(bytes).bytes);
|
||||
|
||||
final exsits = await twonlyDB.mediaFilesDao.getMediaByHash(hash);
|
||||
if (exsits.isNotEmpty) {
|
||||
final exists = await twonlyDB.mediaFilesDao.getMediaByHash(hash);
|
||||
if (exists.isNotEmpty) {
|
||||
duplicated += 1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -345,8 +346,8 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
|
||||
final hash = Uint8List.fromList(await sha256File(file));
|
||||
|
||||
final exsits = await twonlyDB.mediaFilesDao.getMediaByHash(hash);
|
||||
if (exsits.isNotEmpty) {
|
||||
final exists = await twonlyDB.mediaFilesDao.getMediaByHash(hash);
|
||||
if (exists.isNotEmpty) {
|
||||
duplicated += 1;
|
||||
continue;
|
||||
}
|
||||
|
|
@ -363,7 +364,42 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
type = MediaType.image;
|
||||
}
|
||||
|
||||
final mediaFile = await twonlyDB.mediaFilesDao.insertOrUpdateMedia(
|
||||
MediaFile? mediaFile;
|
||||
var isRestored = false;
|
||||
|
||||
if (Platform.isIOS) {
|
||||
try {
|
||||
final assetName = await asset.titleAsync;
|
||||
final dotIndex = assetName.lastIndexOf('.');
|
||||
final baseName = dotIndex != -1 ? assetName.substring(0, dotIndex) : assetName;
|
||||
|
||||
final uuidRegex = RegExp(
|
||||
r'^[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$',
|
||||
);
|
||||
if (uuidRegex.hasMatch(baseName)) {
|
||||
final existing = await twonlyDB.mediaFilesDao.getMediaFileById(baseName);
|
||||
if (existing != null) {
|
||||
final mediaService = MediaFileService(existing);
|
||||
if (!mediaService.storedPath.existsSync()) {
|
||||
await twonlyDB.mediaFilesDao.updateMedia(
|
||||
baseName,
|
||||
MediaFilesCompanion(
|
||||
storedFileHash: Value(hash),
|
||||
stored: const Value(true),
|
||||
),
|
||||
);
|
||||
mediaFile = await twonlyDB.mediaFilesDao.getMediaFileById(baseName);
|
||||
isRestored = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (e) {
|
||||
Log.error('Error checking iOS asset UUID name: $e');
|
||||
}
|
||||
}
|
||||
|
||||
if (!isRestored) {
|
||||
mediaFile = await twonlyDB.mediaFilesDao.insertOrUpdateMedia(
|
||||
MediaFilesCompanion(
|
||||
type: Value(type),
|
||||
createdAt: Value(createdAt),
|
||||
|
|
@ -371,6 +407,7 @@ class _ImportFromGalleryViewState extends State<ImportFromGalleryView> {
|
|||
stored: const Value(true),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
if (mediaFile != null) {
|
||||
final mediaService = MediaFileService(mediaFile);
|
||||
|
|
|
|||
Loading…
Reference in a new issue