♻️ Use drift instead for floor
This commit is contained in:
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());
|
||||
}
|
Reference in New Issue
Block a user