♻️ Use drift instead for floor
This commit is contained in:
@ -6,7 +6,6 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:get/get_connect/http/src/request/request.dart';
|
||||
import 'package:solian/controllers/chat_events_controller.dart';
|
||||
import 'package:solian/exceptions/request.dart';
|
||||
import 'package:solian/exceptions/unauthorized.dart';
|
||||
import 'package:solian/providers/websocket.dart';
|
||||
@ -199,11 +198,6 @@ class AuthProvider extends GetConnect {
|
||||
Get.find<WebSocketProvider>().notifications.clear();
|
||||
Get.find<WebSocketProvider>().notificationUnread.value = 0;
|
||||
|
||||
final chatHistory = ChatEventController();
|
||||
chatHistory.initialize().then((_) async {
|
||||
await chatHistory.database.localEvents.wipeLocalEvents();
|
||||
});
|
||||
|
||||
storage.deleteAll();
|
||||
}
|
||||
|
||||
|
24
lib/providers/database/database.dart
Normal file
24
lib/providers/database/database.dart
Normal file
@ -0,0 +1,24 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift_flutter/drift_flutter.dart';
|
||||
import 'package:get/get.dart' hide Value;
|
||||
import 'package:solian/providers/database/tables/messages.dart';
|
||||
|
||||
import 'package:solian/models/event.dart';
|
||||
|
||||
part 'database.g.dart';
|
||||
|
||||
@DriftDatabase(tables: [LocalMessageEventTable])
|
||||
class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase() : super(_openConnection());
|
||||
|
||||
@override
|
||||
int get schemaVersion => 1;
|
||||
|
||||
static QueryExecutor _openConnection() {
|
||||
return driftDatabase(name: 'solar_network_local_db');
|
||||
}
|
||||
}
|
||||
|
||||
class DatabaseProvider extends GetxController {
|
||||
final database = AppDatabase();
|
||||
}
|
429
lib/providers/database/database.g.dart
Normal file
429
lib/providers/database/database.g.dart
Normal file
@ -0,0 +1,429 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'database.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
class $LocalMessageEventTableTable extends LocalMessageEventTable
|
||||
with TableInfo<$LocalMessageEventTableTable, LocalMessageEventTableData> {
|
||||
@override
|
||||
final GeneratedDatabase attachedDatabase;
|
||||
final String? _alias;
|
||||
$LocalMessageEventTableTable(this.attachedDatabase, [this._alias]);
|
||||
static const VerificationMeta _idMeta = const VerificationMeta('id');
|
||||
@override
|
||||
late final GeneratedColumn<int> id = GeneratedColumn<int>(
|
||||
'id', aliasedName, false,
|
||||
hasAutoIncrement: true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultConstraints:
|
||||
GeneratedColumn.constraintIsAlways('PRIMARY KEY AUTOINCREMENT'));
|
||||
static const VerificationMeta _channelIdMeta =
|
||||
const VerificationMeta('channelId');
|
||||
@override
|
||||
late final GeneratedColumn<int> channelId = GeneratedColumn<int>(
|
||||
'channel_id', aliasedName, false,
|
||||
type: DriftSqlType.int, requiredDuringInsert: true);
|
||||
static const VerificationMeta _dataMeta = const VerificationMeta('data');
|
||||
@override
|
||||
late final GeneratedColumnWithTypeConverter<Event?, String> data =
|
||||
GeneratedColumn<String>('data', aliasedName, false,
|
||||
type: DriftSqlType.string, requiredDuringInsert: true)
|
||||
.withConverter<Event?>($LocalMessageEventTableTable.$converterdata);
|
||||
static const VerificationMeta _createdAtMeta =
|
||||
const VerificationMeta('createdAt');
|
||||
@override
|
||||
late final GeneratedColumn<DateTime> createdAt = GeneratedColumn<DateTime>(
|
||||
'created_at', aliasedName, false,
|
||||
type: DriftSqlType.dateTime,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: Constant(DateTime.now()));
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, channelId, data, createdAt];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
String get actualTableName => $name;
|
||||
static const String $name = 'local_message_event_table';
|
||||
@override
|
||||
VerificationContext validateIntegrity(
|
||||
Insertable<LocalMessageEventTableData> instance,
|
||||
{bool isInserting = false}) {
|
||||
final context = VerificationContext();
|
||||
final data = instance.toColumns(true);
|
||||
if (data.containsKey('id')) {
|
||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
||||
}
|
||||
if (data.containsKey('channel_id')) {
|
||||
context.handle(_channelIdMeta,
|
||||
channelId.isAcceptableOrUnknown(data['channel_id']!, _channelIdMeta));
|
||||
} else if (isInserting) {
|
||||
context.missing(_channelIdMeta);
|
||||
}
|
||||
context.handle(_dataMeta, const VerificationResult.success());
|
||||
if (data.containsKey('created_at')) {
|
||||
context.handle(_createdAtMeta,
|
||||
createdAt.isAcceptableOrUnknown(data['created_at']!, _createdAtMeta));
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@override
|
||||
Set<GeneratedColumn> get $primaryKey => {id};
|
||||
@override
|
||||
LocalMessageEventTableData map(Map<String, dynamic> data,
|
||||
{String? tablePrefix}) {
|
||||
final effectivePrefix = tablePrefix != null ? '$tablePrefix.' : '';
|
||||
return LocalMessageEventTableData(
|
||||
id: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}id'])!,
|
||||
channelId: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.int, data['${effectivePrefix}channel_id'])!,
|
||||
data: $LocalMessageEventTableTable.$converterdata.fromSql(attachedDatabase
|
||||
.typeMapping
|
||||
.read(DriftSqlType.string, data['${effectivePrefix}data'])!),
|
||||
createdAt: attachedDatabase.typeMapping
|
||||
.read(DriftSqlType.dateTime, data['${effectivePrefix}created_at'])!,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
$LocalMessageEventTableTable createAlias(String alias) {
|
||||
return $LocalMessageEventTableTable(attachedDatabase, alias);
|
||||
}
|
||||
|
||||
static TypeConverter<Event?, String> $converterdata =
|
||||
const MessageEventConverter();
|
||||
}
|
||||
|
||||
class LocalMessageEventTableData extends DataClass
|
||||
implements Insertable<LocalMessageEventTableData> {
|
||||
final int id;
|
||||
final int channelId;
|
||||
final Event? data;
|
||||
final DateTime createdAt;
|
||||
const LocalMessageEventTableData(
|
||||
{required this.id,
|
||||
required this.channelId,
|
||||
this.data,
|
||||
required this.createdAt});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<int>(id);
|
||||
map['channel_id'] = Variable<int>(channelId);
|
||||
if (!nullToAbsent || data != null) {
|
||||
map['data'] = Variable<String>(
|
||||
$LocalMessageEventTableTable.$converterdata.toSql(data));
|
||||
}
|
||||
map['created_at'] = Variable<DateTime>(createdAt);
|
||||
return map;
|
||||
}
|
||||
|
||||
LocalMessageEventTableCompanion toCompanion(bool nullToAbsent) {
|
||||
return LocalMessageEventTableCompanion(
|
||||
id: Value(id),
|
||||
channelId: Value(channelId),
|
||||
data: data == null && nullToAbsent ? const Value.absent() : Value(data),
|
||||
createdAt: Value(createdAt),
|
||||
);
|
||||
}
|
||||
|
||||
factory LocalMessageEventTableData.fromJson(Map<String, dynamic> json,
|
||||
{ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return LocalMessageEventTableData(
|
||||
id: serializer.fromJson<int>(json['id']),
|
||||
channelId: serializer.fromJson<int>(json['channelId']),
|
||||
data: serializer.fromJson<Event?>(json['data']),
|
||||
createdAt: serializer.fromJson<DateTime>(json['createdAt']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<int>(id),
|
||||
'channelId': serializer.toJson<int>(channelId),
|
||||
'data': serializer.toJson<Event?>(data),
|
||||
'createdAt': serializer.toJson<DateTime>(createdAt),
|
||||
};
|
||||
}
|
||||
|
||||
LocalMessageEventTableData copyWith(
|
||||
{int? id,
|
||||
int? channelId,
|
||||
Value<Event?> data = const Value.absent(),
|
||||
DateTime? createdAt}) =>
|
||||
LocalMessageEventTableData(
|
||||
id: id ?? this.id,
|
||||
channelId: channelId ?? this.channelId,
|
||||
data: data.present ? data.value : this.data,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
LocalMessageEventTableData copyWithCompanion(
|
||||
LocalMessageEventTableCompanion data) {
|
||||
return LocalMessageEventTableData(
|
||||
id: data.id.present ? data.id.value : this.id,
|
||||
channelId: data.channelId.present ? data.channelId.value : this.channelId,
|
||||
data: data.data.present ? data.data.value : this.data,
|
||||
createdAt: data.createdAt.present ? data.createdAt.value : this.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('LocalMessageEventTableData(')
|
||||
..write('id: $id, ')
|
||||
..write('channelId: $channelId, ')
|
||||
..write('data: $data, ')
|
||||
..write('createdAt: $createdAt')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, channelId, data, createdAt);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is LocalMessageEventTableData &&
|
||||
other.id == this.id &&
|
||||
other.channelId == this.channelId &&
|
||||
other.data == this.data &&
|
||||
other.createdAt == this.createdAt);
|
||||
}
|
||||
|
||||
class LocalMessageEventTableCompanion
|
||||
extends UpdateCompanion<LocalMessageEventTableData> {
|
||||
final Value<int> id;
|
||||
final Value<int> channelId;
|
||||
final Value<Event?> data;
|
||||
final Value<DateTime> createdAt;
|
||||
const LocalMessageEventTableCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.channelId = const Value.absent(),
|
||||
this.data = const Value.absent(),
|
||||
this.createdAt = const Value.absent(),
|
||||
});
|
||||
LocalMessageEventTableCompanion.insert({
|
||||
this.id = const Value.absent(),
|
||||
required int channelId,
|
||||
required Event? data,
|
||||
this.createdAt = const Value.absent(),
|
||||
}) : channelId = Value(channelId),
|
||||
data = Value(data);
|
||||
static Insertable<LocalMessageEventTableData> custom({
|
||||
Expression<int>? id,
|
||||
Expression<int>? channelId,
|
||||
Expression<String>? data,
|
||||
Expression<DateTime>? createdAt,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (channelId != null) 'channel_id': channelId,
|
||||
if (data != null) 'data': data,
|
||||
if (createdAt != null) 'created_at': createdAt,
|
||||
});
|
||||
}
|
||||
|
||||
LocalMessageEventTableCompanion copyWith(
|
||||
{Value<int>? id,
|
||||
Value<int>? channelId,
|
||||
Value<Event?>? data,
|
||||
Value<DateTime>? createdAt}) {
|
||||
return LocalMessageEventTableCompanion(
|
||||
id: id ?? this.id,
|
||||
channelId: channelId ?? this.channelId,
|
||||
data: data ?? this.data,
|
||||
createdAt: createdAt ?? this.createdAt,
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
if (id.present) {
|
||||
map['id'] = Variable<int>(id.value);
|
||||
}
|
||||
if (channelId.present) {
|
||||
map['channel_id'] = Variable<int>(channelId.value);
|
||||
}
|
||||
if (data.present) {
|
||||
map['data'] = Variable<String>(
|
||||
$LocalMessageEventTableTable.$converterdata.toSql(data.value));
|
||||
}
|
||||
if (createdAt.present) {
|
||||
map['created_at'] = Variable<DateTime>(createdAt.value);
|
||||
}
|
||||
return map;
|
||||
}
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return (StringBuffer('LocalMessageEventTableCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('channelId: $channelId, ')
|
||||
..write('data: $data, ')
|
||||
..write('createdAt: $createdAt')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
}
|
||||
|
||||
abstract class _$AppDatabase extends GeneratedDatabase {
|
||||
_$AppDatabase(QueryExecutor e) : super(e);
|
||||
$AppDatabaseManager get managers => $AppDatabaseManager(this);
|
||||
late final $LocalMessageEventTableTable localMessageEventTable =
|
||||
$LocalMessageEventTableTable(this);
|
||||
@override
|
||||
Iterable<TableInfo<Table, Object?>> get allTables =>
|
||||
allSchemaEntities.whereType<TableInfo<Table, Object?>>();
|
||||
@override
|
||||
List<DatabaseSchemaEntity> get allSchemaEntities => [localMessageEventTable];
|
||||
}
|
||||
|
||||
typedef $$LocalMessageEventTableTableCreateCompanionBuilder
|
||||
= LocalMessageEventTableCompanion Function({
|
||||
Value<int> id,
|
||||
required int channelId,
|
||||
required Event? data,
|
||||
Value<DateTime> createdAt,
|
||||
});
|
||||
typedef $$LocalMessageEventTableTableUpdateCompanionBuilder
|
||||
= LocalMessageEventTableCompanion Function({
|
||||
Value<int> id,
|
||||
Value<int> channelId,
|
||||
Value<Event?> data,
|
||||
Value<DateTime> createdAt,
|
||||
});
|
||||
|
||||
class $$LocalMessageEventTableTableFilterComposer
|
||||
extends FilterComposer<_$AppDatabase, $LocalMessageEventTableTable> {
|
||||
$$LocalMessageEventTableTableFilterComposer(super.$state);
|
||||
ColumnFilters<int> get id => $state.composableBuilder(
|
||||
column: $state.table.id,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
||||
|
||||
ColumnFilters<int> get channelId => $state.composableBuilder(
|
||||
column: $state.table.channelId,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
||||
|
||||
ColumnWithTypeConverterFilters<Event?, Event, String> get data =>
|
||||
$state.composableBuilder(
|
||||
column: $state.table.data,
|
||||
builder: (column, joinBuilders) => ColumnWithTypeConverterFilters(
|
||||
column,
|
||||
joinBuilders: joinBuilders));
|
||||
|
||||
ColumnFilters<DateTime> get createdAt => $state.composableBuilder(
|
||||
column: $state.table.createdAt,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnFilters(column, joinBuilders: joinBuilders));
|
||||
}
|
||||
|
||||
class $$LocalMessageEventTableTableOrderingComposer
|
||||
extends OrderingComposer<_$AppDatabase, $LocalMessageEventTableTable> {
|
||||
$$LocalMessageEventTableTableOrderingComposer(super.$state);
|
||||
ColumnOrderings<int> get id => $state.composableBuilder(
|
||||
column: $state.table.id,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
||||
|
||||
ColumnOrderings<int> get channelId => $state.composableBuilder(
|
||||
column: $state.table.channelId,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
||||
|
||||
ColumnOrderings<String> get data => $state.composableBuilder(
|
||||
column: $state.table.data,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
||||
|
||||
ColumnOrderings<DateTime> get createdAt => $state.composableBuilder(
|
||||
column: $state.table.createdAt,
|
||||
builder: (column, joinBuilders) =>
|
||||
ColumnOrderings(column, joinBuilders: joinBuilders));
|
||||
}
|
||||
|
||||
class $$LocalMessageEventTableTableTableManager extends RootTableManager<
|
||||
_$AppDatabase,
|
||||
$LocalMessageEventTableTable,
|
||||
LocalMessageEventTableData,
|
||||
$$LocalMessageEventTableTableFilterComposer,
|
||||
$$LocalMessageEventTableTableOrderingComposer,
|
||||
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
||||
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
||||
(
|
||||
LocalMessageEventTableData,
|
||||
BaseReferences<_$AppDatabase, $LocalMessageEventTableTable,
|
||||
LocalMessageEventTableData>
|
||||
),
|
||||
LocalMessageEventTableData,
|
||||
PrefetchHooks Function()> {
|
||||
$$LocalMessageEventTableTableTableManager(
|
||||
_$AppDatabase db, $LocalMessageEventTableTable table)
|
||||
: super(TableManagerState(
|
||||
db: db,
|
||||
table: table,
|
||||
filteringComposer: $$LocalMessageEventTableTableFilterComposer(
|
||||
ComposerState(db, table)),
|
||||
orderingComposer: $$LocalMessageEventTableTableOrderingComposer(
|
||||
ComposerState(db, table)),
|
||||
updateCompanionCallback: ({
|
||||
Value<int> id = const Value.absent(),
|
||||
Value<int> channelId = const Value.absent(),
|
||||
Value<Event?> data = const Value.absent(),
|
||||
Value<DateTime> createdAt = const Value.absent(),
|
||||
}) =>
|
||||
LocalMessageEventTableCompanion(
|
||||
id: id,
|
||||
channelId: channelId,
|
||||
data: data,
|
||||
createdAt: createdAt,
|
||||
),
|
||||
createCompanionCallback: ({
|
||||
Value<int> id = const Value.absent(),
|
||||
required int channelId,
|
||||
required Event? data,
|
||||
Value<DateTime> createdAt = const Value.absent(),
|
||||
}) =>
|
||||
LocalMessageEventTableCompanion.insert(
|
||||
id: id,
|
||||
channelId: channelId,
|
||||
data: data,
|
||||
createdAt: createdAt,
|
||||
),
|
||||
withReferenceMapper: (p0) => p0
|
||||
.map((e) => (e.readTable(table), BaseReferences(db, table, e)))
|
||||
.toList(),
|
||||
prefetchHooksCallback: null,
|
||||
));
|
||||
}
|
||||
|
||||
typedef $$LocalMessageEventTableTableProcessedTableManager
|
||||
= ProcessedTableManager<
|
||||
_$AppDatabase,
|
||||
$LocalMessageEventTableTable,
|
||||
LocalMessageEventTableData,
|
||||
$$LocalMessageEventTableTableFilterComposer,
|
||||
$$LocalMessageEventTableTableOrderingComposer,
|
||||
$$LocalMessageEventTableTableCreateCompanionBuilder,
|
||||
$$LocalMessageEventTableTableUpdateCompanionBuilder,
|
||||
(
|
||||
LocalMessageEventTableData,
|
||||
BaseReferences<_$AppDatabase, $LocalMessageEventTableTable,
|
||||
LocalMessageEventTableData>
|
||||
),
|
||||
LocalMessageEventTableData,
|
||||
PrefetchHooks Function()>;
|
||||
|
||||
class $AppDatabaseManager {
|
||||
final _$AppDatabase _db;
|
||||
$AppDatabaseManager(this._db);
|
||||
$$LocalMessageEventTableTableTableManager get localMessageEventTable =>
|
||||
$$LocalMessageEventTableTableTableManager(
|
||||
_db, _db.localMessageEventTable);
|
||||
}
|
202
lib/providers/database/services/messages.dart
Normal file
202
lib/providers/database/services/messages.dart
Normal file
@ -0,0 +1,202 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:get/get.dart' hide Value;
|
||||
import 'package:solian/exceptions/request.dart';
|
||||
import 'package:solian/models/channel.dart';
|
||||
import 'package:solian/models/event.dart';
|
||||
import 'package:solian/models/pagination.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/providers/database/database.dart';
|
||||
|
||||
class MessagesFetchingProvider extends GetxController {
|
||||
Future<(List<Event>, int)?> getWhatsNewEvents(int pivot, {take = 10}) async {
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/whats-new?pivot=$pivot&take=$take',
|
||||
);
|
||||
|
||||
if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
final PaginationResult response = PaginationResult.fromJson(resp.body);
|
||||
final result =
|
||||
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
||||
|
||||
return (result, response.count);
|
||||
}
|
||||
|
||||
Future<Event?> fetchRemoteEvent(int id, Channel channel, String scope) async {
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/channels/$scope/${channel.alias}/events/$id',
|
||||
);
|
||||
|
||||
if (resp.statusCode == 404) {
|
||||
return null;
|
||||
} else if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
return Event.fromJson(resp.body);
|
||||
}
|
||||
|
||||
Future<(List<Event>, int)?> fetchRemoteEvents(
|
||||
Channel channel,
|
||||
String scope, {
|
||||
required int remainDepth,
|
||||
bool Function(List<Event> items)? onBrake,
|
||||
take = 10,
|
||||
offset = 0,
|
||||
}) async {
|
||||
if (remainDepth <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/channels/$scope/${channel.alias}/events?take=$take&offset=$offset',
|
||||
);
|
||||
|
||||
if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
final PaginationResult response = PaginationResult.fromJson(resp.body);
|
||||
final result =
|
||||
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
||||
|
||||
if (onBrake != null && onBrake(result)) {
|
||||
return (result, response.count);
|
||||
}
|
||||
|
||||
final expandResult = (await fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: remainDepth - 1,
|
||||
take: take,
|
||||
offset: offset + result.length,
|
||||
))
|
||||
?.$1 ??
|
||||
List.empty();
|
||||
|
||||
return ([...result, ...expandResult], response.count);
|
||||
}
|
||||
|
||||
Future<LocalMessageEventTableData> receiveEvent(Event remote) async {
|
||||
// Insert record
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
final entry = await database
|
||||
.into(database.localMessageEventTable)
|
||||
.insertReturning(LocalMessageEventTableCompanion.insert(
|
||||
id: Value(remote.id),
|
||||
channelId: remote.channelId,
|
||||
data: remote,
|
||||
createdAt: Value(remote.createdAt),
|
||||
));
|
||||
|
||||
// Handle side-effect like editing and deleting
|
||||
switch (remote.type) {
|
||||
case 'messages.edit':
|
||||
final body = EventMessageBody.fromJson(remote.body);
|
||||
if (body.relatedEvent != null) {
|
||||
final target = await (database.select(database.localMessageEventTable)
|
||||
..where((x) => x.id.equals(body.relatedEvent!)))
|
||||
.getSingleOrNull();
|
||||
if (target != null) {
|
||||
target.data!.body = remote.body;
|
||||
target.data!.updatedAt = remote.updatedAt;
|
||||
await (database.update(database.localMessageEventTable)
|
||||
..where((x) => x.id.equals(target.id)))
|
||||
.write(
|
||||
LocalMessageEventTableCompanion(data: Value(target.data)),
|
||||
);
|
||||
}
|
||||
}
|
||||
case 'messages.delete':
|
||||
final body = EventMessageBody.fromJson(remote.body);
|
||||
if (body.relatedEvent != null) {
|
||||
await (database.delete(database.localMessageEventTable)
|
||||
..where((x) => x.id.equals(body.relatedEvent!)))
|
||||
.go();
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
Future<LocalMessageEventTableData?> getEvent(int id, Channel channel,
|
||||
{String scope = 'global'}) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
final localRecord = await (database.select(database.localMessageEventTable)
|
||||
..where((x) => x.id.equals(id)))
|
||||
.getSingleOrNull();
|
||||
if (localRecord != null) return localRecord;
|
||||
|
||||
final remoteRecord = await fetchRemoteEvent(id, channel, scope);
|
||||
if (remoteRecord == null) return null;
|
||||
|
||||
return await receiveEvent(remoteRecord);
|
||||
}
|
||||
|
||||
/// Pull the remote events to local database
|
||||
Future<(List<Event>, int)?> pullRemoteEvents(Channel channel,
|
||||
{String scope = 'global', depth = 10, offset = 0}) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
final lastOne = await (database.select(database.localMessageEventTable)
|
||||
..where((x) => x.channelId.equals(channel.id))
|
||||
..orderBy([(t) => OrderingTerm.desc(t.id)]))
|
||||
.getSingleOrNull();
|
||||
|
||||
final data = await fetchRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: depth,
|
||||
offset: offset,
|
||||
onBrake: (items) {
|
||||
return items.any((x) => x.id == lastOne?.id);
|
||||
},
|
||||
);
|
||||
if (data != null) {
|
||||
await database.batch((batch) {
|
||||
batch.insertAll(
|
||||
database.localMessageEventTable,
|
||||
data.$1.map((x) => LocalMessageEventTableCompanion(
|
||||
id: Value(x.id),
|
||||
channelId: Value(x.channelId),
|
||||
data: Value(x),
|
||||
createdAt: Value(x.createdAt),
|
||||
)),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<List<LocalMessageEventTableData>> listEvents(Channel channel) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
return await (database.select(database.localMessageEventTable)
|
||||
..where((x) => x.channelId.equals(channel.id))
|
||||
..orderBy([(t) => OrderingTerm.desc(t.id)]))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future<LocalMessageEventTableData?> getLastInChannel(Channel channel) async {
|
||||
final database = Get.find<DatabaseProvider>().database;
|
||||
return await (database.select(database.localMessageEventTable)
|
||||
..where((x) => x.channelId.equals(channel.id))
|
||||
..orderBy([(t) => OrderingTerm.desc(t.id)]))
|
||||
.getSingleOrNull();
|
||||
}
|
||||
}
|
13
lib/providers/database/tables/json.dart
Normal file
13
lib/providers/database/tables/json.dart
Normal file
@ -0,0 +1,13 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
|
||||
class JsonConverter extends TypeConverter<Object?, String> {
|
||||
const JsonConverter();
|
||||
|
||||
@override
|
||||
Object? fromSql(String fromDb) => jsonDecode(fromDb);
|
||||
|
||||
@override
|
||||
String toSql(Object? value) => jsonEncode(value);
|
||||
}
|
22
lib/providers/database/tables/messages.dart
Normal file
22
lib/providers/database/tables/messages.dart
Normal file
@ -0,0 +1,22 @@
|
||||
import 'dart:convert';
|
||||
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:solian/models/event.dart';
|
||||
|
||||
class LocalMessageEventTable extends Table {
|
||||
IntColumn get id => integer().autoIncrement()();
|
||||
IntColumn get channelId => integer()();
|
||||
TextColumn get data => text().map(const MessageEventConverter())();
|
||||
DateTimeColumn get createdAt =>
|
||||
dateTime().withDefault(Constant(DateTime.now()))();
|
||||
}
|
||||
|
||||
class MessageEventConverter extends TypeConverter<Event?, String> {
|
||||
const MessageEventConverter();
|
||||
|
||||
@override
|
||||
Event? fromSql(String fromDb) => Event.fromJson(jsonDecode(fromDb));
|
||||
|
||||
@override
|
||||
String toSql(Event? value) => jsonEncode(value?.toJson());
|
||||
}
|
@ -1,173 +0,0 @@
|
||||
import 'package:floor/floor.dart';
|
||||
import 'package:get/get.dart';
|
||||
import 'package:solian/exceptions/request.dart';
|
||||
import 'package:solian/models/channel.dart';
|
||||
import 'package:solian/models/event.dart';
|
||||
import 'package:solian/models/pagination.dart';
|
||||
import 'package:solian/providers/auth.dart';
|
||||
import 'package:solian/providers/message/events.dart';
|
||||
|
||||
Future<MessageHistoryDb> createHistoryDb() async {
|
||||
final migration1to2 = Migration(1, 2, (database) async {
|
||||
await database.execute('DROP TABLE IF EXISTS LocalMessage');
|
||||
});
|
||||
|
||||
return await $FloorMessageHistoryDb
|
||||
.databaseBuilder('messaging_data.dart')
|
||||
.addMigrations([migration1to2]).build();
|
||||
}
|
||||
|
||||
Future<(List<Event>, int)?> getWhatsNewEvents(int pivot, {take = 10}) async {
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/whats-new?pivot=$pivot&take=$take',
|
||||
);
|
||||
|
||||
if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
final PaginationResult response = PaginationResult.fromJson(resp.body);
|
||||
final result =
|
||||
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
||||
|
||||
return (result, response.count);
|
||||
}
|
||||
|
||||
Future<Event?> getRemoteEvent(int id, Channel channel, String scope) async {
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/channels/$scope/${channel.alias}/events/$id',
|
||||
);
|
||||
|
||||
if (resp.statusCode == 404) {
|
||||
return null;
|
||||
} else if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
return Event.fromJson(resp.body);
|
||||
}
|
||||
|
||||
Future<(List<Event>, int)?> getRemoteEvents(
|
||||
Channel channel,
|
||||
String scope, {
|
||||
required int remainDepth,
|
||||
bool Function(List<Event> items)? onBrake,
|
||||
take = 10,
|
||||
offset = 0,
|
||||
}) async {
|
||||
if (remainDepth <= 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
final AuthProvider auth = Get.find();
|
||||
if (auth.isAuthorized.isFalse) return null;
|
||||
|
||||
final client = auth.configureClient('messaging');
|
||||
|
||||
final resp = await client.get(
|
||||
'/channels/$scope/${channel.alias}/events?take=$take&offset=$offset',
|
||||
);
|
||||
|
||||
if (resp.statusCode != 200) {
|
||||
throw RequestException(resp);
|
||||
}
|
||||
|
||||
final PaginationResult response = PaginationResult.fromJson(resp.body);
|
||||
final result =
|
||||
response.data?.map((e) => Event.fromJson(e)).toList() ?? List.empty();
|
||||
|
||||
if (onBrake != null && onBrake(result)) {
|
||||
return (result, response.count);
|
||||
}
|
||||
|
||||
final expandResult = (await getRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: remainDepth - 1,
|
||||
take: take,
|
||||
offset: offset + result.length,
|
||||
))
|
||||
?.$1 ??
|
||||
List.empty();
|
||||
|
||||
return ([...result, ...expandResult], response.count);
|
||||
}
|
||||
|
||||
extension MessageHistoryAdaptor on MessageHistoryDb {
|
||||
Future<LocalEvent> receiveEvent(Event remote) async {
|
||||
final entry = LocalEvent(
|
||||
remote.id,
|
||||
remote,
|
||||
remote.channelId,
|
||||
remote.createdAt,
|
||||
);
|
||||
await localEvents.insert(entry);
|
||||
switch (remote.type) {
|
||||
case 'messages.edit':
|
||||
final body = EventMessageBody.fromJson(remote.body);
|
||||
if (body.relatedEvent != null) {
|
||||
final target = await localEvents.findById(body.relatedEvent!);
|
||||
if (target != null) {
|
||||
target.data.body = remote.body;
|
||||
target.data.updatedAt = remote.updatedAt;
|
||||
await localEvents.update(target);
|
||||
}
|
||||
}
|
||||
case 'messages.delete':
|
||||
final body = EventMessageBody.fromJson(remote.body);
|
||||
if (body.relatedEvent != null) {
|
||||
await localEvents.delete(body.relatedEvent!);
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
Future<LocalEvent?> getEvent(int id, Channel channel,
|
||||
{String scope = 'global'}) async {
|
||||
final localRecord = await localEvents.findById(id);
|
||||
if (localRecord != null) return localRecord;
|
||||
|
||||
final remoteRecord = await getRemoteEvent(id, channel, scope);
|
||||
if (remoteRecord == null) return null;
|
||||
|
||||
return await receiveEvent(remoteRecord);
|
||||
}
|
||||
|
||||
Future<(List<Event>, int)?> syncRemoteEvents(Channel channel,
|
||||
{String scope = 'global', depth = 10, offset = 0}) async {
|
||||
final lastOne = await localEvents.findLastByChannel(channel.id);
|
||||
|
||||
final data = await getRemoteEvents(
|
||||
channel,
|
||||
scope,
|
||||
remainDepth: depth,
|
||||
offset: offset,
|
||||
onBrake: (items) {
|
||||
return items.any((x) => x.id == lastOne?.id);
|
||||
},
|
||||
);
|
||||
if (data != null) {
|
||||
await localEvents.insertBulk(
|
||||
data.$1
|
||||
.map((x) => LocalEvent(x.id, x, x.channelId, x.createdAt))
|
||||
.toList(),
|
||||
);
|
||||
}
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
Future<List<LocalEvent>> listEvents(Channel channel) async {
|
||||
return await localEvents.findAllByChannel(channel.id);
|
||||
}
|
||||
}
|
@ -1,83 +0,0 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'package:floor/floor.dart';
|
||||
import 'package:solian/models/event.dart';
|
||||
import 'package:sqflite/sqflite.dart' as sqflite;
|
||||
|
||||
part 'events.g.dart';
|
||||
|
||||
@entity
|
||||
class LocalEvent {
|
||||
@primaryKey
|
||||
final int id;
|
||||
|
||||
final Event data;
|
||||
final int channelId;
|
||||
|
||||
final DateTime createdAt;
|
||||
|
||||
LocalEvent(this.id, this.data, this.channelId, this.createdAt);
|
||||
}
|
||||
|
||||
class DateTimeConverter extends TypeConverter<DateTime, int> {
|
||||
@override
|
||||
DateTime decode(int databaseValue) {
|
||||
return DateTime.fromMillisecondsSinceEpoch(databaseValue);
|
||||
}
|
||||
|
||||
@override
|
||||
int encode(DateTime value) {
|
||||
return value.millisecondsSinceEpoch;
|
||||
}
|
||||
}
|
||||
|
||||
class RemoteEventConverter extends TypeConverter<Event, String> {
|
||||
@override
|
||||
Event decode(String databaseValue) {
|
||||
return Event.fromJson(jsonDecode(databaseValue));
|
||||
}
|
||||
|
||||
@override
|
||||
String encode(Event value) {
|
||||
return jsonEncode(value.toJson());
|
||||
}
|
||||
}
|
||||
|
||||
@dao
|
||||
abstract class LocalEventDao {
|
||||
@Query('SELECT COUNT(id) FROM LocalEvent WHERE channelId = :channelId')
|
||||
Future<int?> countByChannel(int channelId);
|
||||
|
||||
@Query('SELECT * FROM LocalEvent WHERE id = :id')
|
||||
Future<LocalEvent?> findById(int id);
|
||||
|
||||
@Query('SELECT * FROM LocalEvent WHERE channelId = :channelId ORDER BY createdAt DESC')
|
||||
Future<List<LocalEvent>> findAllByChannel(int channelId);
|
||||
|
||||
@Query('SELECT * FROM LocalEvent WHERE channelId = :channelId ORDER BY createdAt DESC LIMIT 1')
|
||||
Future<LocalEvent?> findLastByChannel(int channelId);
|
||||
|
||||
@Insert(onConflict: OnConflictStrategy.replace)
|
||||
Future<void> insert(LocalEvent m);
|
||||
|
||||
@Insert(onConflict: OnConflictStrategy.replace)
|
||||
Future<void> insertBulk(List<LocalEvent> m);
|
||||
|
||||
@Update(onConflict: OnConflictStrategy.replace)
|
||||
Future<void> update(LocalEvent m);
|
||||
|
||||
@Query('DELETE FROM LocalEvent WHERE id = :id')
|
||||
Future<void> delete(int id);
|
||||
|
||||
@Query('DELETE FROM LocalEvent WHERE channelId = :channelId')
|
||||
Future<List<LocalEvent>> deleteByChannel(int channelId);
|
||||
|
||||
@Query('DELETE FROM LocalEvent')
|
||||
Future<void> wipeLocalEvents();
|
||||
}
|
||||
|
||||
@TypeConverters([DateTimeConverter, RemoteEventConverter])
|
||||
@Database(version: 2, entities: [LocalEvent])
|
||||
abstract class MessageHistoryDb extends FloorDatabase {
|
||||
LocalEventDao get localEvents;
|
||||
}
|
@ -1,228 +0,0 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'events.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FloorGenerator
|
||||
// **************************************************************************
|
||||
|
||||
abstract class $MessageHistoryDbBuilderContract {
|
||||
/// Adds migrations to the builder.
|
||||
$MessageHistoryDbBuilderContract addMigrations(List<Migration> migrations);
|
||||
|
||||
/// Adds a database [Callback] to the builder.
|
||||
$MessageHistoryDbBuilderContract addCallback(Callback callback);
|
||||
|
||||
/// Creates the database and initializes it.
|
||||
Future<MessageHistoryDb> build();
|
||||
}
|
||||
|
||||
// ignore: avoid_classes_with_only_static_members
|
||||
class $FloorMessageHistoryDb {
|
||||
/// Creates a database builder for a persistent database.
|
||||
/// Once a database is built, you should keep a reference to it and re-use it.
|
||||
static $MessageHistoryDbBuilderContract databaseBuilder(String name) =>
|
||||
_$MessageHistoryDbBuilder(name);
|
||||
|
||||
/// Creates a database builder for an in memory database.
|
||||
/// Information stored in an in memory database disappears when the process is killed.
|
||||
/// Once a database is built, you should keep a reference to it and re-use it.
|
||||
static $MessageHistoryDbBuilderContract inMemoryDatabaseBuilder() =>
|
||||
_$MessageHistoryDbBuilder(null);
|
||||
}
|
||||
|
||||
class _$MessageHistoryDbBuilder implements $MessageHistoryDbBuilderContract {
|
||||
_$MessageHistoryDbBuilder(this.name);
|
||||
|
||||
final String? name;
|
||||
|
||||
final List<Migration> _migrations = [];
|
||||
|
||||
Callback? _callback;
|
||||
|
||||
@override
|
||||
$MessageHistoryDbBuilderContract addMigrations(List<Migration> migrations) {
|
||||
_migrations.addAll(migrations);
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
$MessageHistoryDbBuilderContract addCallback(Callback callback) {
|
||||
_callback = callback;
|
||||
return this;
|
||||
}
|
||||
|
||||
@override
|
||||
Future<MessageHistoryDb> build() async {
|
||||
final path = name != null
|
||||
? await sqfliteDatabaseFactory.getDatabasePath(name!)
|
||||
: ':memory:';
|
||||
final database = _$MessageHistoryDb();
|
||||
database.database = await database.open(
|
||||
path,
|
||||
_migrations,
|
||||
_callback,
|
||||
);
|
||||
return database;
|
||||
}
|
||||
}
|
||||
|
||||
class _$MessageHistoryDb extends MessageHistoryDb {
|
||||
_$MessageHistoryDb([StreamController<String>? listener]) {
|
||||
changeListener = listener ?? StreamController<String>.broadcast();
|
||||
}
|
||||
|
||||
LocalEventDao? _localEventsInstance;
|
||||
|
||||
Future<sqflite.Database> open(
|
||||
String path,
|
||||
List<Migration> migrations, [
|
||||
Callback? callback,
|
||||
]) async {
|
||||
final databaseOptions = sqflite.OpenDatabaseOptions(
|
||||
version: 2,
|
||||
onConfigure: (database) async {
|
||||
await database.execute('PRAGMA foreign_keys = ON');
|
||||
await callback?.onConfigure?.call(database);
|
||||
},
|
||||
onOpen: (database) async {
|
||||
await callback?.onOpen?.call(database);
|
||||
},
|
||||
onUpgrade: (database, startVersion, endVersion) async {
|
||||
await MigrationAdapter.runMigrations(
|
||||
database, startVersion, endVersion, migrations);
|
||||
|
||||
await callback?.onUpgrade?.call(database, startVersion, endVersion);
|
||||
},
|
||||
onCreate: (database, version) async {
|
||||
await database.execute(
|
||||
'CREATE TABLE IF NOT EXISTS `LocalEvent` (`id` INTEGER NOT NULL, `data` TEXT NOT NULL, `channelId` INTEGER NOT NULL, `createdAt` INTEGER NOT NULL, PRIMARY KEY (`id`))');
|
||||
|
||||
await callback?.onCreate?.call(database, version);
|
||||
},
|
||||
);
|
||||
return sqfliteDatabaseFactory.openDatabase(path, options: databaseOptions);
|
||||
}
|
||||
|
||||
@override
|
||||
LocalEventDao get localEvents {
|
||||
return _localEventsInstance ??= _$LocalEventDao(database, changeListener);
|
||||
}
|
||||
}
|
||||
|
||||
class _$LocalEventDao extends LocalEventDao {
|
||||
_$LocalEventDao(
|
||||
this.database,
|
||||
this.changeListener,
|
||||
) : _queryAdapter = QueryAdapter(database),
|
||||
_localEventInsertionAdapter = InsertionAdapter(
|
||||
database,
|
||||
'LocalEvent',
|
||||
(LocalEvent item) => <String, Object?>{
|
||||
'id': item.id,
|
||||
'data': _remoteEventConverter.encode(item.data),
|
||||
'channelId': item.channelId,
|
||||
'createdAt': _dateTimeConverter.encode(item.createdAt)
|
||||
}),
|
||||
_localEventUpdateAdapter = UpdateAdapter(
|
||||
database,
|
||||
'LocalEvent',
|
||||
['id'],
|
||||
(LocalEvent item) => <String, Object?>{
|
||||
'id': item.id,
|
||||
'data': _remoteEventConverter.encode(item.data),
|
||||
'channelId': item.channelId,
|
||||
'createdAt': _dateTimeConverter.encode(item.createdAt)
|
||||
});
|
||||
|
||||
final sqflite.DatabaseExecutor database;
|
||||
|
||||
final StreamController<String> changeListener;
|
||||
|
||||
final QueryAdapter _queryAdapter;
|
||||
|
||||
final InsertionAdapter<LocalEvent> _localEventInsertionAdapter;
|
||||
|
||||
final UpdateAdapter<LocalEvent> _localEventUpdateAdapter;
|
||||
|
||||
@override
|
||||
Future<int?> countByChannel(int channelId) async {
|
||||
return _queryAdapter.query(
|
||||
'SELECT COUNT(id) FROM LocalEvent WHERE channelId = ?1',
|
||||
mapper: (Map<String, Object?> row) => row.values.first as int,
|
||||
arguments: [channelId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LocalEvent?> findById(int id) async {
|
||||
return _queryAdapter.query('SELECT * FROM LocalEvent WHERE id = ?1',
|
||||
mapper: (Map<String, Object?> row) => LocalEvent(
|
||||
row['id'] as int,
|
||||
_remoteEventConverter.decode(row['data'] as String),
|
||||
row['channelId'] as int,
|
||||
_dateTimeConverter.decode(row['createdAt'] as int)),
|
||||
arguments: [id]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalEvent>> findAllByChannel(int channelId) async {
|
||||
return _queryAdapter.queryList(
|
||||
'SELECT * FROM LocalEvent WHERE channelId = ?1 ORDER BY createdAt DESC',
|
||||
mapper: (Map<String, Object?> row) => LocalEvent(
|
||||
row['id'] as int,
|
||||
_remoteEventConverter.decode(row['data'] as String),
|
||||
row['channelId'] as int,
|
||||
_dateTimeConverter.decode(row['createdAt'] as int)),
|
||||
arguments: [channelId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<LocalEvent?> findLastByChannel(int channelId) async {
|
||||
return _queryAdapter.query(
|
||||
'SELECT * FROM LocalEvent WHERE channelId = ?1 ORDER BY createdAt DESC LIMIT 1',
|
||||
mapper: (Map<String, Object?> row) => LocalEvent(row['id'] as int, _remoteEventConverter.decode(row['data'] as String), row['channelId'] as int, _dateTimeConverter.decode(row['createdAt'] as int)),
|
||||
arguments: [channelId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> delete(int id) async {
|
||||
await _queryAdapter
|
||||
.queryNoReturn('DELETE FROM LocalEvent WHERE id = ?1', arguments: [id]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<List<LocalEvent>> deleteByChannel(int channelId) async {
|
||||
return _queryAdapter.queryList(
|
||||
'DELETE FROM LocalEvent WHERE channelId = ?1',
|
||||
mapper: (Map<String, Object?> row) => LocalEvent(
|
||||
row['id'] as int,
|
||||
_remoteEventConverter.decode(row['data'] as String),
|
||||
row['channelId'] as int,
|
||||
_dateTimeConverter.decode(row['createdAt'] as int)),
|
||||
arguments: [channelId]);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> wipeLocalEvents() async {
|
||||
await _queryAdapter.queryNoReturn('DELETE FROM LocalEvent');
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> insert(LocalEvent m) async {
|
||||
await _localEventInsertionAdapter.insert(m, OnConflictStrategy.replace);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> insertBulk(List<LocalEvent> m) async {
|
||||
await _localEventInsertionAdapter.insertList(m, OnConflictStrategy.replace);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> update(LocalEvent m) async {
|
||||
await _localEventUpdateAdapter.update(m, OnConflictStrategy.replace);
|
||||
}
|
||||
}
|
||||
|
||||
// ignore_for_file: unused_element
|
||||
final _dateTimeConverter = DateTimeConverter();
|
||||
final _remoteEventConverter = RemoteEventConverter();
|
Reference in New Issue
Block a user