diff --git a/lib/controllers/author_controller.dart b/lib/controllers/author_controller.dart index c7e4e05..72b0f72 100644 --- a/lib/controllers/author_controller.dart +++ b/lib/controllers/author_controller.dart @@ -2,6 +2,7 @@ import "dart:async"; import "package:collection/collection.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:nexus/controllers/client_state_controller.dart"; import "package:nexus/controllers/members_controller.dart"; import "package:nexus/models/configs/author_config.dart"; import "package:nexus/models/membership.dart"; @@ -12,7 +13,7 @@ class AuthorController extends AsyncNotifier { @override Future build() async { - var member = await ref.watch( + final member = await ref.watch( MembersController.provider(config.room).selectAsync( (value) => value.firstWhereOrNull( (membership) => membership.userId == config.message.authorId, @@ -25,6 +26,12 @@ class AuthorController extends AsyncNotifier { : Membership.fromContent( IMap(config.message.metadata?["pmp"]), config.message.authorId, + ref.watch( + ClientStateController.provider.select( + (value) => value?.homeserverUrl, + ), + ) ?? + "", ); return Membership( diff --git a/lib/controllers/members_controller.dart b/lib/controllers/members_controller.dart index 80e73a0..8d79f71 100644 --- a/lib/controllers/members_controller.dart +++ b/lib/controllers/members_controller.dart @@ -1,6 +1,7 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/controllers/client_controller.dart"; +import "package:nexus/controllers/client_state_controller.dart"; import "package:nexus/models/membership.dart"; import "package:nexus/models/requests/get_room_state_request.dart"; import "package:nexus/models/room.dart"; @@ -26,8 +27,16 @@ class MembersController extends AsyncNotifier> { return state.nonNulls .where((member) => member.content["membership"] == "join") .map( - (membership) => - Membership.fromContent(membership.content, membership.stateKey!), + (membership) => Membership.fromContent( + membership.content, + membership.stateKey!, + ref.watch( + ClientStateController.provider.select( + (value) => value?.homeserverUrl, + ), + ) ?? + "", + ), ) .toIList(); } diff --git a/lib/controllers/rooms_controller.dart b/lib/controllers/rooms_controller.dart index 3c6e287..27eb18e 100644 --- a/lib/controllers/rooms_controller.dart +++ b/lib/controllers/rooms_controller.dart @@ -1,7 +1,9 @@ import "package:collection/collection.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:nexus/controllers/client_state_controller.dart"; import "package:nexus/controllers/new_events_controller.dart"; +import "package:nexus/helpers/extensions/mxc_to_https.dart"; import "package:nexus/models/read_receipt.dart"; import "package:nexus/models/room.dart"; @@ -10,6 +12,13 @@ class RoomsController extends Notifier> { IMap build() => const IMap.empty(); void update(IMap rooms, ISet leftRooms) { + final homeserver = + ref.watch( + ClientStateController.provider.select( + (value) => value?.homeserverUrl, + ), + ) ?? + ""; final merged = rooms.entries.fold(state, (acc, entry) { final roomId = entry.key; final incoming = entry.value; @@ -37,7 +46,13 @@ class RoomsController extends Notifier> { roomId, existing?.copyWith( hasMore: incoming.hasMore, - metadata: incoming.metadata ?? existing.metadata, + metadata: + incoming.metadata?.copyWith( + avatar: + incoming.metadata?.avatar?.mxcToHttps(homeserver) ?? + existing.metadata?.avatar, + ) ?? + existing.metadata, events: events!, state: incoming.state.entries.fold( existing.state, @@ -67,7 +82,11 @@ class RoomsController extends Notifier> { ), ), ) ?? - incoming, + incoming.copyWith( + metadata: incoming.metadata?.copyWith( + avatar: incoming.metadata?.avatar?.mxcToHttps(homeserver), + ), + ), ); }); diff --git a/lib/models/membership.dart b/lib/models/membership.dart index ec18be7..4e2bf4c 100644 --- a/lib/models/membership.dart +++ b/lib/models/membership.dart @@ -1,5 +1,6 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:freezed_annotation/freezed_annotation.dart"; +import "package:nexus/helpers/extensions/mxc_to_https.dart"; part "membership.freezed.dart"; @freezed @@ -14,8 +15,11 @@ abstract class Membership with _$Membership { factory Membership.fromContent( IMap content, String userId, + String homeserver, ) => Membership( - avatarUrl: Uri.tryParse(content["avatar_url"] ?? ""), + avatarUrl: Uri.tryParse( + content["avatar_url"] ?? "", + )?.mxcToHttps(homeserver), userId: userId, displayName: content["displayname"] ?? userId.substring(1).split(":").first, ); diff --git a/lib/widgets/avatar_or_hash.dart b/lib/widgets/avatar_or_hash.dart index 8e93b6b..147c249 100644 --- a/lib/widgets/avatar_or_hash.dart +++ b/lib/widgets/avatar_or_hash.dart @@ -2,10 +2,8 @@ import "package:color_hash/color_hash.dart"; import "package:cross_cache/cross_cache.dart"; import "package:flutter/material.dart"; import "package:flutter_riverpod/flutter_riverpod.dart"; -import "package:nexus/controllers/client_state_controller.dart"; import "package:nexus/controllers/cross_cache_controller.dart"; import "package:nexus/helpers/extensions/get_headers.dart"; -import "package:nexus/helpers/extensions/mxc_to_https.dart"; class AvatarOrHash extends ConsumerWidget { final Uri? avatar; @@ -48,16 +46,7 @@ class AvatarOrHash extends ConsumerWidget { ? fallback ?? box : Image( image: CachedNetworkImage( - avatar! - .mxcToHttps( - ref.watch( - ClientStateController.provider.select( - (value) => value?.homeserverUrl, - ), - ) ?? - "", - ) - .toString(), + avatar.toString(), ref.watch(CrossCacheController.provider), headers: ref.headers, ), diff --git a/lib/widgets/chat_page/expandable_image.dart b/lib/widgets/chat_page/expandable_image.dart new file mode 100644 index 0000000..ac5bbe1 --- /dev/null +++ b/lib/widgets/chat_page/expandable_image.dart @@ -0,0 +1,48 @@ +import "dart:math"; +import "package:cross_cache/cross_cache.dart"; +import "package:flutter/material.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:nexus/controllers/cross_cache_controller.dart"; +import "package:nexus/helpers/extensions/get_headers.dart"; +import "package:nexus/widgets/error_dialog.dart"; + +class ExpandableImage extends ConsumerWidget { + final Widget child; + final String? source; + const ExpandableImage(this.source, {required this.child, super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) => InkWell( + onTap: source == null + ? null + : () => showDialog( + context: context, + builder: (_) => LayoutBuilder( + builder: (context, constraints) => Dialog( + backgroundColor: Colors.transparent, + insetPadding: EdgeInsets.all(constraints.maxWidth / 100), + child: ConstrainedBox( + constraints: BoxConstraints( + minWidth: min(constraints.maxWidth, 1000), + ), + child: InteractiveViewer( + child: Image( + fit: BoxFit.contain, + errorBuilder: (_, error, stackTrace) => ErrorDialog( + "Loading failed for $source\nError: $error", + stackTrace, + ), + image: CachedNetworkImage( + source!, + ref.watch(CrossCacheController.provider), + headers: ref.headers, + ), + ), + ), + ), + ), + ), + ), + child: child, + ); +} diff --git a/lib/widgets/chat_page/expandable_image_message.dart b/lib/widgets/chat_page/expandable_image_message.dart new file mode 100644 index 0000000..f6e8a03 --- /dev/null +++ b/lib/widgets/chat_page/expandable_image_message.dart @@ -0,0 +1,35 @@ +import "package:cross_cache/cross_cache.dart"; +import "package:flutter/material.dart"; +import "package:flutter_chat_core/flutter_chat_core.dart"; +import "package:flutter_riverpod/flutter_riverpod.dart"; +import "package:flyer_chat_image_message/flyer_chat_image_message.dart"; +import "package:nexus/controllers/cross_cache_controller.dart"; +import "package:nexus/helpers/extensions/get_headers.dart"; +import "package:nexus/widgets/chat_page/expandable_image.dart"; + +class ExpandableImageMessage extends ConsumerWidget { + final ImageMessage message; + final int index; + + const ExpandableImageMessage(this.message, {required this.index, super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) => ExpandableImage( + message.source, + child: FlyerChatImageMessage( + customImageProvider: CachedNetworkImage( + message.source, + ref.watch(CrossCacheController.provider), + headers: ref.headers, + ), + errorBuilder: (context, error, stackTrace) => Center( + child: Text( + "Image Failed to Load", + style: TextStyle(color: Theme.of(context).colorScheme.error), + ), + ), + message: message, + index: index, + ), + ); +} diff --git a/lib/widgets/chat_page/image_message.dart b/lib/widgets/chat_page/image_message.dart deleted file mode 100644 index f197e66..0000000 --- a/lib/widgets/chat_page/image_message.dart +++ /dev/null @@ -1,63 +0,0 @@ -import "dart:math"; -import "package:cross_cache/cross_cache.dart"; -import "package:flutter/material.dart"; -import "package:flutter_chat_core/flutter_chat_core.dart"; -import "package:flutter_riverpod/flutter_riverpod.dart"; -import "package:flyer_chat_image_message/flyer_chat_image_message.dart"; -import "package:nexus/controllers/cross_cache_controller.dart"; -import "package:nexus/helpers/extensions/get_headers.dart"; -import "package:nexus/widgets/error_dialog.dart"; - -class ExpandableImageMessage extends ConsumerWidget { - final ImageMessage message; - final int index; - - const ExpandableImageMessage(this.message, {required this.index, super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) => InkWell( - onTap: () => showDialog( - context: context, - builder: (_) => LayoutBuilder( - builder: (context, constraints) => Dialog( - backgroundColor: Colors.transparent, - insetPadding: EdgeInsets.all(constraints.maxWidth / 100), - child: ConstrainedBox( - constraints: BoxConstraints( - minWidth: min(constraints.maxWidth, 1000), - ), - child: InteractiveViewer( - child: Image( - fit: BoxFit.contain, - errorBuilder: (_, error, stackTrace) => ErrorDialog( - "Loading failed for ${message.source}\nError: $error", - stackTrace, - ), - image: CachedNetworkImage( - message.source, - ref.watch(CrossCacheController.provider), - headers: ref.headers, - ), - ), - ), - ), - ), - ), - ), - child: FlyerChatImageMessage( - customImageProvider: CachedNetworkImage( - message.source, - ref.watch(CrossCacheController.provider), - headers: ref.headers, - ), - errorBuilder: (context, error, stackTrace) => Center( - child: Text( - "Image Failed to Load", - style: TextStyle(color: Theme.of(context).colorScheme.error), - ), - ), - message: message, - index: index, - ), - ); -} diff --git a/lib/widgets/chat_page/room_appbar.dart b/lib/widgets/chat_page/room_appbar.dart index 436bcb9..03cd994 100644 --- a/lib/widgets/chat_page/room_appbar.dart +++ b/lib/widgets/chat_page/room_appbar.dart @@ -3,6 +3,7 @@ import "package:flutter/material.dart"; import "package:nexus/models/room.dart"; import "package:nexus/widgets/appbar.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/chat_page/expandable_image.dart"; import "package:nexus/widgets/chat_page/room_menu.dart"; class RoomAppbar extends StatelessWidget implements PreferredSizeWidget { @@ -24,11 +25,14 @@ class RoomAppbar extends StatelessWidget implements PreferredSizeWidget { @override Widget build(BuildContext context) => Appbar( leading: isDesktop - ? AvatarOrHash( - room.metadata?.avatar, - room.metadata?.name ?? "Unnamed Rooms", - height: 24, - fallback: Icon(Icons.numbers), + ? ExpandableImage( + room.metadata?.avatar?.toString(), + child: AvatarOrHash( + room.metadata?.avatar, + room.metadata?.name ?? "Unnamed Rooms", + height: 24, + fallback: Icon(Icons.numbers), + ), ) : DrawerButton(onPressed: () => onOpenDrawer(context)), scrolledUnderElevation: 0, diff --git a/lib/widgets/chat_page/room_chat.dart b/lib/widgets/chat_page/room_chat.dart index 6b3839a..cfbd1a8 100644 --- a/lib/widgets/chat_page/room_chat.dart +++ b/lib/widgets/chat_page/room_chat.dart @@ -14,7 +14,7 @@ import "package:nexus/helpers/extensions/show_context_menu.dart"; import "package:nexus/models/relation_type.dart"; import "package:nexus/models/requests/report_request.dart"; import "package:nexus/widgets/chat_page/composer/chat_box.dart"; -import "package:nexus/widgets/chat_page/image_message.dart"; +import "package:nexus/widgets/chat_page/expandable_image_message.dart"; import "package:nexus/widgets/chat_page/member_list.dart"; import "package:nexus/widgets/chat_page/wrappers/message_wrapper.dart"; import "package:nexus/widgets/chat_page/room_appbar.dart";