diff --git a/README.md b/README.md index b97e9e7..73f00de 100644 --- a/README.md +++ b/README.md @@ -108,8 +108,8 @@ A simple and user-friendly Matrix client made with Flutter and a Gomuks backend. - [x] Events - [ ] Rooms - [x] Member list - - [x] Sort by power level - [ ] Colors based off of power level + - [ ] Sort by power level - [ ] Notifications using UnifiedPush ([#35](https://git.federated.nexus/Nexus/nexus/issues/35)) - [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195) - [ ] Invites diff --git a/assets/screenshotDark.png b/assets/screenshotDark.png index 322a64e..0a89f01 100644 Binary files a/assets/screenshotDark.png and b/assets/screenshotDark.png differ diff --git a/assets/screenshotLight.png b/assets/screenshotLight.png index 8772bcf..4e6fd36 100644 Binary files a/assets/screenshotLight.png and b/assets/screenshotLight.png differ diff --git a/lib/helpers/extensions/string_to_color.dart b/lib/helpers/extensions/string_to_color.dart index eaa7714..8d30e76 100644 --- a/lib/helpers/extensions/string_to_color.dart +++ b/lib/helpers/extensions/string_to_color.dart @@ -2,5 +2,5 @@ import "package:color_hash/color_hash.dart"; import "package:flutter/material.dart"; extension ToColor on String { - Color get colorHash => ColorHash(this, lightness: .5, saturation: .7).color; + Color get colorHash => ColorHash(this, lightness: .7, saturation: .7).color; } diff --git a/lib/widgets/divider_text.dart b/lib/widgets/divider_text.dart index 2b0f9bd..f53795d 100644 --- a/lib/widgets/divider_text.dart +++ b/lib/widgets/divider_text.dart @@ -1,5 +1,4 @@ import "package:flutter/material.dart"; -import "package:nexus/widgets/divider_widget.dart"; class DividerText extends StatelessWidget { final String text; @@ -7,6 +6,24 @@ class DividerText extends StatelessWidget { const DividerText(this.text, {super.key}); @override - Widget build(BuildContext context) => - DividerWidget(Text(text, style: Theme.of(context).textTheme.labelLarge)); + Widget build(BuildContext context) => LayoutBuilder( + builder: (context, constraints) => Row( + children: [ + SizedBox( + width: 16, + child: Divider(color: Theme.of(context).colorScheme.onSurface), + ), + ConstrainedBox( + constraints: .new(maxWidth: constraints.maxWidth - 32), + child: Padding( + padding: const .all(8), + child: Text(text, style: Theme.of(context).textTheme.labelLarge), + ), + ), + Expanded( + child: Divider(color: Theme.of(context).colorScheme.onSurface), + ), + ], + ), + ); } diff --git a/lib/widgets/divider_widget.dart b/lib/widgets/divider_widget.dart deleted file mode 100644 index 6f13bd4..0000000 --- a/lib/widgets/divider_widget.dart +++ /dev/null @@ -1,25 +0,0 @@ -import "package:flutter/material.dart"; - -class DividerWidget extends StatelessWidget { - final Widget widget; - const DividerWidget(this.widget, {super.key}); - - @override - Widget build(BuildContext context) => LayoutBuilder( - builder: (_, constraints) => Row( - children: [ - SizedBox( - width: 16, - child: Divider(color: Theme.of(context).colorScheme.onSurface), - ), - ConstrainedBox( - constraints: .new(maxWidth: constraints.maxWidth - 32), - child: Padding(padding: const .all(8), child: widget), - ), - Expanded( - child: Divider(color: Theme.of(context).colorScheme.onSurface), - ), - ], - ), - ); -} diff --git a/lib/widgets/error_dialog.dart b/lib/widgets/error_dialog.dart index 9b62200..b016a8b 100644 --- a/lib/widgets/error_dialog.dart +++ b/lib/widgets/error_dialog.dart @@ -21,12 +21,11 @@ class ErrorDialog extends ConsumerWidget { onPressed: () => ref.invalidate(provider!), child: const Text("Try Again"), ), - if (Navigator.of(context).canPop()) - TextButton( - onPressed: () => - Navigator.of(context).popUntil((route) => route.isFirst), - child: const Text("Go Back"), - ), + TextButton( + onPressed: () => + Navigator.of(context).popUntil((route) => route.isFirst), + child: const Text("Go Back"), + ), ], ); } diff --git a/lib/widgets/message_image.dart b/lib/widgets/message_image.dart index 8865a5c..d92783a 100644 --- a/lib/widgets/message_image.dart +++ b/lib/widgets/message_image.dart @@ -18,37 +18,36 @@ class MessageImage extends ConsumerWidget { url.toString(), child: ClipRRect( borderRadius: .all(.circular(8)), - child: AspectRatio( - aspectRatio: info!.width! / info!.height!, - child: Image( - image: CachedNetworkImage( - url.toString(), - ref.watch(CrossCacheController.provider), - headers: ref.headers, - ), - width: info?.width, - fit: BoxFit.fitWidth, - loadingBuilder: (_, child, loadingProgress) => loadingProgress == null - ? child - : switch (info?.blurHash) { - final blurHash? => - info?.width == null || info?.height == null - ? SizedBox( - width: 200, - height: 200, - child: BlurHash(hash: blurHash), - ) - : SizedBox( + child: Image( + image: CachedNetworkImage( + url.toString(), + ref.watch(CrossCacheController.provider), + headers: ref.headers, + ), + width: info?.width, + loadingBuilder: (_, child, loadingProgress) => loadingProgress == null + ? child + : switch (info?.blurHash) { + final blurHash? => + info?.width == null || info?.height == null + ? SizedBox( + width: 200, + height: 200, + child: BlurHash(hash: blurHash), + ) + : AspectRatio( + aspectRatio: info!.width! / info!.height!, + child: SizedBox( width: info!.width, child: BlurHash(hash: blurHash), ), - _ => Loading(), - }, - errorBuilder: (context, error, stackTrace) => Center( - child: Text( - "Image Failed to Load", - style: .new(color: Theme.of(context).colorScheme.error), - ), + ), + _ => Loading(), + }, + errorBuilder: (context, error, stackTrace) => Center( + child: Text( + "Image Failed to Load", + style: .new(color: Theme.of(context).colorScheme.error), ), ), ), diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index a4f659c..d1c1c7c 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -17,7 +17,6 @@ import "package:nexus/models/content/server_acl.dart"; import "package:nexus/models/content/sticker.dart"; import "package:nexus/models/content/topic.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/error_dialog.dart"; import "package:nexus/widgets/lazy_loading/message_displayname.dart"; import "package:nexus/widgets/renderers/message.dart"; import "package:nexus/widgets/reaction_row.dart"; @@ -50,13 +49,9 @@ class EventRenderer extends ConsumerWidget { final child = event.redactedBy != null || event.relationType == "m.replace" ? null : switch (event.content) { - Content(:final parseError?) => Row( - children: [ - ErrorDialog( - "An error occurred while parsing event ${event.eventId}:\n$parseError", - parseError.stackTrace, - ), - ], + Content(:final parseError?) => SelectableText( + "An error occurred while parsing this event:\n$parseError\n${parseError.stackTrace}", + style: errorStyle, ), MessageContent() || diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar.dart index 591e25f..abe9a0a 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar.dart @@ -7,7 +7,6 @@ import "package:nexus/controllers/key_controller.dart"; import "package:nexus/controllers/spaces_controller.dart"; import "package:nexus/models/room.dart"; import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/divider_widget.dart"; import "package:nexus/widgets/join_dialog.dart"; import "package:nexus/widgets/room_menu.dart"; @@ -39,11 +38,9 @@ class Sidebar extends HookConsumerWidget { spaces.firstWhereOrNull((space) => space.id == selectedSpaceId) ?? spaces.first; - final indexOfSelectedRoom = selectedSpace.children - .addAll( - selectedSpace.subSpaces.map((element) => element.children).flattened, - ) - .indexWhere((room) => room.metadata?.id == selectedRoomId); + final indexOfSelectedRoom = selectedSpace.children.indexWhere( + (room) => room.metadata?.id == selectedRoomId, + ); final selectedRoomIndex = indexOfSelectedRoom == -1 ? null : indexOfSelectedRoom; @@ -63,6 +60,7 @@ class Sidebar extends HookConsumerWidget { fallback: selectedSpaceId == "dms" ? null : Icon(Icons.numbers), + // space.client.headers, ), ), ) @@ -100,32 +98,17 @@ class Sidebar extends HookConsumerWidget { destinations: spaces .map( (space) => NavigationRailM3EDestination( - badgeCount: switch (space.children - .addAll( - space.subSpaces - .map((element) => element.children) - .flattened, - ) - .fold( - 0, - (previousValue, room) => - previousValue + - (room.metadata?.unreadNotifications ?? 0), - )) { + badgeCount: switch (space.children.fold( + 0, + (previousValue, room) => + previousValue + + (room.metadata?.unreadNotifications ?? 0), + )) { 0 => - space.children - .addAll( - space.subSpaces - .map( - (element) => element.children, - ) - .flattened, - ) - .any( - (room) => - room.metadata?.unreadMessages != - 0, - ) + space.children.any( + (room) => + room.metadata?.unreadMessages != 0, + ) ? 0 : null, int badgeCount => badgeCount, @@ -230,47 +213,20 @@ class Sidebar extends HookConsumerWidget { selectedIndex: selectedRoomIndex ?? 0, sections: [ .new( - header: selectedSpace.room == null - ? null - : DividerWidget(Text("Rooms")), + header: selectedSpace.room == null ? null : Text("Rooms"), destinations: roomsToDestinations(selectedSpace.children), ), for (final subSpace in selectedSpace.subSpaces) .new( - header: DividerWidget( - Row( - mainAxisSize: MainAxisSize.min, - spacing: 8, - children: [ - if (subSpace.room.metadata?.avatar != null) - AvatarOrHash( - subSpace.room.metadata?.avatar, - subSpace.room.metadata?.name ?? - "Unnamed Room", - height: 16, - ), - Flexible( - child: Text( - subSpace.room.metadata?.name ?? - "Unnamed Space", - maxLines: 1, - overflow: TextOverflow.ellipsis, - ), - ), - ], - ), + header: Text( + subSpace.room.metadata?.name ?? "Unnamed Space", ), destinations: roomsToDestinations(subSpace.children), ), ], onDestinationSelected: (value) { - final children = selectedSpace.children.addAll( - selectedSpace.subSpaces - .map((element) => element.children) - .flattened, - ); selectedRoomIdNotifier.set( - children[value].metadata?.id, // + selectedSpace.children[value].metadata?.id, ); if (!isDesktop) Navigator.of(context).pop(); },