diff --git a/ios/Podfile.lock b/ios/Podfile.lock index 60dafd4..580a00d 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -47,6 +47,8 @@ PODS: - Flutter - image_picker_ios (0.0.1): - Flutter + - isar_flutter_libs (1.0.0): + - Flutter - path_provider_foundation (0.0.1): - Flutter - FlutterMacOS @@ -72,6 +74,7 @@ DEPENDENCIES: - flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`) - flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`) - image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`) + - isar_flutter_libs (from `.symlinks/plugins/isar_flutter_libs/ios`) - path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`) - shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`) - sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`) @@ -101,6 +104,8 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/flutter_secure_storage/ios" image_picker_ios: :path: ".symlinks/plugins/image_picker_ios/ios" + isar_flutter_libs: + :path: ".symlinks/plugins/isar_flutter_libs/ios" path_provider_foundation: :path: ".symlinks/plugins/path_provider_foundation/darwin" shared_preferences_foundation: @@ -121,6 +126,7 @@ SPEC CHECKSUMS: flutter_native_splash: edf599c81f74d093a4daf8e17bd7a018854bc778 flutter_secure_storage: d33dac7ae2ea08509be337e775f6b59f1ff45f12 image_picker_ios: c560581cceedb403a6ff17f2f816d7fea1421fc1 + isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 SDWebImage: 8a6b7b160b4d710e2a22b6900e25301075c34cb3 shared_preferences_foundation: fcdcbc04712aee1108ac7fda236f363274528f78 diff --git a/lib/main.dart b/lib/main.dart index 685668f..eafae08 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -7,6 +7,7 @@ import 'package:hive_flutter/hive_flutter.dart'; import 'package:provider/provider.dart'; import 'package:relative_time/relative_time.dart'; import 'package:responsive_framework/responsive_framework.dart'; +import 'package:surface/providers/channel.dart'; import 'package:surface/providers/navigation.dart'; import 'package:surface/providers/sn_attachment.dart'; import 'package:surface/providers/sn_network.dart'; @@ -14,12 +15,14 @@ import 'package:surface/providers/theme.dart'; import 'package:surface/providers/userinfo.dart'; import 'package:surface/providers/websocket.dart'; import 'package:surface/router.dart'; +import 'package:surface/types/chat.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); await EasyLocalization.ensureInitialized(); await Hive.initFlutter(); + Hive.registerAdapter(SnChannelImplAdapter()); if (!kReleaseMode) { debugInvertOversizedImages = true; @@ -52,6 +55,7 @@ class SolianApp extends StatelessWidget { Provider(create: (ctx) => SnAttachmentProvider(ctx)), ChangeNotifierProvider(create: (ctx) => UserProvider(ctx)), ChangeNotifierProvider(create: (ctx) => WebSocketProvider(ctx)), + ChangeNotifierProvider(create: (ctx) => ChatChannelProvider(ctx)), ], child: AppMainContent(), ), @@ -72,6 +76,7 @@ class AppMainContent extends StatelessWidget { Widget build(BuildContext context) { context.read(); context.read(); + context.read(); final th = context.watch(); diff --git a/lib/providers/channel.dart b/lib/providers/channel.dart new file mode 100644 index 0000000..9403b2a --- /dev/null +++ b/lib/providers/channel.dart @@ -0,0 +1,80 @@ +import 'package:flutter/material.dart'; +import 'package:hive_flutter/hive_flutter.dart'; +import 'package:provider/provider.dart'; +import 'package:surface/providers/sn_network.dart'; +import 'package:surface/types/chat.dart'; +import 'package:surface/types/realm.dart'; + +class ChatChannelProvider extends ChangeNotifier { + static const kChatChannelBoxName = 'nex_chat_channels'; + + late final SnNetworkProvider _sn; + + Box? get _channelBox => Hive.box(kChatChannelBoxName); + + ChatChannelProvider(BuildContext context) { + _sn = context.read(); + _initializeLocalData(); + } + + Future _initializeLocalData() async { + await Hive.openBox(kChatChannelBoxName); + } + + Future _saveChannelToLocal(Iterable channels) async { + if (_channelBox == null) return; + await _channelBox!.putAll({ + for (final channel in channels) channel.key: channel, + }); + } + + Future> _fetchChannelsFromServer( + {scope = 'global', direct = false}) async { + final resp = await _sn.client.get( + '/cgi/im/channels/$scope/me/available', + queryParameters: { + 'direct': direct, + }, + ); + final out = List.from( + resp.data?.map((e) => SnChannel.fromJson(e)) ?? [], + ); + _saveChannelToLocal(out); + return out; + } + + // The fetch channel method return a stream, which will emit twice. + // The first time is when the data was fetched from the local storage. + // And the second time is when the data was fetched from the server. + // But there is some exception that will only cause one of them to be emitted. + // Like the local storage is broken or the server is down. + Stream> fetchChannels() async* { + if (_channelBox != null) yield _channelBox!.values.toList(); + + var resp = await _sn.client.get('/cgi/id/realms/me/available'); + final realms = List.from( + resp.data?.map((e) => SnRealm.fromJson(e)) ?? [], + ); + + final scopeToFetch = {'global', ...realms.map((e) => e.alias)}; + + final List result = List.empty(growable: true); + final dm = + await _fetchChannelsFromServer(scope: scopeToFetch.first, direct: true); + result.addAll(dm); + + for (final scope in scopeToFetch) { + final channel = + await _fetchChannelsFromServer(scope: scope, direct: false); + result.addAll(channel); + } + + yield result; + } + + @override + void dispose() { + _channelBox?.close(); + super.dispose(); + } +} diff --git a/lib/screens/chat.dart b/lib/screens/chat.dart index 5c176fe..a676a79 100644 --- a/lib/screens/chat.dart +++ b/lib/screens/chat.dart @@ -3,10 +3,9 @@ import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:material_symbols_icons/symbols.dart'; import 'package:provider/provider.dart'; -import 'package:surface/providers/sn_network.dart'; +import 'package:surface/providers/channel.dart'; import 'package:surface/types/chat.dart'; import 'package:surface/widgets/account/account_image.dart'; -import 'package:surface/widgets/dialog.dart'; import 'package:surface/widgets/loading_indicator.dart'; class ChatScreen extends StatefulWidget { @@ -17,36 +16,23 @@ class ChatScreen extends StatefulWidget { } class _ChatScreenState extends State { - bool _isBusy = false; + bool _isBusy = true; List? _channels; - Future _fetchChannels({scope = 'global', direct = false}) async { - setState(() => _isBusy = true); - - try { - final sn = context.read(); - final resp = await sn.client.get( - '/cgi/im/channels/$scope/me/available', - queryParameters: { - 'direct': direct, - }, - ); - _channels = List.from( - resp.data?.map((e) => SnChannel.fromJson(e)) ?? [], - ); - } catch (err) { - if (!mounted) return; - context.showErrorDialog(err); - } finally { - setState(() => _isBusy = false); - } - } - @override void initState() { super.initState(); - _fetchChannels(); + final chan = context.read(); + chan.fetchChannels().listen((channels) { + if (mounted) setState(() => _channels = channels); + }) + ..onError((_) { + setState(() => _isBusy = false); + }) + ..onDone(() { + setState(() => _isBusy = false); + }); } @override @@ -71,7 +57,11 @@ class _ChatScreenState extends State { final channel = _channels![idx]; return ListTile( title: Text(channel.name), - subtitle: Text(channel.description), + subtitle: Text( + channel.description, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), contentPadding: const EdgeInsets.symmetric(horizontal: 16), leading: AccountImage( content: null, diff --git a/lib/types/chat.dart b/lib/types/chat.dart index 8df3e67..0a6cf49 100644 --- a/lib/types/chat.dart +++ b/lib/types/chat.dart @@ -1,4 +1,5 @@ import 'package:freezed_annotation/freezed_annotation.dart'; +import 'package:hive_flutter/hive_flutter.dart'; import 'package:surface/types/realm.dart'; part 'chat.freezed.dart'; @@ -6,25 +7,30 @@ part 'chat.g.dart'; @freezed class SnChannel with _$SnChannel { + const SnChannel._(); + + @HiveType(typeId: 2) const factory SnChannel({ - required int id, - required DateTime createdAt, - required DateTime updatedAt, - required dynamic deletedAt, - required String alias, - required String name, - required String description, - required List members, - required dynamic messages, - required dynamic calls, - required int type, - required int accountId, - required bool isPublic, - required bool isCommunity, - required SnRealm? realm, - required int? realmId, + @HiveField(0) required int id, + @HiveField(1) required DateTime createdAt, + @HiveField(2) required DateTime updatedAt, + @HiveField(3) required dynamic deletedAt, + @HiveField(4) required String alias, + @HiveField(5) required String name, + @HiveField(6) required String description, + @HiveField(7) required List members, + dynamic messages, + dynamic calls, + @HiveField(8) required int type, + @HiveField(9) required int accountId, + @HiveField(10) required SnRealm? realm, + @HiveField(11) required int? realmId, + @HiveField(12) required bool isPublic, + @HiveField(13) required bool isCommunity, }) = _SnChannel; factory SnChannel.fromJson(Map json) => _$SnChannelFromJson(json); + + String get key => '${realm?.alias ?? 'global'}:$alias'; } diff --git a/lib/types/chat.freezed.dart b/lib/types/chat.freezed.dart index 0930558..431518c 100644 --- a/lib/types/chat.freezed.dart +++ b/lib/types/chat.freezed.dart @@ -20,22 +20,36 @@ SnChannel _$SnChannelFromJson(Map json) { /// @nodoc mixin _$SnChannel { + @HiveField(0) int get id => throw _privateConstructorUsedError; + @HiveField(1) DateTime get createdAt => throw _privateConstructorUsedError; + @HiveField(2) DateTime get updatedAt => throw _privateConstructorUsedError; + @HiveField(3) dynamic get deletedAt => throw _privateConstructorUsedError; + @HiveField(4) String get alias => throw _privateConstructorUsedError; + @HiveField(5) String get name => throw _privateConstructorUsedError; + @HiveField(6) String get description => throw _privateConstructorUsedError; + @HiveField(7) List get members => throw _privateConstructorUsedError; dynamic get messages => throw _privateConstructorUsedError; dynamic get calls => throw _privateConstructorUsedError; + @HiveField(8) int get type => throw _privateConstructorUsedError; + @HiveField(9) int get accountId => throw _privateConstructorUsedError; - bool get isPublic => throw _privateConstructorUsedError; - bool get isCommunity => throw _privateConstructorUsedError; + @HiveField(10) SnRealm? get realm => throw _privateConstructorUsedError; + @HiveField(11) int? get realmId => throw _privateConstructorUsedError; + @HiveField(12) + bool get isPublic => throw _privateConstructorUsedError; + @HiveField(13) + bool get isCommunity => throw _privateConstructorUsedError; /// Serializes this SnChannel to a JSON map. Map toJson() => throw _privateConstructorUsedError; @@ -53,22 +67,22 @@ abstract class $SnChannelCopyWith<$Res> { _$SnChannelCopyWithImpl<$Res, SnChannel>; @useResult $Res call( - {int id, - DateTime createdAt, - DateTime updatedAt, - dynamic deletedAt, - String alias, - String name, - String description, - List members, + {@HiveField(0) int id, + @HiveField(1) DateTime createdAt, + @HiveField(2) DateTime updatedAt, + @HiveField(3) dynamic deletedAt, + @HiveField(4) String alias, + @HiveField(5) String name, + @HiveField(6) String description, + @HiveField(7) List members, dynamic messages, dynamic calls, - int type, - int accountId, - bool isPublic, - bool isCommunity, - SnRealm? realm, - int? realmId}); + @HiveField(8) int type, + @HiveField(9) int accountId, + @HiveField(10) SnRealm? realm, + @HiveField(11) int? realmId, + @HiveField(12) bool isPublic, + @HiveField(13) bool isCommunity}); $SnRealmCopyWith<$Res>? get realm; } @@ -100,10 +114,10 @@ class _$SnChannelCopyWithImpl<$Res, $Val extends SnChannel> Object? calls = freezed, Object? type = null, Object? accountId = null, - Object? isPublic = null, - Object? isCommunity = null, Object? realm = freezed, Object? realmId = freezed, + Object? isPublic = null, + Object? isCommunity = null, }) { return _then(_value.copyWith( id: null == id @@ -154,14 +168,6 @@ class _$SnChannelCopyWithImpl<$Res, $Val extends SnChannel> ? _value.accountId : accountId // ignore: cast_nullable_to_non_nullable as int, - isPublic: null == isPublic - ? _value.isPublic - : isPublic // ignore: cast_nullable_to_non_nullable - as bool, - isCommunity: null == isCommunity - ? _value.isCommunity - : isCommunity // ignore: cast_nullable_to_non_nullable - as bool, realm: freezed == realm ? _value.realm : realm // ignore: cast_nullable_to_non_nullable @@ -170,6 +176,14 @@ class _$SnChannelCopyWithImpl<$Res, $Val extends SnChannel> ? _value.realmId : realmId // ignore: cast_nullable_to_non_nullable as int?, + isPublic: null == isPublic + ? _value.isPublic + : isPublic // ignore: cast_nullable_to_non_nullable + as bool, + isCommunity: null == isCommunity + ? _value.isCommunity + : isCommunity // ignore: cast_nullable_to_non_nullable + as bool, ) as $Val); } @@ -197,22 +211,22 @@ abstract class _$$SnChannelImplCopyWith<$Res> @override @useResult $Res call( - {int id, - DateTime createdAt, - DateTime updatedAt, - dynamic deletedAt, - String alias, - String name, - String description, - List members, + {@HiveField(0) int id, + @HiveField(1) DateTime createdAt, + @HiveField(2) DateTime updatedAt, + @HiveField(3) dynamic deletedAt, + @HiveField(4) String alias, + @HiveField(5) String name, + @HiveField(6) String description, + @HiveField(7) List members, dynamic messages, dynamic calls, - int type, - int accountId, - bool isPublic, - bool isCommunity, - SnRealm? realm, - int? realmId}); + @HiveField(8) int type, + @HiveField(9) int accountId, + @HiveField(10) SnRealm? realm, + @HiveField(11) int? realmId, + @HiveField(12) bool isPublic, + @HiveField(13) bool isCommunity}); @override $SnRealmCopyWith<$Res>? get realm; @@ -243,10 +257,10 @@ class __$$SnChannelImplCopyWithImpl<$Res> Object? calls = freezed, Object? type = null, Object? accountId = null, - Object? isPublic = null, - Object? isCommunity = null, Object? realm = freezed, Object? realmId = freezed, + Object? isPublic = null, + Object? isCommunity = null, }) { return _then(_$SnChannelImpl( id: null == id @@ -297,14 +311,6 @@ class __$$SnChannelImplCopyWithImpl<$Res> ? _value.accountId : accountId // ignore: cast_nullable_to_non_nullable as int, - isPublic: null == isPublic - ? _value.isPublic - : isPublic // ignore: cast_nullable_to_non_nullable - as bool, - isCommunity: null == isCommunity - ? _value.isCommunity - : isCommunity // ignore: cast_nullable_to_non_nullable - as bool, realm: freezed == realm ? _value.realm : realm // ignore: cast_nullable_to_non_nullable @@ -313,51 +319,69 @@ class __$$SnChannelImplCopyWithImpl<$Res> ? _value.realmId : realmId // ignore: cast_nullable_to_non_nullable as int?, + isPublic: null == isPublic + ? _value.isPublic + : isPublic // ignore: cast_nullable_to_non_nullable + as bool, + isCommunity: null == isCommunity + ? _value.isCommunity + : isCommunity // ignore: cast_nullable_to_non_nullable + as bool, )); } } /// @nodoc @JsonSerializable() -class _$SnChannelImpl implements _SnChannel { +@HiveType(typeId: 2) +class _$SnChannelImpl extends _SnChannel { const _$SnChannelImpl( - {required this.id, - required this.createdAt, - required this.updatedAt, - required this.deletedAt, - required this.alias, - required this.name, - required this.description, - required final List members, - required this.messages, - required this.calls, - required this.type, - required this.accountId, - required this.isPublic, - required this.isCommunity, - required this.realm, - required this.realmId}) - : _members = members; + {@HiveField(0) required this.id, + @HiveField(1) required this.createdAt, + @HiveField(2) required this.updatedAt, + @HiveField(3) required this.deletedAt, + @HiveField(4) required this.alias, + @HiveField(5) required this.name, + @HiveField(6) required this.description, + @HiveField(7) required final List members, + this.messages, + this.calls, + @HiveField(8) required this.type, + @HiveField(9) required this.accountId, + @HiveField(10) required this.realm, + @HiveField(11) required this.realmId, + @HiveField(12) required this.isPublic, + @HiveField(13) required this.isCommunity}) + : _members = members, + super._(); factory _$SnChannelImpl.fromJson(Map json) => _$$SnChannelImplFromJson(json); @override + @HiveField(0) final int id; @override + @HiveField(1) final DateTime createdAt; @override + @HiveField(2) final DateTime updatedAt; @override + @HiveField(3) final dynamic deletedAt; @override + @HiveField(4) final String alias; @override + @HiveField(5) final String name; @override + @HiveField(6) final String description; final List _members; @override + @HiveField(7) List get members { if (_members is EqualUnmodifiableListView) return _members; // ignore: implicit_dynamic_type @@ -369,21 +393,27 @@ class _$SnChannelImpl implements _SnChannel { @override final dynamic calls; @override + @HiveField(8) final int type; @override + @HiveField(9) final int accountId; @override - final bool isPublic; - @override - final bool isCommunity; - @override + @HiveField(10) final SnRealm? realm; @override + @HiveField(11) final int? realmId; + @override + @HiveField(12) + final bool isPublic; + @override + @HiveField(13) + final bool isCommunity; @override String toString() { - return 'SnChannel(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, members: $members, messages: $messages, calls: $calls, type: $type, accountId: $accountId, isPublic: $isPublic, isCommunity: $isCommunity, realm: $realm, realmId: $realmId)'; + return 'SnChannel(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, alias: $alias, name: $name, description: $description, members: $members, messages: $messages, calls: $calls, type: $type, accountId: $accountId, realm: $realm, realmId: $realmId, isPublic: $isPublic, isCommunity: $isCommunity)'; } @override @@ -407,12 +437,12 @@ class _$SnChannelImpl implements _SnChannel { (identical(other.type, type) || other.type == type) && (identical(other.accountId, accountId) || other.accountId == accountId) && + (identical(other.realm, realm) || other.realm == realm) && + (identical(other.realmId, realmId) || other.realmId == realmId) && (identical(other.isPublic, isPublic) || other.isPublic == isPublic) && (identical(other.isCommunity, isCommunity) || - other.isCommunity == isCommunity) && - (identical(other.realm, realm) || other.realm == realm) && - (identical(other.realmId, realmId) || other.realmId == realmId)); + other.isCommunity == isCommunity)); } @JsonKey(includeFromJson: false, includeToJson: false) @@ -431,10 +461,10 @@ class _$SnChannelImpl implements _SnChannel { const DeepCollectionEquality().hash(calls), type, accountId, - isPublic, - isCommunity, realm, - realmId); + realmId, + isPublic, + isCommunity); /// Create a copy of SnChannel /// with the given fields replaced by the non-null parameter values. @@ -452,60 +482,75 @@ class _$SnChannelImpl implements _SnChannel { } } -abstract class _SnChannel implements SnChannel { +abstract class _SnChannel extends SnChannel { const factory _SnChannel( - {required final int id, - required final DateTime createdAt, - required final DateTime updatedAt, - required final dynamic deletedAt, - required final String alias, - required final String name, - required final String description, - required final List members, - required final dynamic messages, - required final dynamic calls, - required final int type, - required final int accountId, - required final bool isPublic, - required final bool isCommunity, - required final SnRealm? realm, - required final int? realmId}) = _$SnChannelImpl; + {@HiveField(0) required final int id, + @HiveField(1) required final DateTime createdAt, + @HiveField(2) required final DateTime updatedAt, + @HiveField(3) required final dynamic deletedAt, + @HiveField(4) required final String alias, + @HiveField(5) required final String name, + @HiveField(6) required final String description, + @HiveField(7) required final List members, + final dynamic messages, + final dynamic calls, + @HiveField(8) required final int type, + @HiveField(9) required final int accountId, + @HiveField(10) required final SnRealm? realm, + @HiveField(11) required final int? realmId, + @HiveField(12) required final bool isPublic, + @HiveField(13) required final bool isCommunity}) = _$SnChannelImpl; + const _SnChannel._() : super._(); factory _SnChannel.fromJson(Map json) = _$SnChannelImpl.fromJson; @override + @HiveField(0) int get id; @override + @HiveField(1) DateTime get createdAt; @override + @HiveField(2) DateTime get updatedAt; @override + @HiveField(3) dynamic get deletedAt; @override + @HiveField(4) String get alias; @override + @HiveField(5) String get name; @override + @HiveField(6) String get description; @override + @HiveField(7) List get members; @override dynamic get messages; @override dynamic get calls; @override + @HiveField(8) int get type; @override + @HiveField(9) int get accountId; @override - bool get isPublic; - @override - bool get isCommunity; - @override + @HiveField(10) SnRealm? get realm; @override + @HiveField(11) int? get realmId; + @override + @HiveField(12) + bool get isPublic; + @override + @HiveField(13) + bool get isCommunity; /// Create a copy of SnChannel /// with the given fields replaced by the non-null parameter values. diff --git a/lib/types/chat.g.dart b/lib/types/chat.g.dart index 1148898..289a817 100644 --- a/lib/types/chat.g.dart +++ b/lib/types/chat.g.dart @@ -2,6 +2,83 @@ part of 'chat.dart'; +// ************************************************************************** +// TypeAdapterGenerator +// ************************************************************************** + +class SnChannelImplAdapter extends TypeAdapter<_$SnChannelImpl> { + @override + final int typeId = 2; + + @override + _$SnChannelImpl read(BinaryReader reader) { + final numOfFields = reader.readByte(); + final fields = { + for (int i = 0; i < numOfFields; i++) reader.readByte(): reader.read(), + }; + return _$SnChannelImpl( + id: fields[0] as int, + createdAt: fields[1] as DateTime, + updatedAt: fields[2] as DateTime, + deletedAt: fields[3] as dynamic, + alias: fields[4] as String, + name: fields[5] as String, + description: fields[6] as String, + members: (fields[7] as List).cast(), + type: fields[8] as int, + accountId: fields[9] as int, + realm: fields[10] as SnRealm?, + realmId: fields[11] as int?, + isPublic: fields[12] as bool, + isCommunity: fields[13] as bool, + ); + } + + @override + void write(BinaryWriter writer, _$SnChannelImpl obj) { + writer + ..writeByte(14) + ..writeByte(0) + ..write(obj.id) + ..writeByte(1) + ..write(obj.createdAt) + ..writeByte(2) + ..write(obj.updatedAt) + ..writeByte(3) + ..write(obj.deletedAt) + ..writeByte(4) + ..write(obj.alias) + ..writeByte(5) + ..write(obj.name) + ..writeByte(6) + ..write(obj.description) + ..writeByte(8) + ..write(obj.type) + ..writeByte(9) + ..write(obj.accountId) + ..writeByte(10) + ..write(obj.realm) + ..writeByte(11) + ..write(obj.realmId) + ..writeByte(12) + ..write(obj.isPublic) + ..writeByte(13) + ..write(obj.isCommunity) + ..writeByte(7) + ..write(obj.members); + } + + @override + int get hashCode => typeId.hashCode; + + @override + bool operator ==(Object other) => + identical(this, other) || + other is SnChannelImplAdapter && + runtimeType == other.runtimeType && + typeId == other.typeId; +} + // ************************************************************************** // JsonSerializableGenerator // ************************************************************************** @@ -20,12 +97,12 @@ _$SnChannelImpl _$$SnChannelImplFromJson(Map json) => calls: json['calls'], type: (json['type'] as num).toInt(), accountId: (json['account_id'] as num).toInt(), - isPublic: json['is_public'] as bool, - isCommunity: json['is_community'] as bool, realm: json['realm'] == null ? null : SnRealm.fromJson(json['realm'] as Map), realmId: (json['realm_id'] as num?)?.toInt(), + isPublic: json['is_public'] as bool, + isCommunity: json['is_community'] as bool, ); Map _$$SnChannelImplToJson(_$SnChannelImpl instance) => @@ -42,8 +119,8 @@ Map _$$SnChannelImplToJson(_$SnChannelImpl instance) => 'calls': instance.calls, 'type': instance.type, 'account_id': instance.accountId, - 'is_public': instance.isPublic, - 'is_community': instance.isCommunity, 'realm': instance.realm?.toJson(), 'realm_id': instance.realmId, + 'is_public': instance.isPublic, + 'is_community': instance.isCommunity, }; diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index 3ccd551..7be807c 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -8,6 +8,7 @@ #include #include +#include #include void fl_register_plugins(FlPluginRegistry* registry) { @@ -17,6 +18,9 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); + g_autoptr(FlPluginRegistrar) isar_flutter_libs_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "IsarFlutterLibsPlugin"); + isar_flutter_libs_plugin_register_with_registrar(isar_flutter_libs_registrar); g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index ea62ffa..88fe520 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -5,6 +5,7 @@ list(APPEND FLUTTER_PLUGIN_LIST file_selector_linux flutter_secure_storage_linux + isar_flutter_libs url_launcher_linux ) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index b4836c9..dc0abdb 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -8,6 +8,7 @@ import Foundation import connectivity_plus import file_selector_macos import flutter_secure_storage_macos +import isar_flutter_libs import path_provider_foundation import shared_preferences_foundation import sqflite_darwin @@ -17,6 +18,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin")) FlutterSecureStoragePlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStoragePlugin")) + IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) diff --git a/pubspec.lock b/pubspec.lock index a1d691a..a70fb34 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -818,6 +818,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.4" + isar: + dependency: "direct main" + description: + name: isar + sha256: "99165dadb2cf2329d3140198363a7e7bff9bbd441871898a87e26914d25cf1ea" + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" + isar_flutter_libs: + dependency: "direct main" + description: + name: isar_flutter_libs + sha256: bc6768cc4b9c61aabff77152e7f33b4b17d2fc93134f7af1c3dd51500fe8d5e8 + url: "https://pub.dev" + source: hosted + version: "3.1.0+1" jni: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index af5c5ba..aac493a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -74,6 +74,8 @@ dependencies: collection: ^1.18.0 mime: ^2.0.0 web_socket_channel: ^3.0.1 + isar: ^3.1.0+1 + isar_flutter_libs: ^3.1.0+1 hive: ^2.2.3 hive_flutter: ^1.1.0 diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 624e8d4..d8c0018 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -9,6 +9,7 @@ #include #include #include +#include #include void RegisterPlugins(flutter::PluginRegistry* registry) { @@ -18,6 +19,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FileSelectorWindows")); FlutterSecureStorageWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); + IsarFlutterLibsPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("IsarFlutterLibsPlugin")); UrlLauncherWindowsRegisterWithRegistrar( registry->GetRegistrarForPlugin("UrlLauncherWindows")); } diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 82c0426..f9878b0 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -6,6 +6,7 @@ list(APPEND FLUTTER_PLUGIN_LIST connectivity_plus file_selector_windows flutter_secure_storage_windows + isar_flutter_libs url_launcher_windows )