This commit is contained in:
otsmr 2025-11-13 21:28:57 +01:00
parent 1eaa1a5edd
commit 7977d171c7
32 changed files with 14201 additions and 78 deletions

View file

@ -12,3 +12,4 @@ targets:
databases:
twonly_db: lib/src/database/twonly.db.dart
twonly_database: lib/src/database/twonly_database_old.dart
schema_dir: lib/src/database/schemas

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -45,9 +45,6 @@ class MediaFiles extends Table {
BoolColumn get requiresAuthentication =>
boolean().withDefault(const Constant(false))();
BoolColumn get reopenByContact =>
boolean().withDefault(const Constant(false))();
BoolColumn get stored => boolean().withDefault(const Constant(false))();
BoolColumn get isDraftMedia => boolean().withDefault(const Constant(false))();

View file

@ -23,6 +23,8 @@ class Messages extends Table {
.references(MediaFiles, #mediaId, onDelete: KeyAction.setNull)();
BoolColumn get mediaStored => boolean().withDefault(const Constant(false))();
BoolColumn get mediaReopened =>
boolean().withDefault(const Constant(false))();
BlobColumn get downloadToken => blob().nullable()();

View file

@ -21,6 +21,7 @@ import 'package:twonly/src/database/tables/signal_identity_key_store.table.dart'
import 'package:twonly/src/database/tables/signal_pre_key_store.table.dart';
import 'package:twonly/src/database/tables/signal_sender_key_store.table.dart';
import 'package:twonly/src/database/tables/signal_session_store.table.dart';
import 'package:twonly/src/database/twonly.db.steps.dart';
import 'package:twonly/src/utils/log.dart';
part 'twonly.db.g.dart';
@ -66,7 +67,7 @@ class TwonlyDB extends _$TwonlyDB {
TwonlyDB.forTesting(DatabaseConnection super.connection);
@override
int get schemaVersion => 1;
int get schemaVersion => 2;
static QueryExecutor _openConnection() {
return driftDatabase(
@ -83,7 +84,12 @@ class TwonlyDB extends _$TwonlyDB {
beforeOpen: (details) async {
await customStatement('PRAGMA foreign_keys = ON');
},
// onUpgrade: stepByStep(),
onUpgrade: stepByStep(
from1To2: (m, schema) async {
await m.addColumn(schema.messages, schema.messages.mediaReopened);
await m.dropColumn(schema.mediaFiles, 'reopen_by_contact');
},
),
);
}

View file

@ -1886,16 +1886,6 @@ class $MediaFilesTable extends MediaFiles
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("requires_authentication" IN (0, 1))'),
defaultValue: const Constant(false));
static const VerificationMeta _reopenByContactMeta =
const VerificationMeta('reopenByContact');
@override
late final GeneratedColumn<bool> reopenByContact = GeneratedColumn<bool>(
'reopen_by_contact', aliasedName, false,
type: DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("reopen_by_contact" IN (0, 1))'),
defaultValue: const Constant(false));
static const VerificationMeta _storedMeta = const VerificationMeta('stored');
@override
late final GeneratedColumn<bool> stored = GeneratedColumn<bool>(
@ -1976,7 +1966,6 @@ class $MediaFilesTable extends MediaFiles
uploadState,
downloadState,
requiresAuthentication,
reopenByContact,
stored,
isDraftMedia,
reuploadRequestedBy,
@ -2010,12 +1999,6 @@ class $MediaFilesTable extends MediaFiles
requiresAuthentication.isAcceptableOrUnknown(
data['requires_authentication']!, _requiresAuthenticationMeta));
}
if (data.containsKey('reopen_by_contact')) {
context.handle(
_reopenByContactMeta,
reopenByContact.isAcceptableOrUnknown(
data['reopen_by_contact']!, _reopenByContactMeta));
}
if (data.containsKey('stored')) {
context.handle(_storedMeta,
stored.isAcceptableOrUnknown(data['stored']!, _storedMeta));
@ -2089,8 +2072,6 @@ class $MediaFilesTable extends MediaFiles
requiresAuthentication: attachedDatabase.typeMapping.read(
DriftSqlType.bool,
data['${effectivePrefix}requires_authentication'])!,
reopenByContact: attachedDatabase.typeMapping.read(
DriftSqlType.bool, data['${effectivePrefix}reopen_by_contact'])!,
stored: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}stored'])!,
isDraftMedia: attachedDatabase.typeMapping
@ -2146,7 +2127,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
final UploadState? uploadState;
final DownloadState? downloadState;
final bool requiresAuthentication;
final bool reopenByContact;
final bool stored;
final bool isDraftMedia;
final List<int>? reuploadRequestedBy;
@ -2163,7 +2143,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
this.uploadState,
this.downloadState,
required this.requiresAuthentication,
required this.reopenByContact,
required this.stored,
required this.isDraftMedia,
this.reuploadRequestedBy,
@ -2191,7 +2170,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
$MediaFilesTable.$converterdownloadStaten.toSql(downloadState));
}
map['requires_authentication'] = Variable<bool>(requiresAuthentication);
map['reopen_by_contact'] = Variable<bool>(reopenByContact);
map['stored'] = Variable<bool>(stored);
map['is_draft_media'] = Variable<bool>(isDraftMedia);
if (!nullToAbsent || reuploadRequestedBy != null) {
@ -2233,7 +2211,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
? const Value.absent()
: Value(downloadState),
requiresAuthentication: Value(requiresAuthentication),
reopenByContact: Value(reopenByContact),
stored: Value(stored),
isDraftMedia: Value(isDraftMedia),
reuploadRequestedBy: reuploadRequestedBy == null && nullToAbsent
@ -2275,7 +2252,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
.fromJson(serializer.fromJson<String?>(json['downloadState'])),
requiresAuthentication:
serializer.fromJson<bool>(json['requiresAuthentication']),
reopenByContact: serializer.fromJson<bool>(json['reopenByContact']),
stored: serializer.fromJson<bool>(json['stored']),
isDraftMedia: serializer.fromJson<bool>(json['isDraftMedia']),
reuploadRequestedBy:
@ -2302,7 +2278,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
'downloadState': serializer.toJson<String?>(
$MediaFilesTable.$converterdownloadStaten.toJson(downloadState)),
'requiresAuthentication': serializer.toJson<bool>(requiresAuthentication),
'reopenByContact': serializer.toJson<bool>(reopenByContact),
'stored': serializer.toJson<bool>(stored),
'isDraftMedia': serializer.toJson<bool>(isDraftMedia),
'reuploadRequestedBy': serializer.toJson<List<int>?>(reuploadRequestedBy),
@ -2323,7 +2298,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
Value<UploadState?> uploadState = const Value.absent(),
Value<DownloadState?> downloadState = const Value.absent(),
bool? requiresAuthentication,
bool? reopenByContact,
bool? stored,
bool? isDraftMedia,
Value<List<int>?> reuploadRequestedBy = const Value.absent(),
@ -2342,7 +2316,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
downloadState.present ? downloadState.value : this.downloadState,
requiresAuthentication:
requiresAuthentication ?? this.requiresAuthentication,
reopenByContact: reopenByContact ?? this.reopenByContact,
stored: stored ?? this.stored,
isDraftMedia: isDraftMedia ?? this.isDraftMedia,
reuploadRequestedBy: reuploadRequestedBy.present
@ -2375,9 +2348,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
requiresAuthentication: data.requiresAuthentication.present
? data.requiresAuthentication.value
: this.requiresAuthentication,
reopenByContact: data.reopenByContact.present
? data.reopenByContact.value
: this.reopenByContact,
stored: data.stored.present ? data.stored.value : this.stored,
isDraftMedia: data.isDraftMedia.present
? data.isDraftMedia.value
@ -2414,7 +2384,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
..write('uploadState: $uploadState, ')
..write('downloadState: $downloadState, ')
..write('requiresAuthentication: $requiresAuthentication, ')
..write('reopenByContact: $reopenByContact, ')
..write('stored: $stored, ')
..write('isDraftMedia: $isDraftMedia, ')
..write('reuploadRequestedBy: $reuploadRequestedBy, ')
@ -2436,7 +2405,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
uploadState,
downloadState,
requiresAuthentication,
reopenByContact,
stored,
isDraftMedia,
reuploadRequestedBy,
@ -2456,7 +2424,6 @@ class MediaFile extends DataClass implements Insertable<MediaFile> {
other.uploadState == this.uploadState &&
other.downloadState == this.downloadState &&
other.requiresAuthentication == this.requiresAuthentication &&
other.reopenByContact == this.reopenByContact &&
other.stored == this.stored &&
other.isDraftMedia == this.isDraftMedia &&
other.reuploadRequestedBy == this.reuploadRequestedBy &&
@ -2476,7 +2443,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
final Value<UploadState?> uploadState;
final Value<DownloadState?> downloadState;
final Value<bool> requiresAuthentication;
final Value<bool> reopenByContact;
final Value<bool> stored;
final Value<bool> isDraftMedia;
final Value<List<int>?> reuploadRequestedBy;
@ -2494,7 +2460,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
this.uploadState = const Value.absent(),
this.downloadState = const Value.absent(),
this.requiresAuthentication = const Value.absent(),
this.reopenByContact = const Value.absent(),
this.stored = const Value.absent(),
this.isDraftMedia = const Value.absent(),
this.reuploadRequestedBy = const Value.absent(),
@ -2513,7 +2478,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
this.uploadState = const Value.absent(),
this.downloadState = const Value.absent(),
this.requiresAuthentication = const Value.absent(),
this.reopenByContact = const Value.absent(),
this.stored = const Value.absent(),
this.isDraftMedia = const Value.absent(),
this.reuploadRequestedBy = const Value.absent(),
@ -2533,7 +2497,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
Expression<String>? uploadState,
Expression<String>? downloadState,
Expression<bool>? requiresAuthentication,
Expression<bool>? reopenByContact,
Expression<bool>? stored,
Expression<bool>? isDraftMedia,
Expression<String>? reuploadRequestedBy,
@ -2553,7 +2516,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
if (downloadState != null) 'download_state': downloadState,
if (requiresAuthentication != null)
'requires_authentication': requiresAuthentication,
if (reopenByContact != null) 'reopen_by_contact': reopenByContact,
if (stored != null) 'stored': stored,
if (isDraftMedia != null) 'is_draft_media': isDraftMedia,
if (reuploadRequestedBy != null)
@ -2576,7 +2538,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
Value<UploadState?>? uploadState,
Value<DownloadState?>? downloadState,
Value<bool>? requiresAuthentication,
Value<bool>? reopenByContact,
Value<bool>? stored,
Value<bool>? isDraftMedia,
Value<List<int>?>? reuploadRequestedBy,
@ -2595,7 +2556,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
downloadState: downloadState ?? this.downloadState,
requiresAuthentication:
requiresAuthentication ?? this.requiresAuthentication,
reopenByContact: reopenByContact ?? this.reopenByContact,
stored: stored ?? this.stored,
isDraftMedia: isDraftMedia ?? this.isDraftMedia,
reuploadRequestedBy: reuploadRequestedBy ?? this.reuploadRequestedBy,
@ -2633,9 +2593,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
map['requires_authentication'] =
Variable<bool>(requiresAuthentication.value);
}
if (reopenByContact.present) {
map['reopen_by_contact'] = Variable<bool>(reopenByContact.value);
}
if (stored.present) {
map['stored'] = Variable<bool>(stored.value);
}
@ -2683,7 +2640,6 @@ class MediaFilesCompanion extends UpdateCompanion<MediaFile> {
..write('uploadState: $uploadState, ')
..write('downloadState: $downloadState, ')
..write('requiresAuthentication: $requiresAuthentication, ')
..write('reopenByContact: $reopenByContact, ')
..write('stored: $stored, ')
..write('isDraftMedia: $isDraftMedia, ')
..write('reuploadRequestedBy: $reuploadRequestedBy, ')
@ -2759,6 +2715,16 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> {
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("media_stored" IN (0, 1))'),
defaultValue: const Constant(false));
static const VerificationMeta _mediaReopenedMeta =
const VerificationMeta('mediaReopened');
@override
late final GeneratedColumn<bool> mediaReopened = GeneratedColumn<bool>(
'media_reopened', aliasedName, false,
type: DriftSqlType.bool,
requiredDuringInsert: false,
defaultConstraints: GeneratedColumn.constraintIsAlways(
'CHECK ("media_reopened" IN (0, 1))'),
defaultValue: const Constant(false));
static const VerificationMeta _downloadTokenMeta =
const VerificationMeta('downloadToken');
@override
@ -2828,6 +2794,7 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> {
content,
mediaId,
mediaStored,
mediaReopened,
downloadToken,
quotesMessageId,
isDeletedFromSender,
@ -2878,6 +2845,12 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> {
mediaStored.isAcceptableOrUnknown(
data['media_stored']!, _mediaStoredMeta));
}
if (data.containsKey('media_reopened')) {
context.handle(
_mediaReopenedMeta,
mediaReopened.isAcceptableOrUnknown(
data['media_reopened']!, _mediaReopenedMeta));
}
if (data.containsKey('download_token')) {
context.handle(
_downloadTokenMeta,
@ -2951,6 +2924,8 @@ class $MessagesTable extends Messages with TableInfo<$MessagesTable, Message> {
.read(DriftSqlType.string, data['${effectivePrefix}media_id']),
mediaStored: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}media_stored'])!,
mediaReopened: attachedDatabase.typeMapping
.read(DriftSqlType.bool, data['${effectivePrefix}media_reopened'])!,
downloadToken: attachedDatabase.typeMapping
.read(DriftSqlType.blob, data['${effectivePrefix}download_token']),
quotesMessageId: attachedDatabase.typeMapping.read(
@ -2989,6 +2964,7 @@ class Message extends DataClass implements Insertable<Message> {
final String? content;
final String? mediaId;
final bool mediaStored;
final bool mediaReopened;
final Uint8List? downloadToken;
final String? quotesMessageId;
final bool isDeletedFromSender;
@ -3006,6 +2982,7 @@ class Message extends DataClass implements Insertable<Message> {
this.content,
this.mediaId,
required this.mediaStored,
required this.mediaReopened,
this.downloadToken,
this.quotesMessageId,
required this.isDeletedFromSender,
@ -3033,6 +3010,7 @@ class Message extends DataClass implements Insertable<Message> {
map['media_id'] = Variable<String>(mediaId);
}
map['media_stored'] = Variable<bool>(mediaStored);
map['media_reopened'] = Variable<bool>(mediaReopened);
if (!nullToAbsent || downloadToken != null) {
map['download_token'] = Variable<Uint8List>(downloadToken);
}
@ -3074,6 +3052,7 @@ class Message extends DataClass implements Insertable<Message> {
? const Value.absent()
: Value(mediaId),
mediaStored: Value(mediaStored),
mediaReopened: Value(mediaReopened),
downloadToken: downloadToken == null && nullToAbsent
? const Value.absent()
: Value(downloadToken),
@ -3112,6 +3091,7 @@ class Message extends DataClass implements Insertable<Message> {
content: serializer.fromJson<String?>(json['content']),
mediaId: serializer.fromJson<String?>(json['mediaId']),
mediaStored: serializer.fromJson<bool>(json['mediaStored']),
mediaReopened: serializer.fromJson<bool>(json['mediaReopened']),
downloadToken: serializer.fromJson<Uint8List?>(json['downloadToken']),
quotesMessageId: serializer.fromJson<String?>(json['quotesMessageId']),
isDeletedFromSender:
@ -3136,6 +3116,7 @@ class Message extends DataClass implements Insertable<Message> {
'content': serializer.toJson<String?>(content),
'mediaId': serializer.toJson<String?>(mediaId),
'mediaStored': serializer.toJson<bool>(mediaStored),
'mediaReopened': serializer.toJson<bool>(mediaReopened),
'downloadToken': serializer.toJson<Uint8List?>(downloadToken),
'quotesMessageId': serializer.toJson<String?>(quotesMessageId),
'isDeletedFromSender': serializer.toJson<bool>(isDeletedFromSender),
@ -3156,6 +3137,7 @@ class Message extends DataClass implements Insertable<Message> {
Value<String?> content = const Value.absent(),
Value<String?> mediaId = const Value.absent(),
bool? mediaStored,
bool? mediaReopened,
Value<Uint8List?> downloadToken = const Value.absent(),
Value<String?> quotesMessageId = const Value.absent(),
bool? isDeletedFromSender,
@ -3173,6 +3155,7 @@ class Message extends DataClass implements Insertable<Message> {
content: content.present ? content.value : this.content,
mediaId: mediaId.present ? mediaId.value : this.mediaId,
mediaStored: mediaStored ?? this.mediaStored,
mediaReopened: mediaReopened ?? this.mediaReopened,
downloadToken:
downloadToken.present ? downloadToken.value : this.downloadToken,
quotesMessageId: quotesMessageId.present
@ -3196,6 +3179,9 @@ class Message extends DataClass implements Insertable<Message> {
mediaId: data.mediaId.present ? data.mediaId.value : this.mediaId,
mediaStored:
data.mediaStored.present ? data.mediaStored.value : this.mediaStored,
mediaReopened: data.mediaReopened.present
? data.mediaReopened.value
: this.mediaReopened,
downloadToken: data.downloadToken.present
? data.downloadToken.value
: this.downloadToken,
@ -3227,6 +3213,7 @@ class Message extends DataClass implements Insertable<Message> {
..write('content: $content, ')
..write('mediaId: $mediaId, ')
..write('mediaStored: $mediaStored, ')
..write('mediaReopened: $mediaReopened, ')
..write('downloadToken: $downloadToken, ')
..write('quotesMessageId: $quotesMessageId, ')
..write('isDeletedFromSender: $isDeletedFromSender, ')
@ -3249,6 +3236,7 @@ class Message extends DataClass implements Insertable<Message> {
content,
mediaId,
mediaStored,
mediaReopened,
$driftBlobEquality.hash(downloadToken),
quotesMessageId,
isDeletedFromSender,
@ -3269,6 +3257,7 @@ class Message extends DataClass implements Insertable<Message> {
other.content == this.content &&
other.mediaId == this.mediaId &&
other.mediaStored == this.mediaStored &&
other.mediaReopened == this.mediaReopened &&
$driftBlobEquality.equals(other.downloadToken, this.downloadToken) &&
other.quotesMessageId == this.quotesMessageId &&
other.isDeletedFromSender == this.isDeletedFromSender &&
@ -3288,6 +3277,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
final Value<String?> content;
final Value<String?> mediaId;
final Value<bool> mediaStored;
final Value<bool> mediaReopened;
final Value<Uint8List?> downloadToken;
final Value<String?> quotesMessageId;
final Value<bool> isDeletedFromSender;
@ -3306,6 +3296,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
this.content = const Value.absent(),
this.mediaId = const Value.absent(),
this.mediaStored = const Value.absent(),
this.mediaReopened = const Value.absent(),
this.downloadToken = const Value.absent(),
this.quotesMessageId = const Value.absent(),
this.isDeletedFromSender = const Value.absent(),
@ -3325,6 +3316,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
this.content = const Value.absent(),
this.mediaId = const Value.absent(),
this.mediaStored = const Value.absent(),
this.mediaReopened = const Value.absent(),
this.downloadToken = const Value.absent(),
this.quotesMessageId = const Value.absent(),
this.isDeletedFromSender = const Value.absent(),
@ -3346,6 +3338,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
Expression<String>? content,
Expression<String>? mediaId,
Expression<bool>? mediaStored,
Expression<bool>? mediaReopened,
Expression<Uint8List>? downloadToken,
Expression<String>? quotesMessageId,
Expression<bool>? isDeletedFromSender,
@ -3365,6 +3358,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
if (content != null) 'content': content,
if (mediaId != null) 'media_id': mediaId,
if (mediaStored != null) 'media_stored': mediaStored,
if (mediaReopened != null) 'media_reopened': mediaReopened,
if (downloadToken != null) 'download_token': downloadToken,
if (quotesMessageId != null) 'quotes_message_id': quotesMessageId,
if (isDeletedFromSender != null)
@ -3387,6 +3381,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
Value<String?>? content,
Value<String?>? mediaId,
Value<bool>? mediaStored,
Value<bool>? mediaReopened,
Value<Uint8List?>? downloadToken,
Value<String?>? quotesMessageId,
Value<bool>? isDeletedFromSender,
@ -3405,6 +3400,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
content: content ?? this.content,
mediaId: mediaId ?? this.mediaId,
mediaStored: mediaStored ?? this.mediaStored,
mediaReopened: mediaReopened ?? this.mediaReopened,
downloadToken: downloadToken ?? this.downloadToken,
quotesMessageId: quotesMessageId ?? this.quotesMessageId,
isDeletedFromSender: isDeletedFromSender ?? this.isDeletedFromSender,
@ -3443,6 +3439,9 @@ class MessagesCompanion extends UpdateCompanion<Message> {
if (mediaStored.present) {
map['media_stored'] = Variable<bool>(mediaStored.value);
}
if (mediaReopened.present) {
map['media_reopened'] = Variable<bool>(mediaReopened.value);
}
if (downloadToken.present) {
map['download_token'] = Variable<Uint8List>(downloadToken.value);
}
@ -3486,6 +3485,7 @@ class MessagesCompanion extends UpdateCompanion<Message> {
..write('content: $content, ')
..write('mediaId: $mediaId, ')
..write('mediaStored: $mediaStored, ')
..write('mediaReopened: $mediaReopened, ')
..write('downloadToken: $downloadToken, ')
..write('quotesMessageId: $quotesMessageId, ')
..write('isDeletedFromSender: $isDeletedFromSender, ')
@ -9203,7 +9203,6 @@ typedef $$MediaFilesTableCreateCompanionBuilder = MediaFilesCompanion Function({
Value<UploadState?> uploadState,
Value<DownloadState?> downloadState,
Value<bool> requiresAuthentication,
Value<bool> reopenByContact,
Value<bool> stored,
Value<bool> isDraftMedia,
Value<List<int>?> reuploadRequestedBy,
@ -9222,7 +9221,6 @@ typedef $$MediaFilesTableUpdateCompanionBuilder = MediaFilesCompanion Function({
Value<UploadState?> uploadState,
Value<DownloadState?> downloadState,
Value<bool> requiresAuthentication,
Value<bool> reopenByContact,
Value<bool> stored,
Value<bool> isDraftMedia,
Value<List<int>?> reuploadRequestedBy,
@ -9287,10 +9285,6 @@ class $$MediaFilesTableFilterComposer
column: $table.requiresAuthentication,
builder: (column) => ColumnFilters(column));
ColumnFilters<bool> get reopenByContact => $composableBuilder(
column: $table.reopenByContact,
builder: (column) => ColumnFilters(column));
ColumnFilters<bool> get stored => $composableBuilder(
column: $table.stored, builder: (column) => ColumnFilters(column));
@ -9373,10 +9367,6 @@ class $$MediaFilesTableOrderingComposer
column: $table.requiresAuthentication,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<bool> get reopenByContact => $composableBuilder(
column: $table.reopenByContact,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<bool> get stored => $composableBuilder(
column: $table.stored, builder: (column) => ColumnOrderings(column));
@ -9441,9 +9431,6 @@ class $$MediaFilesTableAnnotationComposer
GeneratedColumn<bool> get requiresAuthentication => $composableBuilder(
column: $table.requiresAuthentication, builder: (column) => column);
GeneratedColumn<bool> get reopenByContact => $composableBuilder(
column: $table.reopenByContact, builder: (column) => column);
GeneratedColumn<bool> get stored =>
$composableBuilder(column: $table.stored, builder: (column) => column);
@ -9525,7 +9512,6 @@ class $$MediaFilesTableTableManager extends RootTableManager<
Value<UploadState?> uploadState = const Value.absent(),
Value<DownloadState?> downloadState = const Value.absent(),
Value<bool> requiresAuthentication = const Value.absent(),
Value<bool> reopenByContact = const Value.absent(),
Value<bool> stored = const Value.absent(),
Value<bool> isDraftMedia = const Value.absent(),
Value<List<int>?> reuploadRequestedBy = const Value.absent(),
@ -9544,7 +9530,6 @@ class $$MediaFilesTableTableManager extends RootTableManager<
uploadState: uploadState,
downloadState: downloadState,
requiresAuthentication: requiresAuthentication,
reopenByContact: reopenByContact,
stored: stored,
isDraftMedia: isDraftMedia,
reuploadRequestedBy: reuploadRequestedBy,
@ -9563,7 +9548,6 @@ class $$MediaFilesTableTableManager extends RootTableManager<
Value<UploadState?> uploadState = const Value.absent(),
Value<DownloadState?> downloadState = const Value.absent(),
Value<bool> requiresAuthentication = const Value.absent(),
Value<bool> reopenByContact = const Value.absent(),
Value<bool> stored = const Value.absent(),
Value<bool> isDraftMedia = const Value.absent(),
Value<List<int>?> reuploadRequestedBy = const Value.absent(),
@ -9582,7 +9566,6 @@ class $$MediaFilesTableTableManager extends RootTableManager<
uploadState: uploadState,
downloadState: downloadState,
requiresAuthentication: requiresAuthentication,
reopenByContact: reopenByContact,
stored: stored,
isDraftMedia: isDraftMedia,
reuploadRequestedBy: reuploadRequestedBy,
@ -9648,6 +9631,7 @@ typedef $$MessagesTableCreateCompanionBuilder = MessagesCompanion Function({
Value<String?> content,
Value<String?> mediaId,
Value<bool> mediaStored,
Value<bool> mediaReopened,
Value<Uint8List?> downloadToken,
Value<String?> quotesMessageId,
Value<bool> isDeletedFromSender,
@ -9667,6 +9651,7 @@ typedef $$MessagesTableUpdateCompanionBuilder = MessagesCompanion Function({
Value<String?> content,
Value<String?> mediaId,
Value<bool> mediaStored,
Value<bool> mediaReopened,
Value<Uint8List?> downloadToken,
Value<String?> quotesMessageId,
Value<bool> isDeletedFromSender,
@ -9817,6 +9802,9 @@ class $$MessagesTableFilterComposer
ColumnFilters<bool> get mediaStored => $composableBuilder(
column: $table.mediaStored, builder: (column) => ColumnFilters(column));
ColumnFilters<bool> get mediaReopened => $composableBuilder(
column: $table.mediaReopened, builder: (column) => ColumnFilters(column));
ColumnFilters<Uint8List> get downloadToken => $composableBuilder(
column: $table.downloadToken, builder: (column) => ColumnFilters(column));
@ -10012,6 +10000,10 @@ class $$MessagesTableOrderingComposer
ColumnOrderings<bool> get mediaStored => $composableBuilder(
column: $table.mediaStored, builder: (column) => ColumnOrderings(column));
ColumnOrderings<bool> get mediaReopened => $composableBuilder(
column: $table.mediaReopened,
builder: (column) => ColumnOrderings(column));
ColumnOrderings<Uint8List> get downloadToken => $composableBuilder(
column: $table.downloadToken,
builder: (column) => ColumnOrderings(column));
@ -10124,6 +10116,9 @@ class $$MessagesTableAnnotationComposer
GeneratedColumn<bool> get mediaStored => $composableBuilder(
column: $table.mediaStored, builder: (column) => column);
GeneratedColumn<bool> get mediaReopened => $composableBuilder(
column: $table.mediaReopened, builder: (column) => column);
GeneratedColumn<Uint8List> get downloadToken => $composableBuilder(
column: $table.downloadToken, builder: (column) => column);
@ -10333,6 +10328,7 @@ class $$MessagesTableTableManager extends RootTableManager<
Value<String?> content = const Value.absent(),
Value<String?> mediaId = const Value.absent(),
Value<bool> mediaStored = const Value.absent(),
Value<bool> mediaReopened = const Value.absent(),
Value<Uint8List?> downloadToken = const Value.absent(),
Value<String?> quotesMessageId = const Value.absent(),
Value<bool> isDeletedFromSender = const Value.absent(),
@ -10352,6 +10348,7 @@ class $$MessagesTableTableManager extends RootTableManager<
content: content,
mediaId: mediaId,
mediaStored: mediaStored,
mediaReopened: mediaReopened,
downloadToken: downloadToken,
quotesMessageId: quotesMessageId,
isDeletedFromSender: isDeletedFromSender,
@ -10371,6 +10368,7 @@ class $$MessagesTableTableManager extends RootTableManager<
Value<String?> content = const Value.absent(),
Value<String?> mediaId = const Value.absent(),
Value<bool> mediaStored = const Value.absent(),
Value<bool> mediaReopened = const Value.absent(),
Value<Uint8List?> downloadToken = const Value.absent(),
Value<String?> quotesMessageId = const Value.absent(),
Value<bool> isDeletedFromSender = const Value.absent(),
@ -10390,6 +10388,7 @@ class $$MessagesTableTableManager extends RootTableManager<
content: content,
mediaId: mediaId,
mediaStored: mediaStored,
mediaReopened: mediaReopened,
downloadToken: downloadToken,
quotesMessageId: quotesMessageId,
isDeletedFromSender: isDeletedFromSender,

File diff suppressed because it is too large Load diff

View file

@ -148,16 +148,22 @@ Future<void> handleMediaUpdate(
switch (mediaUpdate.type) {
case EncryptedContent_MediaUpdate_Type.REOPENED:
Log.info('Got media file reopened ${mediaFile.mediaId}');
await twonlyDB.mediaFilesDao.updateMedia(
mediaFile.mediaId,
const MediaFilesCompanion(
reopenByContact: Value(true),
await twonlyDB.messagesDao.updateMessageId(
message.messageId,
const MessagesCompanion(
mediaReopened: Value(true),
),
);
case EncryptedContent_MediaUpdate_Type.STORED:
Log.info('Got media file stored ${mediaFile.mediaId}');
final mediaService = await MediaFileService.fromMedia(mediaFile);
await mediaService.storeMediaFile();
await twonlyDB.messagesDao.updateMessageId(
message.messageId,
const MessagesCompanion(
mediaStored: Value(true),
),
);
case EncryptedContent_MediaUpdate_Type.DECRYPTION_ERROR:
Log.info('Got media file decryption error ${mediaFile.mediaId}');

View file

@ -224,12 +224,6 @@ class MediaFileService {
stored: Value(true),
),
);
await twonlyDB.messagesDao.updateMessagesByMediaId(
mediaFile.mediaId,
const MessagesCompanion(
mediaStored: Value(true),
),
);
if (originalPath.existsSync() && !tempPath.existsSync()) {
await compressMedia();

View file

@ -189,7 +189,7 @@ class _MessageSendStateIconState extends State<MessageSendStateIcon> {
}
if (mediaFile != null) {
if (mediaFile.reopenByContact) {
if (message.mediaReopened) {
icon = FaIcon(FontAwesomeIcons.repeat, size: 12, color: color);
text = context.lang.messageReopened;
}

View file

@ -0,0 +1,23 @@
// dart format width=80
// GENERATED CODE, DO NOT EDIT BY HAND.
// ignore_for_file: type=lint
import 'package:drift/drift.dart';
import 'package:drift/internal/migrations.dart';
import 'schema_v1.dart' as v1;
import 'schema_v2.dart' as v2;
class GeneratedHelper implements SchemaInstantiationHelper {
@override
GeneratedDatabase databaseForVersion(QueryExecutor db, int version) {
switch (version) {
case 1:
return v1.DatabaseAtV1(db);
case 2:
return v2.DatabaseAtV2(db);
default:
throw MissingSchemaException(version, versions);
}
}
static const versions = const [1, 2];
}

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,172 @@
// dart format width=80
// ignore_for_file: unused_local_variable, unused_import
import 'package:drift/drift.dart';
import 'package:drift_dev/api/migrations_native.dart';
import 'package:twonly/src/database/twonly.db.dart';
import 'package:flutter_test/flutter_test.dart';
import 'generated/schema.dart';
import 'generated/schema_v1.dart' as v1;
import 'generated/schema_v2.dart' as v2;
void main() {
driftRuntimeOptions.dontWarnAboutMultipleDatabases = true;
late SchemaVerifier verifier;
setUpAll(() {
verifier = SchemaVerifier(GeneratedHelper());
});
group('simple database migrations', () {
// These simple tests verify all possible schema updates with a simple (no
// data) migration. This is a quick way to ensure that written database
// migrations properly alter the schema.
const versions = GeneratedHelper.versions;
for (final (i, fromVersion) in versions.indexed) {
group('from $fromVersion', () {
for (final toVersion in versions.skip(i + 1)) {
test('to $toVersion', () async {
final schema = await verifier.schemaAt(fromVersion);
final db = TwonlyDB(schema.newConnection());
await verifier.migrateAndValidate(db, toVersion);
await db.close();
});
}
});
}
});
// The following template shows how to write tests ensuring your migrations
// preserve existing data.
// Testing this can be useful for migrations that change existing columns
// (e.g. by alterating their type or constraints). Migrations that only add
// tables or columns typically don't need these advanced tests. For more
// information, see https://drift.simonbinder.eu/migrations/tests/#verifying-data-integrity
// TODO: This generated template shows how these tests could be written. Adopt
// it to your own needs when testing migrations with data integrity.
test('migration from v1 to v2 does not corrupt data', () async {
// Add data to insert into the old database, and the expected rows after the
// migration.
// TODO: Fill these lists
final oldContactsData = <v1.ContactsData>[];
final expectedNewContactsData = <v2.ContactsData>[];
final oldGroupsData = <v1.GroupsData>[];
final expectedNewGroupsData = <v2.GroupsData>[];
final oldMediaFilesData = <v1.MediaFilesData>[];
final expectedNewMediaFilesData = <v2.MediaFilesData>[];
final oldMessagesData = <v1.MessagesData>[];
final expectedNewMessagesData = <v2.MessagesData>[];
final oldMessageHistoriesData = <v1.MessageHistoriesData>[];
final expectedNewMessageHistoriesData = <v2.MessageHistoriesData>[];
final oldReactionsData = <v1.ReactionsData>[];
final expectedNewReactionsData = <v2.ReactionsData>[];
final oldGroupMembersData = <v1.GroupMembersData>[];
final expectedNewGroupMembersData = <v2.GroupMembersData>[];
final oldReceiptsData = <v1.ReceiptsData>[];
final expectedNewReceiptsData = <v2.ReceiptsData>[];
final oldReceivedReceiptsData = <v1.ReceivedReceiptsData>[];
final expectedNewReceivedReceiptsData = <v2.ReceivedReceiptsData>[];
final oldSignalIdentityKeyStoresData = <v1.SignalIdentityKeyStoresData>[];
final expectedNewSignalIdentityKeyStoresData =
<v2.SignalIdentityKeyStoresData>[];
final oldSignalPreKeyStoresData = <v1.SignalPreKeyStoresData>[];
final expectedNewSignalPreKeyStoresData = <v2.SignalPreKeyStoresData>[];
final oldSignalSenderKeyStoresData = <v1.SignalSenderKeyStoresData>[];
final expectedNewSignalSenderKeyStoresData =
<v2.SignalSenderKeyStoresData>[];
final oldSignalSessionStoresData = <v1.SignalSessionStoresData>[];
final expectedNewSignalSessionStoresData = <v2.SignalSessionStoresData>[];
final oldSignalContactPreKeysData = <v1.SignalContactPreKeysData>[];
final expectedNewSignalContactPreKeysData = <v2.SignalContactPreKeysData>[];
final oldSignalContactSignedPreKeysData =
<v1.SignalContactSignedPreKeysData>[];
final expectedNewSignalContactSignedPreKeysData =
<v2.SignalContactSignedPreKeysData>[];
final oldMessageActionsData = <v1.MessageActionsData>[];
final expectedNewMessageActionsData = <v2.MessageActionsData>[];
final oldGroupHistoriesData = <v1.GroupHistoriesData>[];
final expectedNewGroupHistoriesData = <v2.GroupHistoriesData>[];
await verifier.testWithDataIntegrity(
oldVersion: 1,
newVersion: 2,
createOld: v1.DatabaseAtV1.new,
createNew: v2.DatabaseAtV2.new,
openTestedDatabase: TwonlyDB.new,
createItems: (batch, oldDb) {
batch.insertAll(oldDb.contacts, oldContactsData);
batch.insertAll(oldDb.groups, oldGroupsData);
batch.insertAll(oldDb.mediaFiles, oldMediaFilesData);
batch.insertAll(oldDb.messages, oldMessagesData);
batch.insertAll(oldDb.messageHistories, oldMessageHistoriesData);
batch.insertAll(oldDb.reactions, oldReactionsData);
batch.insertAll(oldDb.groupMembers, oldGroupMembersData);
batch.insertAll(oldDb.receipts, oldReceiptsData);
batch.insertAll(oldDb.receivedReceipts, oldReceivedReceiptsData);
batch.insertAll(
oldDb.signalIdentityKeyStores, oldSignalIdentityKeyStoresData);
batch.insertAll(oldDb.signalPreKeyStores, oldSignalPreKeyStoresData);
batch.insertAll(
oldDb.signalSenderKeyStores, oldSignalSenderKeyStoresData);
batch.insertAll(oldDb.signalSessionStores, oldSignalSessionStoresData);
batch.insertAll(
oldDb.signalContactPreKeys, oldSignalContactPreKeysData);
batch.insertAll(oldDb.signalContactSignedPreKeys,
oldSignalContactSignedPreKeysData);
batch.insertAll(oldDb.messageActions, oldMessageActionsData);
batch.insertAll(oldDb.groupHistories, oldGroupHistoriesData);
},
validateItems: (newDb) async {
expect(
expectedNewContactsData, await newDb.select(newDb.contacts).get());
expect(expectedNewGroupsData, await newDb.select(newDb.groups).get());
expect(expectedNewMediaFilesData,
await newDb.select(newDb.mediaFiles).get());
expect(
expectedNewMessagesData, await newDb.select(newDb.messages).get());
expect(expectedNewMessageHistoriesData,
await newDb.select(newDb.messageHistories).get());
expect(expectedNewReactionsData,
await newDb.select(newDb.reactions).get());
expect(expectedNewGroupMembersData,
await newDb.select(newDb.groupMembers).get());
expect(
expectedNewReceiptsData, await newDb.select(newDb.receipts).get());
expect(expectedNewReceivedReceiptsData,
await newDb.select(newDb.receivedReceipts).get());
expect(expectedNewSignalIdentityKeyStoresData,
await newDb.select(newDb.signalIdentityKeyStores).get());
expect(expectedNewSignalPreKeyStoresData,
await newDb.select(newDb.signalPreKeyStores).get());
expect(expectedNewSignalSenderKeyStoresData,
await newDb.select(newDb.signalSenderKeyStores).get());
expect(expectedNewSignalSessionStoresData,
await newDb.select(newDb.signalSessionStores).get());
expect(expectedNewSignalContactPreKeysData,
await newDb.select(newDb.signalContactPreKeys).get());
expect(expectedNewSignalContactSignedPreKeysData,
await newDb.select(newDb.signalContactSignedPreKeys).get());
expect(expectedNewMessageActionsData,
await newDb.select(newDb.messageActions).get());
expect(expectedNewGroupHistoriesData,
await newDb.select(newDb.groupHistories).get());
},
);
});
}