mirror of
https://github.com/twonlyapp/twonly-app.git
synced 2026-01-15 09:28:41 +00:00
fix #172
This commit is contained in:
parent
f3c9dbb796
commit
87bc1ed824
18 changed files with 3909 additions and 402 deletions
1
drift_schemas/twonly_database/drift_schema_v9.json
Normal file
1
drift_schemas/twonly_database/drift_schema_v9.json
Normal file
File diff suppressed because one or more lines are too long
|
|
@ -129,8 +129,8 @@ class _AppState extends State<App> with WidgetsBindingObserver {
|
|||
themeMode: context.watch<SettingsChangeProvider>().themeMode,
|
||||
initialRoute: '/',
|
||||
routes: {
|
||||
"/": (context) => AppMainWidget(initialPage: 0),
|
||||
"/chats": (context) => AppMainWidget(initialPage: 1)
|
||||
"/": (context) => AppMainWidget(initialPage: 1),
|
||||
"/chats": (context) => AppMainWidget(initialPage: 0)
|
||||
},
|
||||
);
|
||||
},
|
||||
|
|
|
|||
|
|
@ -2,16 +2,18 @@ import 'dart:convert';
|
|||
import 'package:drift/drift.dart';
|
||||
|
||||
enum UploadState {
|
||||
pending,
|
||||
// legacy
|
||||
addedToMessagesDb,
|
||||
// added .compressed to filename
|
||||
isCompressed,
|
||||
// added .encypted to filename
|
||||
isEncrypted,
|
||||
hasUploadToken,
|
||||
isUploaded,
|
||||
// ^^ legacy ^^
|
||||
|
||||
pending,
|
||||
readyToUpload,
|
||||
receiverNotified,
|
||||
// after all users notified all media files that are not storeable by the other person will be deleted
|
||||
// after all users notified all media files that are not storable by the other person will be deleted
|
||||
}
|
||||
|
||||
@DataClassName('MediaUpload')
|
||||
|
|
@ -20,7 +22,8 @@ class MediaUploads extends Table {
|
|||
TextColumn get state =>
|
||||
textEnum<UploadState>().withDefault(Constant(UploadState.pending.name))();
|
||||
|
||||
TextColumn get metadata => text().map(MediaUploadMetadataConverter())();
|
||||
TextColumn get metadata =>
|
||||
text().map(MediaUploadMetadataConverter()).nullable()();
|
||||
|
||||
/// exists in UploadState.addedToMessagesDb
|
||||
TextColumn get messageIds => text().map(IntListTypeConverter()).nullable()();
|
||||
|
|
|
|||
|
|
@ -43,7 +43,7 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
|||
TwonlyDatabase.forTesting(DatabaseConnection super.connection);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 8;
|
||||
int get schemaVersion => 9;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(
|
||||
|
|
@ -57,34 +57,34 @@ class TwonlyDatabase extends _$TwonlyDatabase {
|
|||
@override
|
||||
MigrationStrategy get migration {
|
||||
return MigrationStrategy(
|
||||
onUpgrade: stepByStep(
|
||||
from1To2: (m, schema) async {
|
||||
m.addColumn(schema.messages, schema.messages.errorWhileSending);
|
||||
},
|
||||
from2To3: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.archived);
|
||||
m.addColumn(
|
||||
schema.contacts, schema.contacts.deleteMessagesAfterXMinutes);
|
||||
},
|
||||
from3To4: (m, schema) async {
|
||||
m.createTable(mediaUploads);
|
||||
},
|
||||
from4To5: (m, schema) async {
|
||||
m.createTable(mediaDownloads);
|
||||
m.addColumn(schema.messages, schema.messages.mediaDownloadId);
|
||||
m.addColumn(schema.messages, schema.messages.mediaUploadId);
|
||||
},
|
||||
from5To6: (m, schema) async {
|
||||
m.addColumn(schema.messages, schema.messages.mediaStored);
|
||||
},
|
||||
from6To7: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.pinned);
|
||||
},
|
||||
from7To8: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.alsoBestFriend);
|
||||
m.addColumn(schema.contacts, schema.contacts.lastFlameSync);
|
||||
},
|
||||
),
|
||||
onUpgrade: stepByStep(from1To2: (m, schema) async {
|
||||
m.addColumn(schema.messages, schema.messages.errorWhileSending);
|
||||
}, from2To3: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.archived);
|
||||
m.addColumn(
|
||||
schema.contacts, schema.contacts.deleteMessagesAfterXMinutes);
|
||||
}, from3To4: (m, schema) async {
|
||||
m.createTable(mediaUploads);
|
||||
}, from4To5: (m, schema) async {
|
||||
m.createTable(mediaDownloads);
|
||||
m.addColumn(schema.messages, schema.messages.mediaDownloadId);
|
||||
m.addColumn(schema.messages, schema.messages.mediaUploadId);
|
||||
}, from5To6: (m, schema) async {
|
||||
m.addColumn(schema.messages, schema.messages.mediaStored);
|
||||
}, from6To7: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.pinned);
|
||||
}, from7To8: (m, schema) async {
|
||||
m.addColumn(schema.contacts, schema.contacts.alsoBestFriend);
|
||||
m.addColumn(schema.contacts, schema.contacts.lastFlameSync);
|
||||
}, from8To9: (m, schema) async {
|
||||
await m.alterTable(TableMigration(
|
||||
schema.mediaUploads,
|
||||
columnTransformer: {
|
||||
schema.mediaUploads.metadata:
|
||||
schema.mediaUploads.metadata.cast<String>(),
|
||||
},
|
||||
));
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1934,11 +1934,11 @@ class $MediaUploadsTable extends MediaUploads
|
|||
defaultValue: Constant(UploadState.pending.name))
|
||||
.withConverter<UploadState>($MediaUploadsTable.$converterstate);
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<MediaUploadMetadata, String>
|
||||
metadata = GeneratedColumn<String>('metadata', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<MediaUploadMetadata>(
|
||||
$MediaUploadsTable.$convertermetadata);
|
||||
late final GeneratedColumnWithTypeConverter<MediaUploadMetadata?, String>
|
||||
metadata = GeneratedColumn<String>('metadata', aliasedName, true,
|
||||
type: DriftSqlType.string, requiredDuringInsert: false)
|
||||
.withConverter<MediaUploadMetadata?>(
|
||||
$MediaUploadsTable.$convertermetadatan);
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<List<int>?, String> messageIds =
|
||||
GeneratedColumn<String>('message_ids', aliasedName, true,
|
||||
|
|
@ -2006,9 +2006,9 @@ class $MediaUploadsTable extends MediaUploads
|
|||
state: $MediaUploadsTable.$converterstate.fromSql(attachedDatabase
|
||||
.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}state'])!),
|
||||
metadata: $MediaUploadsTable.$convertermetadata.fromSql(attachedDatabase
|
||||
metadata: $MediaUploadsTable.$convertermetadatan.fromSql(attachedDatabase
|
||||
.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}metadata'])!),
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}metadata'])),
|
||||
messageIds: $MediaUploadsTable.$convertermessageIdsn.fromSql(
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string, data['${effectivePrefix}message_ids'])),
|
||||
|
|
@ -2033,6 +2033,9 @@ class $MediaUploadsTable extends MediaUploads
|
|||
const EnumNameConverter<UploadState>(UploadState.values);
|
||||
static JsonTypeConverter2<MediaUploadMetadata, String, Map<String, Object?>>
|
||||
$convertermetadata = MediaUploadMetadataConverter();
|
||||
static JsonTypeConverter2<MediaUploadMetadata?, String?,
|
||||
Map<String, Object?>?> $convertermetadatan =
|
||||
JsonTypeConverter2.asNullable($convertermetadata);
|
||||
static TypeConverter<List<int>, String> $convertermessageIds =
|
||||
IntListTypeConverter();
|
||||
static TypeConverter<List<int>?, String?> $convertermessageIdsn =
|
||||
|
|
@ -2054,7 +2057,7 @@ class $MediaUploadsTable extends MediaUploads
|
|||
class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
||||
final int mediaUploadId;
|
||||
final UploadState state;
|
||||
final MediaUploadMetadata metadata;
|
||||
final MediaUploadMetadata? metadata;
|
||||
|
||||
/// exists in UploadState.addedToMessagesDb
|
||||
final List<int>? messageIds;
|
||||
|
|
@ -2070,7 +2073,7 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
const MediaUpload(
|
||||
{required this.mediaUploadId,
|
||||
required this.state,
|
||||
required this.metadata,
|
||||
this.metadata,
|
||||
this.messageIds,
|
||||
this.encryptionData,
|
||||
this.uploadTokens,
|
||||
|
|
@ -2083,9 +2086,9 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
map['state'] =
|
||||
Variable<String>($MediaUploadsTable.$converterstate.toSql(state));
|
||||
}
|
||||
{
|
||||
if (!nullToAbsent || metadata != null) {
|
||||
map['metadata'] = Variable<String>(
|
||||
$MediaUploadsTable.$convertermetadata.toSql(metadata));
|
||||
$MediaUploadsTable.$convertermetadatan.toSql(metadata));
|
||||
}
|
||||
if (!nullToAbsent || messageIds != null) {
|
||||
map['message_ids'] = Variable<String>(
|
||||
|
|
@ -2110,7 +2113,9 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
return MediaUploadsCompanion(
|
||||
mediaUploadId: Value(mediaUploadId),
|
||||
state: Value(state),
|
||||
metadata: Value(metadata),
|
||||
metadata: metadata == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(metadata),
|
||||
messageIds: messageIds == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(messageIds),
|
||||
|
|
@ -2131,8 +2136,8 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
mediaUploadId: serializer.fromJson<int>(json['mediaUploadId']),
|
||||
state: $MediaUploadsTable.$converterstate
|
||||
.fromJson(serializer.fromJson<String>(json['state'])),
|
||||
metadata: $MediaUploadsTable.$convertermetadata.fromJson(
|
||||
serializer.fromJson<Map<String, Object?>>(json['metadata'])),
|
||||
metadata: $MediaUploadsTable.$convertermetadatan.fromJson(
|
||||
serializer.fromJson<Map<String, Object?>?>(json['metadata'])),
|
||||
messageIds: serializer.fromJson<List<int>?>(json['messageIds']),
|
||||
encryptionData: $MediaUploadsTable.$converterencryptionDatan.fromJson(
|
||||
serializer.fromJson<Map<String, Object?>?>(json['encryptionData'])),
|
||||
|
|
@ -2148,8 +2153,8 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
'mediaUploadId': serializer.toJson<int>(mediaUploadId),
|
||||
'state': serializer
|
||||
.toJson<String>($MediaUploadsTable.$converterstate.toJson(state)),
|
||||
'metadata': serializer.toJson<Map<String, Object?>>(
|
||||
$MediaUploadsTable.$convertermetadata.toJson(metadata)),
|
||||
'metadata': serializer.toJson<Map<String, Object?>?>(
|
||||
$MediaUploadsTable.$convertermetadatan.toJson(metadata)),
|
||||
'messageIds': serializer.toJson<List<int>?>(messageIds),
|
||||
'encryptionData': serializer.toJson<Map<String, Object?>?>(
|
||||
$MediaUploadsTable.$converterencryptionDatan.toJson(encryptionData)),
|
||||
|
|
@ -2162,7 +2167,7 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
MediaUpload copyWith(
|
||||
{int? mediaUploadId,
|
||||
UploadState? state,
|
||||
MediaUploadMetadata? metadata,
|
||||
Value<MediaUploadMetadata?> metadata = const Value.absent(),
|
||||
Value<List<int>?> messageIds = const Value.absent(),
|
||||
Value<MediaEncryptionData?> encryptionData = const Value.absent(),
|
||||
Value<MediaUploadTokens?> uploadTokens = const Value.absent(),
|
||||
|
|
@ -2170,7 +2175,7 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
MediaUpload(
|
||||
mediaUploadId: mediaUploadId ?? this.mediaUploadId,
|
||||
state: state ?? this.state,
|
||||
metadata: metadata ?? this.metadata,
|
||||
metadata: metadata.present ? metadata.value : this.metadata,
|
||||
messageIds: messageIds.present ? messageIds.value : this.messageIds,
|
||||
encryptionData:
|
||||
encryptionData.present ? encryptionData.value : this.encryptionData,
|
||||
|
|
@ -2232,7 +2237,7 @@ class MediaUpload extends DataClass implements Insertable<MediaUpload> {
|
|||
class MediaUploadsCompanion extends UpdateCompanion<MediaUpload> {
|
||||
final Value<int> mediaUploadId;
|
||||
final Value<UploadState> state;
|
||||
final Value<MediaUploadMetadata> metadata;
|
||||
final Value<MediaUploadMetadata?> metadata;
|
||||
final Value<List<int>?> messageIds;
|
||||
final Value<MediaEncryptionData?> encryptionData;
|
||||
final Value<MediaUploadTokens?> uploadTokens;
|
||||
|
|
@ -2249,12 +2254,12 @@ class MediaUploadsCompanion extends UpdateCompanion<MediaUpload> {
|
|||
MediaUploadsCompanion.insert({
|
||||
this.mediaUploadId = const Value.absent(),
|
||||
this.state = const Value.absent(),
|
||||
required MediaUploadMetadata metadata,
|
||||
this.metadata = const Value.absent(),
|
||||
this.messageIds = const Value.absent(),
|
||||
this.encryptionData = const Value.absent(),
|
||||
this.uploadTokens = const Value.absent(),
|
||||
this.alreadyNotified = const Value.absent(),
|
||||
}) : metadata = Value(metadata);
|
||||
});
|
||||
static Insertable<MediaUpload> custom({
|
||||
Expression<int>? mediaUploadId,
|
||||
Expression<String>? state,
|
||||
|
|
@ -2278,7 +2283,7 @@ class MediaUploadsCompanion extends UpdateCompanion<MediaUpload> {
|
|||
MediaUploadsCompanion copyWith(
|
||||
{Value<int>? mediaUploadId,
|
||||
Value<UploadState>? state,
|
||||
Value<MediaUploadMetadata>? metadata,
|
||||
Value<MediaUploadMetadata?>? metadata,
|
||||
Value<List<int>?>? messageIds,
|
||||
Value<MediaEncryptionData?>? encryptionData,
|
||||
Value<MediaUploadTokens?>? uploadTokens,
|
||||
|
|
@ -2306,7 +2311,7 @@ class MediaUploadsCompanion extends UpdateCompanion<MediaUpload> {
|
|||
}
|
||||
if (metadata.present) {
|
||||
map['metadata'] = Variable<String>(
|
||||
$MediaUploadsTable.$convertermetadata.toSql(metadata.value));
|
||||
$MediaUploadsTable.$convertermetadatan.toSql(metadata.value));
|
||||
}
|
||||
if (messageIds.present) {
|
||||
map['message_ids'] = Variable<String>(
|
||||
|
|
@ -4549,7 +4554,7 @@ typedef $$MediaUploadsTableCreateCompanionBuilder = MediaUploadsCompanion
|
|||
Function({
|
||||
Value<int> mediaUploadId,
|
||||
Value<UploadState> state,
|
||||
required MediaUploadMetadata metadata,
|
||||
Value<MediaUploadMetadata?> metadata,
|
||||
Value<List<int>?> messageIds,
|
||||
Value<MediaEncryptionData?> encryptionData,
|
||||
Value<MediaUploadTokens?> uploadTokens,
|
||||
|
|
@ -4559,7 +4564,7 @@ typedef $$MediaUploadsTableUpdateCompanionBuilder = MediaUploadsCompanion
|
|||
Function({
|
||||
Value<int> mediaUploadId,
|
||||
Value<UploadState> state,
|
||||
Value<MediaUploadMetadata> metadata,
|
||||
Value<MediaUploadMetadata?> metadata,
|
||||
Value<List<int>?> messageIds,
|
||||
Value<MediaEncryptionData?> encryptionData,
|
||||
Value<MediaUploadTokens?> uploadTokens,
|
||||
|
|
@ -4583,7 +4588,7 @@ class $$MediaUploadsTableFilterComposer
|
|||
column: $table.state,
|
||||
builder: (column) => ColumnWithTypeConverterFilters(column));
|
||||
|
||||
ColumnWithTypeConverterFilters<MediaUploadMetadata, MediaUploadMetadata,
|
||||
ColumnWithTypeConverterFilters<MediaUploadMetadata?, MediaUploadMetadata,
|
||||
String>
|
||||
get metadata => $composableBuilder(
|
||||
column: $table.metadata,
|
||||
|
|
@ -4661,7 +4666,7 @@ class $$MediaUploadsTableAnnotationComposer
|
|||
GeneratedColumnWithTypeConverter<UploadState, String> get state =>
|
||||
$composableBuilder(column: $table.state, builder: (column) => column);
|
||||
|
||||
GeneratedColumnWithTypeConverter<MediaUploadMetadata, String> get metadata =>
|
||||
GeneratedColumnWithTypeConverter<MediaUploadMetadata?, String> get metadata =>
|
||||
$composableBuilder(column: $table.metadata, builder: (column) => column);
|
||||
|
||||
GeneratedColumnWithTypeConverter<List<int>?, String> get messageIds =>
|
||||
|
|
@ -4709,7 +4714,7 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
|
|||
updateCompanionCallback: ({
|
||||
Value<int> mediaUploadId = const Value.absent(),
|
||||
Value<UploadState> state = const Value.absent(),
|
||||
Value<MediaUploadMetadata> metadata = const Value.absent(),
|
||||
Value<MediaUploadMetadata?> metadata = const Value.absent(),
|
||||
Value<List<int>?> messageIds = const Value.absent(),
|
||||
Value<MediaEncryptionData?> encryptionData = const Value.absent(),
|
||||
Value<MediaUploadTokens?> uploadTokens = const Value.absent(),
|
||||
|
|
@ -4727,7 +4732,7 @@ class $$MediaUploadsTableTableManager extends RootTableManager<
|
|||
createCompanionCallback: ({
|
||||
Value<int> mediaUploadId = const Value.absent(),
|
||||
Value<UploadState> state = const Value.absent(),
|
||||
required MediaUploadMetadata metadata,
|
||||
Value<MediaUploadMetadata?> metadata = const Value.absent(),
|
||||
Value<List<int>?> messageIds = const Value.absent(),
|
||||
Value<MediaEncryptionData?> encryptionData = const Value.absent(),
|
||||
Value<MediaUploadTokens?> uploadTokens = const Value.absent(),
|
||||
|
|
|
|||
|
|
@ -1701,6 +1701,184 @@ i1.GeneratedColumn<bool> _column_54(String aliasedName) =>
|
|||
i1.GeneratedColumn<DateTime> _column_55(String aliasedName) =>
|
||||
i1.GeneratedColumn<DateTime>('last_flame_sync', aliasedName, true,
|
||||
type: i1.DriftSqlType.dateTime);
|
||||
|
||||
final class Schema9 extends i0.VersionedSchema {
|
||||
Schema9({required super.database}) : super(version: 9);
|
||||
@override
|
||||
late final List<i1.DatabaseSchemaEntity> entities = [
|
||||
contacts,
|
||||
messages,
|
||||
mediaUploads,
|
||||
mediaDownloads,
|
||||
signalIdentityKeyStores,
|
||||
signalPreKeyStores,
|
||||
signalSenderKeyStores,
|
||||
signalSessionStores,
|
||||
];
|
||||
late final Shape12 contacts = Shape12(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'contacts',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(user_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_0,
|
||||
_column_1,
|
||||
_column_2,
|
||||
_column_3,
|
||||
_column_4,
|
||||
_column_5,
|
||||
_column_6,
|
||||
_column_7,
|
||||
_column_8,
|
||||
_column_9,
|
||||
_column_39,
|
||||
_column_53,
|
||||
_column_54,
|
||||
_column_40,
|
||||
_column_10,
|
||||
_column_11,
|
||||
_column_12,
|
||||
_column_13,
|
||||
_column_14,
|
||||
_column_55,
|
||||
_column_15,
|
||||
_column_16,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape10 messages = Shape10(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'messages',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_17,
|
||||
_column_18,
|
||||
_column_19,
|
||||
_column_48,
|
||||
_column_49,
|
||||
_column_20,
|
||||
_column_21,
|
||||
_column_22,
|
||||
_column_52,
|
||||
_column_23,
|
||||
_column_24,
|
||||
_column_25,
|
||||
_column_26,
|
||||
_column_27,
|
||||
_column_28,
|
||||
_column_29,
|
||||
_column_30,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape7 mediaUploads = Shape7(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'media_uploads',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_41,
|
||||
_column_42,
|
||||
_column_56,
|
||||
_column_44,
|
||||
_column_45,
|
||||
_column_46,
|
||||
_column_47,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape9 mediaDownloads = Shape9(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'media_downloads',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [],
|
||||
columns: [
|
||||
_column_50,
|
||||
_column_51,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape2 signalIdentityKeyStores = Shape2(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_identity_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(device_id, name)',
|
||||
],
|
||||
columns: [
|
||||
_column_31,
|
||||
_column_32,
|
||||
_column_33,
|
||||
_column_10,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape3 signalPreKeyStores = Shape3(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_pre_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(pre_key_id)',
|
||||
],
|
||||
columns: [
|
||||
_column_34,
|
||||
_column_35,
|
||||
_column_10,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape4 signalSenderKeyStores = Shape4(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_sender_key_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(sender_key_name)',
|
||||
],
|
||||
columns: [
|
||||
_column_36,
|
||||
_column_37,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
late final Shape5 signalSessionStores = Shape5(
|
||||
source: i0.VersionedTable(
|
||||
entityName: 'signal_session_stores',
|
||||
withoutRowId: false,
|
||||
isStrict: false,
|
||||
tableConstraints: [
|
||||
'PRIMARY KEY(device_id, name)',
|
||||
],
|
||||
columns: [
|
||||
_column_31,
|
||||
_column_32,
|
||||
_column_38,
|
||||
_column_10,
|
||||
],
|
||||
attachedDatabase: database,
|
||||
),
|
||||
alias: null);
|
||||
}
|
||||
|
||||
i1.GeneratedColumn<String> _column_56(String aliasedName) =>
|
||||
i1.GeneratedColumn<String>('metadata', aliasedName, true,
|
||||
type: i1.DriftSqlType.string);
|
||||
i0.MigrationStepWithVersion migrationSteps({
|
||||
required Future<void> Function(i1.Migrator m, Schema2 schema) from1To2,
|
||||
required Future<void> Function(i1.Migrator m, Schema3 schema) from2To3,
|
||||
|
|
@ -1709,6 +1887,7 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||
}) {
|
||||
return (currentVersion, database) async {
|
||||
switch (currentVersion) {
|
||||
|
|
@ -1747,6 +1926,11 @@ i0.MigrationStepWithVersion migrationSteps({
|
|||
final migrator = i1.Migrator(database, schema);
|
||||
await from7To8(migrator, schema);
|
||||
return 8;
|
||||
case 8:
|
||||
final schema = Schema9(database: database);
|
||||
final migrator = i1.Migrator(database, schema);
|
||||
await from8To9(migrator, schema);
|
||||
return 9;
|
||||
default:
|
||||
throw ArgumentError.value('Unknown migration from $currentVersion');
|
||||
}
|
||||
|
|
@ -1761,6 +1945,7 @@ i1.OnUpgrade stepByStep({
|
|||
required Future<void> Function(i1.Migrator m, Schema6 schema) from5To6,
|
||||
required Future<void> Function(i1.Migrator m, Schema7 schema) from6To7,
|
||||
required Future<void> Function(i1.Migrator m, Schema8 schema) from7To8,
|
||||
required Future<void> Function(i1.Migrator m, Schema9 schema) from8To9,
|
||||
}) =>
|
||||
i0.VersionedSchema.stepByStepHelper(
|
||||
step: migrationSteps(
|
||||
|
|
@ -1771,4 +1956,5 @@ i1.OnUpgrade stepByStep({
|
|||
from5To6: from5To6,
|
||||
from6To7: from6To7,
|
||||
from7To8: from7To8,
|
||||
from8To9: from8To9,
|
||||
));
|
||||
|
|
|
|||
|
|
@ -1545,6 +1545,70 @@ class ApplicationData_UploadData extends $pb.GeneratedMessage {
|
|||
void clearChecksum() => clearField(4);
|
||||
}
|
||||
|
||||
class ApplicationData_UploadDone extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_UploadDone({
|
||||
$core.List<$core.int>? uploadToken,
|
||||
$core.int? recipientsCount,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (uploadToken != null) {
|
||||
$result.uploadToken = uploadToken;
|
||||
}
|
||||
if (recipientsCount != null) {
|
||||
$result.recipientsCount = recipientsCount;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
ApplicationData_UploadDone._() : super();
|
||||
factory ApplicationData_UploadDone.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory ApplicationData_UploadDone.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.UploadDone', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'uploadToken', $pb.PbFieldType.OY)
|
||||
..a<$core.int>(2, _omitFieldNames ? '' : 'recipientsCount', $pb.PbFieldType.OU3)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_UploadDone clone() => ApplicationData_UploadDone()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_UploadDone copyWith(void Function(ApplicationData_UploadDone) updates) => super.copyWith((message) => updates(message as ApplicationData_UploadDone)) as ApplicationData_UploadDone;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UploadDone create() => ApplicationData_UploadDone._();
|
||||
ApplicationData_UploadDone createEmptyInstance() => create();
|
||||
static $pb.PbList<ApplicationData_UploadDone> createRepeated() => $pb.PbList<ApplicationData_UploadDone>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_UploadDone getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplicationData_UploadDone>(create);
|
||||
static ApplicationData_UploadDone? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.int> get uploadToken => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set uploadToken($core.List<$core.int> v) { $_setBytes(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasUploadToken() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearUploadToken() => clearField(1);
|
||||
|
||||
@$pb.TagNumber(2)
|
||||
$core.int get recipientsCount => $_getIZ(1);
|
||||
@$pb.TagNumber(2)
|
||||
set recipientsCount($core.int v) { $_setUnsignedInt32(1, v); }
|
||||
@$pb.TagNumber(2)
|
||||
$core.bool hasRecipientsCount() => $_has(1);
|
||||
@$pb.TagNumber(2)
|
||||
void clearRecipientsCount() => clearField(2);
|
||||
}
|
||||
|
||||
class ApplicationData_DownloadData extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_DownloadData({
|
||||
$core.List<$core.int>? downloadToken,
|
||||
|
|
@ -1609,6 +1673,56 @@ class ApplicationData_DownloadData extends $pb.GeneratedMessage {
|
|||
void clearOffset() => clearField(2);
|
||||
}
|
||||
|
||||
class ApplicationData_DownloadDone extends $pb.GeneratedMessage {
|
||||
factory ApplicationData_DownloadDone({
|
||||
$core.List<$core.int>? downloadToken,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (downloadToken != null) {
|
||||
$result.downloadToken = downloadToken;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
ApplicationData_DownloadDone._() : super();
|
||||
factory ApplicationData_DownloadDone.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory ApplicationData_DownloadDone.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData.DownloadDone', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||
..a<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'downloadToken', $pb.PbFieldType.OY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_DownloadDone clone() => ApplicationData_DownloadDone()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
ApplicationData_DownloadDone copyWith(void Function(ApplicationData_DownloadDone) updates) => super.copyWith((message) => updates(message as ApplicationData_DownloadDone)) as ApplicationData_DownloadDone;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_DownloadDone create() => ApplicationData_DownloadDone._();
|
||||
ApplicationData_DownloadDone createEmptyInstance() => create();
|
||||
static $pb.PbList<ApplicationData_DownloadDone> createRepeated() => $pb.PbList<ApplicationData_DownloadDone>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static ApplicationData_DownloadDone getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<ApplicationData_DownloadDone>(create);
|
||||
static ApplicationData_DownloadDone? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.int> get downloadToken => $_getN(0);
|
||||
@$pb.TagNumber(1)
|
||||
set downloadToken($core.List<$core.int> v) { $_setBytes(0, v); }
|
||||
@$pb.TagNumber(1)
|
||||
$core.bool hasDownloadToken() => $_has(0);
|
||||
@$pb.TagNumber(1)
|
||||
void clearDownloadToken() => clearField(1);
|
||||
}
|
||||
|
||||
enum ApplicationData_ApplicationData {
|
||||
textmessage,
|
||||
getuserbyusername,
|
||||
|
|
@ -1629,6 +1743,8 @@ enum ApplicationData_ApplicationData {
|
|||
redeemadditionalcode,
|
||||
removeadditionaluser,
|
||||
updateplanoptions,
|
||||
downloaddone,
|
||||
uploaddone,
|
||||
notSet
|
||||
}
|
||||
|
||||
|
|
@ -1653,6 +1769,8 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
ApplicationData_RedeemAdditionalCode? redeemadditionalcode,
|
||||
ApplicationData_RemoveAdditionalUser? removeadditionaluser,
|
||||
ApplicationData_UpdatePlanOptions? updateplanoptions,
|
||||
ApplicationData_DownloadDone? downloaddone,
|
||||
ApplicationData_UploadDone? uploaddone,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (textmessage != null) {
|
||||
|
|
@ -1712,6 +1830,12 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
if (updateplanoptions != null) {
|
||||
$result.updateplanoptions = updateplanoptions;
|
||||
}
|
||||
if (downloaddone != null) {
|
||||
$result.downloaddone = downloaddone;
|
||||
}
|
||||
if (uploaddone != null) {
|
||||
$result.uploaddone = uploaddone;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
ApplicationData._() : super();
|
||||
|
|
@ -1738,10 +1862,12 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
17 : ApplicationData_ApplicationData.redeemadditionalcode,
|
||||
18 : ApplicationData_ApplicationData.removeadditionaluser,
|
||||
19 : ApplicationData_ApplicationData.updateplanoptions,
|
||||
20 : ApplicationData_ApplicationData.downloaddone,
|
||||
21 : ApplicationData_ApplicationData.uploaddone,
|
||||
0 : ApplicationData_ApplicationData.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'ApplicationData', package: const $pb.PackageName(_omitMessageNames ? '' : 'client_to_server'), createEmptyInstance: create)
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19])
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21])
|
||||
..aOM<ApplicationData_TextMessage>(1, _omitFieldNames ? '' : 'textmessage', subBuilder: ApplicationData_TextMessage.create)
|
||||
..aOM<ApplicationData_GetUserByUsername>(2, _omitFieldNames ? '' : 'getuserbyusername', subBuilder: ApplicationData_GetUserByUsername.create)
|
||||
..aOM<ApplicationData_GetPrekeysByUserId>(3, _omitFieldNames ? '' : 'getprekeysbyuserid', subBuilder: ApplicationData_GetPrekeysByUserId.create)
|
||||
|
|
@ -1761,6 +1887,8 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
..aOM<ApplicationData_RedeemAdditionalCode>(17, _omitFieldNames ? '' : 'redeemadditionalcode', subBuilder: ApplicationData_RedeemAdditionalCode.create)
|
||||
..aOM<ApplicationData_RemoveAdditionalUser>(18, _omitFieldNames ? '' : 'removeadditionaluser', subBuilder: ApplicationData_RemoveAdditionalUser.create)
|
||||
..aOM<ApplicationData_UpdatePlanOptions>(19, _omitFieldNames ? '' : 'updateplanoptions', subBuilder: ApplicationData_UpdatePlanOptions.create)
|
||||
..aOM<ApplicationData_DownloadDone>(20, _omitFieldNames ? '' : 'downloaddone', subBuilder: ApplicationData_DownloadDone.create)
|
||||
..aOM<ApplicationData_UploadDone>(21, _omitFieldNames ? '' : 'uploaddone', subBuilder: ApplicationData_UploadDone.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
|
|
@ -1996,6 +2124,28 @@ class ApplicationData extends $pb.GeneratedMessage {
|
|||
void clearUpdateplanoptions() => clearField(19);
|
||||
@$pb.TagNumber(19)
|
||||
ApplicationData_UpdatePlanOptions ensureUpdateplanoptions() => $_ensure(18);
|
||||
|
||||
@$pb.TagNumber(20)
|
||||
ApplicationData_DownloadDone get downloaddone => $_getN(19);
|
||||
@$pb.TagNumber(20)
|
||||
set downloaddone(ApplicationData_DownloadDone v) { setField(20, v); }
|
||||
@$pb.TagNumber(20)
|
||||
$core.bool hasDownloaddone() => $_has(19);
|
||||
@$pb.TagNumber(20)
|
||||
void clearDownloaddone() => clearField(20);
|
||||
@$pb.TagNumber(20)
|
||||
ApplicationData_DownloadDone ensureDownloaddone() => $_ensure(19);
|
||||
|
||||
@$pb.TagNumber(21)
|
||||
ApplicationData_UploadDone get uploaddone => $_getN(20);
|
||||
@$pb.TagNumber(21)
|
||||
set uploaddone(ApplicationData_UploadDone v) { setField(21, v); }
|
||||
@$pb.TagNumber(21)
|
||||
$core.bool hasUploaddone() => $_has(20);
|
||||
@$pb.TagNumber(21)
|
||||
void clearUploaddone() => clearField(21);
|
||||
@$pb.TagNumber(21)
|
||||
ApplicationData_UploadDone ensureUploaddone() => $_ensure(20);
|
||||
}
|
||||
|
||||
class Response_PreKey extends $pb.GeneratedMessage {
|
||||
|
|
|
|||
|
|
@ -155,8 +155,10 @@ const ApplicationData$json = {
|
|||
{'1': 'redeemadditionalcode', '3': 17, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.RedeemAdditionalCode', '9': 0, '10': 'redeemadditionalcode'},
|
||||
{'1': 'removeadditionaluser', '3': 18, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.RemoveAdditionalUser', '9': 0, '10': 'removeadditionaluser'},
|
||||
{'1': 'updateplanoptions', '3': 19, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UpdatePlanOptions', '9': 0, '10': 'updateplanoptions'},
|
||||
{'1': 'downloaddone', '3': 20, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.DownloadDone', '9': 0, '10': 'downloaddone'},
|
||||
{'1': 'uploaddone', '3': 21, '4': 1, '5': 11, '6': '.client_to_server.ApplicationData.UploadDone', '9': 0, '10': 'uploaddone'},
|
||||
],
|
||||
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_RedeemVoucher$json, ApplicationData_SwitchToPayedPlan$json, ApplicationData_UpdatePlanOptions$json, ApplicationData_CreateVoucher$json, ApplicationData_GetLocation$json, ApplicationData_GetVouchers$json, ApplicationData_GetAvailablePlans$json, ApplicationData_GetAddAccountsInvites$json, ApplicationData_GetCurrentPlanInfos$json, ApplicationData_RedeemAdditionalCode$json, ApplicationData_RemoveAdditionalUser$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_DownloadData$json],
|
||||
'3': [ApplicationData_TextMessage$json, ApplicationData_GetUserByUsername$json, ApplicationData_UpdateGoogleFcmToken$json, ApplicationData_GetUserById$json, ApplicationData_RedeemVoucher$json, ApplicationData_SwitchToPayedPlan$json, ApplicationData_UpdatePlanOptions$json, ApplicationData_CreateVoucher$json, ApplicationData_GetLocation$json, ApplicationData_GetVouchers$json, ApplicationData_GetAvailablePlans$json, ApplicationData_GetAddAccountsInvites$json, ApplicationData_GetCurrentPlanInfos$json, ApplicationData_RedeemAdditionalCode$json, ApplicationData_RemoveAdditionalUser$json, ApplicationData_GetPrekeysByUserId$json, ApplicationData_GetUploadToken$json, ApplicationData_UploadData$json, ApplicationData_UploadDone$json, ApplicationData_DownloadData$json, ApplicationData_DownloadDone$json],
|
||||
'8': [
|
||||
{'1': 'ApplicationData'},
|
||||
],
|
||||
|
|
@ -304,6 +306,15 @@ const ApplicationData_UploadData$json = {
|
|||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_UploadDone$json = {
|
||||
'1': 'UploadDone',
|
||||
'2': [
|
||||
{'1': 'upload_token', '3': 1, '4': 1, '5': 12, '10': 'uploadToken'},
|
||||
{'1': 'recipients_count', '3': 2, '4': 1, '5': 13, '10': 'recipientsCount'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_DownloadData$json = {
|
||||
'1': 'DownloadData',
|
||||
|
|
@ -313,6 +324,14 @@ const ApplicationData_DownloadData$json = {
|
|||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use applicationDataDescriptor instead')
|
||||
const ApplicationData_DownloadDone$json = {
|
||||
'1': 'DownloadDone',
|
||||
'2': [
|
||||
{'1': 'download_token', '3': 1, '4': 1, '5': 12, '10': 'downloadToken'},
|
||||
],
|
||||
};
|
||||
|
||||
/// Descriptor for `ApplicationData`. Decode as a `google.protobuf.DescriptorProto`.
|
||||
final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
||||
'Cg9BcHBsaWNhdGlvbkRhdGESUQoLdGV4dG1lc3NhZ2UYASABKAsyLS5jbGllbnRfdG9fc2Vydm'
|
||||
|
|
@ -348,26 +367,32 @@ final $typed_data.Uint8List applicationDataDescriptor = $convert.base64Decode(
|
|||
'Y2xpZW50X3RvX3NlcnZlci5BcHBsaWNhdGlvbkRhdGEuUmVtb3ZlQWRkaXRpb25hbFVzZXJIAF'
|
||||
'IUcmVtb3ZlYWRkaXRpb25hbHVzZXISYwoRdXBkYXRlcGxhbm9wdGlvbnMYEyABKAsyMy5jbGll'
|
||||
'bnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGRhdGVQbGFuT3B0aW9uc0gAUhF1cGRhdG'
|
||||
'VwbGFub3B0aW9ucxpqCgtUZXh0TWVzc2FnZRIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQSEgoE'
|
||||
'Ym9keRgDIAEoDFIEYm9keRIgCglwdXNoX2RhdGEYBCABKAxIAFIIcHVzaERhdGGIAQFCDAoKX3'
|
||||
'B1c2hfZGF0YRovChFHZXRVc2VyQnlVc2VybmFtZRIaCgh1c2VybmFtZRgBIAEoCVIIdXNlcm5h'
|
||||
'bWUaNQoUVXBkYXRlR29vZ2xlRmNtVG9rZW4SHQoKZ29vZ2xlX2ZjbRgBIAEoCVIJZ29vZ2xlRm'
|
||||
'NtGiYKC0dldFVzZXJCeUlkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJZBopCg1SZWRlZW1Wb3Vj'
|
||||
'aGVyEhgKB3ZvdWNoZXIYASABKAlSB3ZvdWNoZXIacAoRU3dpdGNoVG9QYXllZFBsYW4SFwoHcG'
|
||||
'xhbl9pZBgBIAEoCVIGcGxhbklkEh8KC3BheV9tb250aGx5GAIgASgIUgpwYXlNb250aGx5EiEK'
|
||||
'DGF1dG9fcmVuZXdhbBgDIAEoCFILYXV0b1JlbmV3YWwaNgoRVXBkYXRlUGxhbk9wdGlvbnMSIQ'
|
||||
'oMYXV0b19yZW5ld2FsGAEgASgIUgthdXRvUmVuZXdhbBowCg1DcmVhdGVWb3VjaGVyEh8KC3Zh'
|
||||
'bHVlX2NlbnRzGAEgASgNUgp2YWx1ZUNlbnRzGg0KC0dldExvY2F0aW9uGg0KC0dldFZvdWNoZX'
|
||||
'JzGhMKEUdldEF2YWlsYWJsZVBsYW5zGhcKFUdldEFkZEFjY291bnRzSW52aXRlcxoVChNHZXRD'
|
||||
'dXJyZW50UGxhbkluZm9zGjcKFFJlZGVlbUFkZGl0aW9uYWxDb2RlEh8KC2ludml0ZV9jb2RlGA'
|
||||
'IgASgJUgppbnZpdGVDb2RlGi8KFFJlbW92ZUFkZGl0aW9uYWxVc2VyEhcKB3VzZXJfaWQYASAB'
|
||||
'KANSBnVzZXJJZBotChJHZXRQcmVrZXlzQnlVc2VySWQSFwoHdXNlcl9pZBgBIAEoA1IGdXNlck'
|
||||
'lkGjsKDkdldFVwbG9hZFRva2VuEikKEHJlY2lwaWVudHNfY291bnQYASABKA1SD3JlY2lwaWVu'
|
||||
'dHNDb3VudBqJAQoKVXBsb2FkRGF0YRIhCgx1cGxvYWRfdG9rZW4YASABKAxSC3VwbG9hZFRva2'
|
||||
'VuEhYKBm9mZnNldBgCIAEoDVIGb2Zmc2V0EhIKBGRhdGEYAyABKAxSBGRhdGESHwoIY2hlY2tz'
|
||||
'dW0YBCABKAxIAFIIY2hlY2tzdW2IAQFCCwoJX2NoZWNrc3VtGk0KDERvd25sb2FkRGF0YRIlCg'
|
||||
'5kb3dubG9hZF90b2tlbhgBIAEoDFINZG93bmxvYWRUb2tlbhIWCgZvZmZzZXQYAiABKA1SBm9m'
|
||||
'ZnNldEIRCg9BcHBsaWNhdGlvbkRhdGE=');
|
||||
'VwbGFub3B0aW9ucxJUCgxkb3dubG9hZGRvbmUYFCABKAsyLi5jbGllbnRfdG9fc2VydmVyLkFw'
|
||||
'cGxpY2F0aW9uRGF0YS5Eb3dubG9hZERvbmVIAFIMZG93bmxvYWRkb25lEk4KCnVwbG9hZGRvbm'
|
||||
'UYFSABKAsyLC5jbGllbnRfdG9fc2VydmVyLkFwcGxpY2F0aW9uRGF0YS5VcGxvYWREb25lSABS'
|
||||
'CnVwbG9hZGRvbmUaagoLVGV4dE1lc3NhZ2USFwoHdXNlcl9pZBgBIAEoA1IGdXNlcklkEhIKBG'
|
||||
'JvZHkYAyABKAxSBGJvZHkSIAoJcHVzaF9kYXRhGAQgASgMSABSCHB1c2hEYXRhiAEBQgwKCl9w'
|
||||
'dXNoX2RhdGEaLwoRR2V0VXNlckJ5VXNlcm5hbWUSGgoIdXNlcm5hbWUYASABKAlSCHVzZXJuYW'
|
||||
'1lGjUKFFVwZGF0ZUdvb2dsZUZjbVRva2VuEh0KCmdvb2dsZV9mY20YASABKAlSCWdvb2dsZUZj'
|
||||
'bRomCgtHZXRVc2VyQnlJZBIXCgd1c2VyX2lkGAEgASgDUgZ1c2VySWQaKQoNUmVkZWVtVm91Y2'
|
||||
'hlchIYCgd2b3VjaGVyGAEgASgJUgd2b3VjaGVyGnAKEVN3aXRjaFRvUGF5ZWRQbGFuEhcKB3Bs'
|
||||
'YW5faWQYASABKAlSBnBsYW5JZBIfCgtwYXlfbW9udGhseRgCIAEoCFIKcGF5TW9udGhseRIhCg'
|
||||
'xhdXRvX3JlbmV3YWwYAyABKAhSC2F1dG9SZW5ld2FsGjYKEVVwZGF0ZVBsYW5PcHRpb25zEiEK'
|
||||
'DGF1dG9fcmVuZXdhbBgBIAEoCFILYXV0b1JlbmV3YWwaMAoNQ3JlYXRlVm91Y2hlchIfCgt2YW'
|
||||
'x1ZV9jZW50cxgBIAEoDVIKdmFsdWVDZW50cxoNCgtHZXRMb2NhdGlvbhoNCgtHZXRWb3VjaGVy'
|
||||
'cxoTChFHZXRBdmFpbGFibGVQbGFucxoXChVHZXRBZGRBY2NvdW50c0ludml0ZXMaFQoTR2V0Q3'
|
||||
'VycmVudFBsYW5JbmZvcxo3ChRSZWRlZW1BZGRpdGlvbmFsQ29kZRIfCgtpbnZpdGVfY29kZRgC'
|
||||
'IAEoCVIKaW52aXRlQ29kZRovChRSZW1vdmVBZGRpdGlvbmFsVXNlchIXCgd1c2VyX2lkGAEgAS'
|
||||
'gDUgZ1c2VySWQaLQoSR2V0UHJla2V5c0J5VXNlcklkEhcKB3VzZXJfaWQYASABKANSBnVzZXJJ'
|
||||
'ZBo7Cg5HZXRVcGxvYWRUb2tlbhIpChByZWNpcGllbnRzX2NvdW50GAEgASgNUg9yZWNpcGllbn'
|
||||
'RzQ291bnQaiQEKClVwbG9hZERhdGESIQoMdXBsb2FkX3Rva2VuGAEgASgMUgt1cGxvYWRUb2tl'
|
||||
'bhIWCgZvZmZzZXQYAiABKA1SBm9mZnNldBISCgRkYXRhGAMgASgMUgRkYXRhEh8KCGNoZWNrc3'
|
||||
'VtGAQgASgMSABSCGNoZWNrc3VtiAEBQgsKCV9jaGVja3N1bRpaCgpVcGxvYWREb25lEiEKDHVw'
|
||||
'bG9hZF90b2tlbhgBIAEoDFILdXBsb2FkVG9rZW4SKQoQcmVjaXBpZW50c19jb3VudBgCIAEoDV'
|
||||
'IPcmVjaXBpZW50c0NvdW50Gk0KDERvd25sb2FkRGF0YRIlCg5kb3dubG9hZF90b2tlbhgBIAEo'
|
||||
'DFINZG93bmxvYWRUb2tlbhIWCgZvZmZzZXQYAiABKA1SBm9mZnNldBo1CgxEb3dubG9hZERvbm'
|
||||
'USJQoOZG93bmxvYWRfdG9rZW4YASABKAxSDWRvd25sb2FkVG9rZW5CEQoPQXBwbGljYXRpb25E'
|
||||
'YXRh');
|
||||
|
||||
@$core.Deprecated('Use responseDescriptor instead')
|
||||
const Response$json = {
|
||||
|
|
|
|||
|
|
@ -1524,6 +1524,50 @@ class Response_UploadToken extends $pb.GeneratedMessage {
|
|||
$core.List<$core.List<$core.int>> get downloadTokens => $_getList(1);
|
||||
}
|
||||
|
||||
class Response_DownloadTokens extends $pb.GeneratedMessage {
|
||||
factory Response_DownloadTokens({
|
||||
$core.Iterable<$core.List<$core.int>>? downloadTokens,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (downloadTokens != null) {
|
||||
$result.downloadTokens.addAll(downloadTokens);
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
Response_DownloadTokens._() : super();
|
||||
factory Response_DownloadTokens.fromBuffer($core.List<$core.int> i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromBuffer(i, r);
|
||||
factory Response_DownloadTokens.fromJson($core.String i, [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) => create()..mergeFromJson(i, r);
|
||||
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.DownloadTokens', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
|
||||
..p<$core.List<$core.int>>(1, _omitFieldNames ? '' : 'downloadTokens', $pb.PbFieldType.PY)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.deepCopy] instead. '
|
||||
'Will be removed in next major version')
|
||||
Response_DownloadTokens clone() => Response_DownloadTokens()..mergeFromMessage(this);
|
||||
@$core.Deprecated(
|
||||
'Using this can add significant overhead to your binary. '
|
||||
'Use [GeneratedMessageGenericExtensions.rebuild] instead. '
|
||||
'Will be removed in next major version')
|
||||
Response_DownloadTokens copyWith(void Function(Response_DownloadTokens) updates) => super.copyWith((message) => updates(message as Response_DownloadTokens)) as Response_DownloadTokens;
|
||||
|
||||
$pb.BuilderInfo get info_ => _i;
|
||||
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Response_DownloadTokens create() => Response_DownloadTokens._();
|
||||
Response_DownloadTokens createEmptyInstance() => create();
|
||||
static $pb.PbList<Response_DownloadTokens> createRepeated() => $pb.PbList<Response_DownloadTokens>();
|
||||
@$core.pragma('dart2js:noInline')
|
||||
static Response_DownloadTokens getDefault() => _defaultInstance ??= $pb.GeneratedMessage.$_defaultFor<Response_DownloadTokens>(create);
|
||||
static Response_DownloadTokens? _defaultInstance;
|
||||
|
||||
@$pb.TagNumber(1)
|
||||
$core.List<$core.List<$core.int>> get downloadTokens => $_getList(0);
|
||||
}
|
||||
|
||||
enum Response_Ok_Ok {
|
||||
none,
|
||||
userid,
|
||||
|
|
@ -1537,6 +1581,7 @@ enum Response_Ok_Ok {
|
|||
planballance,
|
||||
vouchers,
|
||||
addaccountsinvites,
|
||||
downloadtokens,
|
||||
notSet
|
||||
}
|
||||
|
||||
|
|
@ -1554,6 +1599,7 @@ class Response_Ok extends $pb.GeneratedMessage {
|
|||
Response_PlanBallance? planballance,
|
||||
Response_Vouchers? vouchers,
|
||||
Response_AddAccountsInvites? addaccountsinvites,
|
||||
Response_DownloadTokens? downloadtokens,
|
||||
}) {
|
||||
final $result = create();
|
||||
if (none != null) {
|
||||
|
|
@ -1592,6 +1638,9 @@ class Response_Ok extends $pb.GeneratedMessage {
|
|||
if (addaccountsinvites != null) {
|
||||
$result.addaccountsinvites = addaccountsinvites;
|
||||
}
|
||||
if (downloadtokens != null) {
|
||||
$result.downloadtokens = downloadtokens;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
Response_Ok._() : super();
|
||||
|
|
@ -1611,10 +1660,11 @@ class Response_Ok extends $pb.GeneratedMessage {
|
|||
10 : Response_Ok_Ok.planballance,
|
||||
11 : Response_Ok_Ok.vouchers,
|
||||
12 : Response_Ok_Ok.addaccountsinvites,
|
||||
13 : Response_Ok_Ok.downloadtokens,
|
||||
0 : Response_Ok_Ok.notSet
|
||||
};
|
||||
static final $pb.BuilderInfo _i = $pb.BuilderInfo(_omitMessageNames ? '' : 'Response.Ok', package: const $pb.PackageName(_omitMessageNames ? '' : 'server_to_client'), createEmptyInstance: create)
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12])
|
||||
..oo(0, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13])
|
||||
..aOB(1, _omitFieldNames ? '' : 'None', protoName: 'None')
|
||||
..aInt64(2, _omitFieldNames ? '' : 'userid')
|
||||
..a<$core.List<$core.int>>(3, _omitFieldNames ? '' : 'authchallenge', $pb.PbFieldType.OY)
|
||||
|
|
@ -1627,6 +1677,7 @@ class Response_Ok extends $pb.GeneratedMessage {
|
|||
..aOM<Response_PlanBallance>(10, _omitFieldNames ? '' : 'planballance', subBuilder: Response_PlanBallance.create)
|
||||
..aOM<Response_Vouchers>(11, _omitFieldNames ? '' : 'vouchers', subBuilder: Response_Vouchers.create)
|
||||
..aOM<Response_AddAccountsInvites>(12, _omitFieldNames ? '' : 'addaccountsinvites', subBuilder: Response_AddAccountsInvites.create)
|
||||
..aOM<Response_DownloadTokens>(13, _omitFieldNames ? '' : 'downloadtokens', subBuilder: Response_DownloadTokens.create)
|
||||
..hasRequiredFields = false
|
||||
;
|
||||
|
||||
|
|
@ -1777,6 +1828,17 @@ class Response_Ok extends $pb.GeneratedMessage {
|
|||
void clearAddaccountsinvites() => clearField(12);
|
||||
@$pb.TagNumber(12)
|
||||
Response_AddAccountsInvites ensureAddaccountsinvites() => $_ensure(11);
|
||||
|
||||
@$pb.TagNumber(13)
|
||||
Response_DownloadTokens get downloadtokens => $_getN(12);
|
||||
@$pb.TagNumber(13)
|
||||
set downloadtokens(Response_DownloadTokens v) { setField(13, v); }
|
||||
@$pb.TagNumber(13)
|
||||
$core.bool hasDownloadtokens() => $_has(12);
|
||||
@$pb.TagNumber(13)
|
||||
void clearDownloadtokens() => clearField(13);
|
||||
@$pb.TagNumber(13)
|
||||
Response_DownloadTokens ensureDownloadtokens() => $_ensure(12);
|
||||
}
|
||||
|
||||
enum Response_Response {
|
||||
|
|
|
|||
|
|
@ -92,7 +92,7 @@ const Response$json = {
|
|||
{'1': 'ok', '3': 1, '4': 1, '5': 11, '6': '.server_to_client.Response.Ok', '9': 0, '10': 'ok'},
|
||||
{'1': 'error', '3': 2, '4': 1, '5': 14, '6': '.error.ErrorCode', '9': 0, '10': 'error'},
|
||||
],
|
||||
'3': [Response_Authenticated$json, Response_Plan$json, Response_Plans$json, Response_AddAccountsInvite$json, Response_AddAccountsInvites$json, Response_Transaction$json, Response_AdditionalAccount$json, Response_Voucher$json, Response_Vouchers$json, Response_PlanBallance$json, Response_Location$json, Response_PreKey$json, Response_UserData$json, Response_UploadToken$json, Response_Ok$json],
|
||||
'3': [Response_Authenticated$json, Response_Plan$json, Response_Plans$json, Response_AddAccountsInvite$json, Response_AddAccountsInvites$json, Response_Transaction$json, Response_AdditionalAccount$json, Response_Voucher$json, Response_Vouchers$json, Response_PlanBallance$json, Response_Location$json, Response_PreKey$json, Response_UserData$json, Response_UploadToken$json, Response_DownloadTokens$json, Response_Ok$json],
|
||||
'4': [Response_TransactionTypes$json],
|
||||
'8': [
|
||||
{'1': 'Response'},
|
||||
|
|
@ -258,6 +258,14 @@ const Response_UploadToken$json = {
|
|||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use responseDescriptor instead')
|
||||
const Response_DownloadTokens$json = {
|
||||
'1': 'DownloadTokens',
|
||||
'2': [
|
||||
{'1': 'download_tokens', '3': 1, '4': 3, '5': 12, '10': 'downloadTokens'},
|
||||
],
|
||||
};
|
||||
|
||||
@$core.Deprecated('Use responseDescriptor instead')
|
||||
const Response_Ok$json = {
|
||||
'1': 'Ok',
|
||||
|
|
@ -274,6 +282,7 @@ const Response_Ok$json = {
|
|||
{'1': 'planballance', '3': 10, '4': 1, '5': 11, '6': '.server_to_client.Response.PlanBallance', '9': 0, '10': 'planballance'},
|
||||
{'1': 'vouchers', '3': 11, '4': 1, '5': 11, '6': '.server_to_client.Response.Vouchers', '9': 0, '10': 'vouchers'},
|
||||
{'1': 'addaccountsinvites', '3': 12, '4': 1, '5': 11, '6': '.server_to_client.Response.AddAccountsInvites', '9': 0, '10': 'addaccountsinvites'},
|
||||
{'1': 'downloadtokens', '3': 13, '4': 1, '5': 11, '6': '.server_to_client.Response.DownloadTokens', '9': 0, '10': 'downloadtokens'},
|
||||
],
|
||||
'8': [
|
||||
{'1': 'Ok'},
|
||||
|
|
@ -347,21 +356,23 @@ final $typed_data.Uint8List responseDescriptor = $convert.base64Decode(
|
|||
'9wdWJsaWNfaWRlbnRpdHlfa2V5QhAKDl9zaWduZWRfcHJla2V5QhoKGF9zaWduZWRfcHJla2V5'
|
||||
'X3NpZ25hdHVyZUITChFfc2lnbmVkX3ByZWtleV9pZBpZCgtVcGxvYWRUb2tlbhIhCgx1cGxvYW'
|
||||
'RfdG9rZW4YASABKAxSC3VwbG9hZFRva2VuEicKD2Rvd25sb2FkX3Rva2VucxgCIAMoDFIOZG93'
|
||||
'bmxvYWRUb2tlbnMa0wUKAk9rEhQKBE5vbmUYASABKAhIAFIETm9uZRIYCgZ1c2VyaWQYAiABKA'
|
||||
'NIAFIGdXNlcmlkEiYKDWF1dGhjaGFsbGVuZ2UYAyABKAxIAFINYXV0aGNoYWxsZW5nZRJKCgt1'
|
||||
'cGxvYWR0b2tlbhgEIAEoCzImLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuVXBsb2FkVG9rZW'
|
||||
'5IAFILdXBsb2FkdG9rZW4SQQoIdXNlcmRhdGEYBSABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJl'
|
||||
'c3BvbnNlLlVzZXJEYXRhSABSCHVzZXJkYXRhEh4KCWF1dGh0b2tlbhgGIAEoDEgAUglhdXRodG'
|
||||
'9rZW4SQQoIbG9jYXRpb24YByABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkxvY2F0'
|
||||
'aW9uSABSCGxvY2F0aW9uElAKDWF1dGhlbnRpY2F0ZWQYCCABKAsyKC5zZXJ2ZXJfdG9fY2xpZW'
|
||||
'50LlJlc3BvbnNlLkF1dGhlbnRpY2F0ZWRIAFINYXV0aGVudGljYXRlZBI4CgVwbGFucxgJIAEo'
|
||||
'CzIgLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuUGxhbnNIAFIFcGxhbnMSTQoMcGxhbmJhbG'
|
||||
'xhbmNlGAogASgLMicuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuQmFsbGFuY2VIAFIM'
|
||||
'cGxhbmJhbGxhbmNlEkEKCHZvdWNoZXJzGAsgASgLMiMuc2VydmVyX3RvX2NsaWVudC5SZXNwb2'
|
||||
'5zZS5Wb3VjaGVyc0gAUgh2b3VjaGVycxJfChJhZGRhY2NvdW50c2ludml0ZXMYDCABKAsyLS5z'
|
||||
'ZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLkFkZEFjY291bnRzSW52aXRlc0gAUhJhZGRhY2NvdW'
|
||||
'50c2ludml0ZXNCBAoCT2silgEKEFRyYW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91'
|
||||
'Y2hlclJlZGVlbWVkEAESEgoOVm91Y2hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3'
|
||||
'JhZGUQBBILCgdVbmtub3duEAUSFAoQVGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2Fs'
|
||||
'EAdCCgoIUmVzcG9uc2U=');
|
||||
'bmxvYWRUb2tlbnMaOQoORG93bmxvYWRUb2tlbnMSJwoPZG93bmxvYWRfdG9rZW5zGAEgAygMUg'
|
||||
'5kb3dubG9hZFRva2VucxqoBgoCT2sSFAoETm9uZRgBIAEoCEgAUgROb25lEhgKBnVzZXJpZBgC'
|
||||
'IAEoA0gAUgZ1c2VyaWQSJgoNYXV0aGNoYWxsZW5nZRgDIAEoDEgAUg1hdXRoY2hhbGxlbmdlEk'
|
||||
'oKC3VwbG9hZHRva2VuGAQgASgLMiYuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5VcGxvYWRU'
|
||||
'b2tlbkgAUgt1cGxvYWR0b2tlbhJBCgh1c2VyZGF0YRgFIAEoCzIjLnNlcnZlcl90b19jbGllbn'
|
||||
'QuUmVzcG9uc2UuVXNlckRhdGFIAFIIdXNlcmRhdGESHgoJYXV0aHRva2VuGAYgASgMSABSCWF1'
|
||||
'dGh0b2tlbhJBCghsb2NhdGlvbhgHIAEoCzIjLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuTG'
|
||||
'9jYXRpb25IAFIIbG9jYXRpb24SUAoNYXV0aGVudGljYXRlZBgIIAEoCzIoLnNlcnZlcl90b19j'
|
||||
'bGllbnQuUmVzcG9uc2UuQXV0aGVudGljYXRlZEgAUg1hdXRoZW50aWNhdGVkEjgKBXBsYW5zGA'
|
||||
'kgASgLMiAuc2VydmVyX3RvX2NsaWVudC5SZXNwb25zZS5QbGFuc0gAUgVwbGFucxJNCgxwbGFu'
|
||||
'YmFsbGFuY2UYCiABKAsyJy5zZXJ2ZXJfdG9fY2xpZW50LlJlc3BvbnNlLlBsYW5CYWxsYW5jZU'
|
||||
'gAUgxwbGFuYmFsbGFuY2USQQoIdm91Y2hlcnMYCyABKAsyIy5zZXJ2ZXJfdG9fY2xpZW50LlJl'
|
||||
'c3BvbnNlLlZvdWNoZXJzSABSCHZvdWNoZXJzEl8KEmFkZGFjY291bnRzaW52aXRlcxgMIAEoCz'
|
||||
'ItLnNlcnZlcl90b19jbGllbnQuUmVzcG9uc2UuQWRkQWNjb3VudHNJbnZpdGVzSABSEmFkZGFj'
|
||||
'Y291bnRzaW52aXRlcxJTCg5kb3dubG9hZHRva2VucxgNIAEoCzIpLnNlcnZlcl90b19jbGllbn'
|
||||
'QuUmVzcG9uc2UuRG93bmxvYWRUb2tlbnNIAFIOZG93bmxvYWR0b2tlbnNCBAoCT2silgEKEFRy'
|
||||
'YW5zYWN0aW9uVHlwZXMSCgoGUmVmdW5kEAASEwoPVm91Y2hlclJlZGVlbWVkEAESEgoOVm91Y2'
|
||||
'hlckNyZWF0ZWQQAhIICgRDYXNoEAMSDwoLUGxhblVwZ3JhZGUQBBILCgdVbmtub3duEAUSFAoQ'
|
||||
'VGhhbmtzRm9yVGVzdGluZxAGEg8KC0F1dG9SZW5ld2FsEAdCCgoIUmVzcG9uc2U=');
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
|
|
@ -18,6 +19,7 @@ import 'package:twonly/src/model/json/message.dart';
|
|||
import 'package:twonly/src/model/protobuf/api/error.pb.dart';
|
||||
import 'package:twonly/src/model/protobuf/api/server_to_client.pb.dart';
|
||||
import 'package:twonly/src/providers/api/api.dart';
|
||||
import 'package:twonly/src/providers/api/api_utils.dart';
|
||||
import 'package:twonly/src/providers/api/media_received.dart';
|
||||
import 'package:twonly/src/services/notification_service.dart';
|
||||
import 'package:twonly/src/utils/misc.dart';
|
||||
|
|
@ -49,48 +51,17 @@ Future<ErrorCode?> isAllowedToSend() async {
|
|||
return null;
|
||||
}
|
||||
|
||||
/// Process the image up to the point more user informations are required
|
||||
/// Returns the media upload id
|
||||
Future<int> preSendMediaFile(Uint8List imageBytes, File? videoFilePath) async {
|
||||
return 0;
|
||||
}
|
||||
/// States:
|
||||
/// when user recorded an video
|
||||
/// 1. Compress video
|
||||
/// when user clicked the send button (direct send) or share with
|
||||
/// 2. Encrypt media files
|
||||
/// 3. Upload media files
|
||||
/// click send button
|
||||
/// 4. Finalize upload by websocket -> get download tokens
|
||||
/// 5. Send all users the message
|
||||
|
||||
Future cancelSendMediaFile(int mediaUploadId) async {}
|
||||
|
||||
Future finalizeSendMediaFile(int mediaUploadId, List<int> userIds,
|
||||
bool isRealTwonly, bool isVideo, bool mirrorVideo, int maxShowTime) async {}
|
||||
|
||||
Future sendMediaFile(
|
||||
List<int> userIds,
|
||||
Uint8List imageBytes,
|
||||
bool isRealTwonly,
|
||||
int maxShowTime,
|
||||
File? videoFilePath,
|
||||
bool mirrorVideo,
|
||||
) async {
|
||||
MediaUploadMetadata metadata = MediaUploadMetadata();
|
||||
metadata.contactIds = userIds;
|
||||
metadata.isRealTwonly = isRealTwonly;
|
||||
metadata.messageSendAt = DateTime.now();
|
||||
metadata.isVideo = videoFilePath != null;
|
||||
metadata.maxShowTime = maxShowTime;
|
||||
metadata.mirrorVideo = mirrorVideo;
|
||||
|
||||
int? mediaUploadId = await twonlyDatabase.mediaUploadsDao.insertMediaUpload(
|
||||
MediaUploadsCompanion(
|
||||
metadata: Value(metadata),
|
||||
),
|
||||
);
|
||||
|
||||
if (mediaUploadId != null) {
|
||||
if (videoFilePath != null) {
|
||||
String basePath = await getMediaFilePath(mediaUploadId, "send");
|
||||
await videoFilePath.rename("$basePath.orginal.mp4");
|
||||
}
|
||||
await writeMediaFile(mediaUploadId, "orginal.png", imageBytes);
|
||||
await handleSingleMediaFile(mediaUploadId, imageBytes);
|
||||
}
|
||||
}
|
||||
/// Create a new entry in the database
|
||||
|
||||
final lockingHandleMediaFile = Mutex();
|
||||
Future retryMediaUpload({int maxRetries = 3}) async {
|
||||
|
|
@ -99,7 +70,22 @@ Future retryMediaUpload({int maxRetries = 3}) async {
|
|||
await twonlyDatabase.mediaUploadsDao.getMediaUploadsForRetry();
|
||||
if (mediaFiles.isEmpty) return;
|
||||
for (final mediaFile in mediaFiles) {
|
||||
await handleSingleMediaFile(mediaFile.mediaUploadId, null);
|
||||
if (mediaFile.messageIds == null || mediaFile.metadata == null) {
|
||||
// the media upload was canceled,
|
||||
if (mediaFile.uploadTokens != null) {
|
||||
/// the file was already uploaded.
|
||||
/// notify the server to remove the upload
|
||||
}
|
||||
Logger("media_send.dart").shout(
|
||||
"upload can be removed, the finalized function was never called...");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (mediaFile.state == UploadState.readyToUpload) {
|
||||
await handleNextMediaUploadSteps(mediaFile.mediaUploadId);
|
||||
} else {
|
||||
await handlePreProcessingState(mediaFile);
|
||||
}
|
||||
}
|
||||
});
|
||||
if (maxRetries == 0) return;
|
||||
|
|
@ -109,131 +95,19 @@ Future retryMediaUpload({int maxRetries = 3}) async {
|
|||
});
|
||||
}
|
||||
|
||||
Future handleSingleMediaFile(
|
||||
int mediaUploadId, Uint8List? tmpCurrentImageBytes) async {
|
||||
MediaUpload? media = await twonlyDatabase.mediaUploadsDao
|
||||
.getMediaUploadById(mediaUploadId)
|
||||
.getSingleOrNull();
|
||||
if (media == null) return;
|
||||
|
||||
try {
|
||||
switch (media.state) {
|
||||
case UploadState.pending:
|
||||
await handleAddToMessageDb(media);
|
||||
break;
|
||||
case UploadState.addedToMessagesDb:
|
||||
tmpCurrentImageBytes =
|
||||
await handleCompressionState(media, tmpCurrentImageBytes);
|
||||
break;
|
||||
case UploadState.isCompressed:
|
||||
tmpCurrentImageBytes =
|
||||
await handleEncryptionState(media, tmpCurrentImageBytes);
|
||||
break;
|
||||
case UploadState.isEncrypted:
|
||||
if (!await handleGetUploadToken(media)) {
|
||||
return; // recoverable error. try again when connected again to the server...
|
||||
}
|
||||
break;
|
||||
case UploadState.hasUploadToken:
|
||||
if (!await handleUploadHttp(media, tmpCurrentImageBytes)) {
|
||||
return;
|
||||
}
|
||||
// if (!await handleUpload(media, tmpCurrentImageBytes)) {
|
||||
// return; // recoverable error. try again when connected again to the server...
|
||||
// }
|
||||
break;
|
||||
case UploadState.isUploaded:
|
||||
if (!await handleNotifyReceiver(media)) {
|
||||
return; // recoverable error. try again when connected again to the server...
|
||||
}
|
||||
try {
|
||||
// delete non compressed media files
|
||||
await deleteMediaFile(media.mediaUploadId, "orginal.png");
|
||||
await deleteMediaFile(media.mediaUploadId, "orginal.mp4");
|
||||
await deleteMediaFile(media.mediaUploadId, "encrypted");
|
||||
} catch (e) {
|
||||
Logger("media_send.dart").shout("$e");
|
||||
}
|
||||
break;
|
||||
case UploadState.receiverNotified:
|
||||
return;
|
||||
}
|
||||
} catch (e) {
|
||||
// if the messageIds are already there notify the user about this error...
|
||||
if (media.messageIds != null) {
|
||||
for (int messageId in media.messageIds!) {
|
||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
messageId,
|
||||
MessagesCompanion(
|
||||
errorWhileSending: Value(true),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
await twonlyDatabase.mediaUploadsDao.deleteMediaUpload(mediaUploadId);
|
||||
Logger("media_send.dart")
|
||||
.shout("Non recoverable error while sending media file: $e");
|
||||
return;
|
||||
}
|
||||
// this will be called until there is an recoverable error OR
|
||||
// the upload is ready
|
||||
await handleSingleMediaFile(mediaUploadId, tmpCurrentImageBytes);
|
||||
Future<int?> initMediaUpload() async {
|
||||
return await twonlyDatabase.mediaUploadsDao
|
||||
.insertMediaUpload(MediaUploadsCompanion());
|
||||
}
|
||||
|
||||
Future handleAddToMessageDb(MediaUpload media) async {
|
||||
List<int> messageIds = [];
|
||||
|
||||
for (final contactId in media.metadata.contactIds) {
|
||||
int? messageId = await twonlyDatabase.messagesDao.insertMessage(
|
||||
MessagesCompanion(
|
||||
contactId: Value(contactId),
|
||||
kind: Value(MessageKind.media),
|
||||
sendAt: Value(media.metadata.messageSendAt),
|
||||
downloadState: Value(DownloadState.pending),
|
||||
mediaUploadId: Value(media.mediaUploadId),
|
||||
contentJson: Value(
|
||||
jsonEncode(
|
||||
MediaMessageContent(
|
||||
maxShowTime: media.metadata.maxShowTime,
|
||||
isRealTwonly: media.metadata.isRealTwonly,
|
||||
isVideo: media.metadata.isVideo,
|
||||
mirrorVideo: media.metadata.mirrorVideo,
|
||||
).toJson(),
|
||||
),
|
||||
),
|
||||
),
|
||||
); // dearchive contact when sending a new message
|
||||
await twonlyDatabase.contactsDao.updateContact(
|
||||
contactId,
|
||||
ContactsCompanion(
|
||||
archived: Value(false),
|
||||
),
|
||||
);
|
||||
if (messageId != null) {
|
||||
messageIds.add(messageId);
|
||||
} else {
|
||||
Logger("media_send.dart")
|
||||
.shout("Error inserting media upload message in database.");
|
||||
}
|
||||
}
|
||||
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
media.mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
state: Value(UploadState.addedToMessagesDb),
|
||||
messageIds: Value(messageIds),
|
||||
),
|
||||
);
|
||||
Future<bool> addVideoToUpload(int mediaUploadId, File videoFilePath) async {
|
||||
String basePath = await getMediaFilePath(mediaUploadId, "send");
|
||||
await videoFilePath.rename("$basePath.original.mp4");
|
||||
return await compressVideoIfExists(mediaUploadId);
|
||||
}
|
||||
|
||||
Future<Uint8List?> handleCompressionState(
|
||||
MediaUpload media,
|
||||
Uint8List? tmpCurrentImageBytes,
|
||||
) async {
|
||||
Uint8List imageBytes = (tmpCurrentImageBytes != null)
|
||||
? tmpCurrentImageBytes
|
||||
: await readMediaFile(media, "orginal.png");
|
||||
|
||||
Future<Uint8List> addOrModifyImageToUpload(
|
||||
int mediaUploadId, Uint8List imageBytes) async {
|
||||
Uint8List imageBytesCompressed;
|
||||
try {
|
||||
imageBytesCompressed = await FlutterImageCompress.compressWithList(
|
||||
|
|
@ -242,84 +116,62 @@ Future<Uint8List?> handleCompressionState(
|
|||
quality: 90,
|
||||
);
|
||||
|
||||
if (imageBytesCompressed.length >= 1 * 1000 * 1000) {
|
||||
// if the media file is over 1MB compress it with 60%
|
||||
if (imageBytesCompressed.length >= 2 * 1000 * 1000) {
|
||||
// if the media file is over 2MB compress it with 60%
|
||||
imageBytesCompressed = await FlutterImageCompress.compressWithList(
|
||||
format: CompressFormat.png,
|
||||
imageBytes,
|
||||
quality: 60,
|
||||
);
|
||||
}
|
||||
await writeMediaFile(media.mediaUploadId, "png", imageBytesCompressed);
|
||||
await writeMediaFile(mediaUploadId, "png", imageBytesCompressed);
|
||||
} catch (e) {
|
||||
Logger("media_send.dart").shout("$e");
|
||||
// as a fall back use the orginal image
|
||||
await writeMediaFile(media.mediaUploadId, "png", imageBytes);
|
||||
// as a fall back use the original image
|
||||
await writeMediaFile(mediaUploadId, "png", imageBytes);
|
||||
imageBytesCompressed = imageBytes;
|
||||
}
|
||||
|
||||
if (media.metadata.isVideo) {
|
||||
String basePath = await getMediaFilePath(media.mediaUploadId, "send");
|
||||
File videoOriginalFile = File("$basePath.orginal.mp4");
|
||||
File videoCompressedFile = File("$basePath.mp4");
|
||||
|
||||
MediaInfo? mediaInfo;
|
||||
|
||||
try {
|
||||
mediaInfo = await VideoCompress.compressVideo(
|
||||
videoOriginalFile.path,
|
||||
quality: VideoQuality.Res1280x720Quality,
|
||||
deleteOrigin: false,
|
||||
includeAudio:
|
||||
true, // https://github.com/jonataslaw/VideoCompress/issues/184
|
||||
);
|
||||
|
||||
if (mediaInfo!.filesize! >= 30 * 1000 * 1000) {
|
||||
// if the media file is over 20MB compress it with low quality
|
||||
mediaInfo = await VideoCompress.compressVideo(
|
||||
videoOriginalFile.path,
|
||||
quality: VideoQuality.Res960x540Quality,
|
||||
deleteOrigin: false,
|
||||
includeAudio: true,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
Logger("media_send.dart").shout("Video compression: $e");
|
||||
}
|
||||
|
||||
if (mediaInfo == null) {
|
||||
Logger("media_send.dart").shout("Error compressing video.");
|
||||
// as a fall back use the non compressed version
|
||||
await videoOriginalFile.copy(videoCompressedFile.path);
|
||||
await videoOriginalFile.delete();
|
||||
} else {
|
||||
await mediaInfo.file!.copy(videoCompressedFile.path);
|
||||
await mediaInfo.file!.delete();
|
||||
}
|
||||
}
|
||||
|
||||
/// in case the media file was already encrypted of even uploaded
|
||||
/// remove the data so it will be done again.
|
||||
/// TODO: when the uploadTokens are already set notify the server...
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
media.mediaUploadId,
|
||||
mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
state: Value(UploadState.isCompressed),
|
||||
encryptionData: Value(null),
|
||||
uploadTokens: Value(null),
|
||||
),
|
||||
);
|
||||
|
||||
return imageBytesCompressed;
|
||||
}
|
||||
|
||||
Future<Uint8List> handleEncryptionState(
|
||||
MediaUpload media, Uint8List? tmpCurrentImageBytes) async {
|
||||
var state = MediaEncryptionData();
|
||||
|
||||
Uint8List dataToEncrypt = (tmpCurrentImageBytes != null)
|
||||
? tmpCurrentImageBytes
|
||||
: await readMediaFile(media, "png");
|
||||
|
||||
if (media.metadata.isVideo) {
|
||||
Uint8List compressedVideo = await readMediaFile(media, "mp4");
|
||||
dataToEncrypt = combineUint8Lists(dataToEncrypt, compressedVideo);
|
||||
Future handlePreProcessingState(MediaUpload media) async {
|
||||
try {
|
||||
final imageHandler = readMediaFile(media.mediaUploadId, "png");
|
||||
final videoHandler = compressVideoIfExists(media.mediaUploadId);
|
||||
await encryptAndPreUploadMediaFiles(
|
||||
media.mediaUploadId,
|
||||
imageHandler,
|
||||
videoHandler,
|
||||
);
|
||||
} catch (e) {
|
||||
await handleUploadError(media);
|
||||
}
|
||||
}
|
||||
|
||||
Future encryptAndPreUploadMediaFiles(
|
||||
int mediaUploadId, Future imageHandler, Future<bool>? videoHandler) async {
|
||||
Uint8List dataToEncrypt = await imageHandler;
|
||||
|
||||
/// if there is a video wait until it is finished with compression
|
||||
if (videoHandler != null) {
|
||||
if (await videoHandler) {
|
||||
Uint8List compressedVideo = await readMediaFile(mediaUploadId, "mp4");
|
||||
dataToEncrypt = combineUint8Lists(dataToEncrypt, compressedVideo);
|
||||
}
|
||||
}
|
||||
|
||||
var state = MediaEncryptionData();
|
||||
|
||||
final xchacha20 = Xchacha20.poly1305Aead();
|
||||
SecretKeyData secretKey = await (await xchacha20.newSecretKey()).extract();
|
||||
|
|
@ -340,26 +192,161 @@ Future<Uint8List> handleEncryptionState(
|
|||
|
||||
final encryptedBytes = Uint8List.fromList(secretBox.cipherText);
|
||||
await writeMediaFile(
|
||||
media.mediaUploadId,
|
||||
mediaUploadId,
|
||||
"encrypted",
|
||||
encryptedBytes,
|
||||
);
|
||||
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
media.mediaUploadId,
|
||||
mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
state: Value(UploadState.isEncrypted),
|
||||
state: Value(UploadState.readyToUpload),
|
||||
encryptionData: Value(state),
|
||||
),
|
||||
);
|
||||
return encryptedBytes;
|
||||
await handleNextMediaUploadSteps(mediaUploadId);
|
||||
}
|
||||
|
||||
Future<bool> handleGetUploadToken(MediaUpload media) async {
|
||||
final res =
|
||||
await apiProvider.getUploadToken(media.metadata.contactIds.length);
|
||||
Future cancelSendMediaFile(int mediaUploadId) async {
|
||||
await twonlyDatabase.mediaUploadsDao.deleteMediaUpload(mediaUploadId);
|
||||
|
||||
if (res.isError || !res.value.hasUploadtoken()) {
|
||||
/// server should purge the uploads... when it did not receive a
|
||||
}
|
||||
|
||||
Future finalizeUpload(int mediaUploadId, List<int> contactIds,
|
||||
bool isRealTwonly, bool isVideo, bool mirrorVideo, int maxShowTime) async {
|
||||
MediaUploadMetadata metadata = MediaUploadMetadata();
|
||||
metadata.contactIds = contactIds;
|
||||
metadata.isRealTwonly = isRealTwonly;
|
||||
metadata.messageSendAt = DateTime.now();
|
||||
metadata.isVideo = isVideo;
|
||||
metadata.maxShowTime = maxShowTime;
|
||||
metadata.mirrorVideo = mirrorVideo;
|
||||
|
||||
List<int> messageIds = [];
|
||||
|
||||
for (final contactId in contactIds) {
|
||||
int? messageId = await twonlyDatabase.messagesDao.insertMessage(
|
||||
MessagesCompanion(
|
||||
contactId: Value(contactId),
|
||||
kind: Value(MessageKind.media),
|
||||
sendAt: Value(metadata.messageSendAt),
|
||||
downloadState: Value(DownloadState.pending),
|
||||
mediaUploadId: Value(mediaUploadId),
|
||||
contentJson: Value(
|
||||
jsonEncode(
|
||||
MediaMessageContent(
|
||||
maxShowTime: maxShowTime,
|
||||
isRealTwonly: isRealTwonly,
|
||||
isVideo: isVideo,
|
||||
mirrorVideo: mirrorVideo,
|
||||
).toJson(),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
// de-archive contact when sending a new message
|
||||
await twonlyDatabase.contactsDao.updateContact(
|
||||
contactId,
|
||||
ContactsCompanion(
|
||||
archived: Value(false),
|
||||
),
|
||||
);
|
||||
if (messageId != null) {
|
||||
messageIds.add(messageId);
|
||||
} else {
|
||||
Logger("media_send.dart")
|
||||
.shout("Error inserting media upload message in database.");
|
||||
}
|
||||
}
|
||||
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
messageIds: Value(messageIds),
|
||||
metadata: Value(metadata),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
final lockingHandleNextMediaUploadStep = Mutex();
|
||||
Future handleNextMediaUploadSteps(int mediaUploadId) async {
|
||||
bool rerun = await lockingHandleNextMediaUploadStep.protect<bool>(() async {
|
||||
var mediaUpload = await twonlyDatabase.mediaUploadsDao
|
||||
.getMediaUploadById(mediaUploadId)
|
||||
.getSingleOrNull();
|
||||
|
||||
if (mediaUpload == null) return false;
|
||||
if (mediaUpload.state == UploadState.receiverNotified) {
|
||||
/// Upload done and all users are notified :)
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
/// Stage 1: media files are not yet encrypted...
|
||||
if (mediaUpload.encryptionData == null) {
|
||||
// when set this function will be called again by encryptAndPreUploadMediaFiles...
|
||||
return false;
|
||||
}
|
||||
|
||||
if (mediaUpload.uploadTokens == null) {
|
||||
/// the files are not yet uploaded, handle upload...
|
||||
/// if the upload succeed the uploadTokens was updated and this function
|
||||
/// can be called again to processed the upload done
|
||||
return await handleMediaUpload(mediaUploadId);
|
||||
}
|
||||
|
||||
if (mediaUpload.messageIds == null || mediaUpload.metadata == null) {
|
||||
/// the finalize function was not called yet...
|
||||
return false;
|
||||
}
|
||||
|
||||
// at this point the media file is uploaded and the receiver are known.
|
||||
final downloadTokens = mediaUpload.uploadTokens!.downloadTokens;
|
||||
if (downloadTokens.isEmpty) {
|
||||
/// there are no download tokens yet, request them...
|
||||
return await handleUploadDone(mediaUpload);
|
||||
}
|
||||
|
||||
// download tokens are known so send the media file to the receivers
|
||||
await handleNotifyReceiver(mediaUpload);
|
||||
} catch (e) {
|
||||
Logger("media_send.dart")
|
||||
.shout("Non recoverable error while sending media file: $e");
|
||||
await handleUploadError(mediaUpload);
|
||||
}
|
||||
return false;
|
||||
});
|
||||
if (rerun) {
|
||||
handleNextMediaUploadSteps(mediaUploadId);
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// -- private functions --
|
||||
///
|
||||
///
|
||||
///
|
||||
Future handleUploadError(MediaUpload mediaUpload) async {
|
||||
// if the messageIds are already there notify the user about this error...
|
||||
if (mediaUpload.messageIds != null) {
|
||||
for (int messageId in mediaUpload.messageIds!) {
|
||||
await twonlyDatabase.messagesDao.updateMessageByMessageId(
|
||||
messageId,
|
||||
MessagesCompanion(
|
||||
errorWhileSending: Value(true),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
await twonlyDatabase.mediaUploadsDao
|
||||
.deleteMediaUpload(mediaUpload.mediaUploadId);
|
||||
}
|
||||
|
||||
Future<bool> handleUploadDone(MediaUpload media) async {
|
||||
Result res = await apiProvider.getDownloadTokens(
|
||||
media.uploadTokens!.uploadToken, media.messageIds!.length);
|
||||
|
||||
if (res.isError || !res.value.hasDownloadtokens()) {
|
||||
if (res.isError) {
|
||||
if (res.error == ErrorCode.PlanNotAllowed) {
|
||||
throw Exception("PlanNotAllowed");
|
||||
|
|
@ -369,36 +356,33 @@ Future<bool> handleGetUploadToken(MediaUpload media) async {
|
|||
}
|
||||
}
|
||||
Logger("media_send.dart")
|
||||
.shout("Will be tried again when reconnected to server!");
|
||||
.info("Upload done will be tried again when reconnected to server!");
|
||||
return false;
|
||||
}
|
||||
|
||||
Response_UploadToken tokens = res.value.uploadtoken;
|
||||
|
||||
Response_DownloadTokens tokens = res.value.downloadtokens;
|
||||
var token = MediaUploadTokens();
|
||||
token.uploadToken = tokens.uploadToken;
|
||||
token.uploadToken = media.uploadTokens!.uploadToken;
|
||||
token.downloadTokens = tokens.downloadTokens;
|
||||
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
media.mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
state: Value(UploadState.hasUploadToken),
|
||||
uploadTokens: Value(token),
|
||||
),
|
||||
);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
String uint8ListToHex(List<int> bytes) {
|
||||
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
|
||||
}
|
||||
Future<bool> handleMediaUpload(int mediaUploadId) async {
|
||||
Uint8List bytesToUpload = await readMediaFile(mediaUploadId, "encrypted");
|
||||
|
||||
Future<bool> handleUploadHttp(
|
||||
MediaUpload media, Uint8List? tmpCurrentImageBytes) async {
|
||||
Uint8List bytesToUpload = (tmpCurrentImageBytes != null)
|
||||
? tmpCurrentImageBytes
|
||||
: await readMediaFile(media, "encrypted");
|
||||
final storage = FlutterSecureStorage();
|
||||
String? apiAuthToken = await storage.read(key: "api_auth_token");
|
||||
if (apiAuthToken == null) {
|
||||
Logger("media_send.dart").shout("api auth token not defined.");
|
||||
return false;
|
||||
}
|
||||
|
||||
String apiUrl =
|
||||
"http${apiProvider.apiSecure}://${apiProvider.apiHost}/api/upload";
|
||||
|
|
@ -407,33 +391,45 @@ Future<bool> handleUploadHttp(
|
|||
"POST",
|
||||
Uri.parse(apiUrl),
|
||||
);
|
||||
requestMultipart.headers['x-twonly-auth-token'] =
|
||||
uint8ListToHex(base64Decode(apiAuthToken));
|
||||
|
||||
requestMultipart.files.add(http.MultipartFile.fromBytes(
|
||||
"file",
|
||||
bytesToUpload,
|
||||
filename: uint8ListToHex(media.uploadTokens!.uploadToken),
|
||||
filename: "upload",
|
||||
));
|
||||
|
||||
try {
|
||||
var streamedResponse = await requestMultipart.send();
|
||||
|
||||
await streamedResponse.stream.drain();
|
||||
Logger("media_send.dart").info("Uploaded: ${streamedResponse.statusCode}");
|
||||
final response = await http.Response.fromStream(streamedResponse);
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
Logger("media_send.dart").info("Uploaded: $response");
|
||||
if (response.body.length != 64) {
|
||||
Logger("media_send.dart").info("Got invalid upload token.");
|
||||
return false;
|
||||
}
|
||||
|
||||
final uploadToken = hexToUint8List(response.body);
|
||||
|
||||
var token = MediaUploadTokens();
|
||||
token.uploadToken = uploadToken;
|
||||
token.downloadTokens = [];
|
||||
|
||||
if (streamedResponse.statusCode == 200) {
|
||||
await twonlyDatabase.mediaUploadsDao.updateMediaUpload(
|
||||
media.mediaUploadId,
|
||||
mediaUploadId,
|
||||
MediaUploadsCompanion(
|
||||
state: Value(UploadState.isUploaded),
|
||||
uploadTokens: Value(token),
|
||||
),
|
||||
);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} catch (e) {
|
||||
Logger("media_send.dart").shout("Exception during upload: $e");
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
Future<bool> handleNotifyReceiver(MediaUpload media) async {
|
||||
|
|
@ -466,19 +462,19 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
|
|||
messageId: messageId,
|
||||
content: MediaMessageContent(
|
||||
downloadToken: media.uploadTokens!.downloadTokens[i],
|
||||
maxShowTime: media.metadata.maxShowTime,
|
||||
isRealTwonly: media.metadata.isRealTwonly,
|
||||
isVideo: media.metadata.isVideo,
|
||||
mirrorVideo: media.metadata.mirrorVideo,
|
||||
maxShowTime: media.metadata!.maxShowTime,
|
||||
isRealTwonly: media.metadata!.isRealTwonly,
|
||||
isVideo: media.metadata!.isVideo,
|
||||
mirrorVideo: media.metadata!.mirrorVideo,
|
||||
encryptionKey: media.encryptionData!.encryptionKey,
|
||||
encryptionMac: media.encryptionData!.encryptionMac,
|
||||
encryptionNonce: media.encryptionData!.encryptionNonce,
|
||||
),
|
||||
timestamp: media.metadata.messageSendAt,
|
||||
timestamp: media.metadata!.messageSendAt,
|
||||
),
|
||||
pushKind: (media.metadata.isRealTwonly)
|
||||
pushKind: (media.metadata!.isRealTwonly)
|
||||
? PushKind.twonly
|
||||
: (media.metadata.isVideo)
|
||||
: (media.metadata!.isVideo)
|
||||
? PushKind.video
|
||||
: PushKind.image,
|
||||
);
|
||||
|
|
@ -501,10 +497,61 @@ Future<bool> handleNotifyReceiver(MediaUpload media) async {
|
|||
return true;
|
||||
}
|
||||
|
||||
Future<bool> compressVideoIfExists(int mediaUploadId) async {
|
||||
String basePath = await getMediaFilePath(mediaUploadId, "send");
|
||||
File videoOriginalFile = File("$basePath.orginal.mp4");
|
||||
File videoCompressedFile = File("$basePath.mp4");
|
||||
|
||||
if (videoCompressedFile.existsSync()) {
|
||||
// file is already compressed and exists
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!videoOriginalFile.existsSync()) {
|
||||
// media upload does not have a video
|
||||
return false;
|
||||
}
|
||||
|
||||
MediaInfo? mediaInfo;
|
||||
|
||||
try {
|
||||
mediaInfo = await VideoCompress.compressVideo(
|
||||
videoOriginalFile.path,
|
||||
quality: VideoQuality.Res1280x720Quality,
|
||||
deleteOrigin: false,
|
||||
includeAudio:
|
||||
true, // https://github.com/jonataslaw/VideoCompress/issues/184
|
||||
);
|
||||
|
||||
if (mediaInfo!.filesize! >= 30 * 1000 * 1000) {
|
||||
// if the media file is over 20MB compress it with low quality
|
||||
mediaInfo = await VideoCompress.compressVideo(
|
||||
videoOriginalFile.path,
|
||||
quality: VideoQuality.Res960x540Quality,
|
||||
deleteOrigin: false,
|
||||
includeAudio: true,
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
Logger("media_send.dart").shout("Video compression: $e");
|
||||
}
|
||||
|
||||
if (mediaInfo == null) {
|
||||
Logger("media_send.dart").shout("Error compressing video.");
|
||||
// as a fall back use the non compressed version
|
||||
await videoOriginalFile.copy(videoCompressedFile.path);
|
||||
await videoOriginalFile.delete();
|
||||
} else {
|
||||
await mediaInfo.file!.copy(videoCompressedFile.path);
|
||||
await mediaInfo.file!.delete();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// --- helper functions ---
|
||||
|
||||
Future<Uint8List> readMediaFile(MediaUpload media, String type) async {
|
||||
String basePath = await getMediaFilePath(media.mediaUploadId, "send");
|
||||
Future<Uint8List> readMediaFile(int mediaUploadId, String type) async {
|
||||
String basePath = await getMediaFilePath(mediaUploadId, "send");
|
||||
File file = File("$basePath.$type");
|
||||
if (!await file.exists()) {
|
||||
throw Exception("$file not found");
|
||||
|
|
@ -562,3 +609,11 @@ Future<void> purgeSendMediaFiles() async {
|
|||
final directory = Directory(join(basedir.path, 'media', "send"));
|
||||
await purgeMediaFiles(directory);
|
||||
}
|
||||
|
||||
String uint8ListToHex(List<int> bytes) {
|
||||
return bytes.map((byte) => byte.toRadixString(16).padLeft(2, '0')).join();
|
||||
}
|
||||
|
||||
Uint8List hexToUint8List(String hex) => Uint8List.fromList(List<int>.generate(
|
||||
hex.length ~/ 2,
|
||||
(i) => int.parse(hex.substring(i * 2, i * 2 + 2), radix: 16)));
|
||||
|
|
|
|||
|
|
@ -362,6 +362,16 @@ class ApiProvider {
|
|||
return await sendRequestSync(req);
|
||||
}
|
||||
|
||||
Future<Result> getDownloadTokens(
|
||||
List<int> uploadToken, int recipientsCount) async {
|
||||
var get = ApplicationData_UploadDone()
|
||||
..uploadToken = uploadToken
|
||||
..recipientsCount = recipientsCount;
|
||||
var appData = ApplicationData()..uploaddone = get;
|
||||
var req = createClientToServerFromApplicationData(appData);
|
||||
return await sendRequestSync(req);
|
||||
}
|
||||
|
||||
Future<Result> getCurrentLocation() async {
|
||||
var get = ApplicationData_GetLocation();
|
||||
var appData = ApplicationData()..getlocation = get;
|
||||
|
|
|
|||
|
|
@ -267,7 +267,7 @@ class _CameraPreviewViewState extends State<CameraPreviewView> {
|
|||
if (shoudReturn != null && shoudReturn) {
|
||||
// ignore: use_build_context_synchronously
|
||||
if (widget.sendTo == null) {
|
||||
globalUpdateOfHomeViewPageIndex(1);
|
||||
globalUpdateOfHomeViewPageIndex(0);
|
||||
} else {
|
||||
Navigator.pop(context);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -52,23 +52,26 @@ class ShareImageEditorView extends StatefulWidget {
|
|||
|
||||
class _ShareImageEditorView extends State<ShareImageEditorView> {
|
||||
bool _isRealTwonly = false;
|
||||
bool videoWithAudio = true;
|
||||
int maxShowTime = gMediaShowInfinite;
|
||||
String? sendNextMediaToUserName;
|
||||
double tabDownPostion = 0;
|
||||
double tabDownPosition = 0;
|
||||
bool sendingOrLoadingImage = true;
|
||||
bool isDisposed = false;
|
||||
HashSet<int> selectedUserIds = HashSet();
|
||||
double widthRatio = 1, heightRatio = 1, pixelRatio = 1;
|
||||
VideoPlayerController? videoController;
|
||||
|
||||
ImageItem currentImage = ImageItem();
|
||||
ScreenshotController screenshotController = ScreenshotController();
|
||||
|
||||
/// Media upload variables
|
||||
int? mediaUploadId;
|
||||
Future<bool>? videoUploadHandler;
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
initAsync();
|
||||
initMediaFileUpload();
|
||||
if (widget.imageBytes != null) {
|
||||
loadImage(widget.imageBytes!);
|
||||
} else if (widget.videoFilePath != null) {
|
||||
|
|
@ -97,6 +100,19 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
}
|
||||
}
|
||||
|
||||
Future initMediaFileUpload() async {
|
||||
// media init was already called...
|
||||
if (mediaUploadId != null) return;
|
||||
|
||||
mediaUploadId = await initMediaUpload();
|
||||
|
||||
if (widget.videoFilePath != null && mediaUploadId != null) {
|
||||
// start with the video compression...
|
||||
videoUploadHandler =
|
||||
addVideoToUpload(mediaUploadId!, widget.videoFilePath!);
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
isDisposed = true;
|
||||
|
|
@ -221,19 +237,6 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
},
|
||||
),
|
||||
),
|
||||
// https://github.com/jonataslaw/VideoCompress/issues/184
|
||||
// if (widget.videoFilePath != null) const SizedBox(height: 8),
|
||||
// if (widget.videoFilePath != null)
|
||||
// ActionButton(
|
||||
// (videoWithAudio) ? Icons.volume_up_rounded : Icons.volume_off_rounded,
|
||||
// tooltipText: context.lang.protectAsARealTwonly,
|
||||
// color: Colors.white,
|
||||
// onPressed: () async {
|
||||
// setState(() {
|
||||
// videoWithAudio = !videoWithAudio;
|
||||
// });
|
||||
// },
|
||||
// ),
|
||||
const SizedBox(height: 8),
|
||||
ActionButton(
|
||||
FontAwesomeIcons.shieldHeart,
|
||||
|
|
@ -312,8 +315,13 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
}
|
||||
|
||||
Future pushShareImageView() async {
|
||||
if (mediaUploadId == null) {
|
||||
await initMediaFileUpload();
|
||||
if (mediaUploadId == null) return;
|
||||
}
|
||||
Future<Uint8List?> imageBytes = getMergedImage();
|
||||
videoController?.pause();
|
||||
if (isDisposed || !context.mounted) return;
|
||||
bool? wasSend = await Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(
|
||||
|
|
@ -323,7 +331,8 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
maxShowTime: maxShowTime,
|
||||
selectedUserIds: selectedUserIds,
|
||||
updateStatus: updateStatus,
|
||||
videoFilePath: widget.videoFilePath,
|
||||
videoUploadHandler: videoUploadHandler,
|
||||
mediaUploadId: mediaUploadId!,
|
||||
mirrorVideo: widget.mirrorVideo,
|
||||
),
|
||||
),
|
||||
|
|
@ -402,14 +411,26 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
);
|
||||
}));
|
||||
} else {
|
||||
sendMediaFile(
|
||||
Future imageHandler =
|
||||
addOrModifyImageToUpload(mediaUploadId!, imageBytes);
|
||||
|
||||
// first finalize the upload
|
||||
await finalizeUpload(
|
||||
mediaUploadId!,
|
||||
[widget.sendTo!.userId],
|
||||
imageBytes,
|
||||
_isRealTwonly,
|
||||
maxShowTime,
|
||||
widget.videoFilePath,
|
||||
widget.videoFilePath != null,
|
||||
widget.mirrorVideo,
|
||||
maxShowTime,
|
||||
);
|
||||
|
||||
/// then call the upload process in the background
|
||||
encryptAndPreUploadMediaFiles(
|
||||
mediaUploadId!,
|
||||
imageHandler,
|
||||
videoUploadHandler,
|
||||
);
|
||||
|
||||
if (context.mounted) {
|
||||
// ignore: use_build_context_synchronously
|
||||
Navigator.pop(context, true);
|
||||
|
|
@ -434,9 +455,9 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
GestureDetector(
|
||||
onTapDown: (details) {
|
||||
if (details.globalPosition.dy > 60) {
|
||||
tabDownPostion = details.globalPosition.dy - 60;
|
||||
tabDownPosition = details.globalPosition.dy - 60;
|
||||
} else {
|
||||
tabDownPostion = details.globalPosition.dy;
|
||||
tabDownPosition = details.globalPosition.dy;
|
||||
}
|
||||
},
|
||||
onTap: () {
|
||||
|
|
@ -446,7 +467,7 @@ class _ShareImageEditorView extends State<ShareImageEditorView> {
|
|||
undoLayers.clear();
|
||||
removedLayers.clear();
|
||||
layers.add(TextLayerData(
|
||||
offset: Offset(0, tabDownPostion),
|
||||
offset: Offset(0, tabDownPosition),
|
||||
textLayersBefore: layers.whereType<TextLayerData>().length,
|
||||
));
|
||||
setState(() {});
|
||||
|
|
|
|||
|
|
@ -1,6 +1,5 @@
|
|||
import 'dart:async';
|
||||
import 'dart:collection';
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
|
||||
|
|
@ -26,16 +25,18 @@ class ShareImageView extends StatefulWidget {
|
|||
required this.maxShowTime,
|
||||
required this.selectedUserIds,
|
||||
required this.updateStatus,
|
||||
required this.videoFilePath,
|
||||
required this.videoUploadHandler,
|
||||
required this.mediaUploadId,
|
||||
this.enableVideoAudio});
|
||||
final Future<Uint8List?> imageBytesFuture;
|
||||
final bool isRealTwonly;
|
||||
final bool mirrorVideo;
|
||||
final int maxShowTime;
|
||||
final File? videoFilePath;
|
||||
final HashSet<int> selectedUserIds;
|
||||
final bool? enableVideoAudio;
|
||||
final int mediaUploadId;
|
||||
final Function(int, bool) updateStatus;
|
||||
final Future<bool>? videoUploadHandler;
|
||||
|
||||
@override
|
||||
State<ShareImageView> createState() => _ShareImageView();
|
||||
|
|
@ -73,6 +74,13 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
|
||||
Future initAsync() async {
|
||||
imageBytes = await widget.imageBytesFuture;
|
||||
if (imageBytes != null) {
|
||||
final imageHandler =
|
||||
addOrModifyImageToUpload(widget.mediaUploadId, imageBytes!);
|
||||
// start with the pre upload of the media file...
|
||||
encryptAndPreUploadMediaFiles(
|
||||
widget.mediaUploadId, imageHandler, widget.videoUploadHandler);
|
||||
}
|
||||
setState(() {});
|
||||
}
|
||||
|
||||
|
|
@ -287,14 +295,18 @@ class _ShareImageView extends State<ShareImageView> {
|
|||
sendingImage = true;
|
||||
});
|
||||
|
||||
sendMediaFile(
|
||||
await finalizeUpload(
|
||||
widget.mediaUploadId,
|
||||
widget.selectedUserIds.toList(),
|
||||
imageBytes!,
|
||||
widget.isRealTwonly,
|
||||
widget.maxShowTime,
|
||||
widget.videoFilePath,
|
||||
widget.videoUploadHandler != null,
|
||||
widget.mirrorVideo,
|
||||
widget.maxShowTime,
|
||||
);
|
||||
|
||||
/// trigger the upload of the media file.
|
||||
handleNextMediaUploadSteps(widget.mediaUploadId);
|
||||
|
||||
if (context.mounted) {
|
||||
Navigator.pop(context, true);
|
||||
// if (widget.preselectedUser != null) {
|
||||
|
|
|
|||
|
|
@ -39,7 +39,7 @@ class HomeViewState extends State<HomeView> {
|
|||
|
||||
selectNotificationStream.stream
|
||||
.listen((NotificationResponse? response) async {
|
||||
globalUpdateOfHomeViewPageIndex(1);
|
||||
globalUpdateOfHomeViewPageIndex(0);
|
||||
});
|
||||
initAsync();
|
||||
}
|
||||
|
|
@ -50,7 +50,7 @@ class HomeViewState extends State<HomeView> {
|
|||
|
||||
if (notificationAppLaunchDetails != null) {
|
||||
if (notificationAppLaunchDetails.didNotificationLaunchApp) {
|
||||
globalUpdateOfHomeViewPageIndex(1);
|
||||
globalUpdateOfHomeViewPageIndex(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -11,6 +11,7 @@ import 'schema_v5.dart' as v5;
|
|||
import 'schema_v6.dart' as v6;
|
||||
import 'schema_v7.dart' as v7;
|
||||
import 'schema_v8.dart' as v8;
|
||||
import 'schema_v9.dart' as v9;
|
||||
|
||||
class GeneratedHelper implements SchemaInstantiationHelper {
|
||||
@override
|
||||
|
|
@ -32,10 +33,12 @@ class GeneratedHelper implements SchemaInstantiationHelper {
|
|||
return v7.DatabaseAtV7(db);
|
||||
case 8:
|
||||
return v8.DatabaseAtV8(db);
|
||||
case 9:
|
||||
return v9.DatabaseAtV9(db);
|
||||
default:
|
||||
throw MissingSchemaException(version, versions);
|
||||
}
|
||||
}
|
||||
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8];
|
||||
static const versions = const [1, 2, 3, 4, 5, 6, 7, 8, 9];
|
||||
}
|
||||
|
|
|
|||
2963
test/drift/twonly_database/generated/schema_v9.dart
Normal file
2963
test/drift/twonly_database/generated/schema_v9.dart
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue