fixed some issues with the migration

This commit is contained in:
otsmr 2025-11-08 13:36:54 +01:00
parent 80d6f85350
commit d59b8602f9
3 changed files with 103 additions and 129 deletions

View file

@ -1,7 +1,6 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
import 'package:camera/camera.dart'; import 'package:camera/camera.dart';
import 'package:drift/drift.dart' show Value;
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_android_volume_keydown/flutter_android_volume_keydown.dart'; import 'package:flutter_android_volume_keydown/flutter_android_volume_keydown.dart';

View file

@ -218,7 +218,16 @@ class _UserListItem extends State<GroupListItem> {
subtitle: (_currentMessage == null) subtitle: (_currentMessage == null)
? (widget.group.totalMediaCounter == 0) ? (widget.group.totalMediaCounter == 0)
? Text(context.lang.chatsTapToSend) ? Text(context.lang.chatsTapToSend)
: LastMessageTime(dateTime: widget.group.lastMessageExchange) : Row(
children: [
LastMessageTime(
dateTime: widget.group.lastMessageExchange),
FlameCounterWidget(
groupId: widget.group.groupId,
prefix: true,
),
],
)
: Row( : Row(
children: [ children: [
MessageSendStateIcon( MessageSendStateIcon(

View file

@ -1,5 +1,7 @@
import 'dart:collection' show HashSet;
import 'dart:convert'; import 'dart:convert';
import 'dart:io'; import 'dart:io';
import 'package:cryptography_plus/cryptography_plus.dart';
import 'package:drift/drift.dart'; import 'package:drift/drift.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:path/path.dart'; import 'package:path/path.dart';
@ -8,13 +10,11 @@ import 'package:restart_app/restart_app.dart';
import 'package:twonly/globals.dart'; import 'package:twonly/globals.dart';
import 'package:twonly/src/database/daos/contacts.dao.dart'; import 'package:twonly/src/database/daos/contacts.dao.dart';
import 'package:twonly/src/database/tables/mediafiles.table.dart'; import 'package:twonly/src/database/tables/mediafiles.table.dart';
import 'package:twonly/src/database/tables/messages.table.dart';
import 'package:twonly/src/database/twonly.db.dart'; import 'package:twonly/src/database/twonly.db.dart';
import 'package:twonly/src/database/twonly_database_old.dart' import 'package:twonly/src/database/twonly_database_old.dart'
show TwonlyDatabaseOld; show TwonlyDatabaseOld;
import 'package:twonly/src/services/mediafiles/mediafile.service.dart'; import 'package:twonly/src/services/mediafiles/mediafile.service.dart';
import 'package:twonly/src/utils/log.dart'; import 'package:twonly/src/utils/log.dart';
import 'package:twonly/src/utils/misc.dart';
import 'package:twonly/src/utils/storage.dart'; import 'package:twonly/src/utils/storage.dart';
class DatabaseMigrationView extends StatefulWidget { class DatabaseMigrationView extends StatefulWidget {
@ -37,14 +37,14 @@ class _DatabaseMigrationViewState extends State<DatabaseMigrationView> {
final oldDatabase = TwonlyDatabaseOld(); final oldDatabase = TwonlyDatabaseOld();
final oldContacts = await oldDatabase.contacts.select().get(); final oldContacts = await oldDatabase.contacts.select().get();
final oldMessages = await oldDatabase.messages.select().get();
for (final oldContact in oldContacts) { for (final oldContact in oldContacts) {
try {
if (oldContact.deleted) continue; if (oldContact.deleted) continue;
Uint8List? avatarSvg; Uint8List? avatarSvg;
if (oldContact.avatarSvg != null) { if (oldContact.avatarSvg != null) {
avatarSvg = avatarSvg = Uint8List.fromList(
Uint8List.fromList(gzip.encode(utf8.encode(oldContact.avatarSvg!))); gzip.encode(utf8.encode(oldContact.avatarSvg!)));
} }
await twonlyDB.contactsDao.insertContact( await twonlyDB.contactsDao.insertContact(
ContactsCompanion( ContactsCompanion(
@ -64,7 +64,7 @@ class _DatabaseMigrationViewState extends State<DatabaseMigrationView> {
setState(() { setState(() {
_contactsMigrated += 1; _contactsMigrated += 1;
}); });
final group = await twonlyDB.groupsDao.createNewDirectChat( await twonlyDB.groupsDao.createNewDirectChat(
oldContact.userId, oldContact.userId,
GroupsCompanion( GroupsCompanion(
pinned: Value(oldContact.pinned), pinned: Value(oldContact.pinned),
@ -79,86 +79,48 @@ class _DatabaseMigrationViewState extends State<DatabaseMigrationView> {
lastMessageReceived: Value(oldContact.lastMessageReceived), lastMessageReceived: Value(oldContact.lastMessageReceived),
lastMessageSend: Value(oldContact.lastMessageSend), lastMessageSend: Value(oldContact.lastMessageSend),
flameCounter: Value(oldContact.flameCounter), flameCounter: Value(oldContact.flameCounter),
maxFlameCounter: Value(oldContact.flameCounter),
maxFlameCounterFrom: Value(DateTime.now()),
), ),
); );
if (group == null) continue; } catch (e) {
for (final oldMessage in oldMessages) { Log.error(e);
if (oldMessage.mediaUploadId == null &&
oldMessage.mediaDownloadId == null) {
/// only interested in media files...
continue;
}
if (oldMessage.contactId != oldContact.userId) continue;
if (!oldMessage.mediaStored) continue;
var storedMediaPath =
join((await getApplicationSupportDirectory()).path, 'media');
if (oldMessage.mediaDownloadId != null) {
storedMediaPath =
'${join(storedMediaPath, 'received')}/${oldMessage.mediaDownloadId}';
} else {
storedMediaPath =
'${join(storedMediaPath, 'send')}/${oldMessage.mediaDownloadId}';
}
var type = MediaType.image;
if (File('$storedMediaPath.mp4').existsSync()) {
type = MediaType.video;
storedMediaPath = '$storedMediaPath.mp4';
} else if (File('$storedMediaPath.png').existsSync()) {
type = MediaType.image;
storedMediaPath = '$storedMediaPath.png';
} else if (File('$storedMediaPath.webp').existsSync()) {
type = MediaType.image;
storedMediaPath = '$storedMediaPath.webp';
} else {
continue;
}
final uniqueId = Value(
getUUIDforDirectChat(
oldMessage.messageOtherId ?? oldMessage.messageId,
oldMessage.contactId ^ gUser.userId,
),
);
final mediaFile = await twonlyDB.mediaFilesDao.insertMedia(
MediaFilesCompanion(
mediaId: uniqueId,
stored: const Value(true),
type: Value(type),
createdAt: Value(oldMessage.sendAt),
),
);
if (mediaFile == null) continue;
final message = await twonlyDB.messagesDao.insertMessage(
MessagesCompanion(
messageId: uniqueId,
groupId: Value(group.groupId),
mediaId: uniqueId,
type: const Value(MessageType.media),
),
);
if (message == null) continue;
final mediaService = await MediaFileService.fromMedia(mediaFile);
File(storedMediaPath).copySync(mediaService.storedPath.path);
setState(() {
_storedMediaFiles += 1;
});
} }
} }
final folders = ['memories', 'send', 'received'];
final alreadyCopied = HashSet();
for (final folder in folders) {
final memoriesPath = Directory( final memoriesPath = Directory(
join((await getApplicationSupportDirectory()).path, 'media', 'memories'), join(
(await getApplicationSupportDirectory()).path,
'media',
folder,
),
); );
if (memoriesPath.existsSync()) { if (memoriesPath.existsSync()) {
final files = memoriesPath.listSync(); final files = memoriesPath.listSync();
for (final file in files) { for (final file in files) {
try {
if (file.path.contains('thumbnail')) continue; if (file.path.contains('thumbnail')) continue;
final type = late MediaType type;
file.path.contains('mp4') ? MediaType.video : MediaType.image; if (file.path.contains('mp4')) {
type = MediaType.video;
} else if (file.path.contains('png')) {
type = MediaType.image;
} else {
continue;
}
final bytes = File(file.path).readAsBytesSync();
final digest = (await Sha256().hash(bytes)).bytes;
if (alreadyCopied.contains(digest)) {
continue;
}
alreadyCopied.add(digest);
final stat = FileStat.statSync(file.path); final stat = FileStat.statSync(file.path);
final mediaFile = await twonlyDB.mediaFilesDao.insertMedia( final mediaFile = await twonlyDB.mediaFilesDao.insertMedia(
MediaFilesCompanion( MediaFilesCompanion(
@ -172,6 +134,10 @@ class _DatabaseMigrationViewState extends State<DatabaseMigrationView> {
setState(() { setState(() {
_storedMediaFiles += 1; _storedMediaFiles += 1;
}); });
} catch (e) {
Log.error(e);
}
}
} }
} }