From 65028a1231c4073c4ad1f90d3207a43e4ebe5e2e Mon Sep 17 00:00:00 2001 From: Henry-Hiles Date: Mon, 10 Nov 2025 21:50:21 -0500 Subject: [PATCH] loading spaces --- .gitignore | 5 +- devtools_options.yaml | 3 + flake.nix | 3 + lib/controllers/client_controller.dart | 56 +++-- lib/controllers/spaces_controller.dart | 36 ++++ lib/helpers/extension_helper.dart | 17 ++ lib/models/space.dart | 10 + lib/models/space.freezed.dart | 274 +++++++++++++++++++++++++ lib/widgets/error_dialog.dart | 32 +++ lib/widgets/loading.dart | 13 ++ lib/widgets/room_chat.dart | 46 ++--- lib/widgets/sidebar.dart | 50 ++++- pubspec.lock | 161 +++++++++++++-- pubspec.yaml | 9 +- 14 files changed, 629 insertions(+), 86 deletions(-) create mode 100644 devtools_options.yaml create mode 100644 lib/controllers/spaces_controller.dart create mode 100644 lib/helpers/extension_helper.dart create mode 100644 lib/models/space.dart create mode 100644 lib/models/space.freezed.dart create mode 100644 lib/widgets/error_dialog.dart create mode 100644 lib/widgets/loading.dart diff --git a/.gitignore b/.gitignore index d90c7aa..e7049de 100644 --- a/.gitignore +++ b/.gitignore @@ -34,4 +34,7 @@ keystore.jks key.properties # Generated Files -*.g.dart \ No newline at end of file +*.g.dart + +# Devel Password +password.txt \ No newline at end of file diff --git a/devtools_options.yaml b/devtools_options.yaml new file mode 100644 index 0000000..fa0b357 --- /dev/null +++ b/devtools_options.yaml @@ -0,0 +1,3 @@ +description: This file stores settings for Dart & Flutter DevTools. +documentation: https://docs.flutter.dev/tools/devtools/extensions#configure-extension-enablement-states +extensions: diff --git a/flake.nix b/flake.nix index c9d9f09..9fe833a 100644 --- a/flake.nix +++ b/flake.nix @@ -44,10 +44,13 @@ pkgs.mkShell { packages = with pkgs; [ jdk17 + rustc flutter android.platform-tools ]; env = rec { + LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath (with pkgs; [ sqlite ])}:$LD_LIBRARY_PATH"; + ANDROID_HOME = "${android.androidsdk}/libexec/android-sdk"; ANDROID_SDK_ROOT = ANDROID_HOME; JAVA_HOME = pkgs.jdk17; diff --git a/lib/controllers/client_controller.dart b/lib/controllers/client_controller.dart index 71fc0ee..7691a1e 100644 --- a/lib/controllers/client_controller.dart +++ b/lib/controllers/client_controller.dart @@ -1,33 +1,31 @@ -// import "dart:io"; +import "dart:io"; -// import "package:matrix/matrix.dart"; -// import "package:nexusbot/controllers/settings_controller.dart"; -// import "package:riverpod/riverpod.dart"; -// import "package:sqflite_common_ffi/sqflite_ffi.dart"; +import "package:matrix/matrix.dart"; +import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:sqflite_common_ffi/sqflite_ffi.dart"; -// class ClientController extends AsyncNotifier { -// @override -// Future build() async { -// final settings = ref.watch(SettingsController.provider)!; -// final client = Client( -// "nexusbot", -// database: await MatrixSdkDatabase.init( -// "NexusBot", -// database: await databaseFactoryFfi.openDatabase(inMemoryDatabasePath), -// ), -// ); +class ClientController extends AsyncNotifier { + @override + Future build() async { + final client = Client( + "nexus", + database: await MatrixSdkDatabase.init( + "nexus", + database: await databaseFactoryFfi.openDatabase("./test.db"), + ), + ); + //mxc + await client.checkHomeserver(Uri.https("federated.nexus")); + await client.login( + LoginType.mLoginPassword, + identifier: AuthenticationUserIdentifier(user: "quadradical"), + password: File("./password.txt").readAsStringSync(), + ); -// await client.checkHomeserver(settings.homeserver); -// await client.login( -// LoginType.mLoginPassword, -// identifier: AuthenticationUserIdentifier(user: settings.name), -// password: (await File(settings.botPasswordFile).readAsString()).trim(), -// ); + return client; + } -// return client; -// } - -// static final provider = AsyncNotifierProvider( -// ClientController.new, -// ); -// } + static final provider = AsyncNotifierProvider( + ClientController.new, + ); +} diff --git a/lib/controllers/spaces_controller.dart b/lib/controllers/spaces_controller.dart new file mode 100644 index 0000000..e87368e --- /dev/null +++ b/lib/controllers/spaces_controller.dart @@ -0,0 +1,36 @@ +import "package:flutter/widgets.dart"; +import "package:matrix/matrix.dart"; +import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:nexus/controllers/client_controller.dart"; +import "package:nexus/models/space.dart"; + +class SpacesController extends AsyncNotifier> { + @override + Future> build() async { + final client = await ref.watch(ClientController.provider.future); + + return Future.wait( + client.rooms.where((room) => room.isSpace).map((data) async { + final thumb = await data.avatar?.getThumbnailUri( + client, + width: 40, + height: 40, + ); + return Space( + roomData: data, + avatar: thumb == null + ? null + : Image.network( + thumb.toString(), + width: 40, + headers: {"authorization": "Bearer ${client.accessToken}"}, + ), + ); + }), + ); + } + + static final provider = AsyncNotifierProvider>( + SpacesController.new, + ); +} diff --git a/lib/helpers/extension_helper.dart b/lib/helpers/extension_helper.dart new file mode 100644 index 0000000..beaae85 --- /dev/null +++ b/lib/helpers/extension_helper.dart @@ -0,0 +1,17 @@ +import "package:flutter/widgets.dart"; +import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:nexus/widgets/error_dialog.dart"; +import "package:nexus/widgets/loading.dart"; + +extension BetterWhen on AsyncValue { + Widget betterWhen({ + required Widget Function(T value) data, + Widget Function() loading = Loading.new, + bool skipLoadingOnRefresh = false, + }) => when( + data: data, + error: (error, stackTrace) => ErrorDialog(error, stackTrace), + loading: loading, + skipLoadingOnRefresh: skipLoadingOnRefresh, + ); +} diff --git a/lib/models/space.dart b/lib/models/space.dart new file mode 100644 index 0000000..f0220c1 --- /dev/null +++ b/lib/models/space.dart @@ -0,0 +1,10 @@ +import "package:flutter/widgets.dart"; +import "package:freezed_annotation/freezed_annotation.dart"; +import "package:matrix/matrix.dart"; +part "space.freezed.dart"; + +@freezed +abstract class Space with _$Space { + const factory Space({required Room roomData, required Image? avatar}) = + _Space; +} diff --git a/lib/models/space.freezed.dart b/lib/models/space.freezed.dart new file mode 100644 index 0000000..b2a36e9 --- /dev/null +++ b/lib/models/space.freezed.dart @@ -0,0 +1,274 @@ +// GENERATED CODE - DO NOT MODIFY BY HAND +// coverage:ignore-file +// ignore_for_file: type=lint +// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark + +part of 'space.dart'; + +// ************************************************************************** +// FreezedGenerator +// ************************************************************************** + +// dart format off +T _$identity(T value) => value; +/// @nodoc +mixin _$Space { + + Room get roomData; Image? get avatar; +/// Create a copy of Space +/// with the given fields replaced by the non-null parameter values. +@JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +$SpaceCopyWith get copyWith => _$SpaceCopyWithImpl(this as Space, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is Space&&(identical(other.roomData, roomData) || other.roomData == roomData)&&(identical(other.avatar, avatar) || other.avatar == avatar)); +} + + +@override +int get hashCode => Object.hash(runtimeType,roomData,avatar); + +@override +String toString() { + return 'Space(roomData: $roomData, avatar: $avatar)'; +} + + +} + +/// @nodoc +abstract mixin class $SpaceCopyWith<$Res> { + factory $SpaceCopyWith(Space value, $Res Function(Space) _then) = _$SpaceCopyWithImpl; +@useResult +$Res call({ + Room roomData, Image? avatar +}); + + + + +} +/// @nodoc +class _$SpaceCopyWithImpl<$Res> + implements $SpaceCopyWith<$Res> { + _$SpaceCopyWithImpl(this._self, this._then); + + final Space _self; + final $Res Function(Space) _then; + +/// Create a copy of Space +/// with the given fields replaced by the non-null parameter values. +@pragma('vm:prefer-inline') @override $Res call({Object? roomData = null,Object? avatar = freezed,}) { + return _then(_self.copyWith( +roomData: null == roomData ? _self.roomData : roomData // ignore: cast_nullable_to_non_nullable +as Room,avatar: freezed == avatar ? _self.avatar : avatar // ignore: cast_nullable_to_non_nullable +as Image?, + )); +} + +} + + +/// Adds pattern-matching-related methods to [Space]. +extension SpacePatterns on Space { +/// A variant of `map` that fallback to returning `orElse`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeMap(TResult Function( _Space value)? $default,{required TResult orElse(),}){ +final _that = this; +switch (_that) { +case _Space() when $default != null: +return $default(_that);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// Callbacks receives the raw object, upcasted. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case final Subclass2 value: +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult map(TResult Function( _Space value) $default,){ +final _that = this; +switch (_that) { +case _Space(): +return $default(_that);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `map` that fallback to returning `null`. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case final Subclass value: +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? mapOrNull(TResult? Function( _Space value)? $default,){ +final _that = this; +switch (_that) { +case _Space() when $default != null: +return $default(_that);case _: + return null; + +} +} +/// A variant of `when` that fallback to an `orElse` callback. +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return orElse(); +/// } +/// ``` + +@optionalTypeArgs TResult maybeWhen(TResult Function( Room roomData, Image? avatar)? $default,{required TResult orElse(),}) {final _that = this; +switch (_that) { +case _Space() when $default != null: +return $default(_that.roomData,_that.avatar);case _: + return orElse(); + +} +} +/// A `switch`-like method, using callbacks. +/// +/// As opposed to `map`, this offers destructuring. +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case Subclass2(:final field2): +/// return ...; +/// } +/// ``` + +@optionalTypeArgs TResult when(TResult Function( Room roomData, Image? avatar) $default,) {final _that = this; +switch (_that) { +case _Space(): +return $default(_that.roomData,_that.avatar);case _: + throw StateError('Unexpected subclass'); + +} +} +/// A variant of `when` that fallback to returning `null` +/// +/// It is equivalent to doing: +/// ```dart +/// switch (sealedClass) { +/// case Subclass(:final field): +/// return ...; +/// case _: +/// return null; +/// } +/// ``` + +@optionalTypeArgs TResult? whenOrNull(TResult? Function( Room roomData, Image? avatar)? $default,) {final _that = this; +switch (_that) { +case _Space() when $default != null: +return $default(_that.roomData,_that.avatar);case _: + return null; + +} +} + +} + +/// @nodoc + + +class _Space implements Space { + const _Space({required this.roomData, required this.avatar}); + + +@override final Room roomData; +@override final Image? avatar; + +/// Create a copy of Space +/// with the given fields replaced by the non-null parameter values. +@override @JsonKey(includeFromJson: false, includeToJson: false) +@pragma('vm:prefer-inline') +_$SpaceCopyWith<_Space> get copyWith => __$SpaceCopyWithImpl<_Space>(this, _$identity); + + + +@override +bool operator ==(Object other) { + return identical(this, other) || (other.runtimeType == runtimeType&&other is _Space&&(identical(other.roomData, roomData) || other.roomData == roomData)&&(identical(other.avatar, avatar) || other.avatar == avatar)); +} + + +@override +int get hashCode => Object.hash(runtimeType,roomData,avatar); + +@override +String toString() { + return 'Space(roomData: $roomData, avatar: $avatar)'; +} + + +} + +/// @nodoc +abstract mixin class _$SpaceCopyWith<$Res> implements $SpaceCopyWith<$Res> { + factory _$SpaceCopyWith(_Space value, $Res Function(_Space) _then) = __$SpaceCopyWithImpl; +@override @useResult +$Res call({ + Room roomData, Image? avatar +}); + + + + +} +/// @nodoc +class __$SpaceCopyWithImpl<$Res> + implements _$SpaceCopyWith<$Res> { + __$SpaceCopyWithImpl(this._self, this._then); + + final _Space _self; + final $Res Function(_Space) _then; + +/// Create a copy of Space +/// with the given fields replaced by the non-null parameter values. +@override @pragma('vm:prefer-inline') $Res call({Object? roomData = null,Object? avatar = freezed,}) { + return _then(_Space( +roomData: null == roomData ? _self.roomData : roomData // ignore: cast_nullable_to_non_nullable +as Room,avatar: freezed == avatar ? _self.avatar : avatar // ignore: cast_nullable_to_non_nullable +as Image?, + )); +} + + +} + +// dart format on diff --git a/lib/widgets/error_dialog.dart b/lib/widgets/error_dialog.dart new file mode 100644 index 0000000..b016a8b --- /dev/null +++ b/lib/widgets/error_dialog.dart @@ -0,0 +1,32 @@ +import "package:flutter/material.dart"; +import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:flutter_riverpod/misc.dart"; + +class ErrorDialog extends ConsumerWidget { + final Object error; + final StackTrace? stackTrace; + final ProviderOrFamily? provider; + const ErrorDialog(this.error, this.stackTrace, {this.provider, super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return AlertDialog( + title: Text("An Error Occurred"), + content: SingleChildScrollView( + child: SelectableText("$error\n\n$stackTrace"), + ), + actions: [ + if (provider != null) + TextButton( + onPressed: () => ref.invalidate(provider!), + child: const Text("Try Again"), + ), + TextButton( + onPressed: () => + Navigator.of(context).popUntil((route) => route.isFirst), + child: const Text("Go Back"), + ), + ], + ); + } +} diff --git a/lib/widgets/loading.dart b/lib/widgets/loading.dart new file mode 100644 index 0000000..aadc43c --- /dev/null +++ b/lib/widgets/loading.dart @@ -0,0 +1,13 @@ +import "package:flutter/material.dart"; + +class Loading extends StatelessWidget { + const Loading({super.key}); + + @override + Widget build(BuildContext context) => const Center( + child: Padding( + padding: EdgeInsets.all(16), + child: CircularProgressIndicator(), + ), + ); +} diff --git a/lib/widgets/room_chat.dart b/lib/widgets/room_chat.dart index fc836d9..321d27f 100644 --- a/lib/widgets/room_chat.dart +++ b/lib/widgets/room_chat.dart @@ -14,6 +14,7 @@ class RoomChat extends HookConsumerWidget { @override Widget build(BuildContext context, WidgetRef ref) { + final urlRegex = RegExp(r"https?://[^\s\]\(\)]+"); final controller = RoomChatController.provider("1"); final theme = Theme.of(context); return Chat( @@ -25,7 +26,10 @@ class RoomChat extends HookConsumerWidget { ), ), builders: Builders( - composerBuilder: (_) => Composer(), + composerBuilder: (_) => Composer( + sendIconColor: theme.colorScheme.primary, + sendOnEnter: true, + ), textMessageBuilder: ( context, @@ -36,9 +40,7 @@ class RoomChat extends HookConsumerWidget { }) => FlyerChatTextMessage( message: message.copyWith( text: message.text.replaceAllMapped( - RegExp( - r"http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\\(\\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+", - ), + urlRegex, (match) => "[${match.group(0)}](${match.group(0)})", ), ), @@ -49,26 +51,22 @@ class RoomChat extends HookConsumerWidget { sentLinksColor: Colors.blue, receivedLinksColor: Colors.blue, ), - linkPreviewBuilder: (_, message, isSentByMe) { - return LinkPreview( - text: message.text, - backgroundColor: isSentByMe - ? theme.colorScheme.inversePrimary - : theme.colorScheme.surfaceContainerLow, - insidePadding: EdgeInsets.symmetric(vertical: 8, horizontal: 16), - linkPreviewData: message.linkPreviewData, - onLinkPreviewDataFetched: (linkPreviewData) { - ref - .watch(controller) - .updateMessage( - message, - message.copyWith(linkPreviewData: linkPreviewData), - ); - }, - // You can still customize the appearance - parentContent: message.text, - ); - }, + linkPreviewBuilder: (_, message, isSentByMe) => LinkPreview( + text: urlRegex.firstMatch(message.text)?.group(0) ?? "", + backgroundColor: isSentByMe + ? theme.colorScheme.inversePrimary + : theme.colorScheme.surfaceContainerLow, + insidePadding: EdgeInsets.symmetric(vertical: 8, horizontal: 16), + linkPreviewData: message.linkPreviewData, + onLinkPreviewDataFetched: (linkPreviewData) { + ref + .watch(controller) + .updateMessage( + message, + message.copyWith(linkPreviewData: linkPreviewData), + ); + }, + ), imageMessageBuilder: ( _, diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index b2d5389..8a82f68 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -1,21 +1,22 @@ -import "dart:io"; - +import "package:color_hash/color_hash.dart"; import "package:flutter/material.dart"; import "package:flutter_hooks/flutter_hooks.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:nexus/controllers/spaces_controller.dart"; -class Sidebar extends HookWidget { +class Sidebar extends HookConsumerWidget { const Sidebar({super.key}); @override - Widget build(BuildContext context) { + Widget build(BuildContext context, WidgetRef ref) { final index = useState(0); return Drawer( shape: Border(), child: Row( children: [ NavigationRail( + scrollable: true, useIndicator: false, - labelType: NavigationRailLabelType.none, onDestinationSelected: (value) => index.value = value, destinations: [ NavigationRailDestination( @@ -28,11 +29,39 @@ class Sidebar extends HookWidget { label: Text("Messages"), padding: EdgeInsets.only(top: 12), ), - NavigationRailDestination( - icon: Image.file(File("assets/icon.png"), width: 40), - label: Text("Space 1"), - padding: EdgeInsets.only(top: 12), - ), + ...ref + .watch(SpacesController.provider) + .when( + loading: () => [], + error: (error, stack) { + debugPrintStack( + label: error.toString(), + stackTrace: stack, + ); + throw error; + }, + data: (spaces) => spaces.map( + (space) => NavigationRailDestination( + icon: ClipRRect( + borderRadius: BorderRadius.all(Radius.circular(12)), + child: SizedBox( + width: 40, + height: 40, + child: + space.avatar ?? + ColoredBox( + color: ColorHash(space.roomData.name).color, + child: Center( + child: Text(space.roomData.name[0]), + ), + ), + ), + ), + label: Text(space.roomData.name), + padding: EdgeInsets.only(top: 12), + ), + ), + ), ], selectedIndex: index.value, ), @@ -44,6 +73,7 @@ class Sidebar extends HookWidget { backgroundColor: Colors.transparent, ), body: NavigationRail( + scrollable: true, backgroundColor: Colors.transparent, extended: true, destinations: [ diff --git a/pubspec.lock b/pubspec.lock index a46382a..cc20fe7 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -89,6 +89,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.13.0" + base58check: + dependency: transitive + description: + name: base58check + sha256: "6c300dfc33e598d2fe26319e13f6243fea81eaf8204cb4c6b69ef20a625319a5" + url: "https://pub.dev" + source: hosted + version: "2.0.0" blurhash_dart: dependency: transitive description: @@ -113,6 +121,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.1.0" + build_cli_annotations: + dependency: transitive + description: + name: build_cli_annotations + sha256: e563c2e01de8974566a1998410d3f6f03521788160a02503b0b1f1a46c7b3d95 + url: "https://pub.dev" + source: hosted + version: "2.1.1" build_config: dependency: transitive description: @@ -169,6 +185,14 @@ packages: url: "https://pub.dev" source: hosted version: "8.12.0" + canonical_json: + dependency: transitive + description: + name: canonical_json + sha256: d6be1dd66b420c6ac9f42e3693e09edf4ff6edfee26cb4c28c1c019fdb8c0c15 + url: "https://pub.dev" + source: hosted + version: "1.1.2" characters: dependency: transitive description: @@ -233,6 +257,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.19.1" + color_hash: + dependency: "direct main" + description: + name: color_hash + sha256: caf944576d465b17f273d2bc14b50e37e9292f6f20975771edde4916301dde74 + url: "https://pub.dev" + source: hosted + version: "1.0.1" convert: dependency: transitive description: @@ -457,10 +489,11 @@ packages: flutter_chat_ui: dependency: "direct main" description: - name: flutter_chat_ui - sha256: "08a13577ea943d7965e3b1766d3a2119b07b56aced5336900ab7fb4c377d4ca0" - url: "https://pub.dev" - source: hosted + path: "packages/flutter_chat_ui" + ref: HEAD + resolved-ref: c1ef794e78e56308872ec377c91645a483204a02 + url: "https://github.com/Henry-Hiles/flutter_chat_ui" + source: git version: "2.9.1" flutter_hooks: dependency: "direct main" @@ -523,6 +556,14 @@ packages: url: "https://pub.dev" source: hosted version: "3.0.3" + flutter_rust_bridge: + dependency: transitive + description: + name: flutter_rust_bridge + sha256: "37ef40bc6f863652e865f0b2563ea07f0d3c58d8efad803cc01933a4b2ee067e" + url: "https://pub.dev" + source: hosted + version: "2.11.1" flutter_svg: dependency: transitive description: @@ -645,6 +686,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.15.6" + html_unescape: + dependency: transitive + description: + name: html_unescape + sha256: "15362d7a18f19d7b742ef8dcb811f5fd2a2df98db9f80ea393c075189e0b61e3" + url: "https://pub.dev" + source: hosted + version: "2.0.0" http: dependency: transitive description: @@ -781,14 +830,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.9.0" - json_serializable: - dependency: "direct dev" - description: - name: json_serializable - sha256: "33a040668b31b320aafa4822b7b1e177e163fc3c1e835c6750319d4ab23aa6fe" - url: "https://pub.dev" - source: hosted - version: "6.11.1" leak_tracker: dependency: transitive description: @@ -829,6 +870,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.3.0" + markdown: + dependency: transitive + description: + name: markdown + sha256: "935e23e1ff3bc02d390bad4d4be001208ee92cc217cb5b5a6c19bc14aaa318c1" + url: "https://pub.dev" + source: hosted + version: "7.3.0" matcher: dependency: transitive description: @@ -845,6 +894,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.11.1" + matrix: + dependency: "direct main" + description: + name: matrix + sha256: "94f5284c4ee521ae9d61f30cbb7c299d02d820e35509c028090d3b1901f520a3" + url: "https://pub.dev" + source: hosted + version: "3.0.2" meta: dependency: transitive description: @@ -1069,6 +1126,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + random_string: + dependency: transitive + description: + name: random_string + sha256: "03b52435aae8cbdd1056cf91bfc5bf845e9706724dd35ae2e99fa14a1ef79d02" + url: "https://pub.dev" + source: hosted + version: "2.3.1" riverpod: dependency: transitive description: @@ -1149,6 +1214,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.26.2" + sdp_transform: + dependency: transitive + description: + name: sdp_transform + sha256: "73e412a5279a5c2de74001535208e20fff88f225c9a4571af0f7146202755e45" + url: "https://pub.dev" + source: hosted + version: "0.3.2" sembast: dependency: transitive description: @@ -1250,6 +1323,14 @@ packages: description: flutter source: sdk version: "0.0.0" + slugify: + dependency: transitive + description: + name: slugify + sha256: b272501565cb28050cac2d96b7bf28a2d24c8dae359280361d124f3093d337c3 + url: "https://pub.dev" + source: hosted + version: "2.0.0" source_gen: dependency: "direct overridden" description: @@ -1258,14 +1339,6 @@ packages: url: "https://pub.dev" source: hosted version: "4.0.2" - source_helper: - dependency: transitive - description: - name: source_helper - sha256: "6a3c6cc82073a8797f8c4dc4572146114a39652851c157db37e964d9c7038723" - url: "https://pub.dev" - source: hosted - version: "1.3.8" source_map_stack_trace: dependency: transitive description: @@ -1290,6 +1363,30 @@ packages: url: "https://pub.dev" source: hosted version: "1.10.1" + sqflite_common: + dependency: transitive + description: + name: sqflite_common + sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6" + url: "https://pub.dev" + source: hosted + version: "2.5.6" + sqflite_common_ffi: + dependency: "direct main" + description: + name: sqflite_common_ffi + sha256: "9faa2fedc5385ef238ce772589f7718c24cdddd27419b609bb9c6f703ea27988" + url: "https://pub.dev" + source: hosted + version: "2.3.6" + sqlite3: + dependency: transitive + description: + name: sqlite3 + sha256: "3145bd74dcdb4fd6f5c6dda4d4e4490a8087d7f286a14dee5d37087290f0f8a2" + url: "https://pub.dev" + source: hosted + version: "2.9.4" stack_trace: dependency: transitive description: @@ -1402,6 +1499,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.4.0" + unorm_dart: + dependency: transitive + description: + name: unorm_dart + sha256: "5b35bff83fce4d76467641438f9e867dc9bcfdb8c1694854f230579d68cd8f4b" + url: "https://pub.dev" + source: hosted + version: "0.2.0" url_launcher: dependency: "direct main" description: @@ -1514,6 +1619,14 @@ packages: url: "https://pub.dev" source: hosted version: "15.0.2" + vodozemac: + dependency: transitive + description: + name: vodozemac + sha256: "39144e20740807731871c9248d811ed5a037b21d0aa9ffcfa630954de74139d9" + url: "https://pub.dev" + source: hosted + version: "0.4.0" watcher: dependency: transitive description: @@ -1554,6 +1667,14 @@ packages: url: "https://pub.dev" source: hosted version: "1.2.1" + webrtc_interface: + dependency: transitive + description: + name: webrtc_interface + sha256: "2e604a31703ad26781782fb14fa8a4ee621154ee2c513d2b9938e486fa695233" + url: "https://pub.dev" + source: hosted + version: "1.3.0" win32: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index ee4c289..59a906a 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -40,18 +40,23 @@ dependencies: url: https://github.com/google/flutter-desktop-embedding path: plugins/window_size flutter_chat_core: ^2.0.0 - flutter_chat_ui: ^2.0.0 flyer_chat_image_message: ^2.0.0 flyer_chat_system_message: ^2.0.0 flutter_link_previewer: ^4.0.0 flyer_chat_text_message: ^2.0.0 + flutter_chat_ui: + git: + url: https://github.com/Henry-Hiles/flutter_chat_ui + path: packages/flutter_chat_ui + matrix: ^3.0.2 + sqflite_common_ffi: ^2.3.6 + color_hash: ^1.0.1 dev_dependencies: build_runner: ^2.4.11 custom_lint: ^0.8.0 flutter_lints: ^6.0.0 freezed: ^3.2.3 - json_serializable: ^6.8.0 riverpod_lint: ^3.0.3 flutter_launcher_icons: ^0.14.1