diff --git a/lib/controllers/room_settings_sections.dart b/lib/controllers/room_settings_sections.dart index bf7159a..bababee 100644 --- a/lib/controllers/room_settings_sections.dart +++ b/lib/controllers/room_settings_sections.dart @@ -36,9 +36,9 @@ import "package:nexus/models/join_rule.dart"; import "package:nexus/models/power_level_permission.dart"; import "package:nexus/models/setting.dart"; import "package:nexus/models/settings_category.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/image_pack_avatar.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/divider_text.dart"; +import "package:nexus/widgets/avatars/image_pack_avatar.dart"; import "package:nexus/widgets/settings/add_users_power_level_sheet.dart"; import "package:nexus/widgets/settings/aliases_sheet.dart"; import "package:nexus/widgets/settings/allowed_rooms_sheet.dart"; diff --git a/lib/controllers/settings_sections.dart b/lib/controllers/settings_sections.dart index 35c7f94..999fea6 100644 --- a/lib/controllers/settings_sections.dart +++ b/lib/controllers/settings_sections.dart @@ -35,15 +35,15 @@ import "package:nexus/models/settings.dart"; import "package:nexus/models/settings_category.dart"; import "package:nexus/models/show_and_send.dart"; import "package:nexus/main.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/image_pack_avatar.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/divider_text.dart"; +import "package:nexus/widgets/avatars/image_pack_avatar.dart"; import "package:nexus/widgets/settings/block_user_field.dart"; import "package:nexus/widgets/settings/dialog_list_tile.dart"; import "package:nexus/widgets/settings/enable_image_packs_sheet.dart"; import "package:nexus/widgets/settings/keyword_field.dart"; -import "package:nexus/widgets/user_bottom_sheet.dart"; -import "package:nexus/widgets/reset_encryption_sheet.dart"; +import "package:nexus/widgets/users/user_bottom_sheet.dart"; +import "package:nexus/widgets/encryption/reset_encryption_sheet.dart"; class SettingsSectionsController extends AsyncNotifier>> { diff --git a/lib/helpers/extensions/better_when.dart b/lib/helpers/extensions/better_when.dart index e054d02..459d139 100644 --- a/lib/helpers/extensions/better_when.dart +++ b/lib/helpers/extensions/better_when.dart @@ -1,7 +1,7 @@ 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"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; extension BetterWhen on AsyncValue { Widget betterWhen({ diff --git a/lib/helpers/extensions/build_event_options.dart b/lib/helpers/extensions/build_event_options.dart index aff4ba0..a6ecc06 100644 --- a/lib/helpers/extensions/build_event_options.dart +++ b/lib/helpers/extensions/build_event_options.dart @@ -15,8 +15,8 @@ import "package:nexus/helpers/extensions/event_id_is_fake.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/event.dart"; import "package:nexus/models/relation_type.dart"; -import "package:nexus/widgets/emoji_picker.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; +import "package:nexus/widgets/emoji/emoji_picker.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; import "package:nexus/main.dart"; extension BuildEventOptions on Event { diff --git a/lib/helpers/extensions/image_pack_emoji.dart b/lib/helpers/extensions/image_pack_emoji.dart index 2b04cf1..fe480d5 100644 --- a/lib/helpers/extensions/image_pack_emoji.dart +++ b/lib/helpers/extensions/image_pack_emoji.dart @@ -2,7 +2,7 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:material_emoji_picker/material_emoji_picker.dart"; import "package:nexus/models/content/image_pack.dart"; import "package:nexus/models/image_pack.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; extension ImagePackEmoji on ImagePack { EmojiCategory? get emojiCategory => _category(emoticons); diff --git a/lib/helpers/extensions/open_link_info.dart b/lib/helpers/extensions/open_link_info.dart index e15e9b0..60947bb 100644 --- a/lib/helpers/extensions/open_link_info.dart +++ b/lib/helpers/extensions/open_link_info.dart @@ -7,7 +7,7 @@ import "package:nexus/helpers/extensions/focus_room.dart"; import "package:nexus/helpers/extensions/get_link_info.dart"; import "package:nexus/helpers/extensions/show_user_popover.dart"; import "package:nexus/models/room_summary.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; extension OpenLinkInfo on WidgetRef { Future openLinkInfo( diff --git a/lib/helpers/extensions/room_destinations.dart b/lib/helpers/extensions/room_destinations.dart index 3628d05..3d0323b 100644 --- a/lib/helpers/extensions/room_destinations.dart +++ b/lib/helpers/extensions/room_destinations.dart @@ -2,7 +2,7 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:material_ui/material_ui.dart"; import "package:navigation_rail_m3e/navigation_rail_m3e.dart"; import "package:nexus/models/room.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; extension RoomDestination on Room { NavigationRailM3EDestination toDestination({ diff --git a/lib/helpers/extensions/show_image_viewer.dart b/lib/helpers/extensions/show_image_viewer.dart index ec40344..9be95b8 100644 --- a/lib/helpers/extensions/show_image_viewer.dart +++ b/lib/helpers/extensions/show_image_viewer.dart @@ -5,7 +5,7 @@ import "package:nexus/helpers/extensions/save_attachment.dart"; import "package:nexus/helpers/extensions/size_to_string.dart"; import "package:nexus/helpers/mxc_image.dart"; import "package:nexus/models/requests/download_media.dart"; -import "package:nexus/widgets/error_dialog.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; extension ShowImageViewer on BuildContext { /// Shows the image from [request] fullscreen, zoomable. diff --git a/lib/helpers/extensions/show_user_popover.dart b/lib/helpers/extensions/show_user_popover.dart index af3e00e..e7018c0 100644 --- a/lib/helpers/extensions/show_user_popover.dart +++ b/lib/helpers/extensions/show_user_popover.dart @@ -1,6 +1,6 @@ import "package:material_ui/material_ui.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; -import "package:nexus/widgets/user_bottom_sheet.dart"; +import "package:nexus/widgets/users/user_bottom_sheet.dart"; extension ShowUserPopover on BuildContext { void showUserPopover(String userId, {String? roomId, Rect? anchor}) => diff --git a/lib/main.dart b/lib/main.dart index 6234b0c..590c74d 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -22,9 +22,9 @@ import "package:nexus/widgets/pages/select_server.dart"; import "package:nexus/widgets/pages/settings.dart"; import "package:nexus/widgets/pages/verify.dart"; import "package:nexus/widgets/account_scope.dart"; -import "package:nexus/widgets/appbar.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/appbar.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:window_manager/window_manager.dart"; import "package:material_ui/material_ui.dart"; diff --git a/lib/widgets/avatar_or_hash.dart b/lib/widgets/avatars/avatar_or_hash.dart similarity index 100% rename from lib/widgets/avatar_or_hash.dart rename to lib/widgets/avatars/avatar_or_hash.dart diff --git a/lib/widgets/avatar_ring.dart b/lib/widgets/avatars/avatar_ring.dart similarity index 100% rename from lib/widgets/avatar_ring.dart rename to lib/widgets/avatars/avatar_ring.dart diff --git a/lib/widgets/editable_avatar.dart b/lib/widgets/avatars/editable_avatar.dart similarity index 100% rename from lib/widgets/editable_avatar.dart rename to lib/widgets/avatars/editable_avatar.dart diff --git a/lib/widgets/image_pack_avatar.dart b/lib/widgets/avatars/image_pack_avatar.dart similarity index 86% rename from lib/widgets/image_pack_avatar.dart rename to lib/widgets/avatars/image_pack_avatar.dart index aaebca2..42504ae 100644 --- a/lib/widgets/image_pack_avatar.dart +++ b/lib/widgets/avatars/image_pack_avatar.dart @@ -1,5 +1,5 @@ import "package:material_ui/material_ui.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; class const ImagePackAvatar(final Uri? icon, {super.key}) extends StatelessWidget { diff --git a/lib/widgets/account_switcher.dart b/lib/widgets/common/account_switcher.dart similarity index 98% rename from lib/widgets/account_switcher.dart rename to lib/widgets/common/account_switcher.dart index 6c9c93b..3d0f996 100644 --- a/lib/widgets/account_switcher.dart +++ b/lib/widgets/common/account_switcher.dart @@ -7,7 +7,7 @@ import "package:nexus/controllers/active_account.dart"; import "package:nexus/helpers/extensions/log_out.dart"; import "package:nexus/main.dart"; import "package:nexus/models/account.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; /// Switches between, adds and logs out of accounts. With [onlyWithOthers], it's /// hidden when there's only one account. diff --git a/lib/widgets/appbar.dart b/lib/widgets/common/appbar.dart similarity index 100% rename from lib/widgets/appbar.dart rename to lib/widgets/common/appbar.dart diff --git a/lib/widgets/bouncing_dots.dart b/lib/widgets/common/bouncing_dots.dart similarity index 100% rename from lib/widgets/bouncing_dots.dart rename to lib/widgets/common/bouncing_dots.dart diff --git a/lib/widgets/count_badge.dart b/lib/widgets/common/count_badge.dart similarity index 100% rename from lib/widgets/count_badge.dart rename to lib/widgets/common/count_badge.dart diff --git a/lib/widgets/divider_text.dart b/lib/widgets/common/divider_text.dart similarity index 82% rename from lib/widgets/divider_text.dart rename to lib/widgets/common/divider_text.dart index c44ae11..2c623ba 100644 --- a/lib/widgets/divider_text.dart +++ b/lib/widgets/common/divider_text.dart @@ -1,5 +1,5 @@ import "package:material_ui/material_ui.dart"; -import "package:nexus/widgets/divider_widget.dart"; +import "package:nexus/widgets/common/divider_widget.dart"; final class const DividerText(final String text, {super.key}) extends StatelessWidget { diff --git a/lib/widgets/divider_widget.dart b/lib/widgets/common/divider_widget.dart similarity index 100% rename from lib/widgets/divider_widget.dart rename to lib/widgets/common/divider_widget.dart diff --git a/lib/widgets/error_dialog.dart b/lib/widgets/common/error_dialog.dart similarity index 100% rename from lib/widgets/error_dialog.dart rename to lib/widgets/common/error_dialog.dart diff --git a/lib/widgets/expandable_image.dart b/lib/widgets/common/expandable_image.dart similarity index 100% rename from lib/widgets/expandable_image.dart rename to lib/widgets/common/expandable_image.dart diff --git a/lib/widgets/highlight_wrapper.dart b/lib/widgets/common/highlight_wrapper.dart similarity index 100% rename from lib/widgets/highlight_wrapper.dart rename to lib/widgets/common/highlight_wrapper.dart diff --git a/lib/widgets/linkified_text.dart b/lib/widgets/common/linkified_text.dart similarity index 100% rename from lib/widgets/linkified_text.dart rename to lib/widgets/common/linkified_text.dart diff --git a/lib/widgets/loading.dart b/lib/widgets/common/loading.dart similarity index 100% rename from lib/widgets/loading.dart rename to lib/widgets/common/loading.dart diff --git a/lib/widgets/m3e_rail_theme.dart b/lib/widgets/common/m3e_rail_theme.dart similarity index 100% rename from lib/widgets/m3e_rail_theme.dart rename to lib/widgets/common/m3e_rail_theme.dart diff --git a/lib/widgets/sync_status_banner.dart b/lib/widgets/common/sync_status_banner.dart similarity index 98% rename from lib/widgets/sync_status_banner.dart rename to lib/widgets/common/sync_status_banner.dart index 10aec7e..4199866 100644 --- a/lib/widgets/sync_status_banner.dart +++ b/lib/widgets/common/sync_status_banner.dart @@ -1,7 +1,7 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:material_ui/material_ui.dart"; import "package:nexus/controllers/sync_status.dart"; -import "package:nexus/widgets/error_dialog.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; import "package:timeago/timeago.dart"; class const SyncStatusBanner({super.key}) extends ConsumerWidget { diff --git a/lib/widgets/timestamp.dart b/lib/widgets/common/timestamp.dart similarity index 100% rename from lib/widgets/timestamp.dart rename to lib/widgets/common/timestamp.dart diff --git a/lib/widgets/composer/bot_command_panel.dart b/lib/widgets/composer/bot_command_panel.dart index 8a06754..bc6c05a 100644 --- a/lib/widgets/composer/bot_command_panel.dart +++ b/lib/widgets/composer/bot_command_panel.dart @@ -9,7 +9,7 @@ import "package:nexus/controllers/bot_command_draft.dart"; import "package:nexus/models/bot_argument_suggestion.dart"; import "package:nexus/models/bot_command.dart"; import "package:nexus/models/text_command.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; class const BotCommandPanel( final ComposerParams composer, { diff --git a/lib/widgets/composer/composer.dart b/lib/widgets/composer/composer.dart index 1b70ec3..4c3caf6 100644 --- a/lib/widgets/composer/composer.dart +++ b/lib/widgets/composer/composer.dart @@ -17,7 +17,7 @@ import "package:nexus/models/composer_params.dart"; import "package:nexus/models/text_command.dart"; import "package:nexus/widgets/composer/bot_command_form.dart"; import "package:nexus/widgets/composer/bot_command_panel.dart"; -import "package:nexus/widgets/emoji_picker.dart"; +import "package:nexus/widgets/emoji/emoji_picker.dart"; import "package:material_ui/material_ui.dart"; import "package:flutter/services.dart"; import "package:flutter_hooks/flutter_hooks.dart"; @@ -35,10 +35,10 @@ import "package:nexus/models/content/image_pack.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/content/poll_start.dart"; import "package:nexus/models/image_pack.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; -import "package:nexus/widgets/sticker_picker.dart"; -import "package:nexus/widgets/create_poll_sheet.dart"; -import "package:nexus/widgets/location_picker_sheet.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; +import "package:nexus/widgets/emoji/sticker_picker.dart"; +import "package:nexus/widgets/composer/create_poll_sheet.dart"; +import "package:nexus/widgets/location/location_picker_sheet.dart"; import "package:nexus/models/location.dart"; import "package:nexus/widgets/composer/overlays/tagger_overlay.dart"; import "package:nexus/widgets/composer/paste_files_action.dart"; diff --git a/lib/widgets/create_poll_sheet.dart b/lib/widgets/composer/create_poll_sheet.dart similarity index 100% rename from lib/widgets/create_poll_sheet.dart rename to lib/widgets/composer/create_poll_sheet.dart diff --git a/lib/widgets/composer/overlays/room_overlay.dart b/lib/widgets/composer/overlays/room_overlay.dart index f4778a8..c95db16 100644 --- a/lib/widgets/composer/overlays/room_overlay.dart +++ b/lib/widgets/composer/overlays/room_overlay.dart @@ -3,7 +3,7 @@ import "package:material_ui/material_ui.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/controllers/via.dart"; import "package:nexus/helpers/extensions/weighted_search.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; class const RoomOverlay( final String query, { diff --git a/lib/widgets/composer/overlays/tagger_overlay.dart b/lib/widgets/composer/overlays/tagger_overlay.dart index 7d973dc..f760e01 100644 --- a/lib/widgets/composer/overlays/tagger_overlay.dart +++ b/lib/widgets/composer/overlays/tagger_overlay.dart @@ -3,7 +3,7 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/widgets/composer/overlays/room_overlay.dart"; import "package:nexus/widgets/composer/overlays/user_overlay.dart"; import "package:nexus/widgets/composer/overlays/emoji_overlay.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/loading.dart"; class const TaggerOverlay( final String query, { diff --git a/lib/widgets/composer/overlays/user_overlay.dart b/lib/widgets/composer/overlays/user_overlay.dart index e6f122b..eec15f5 100644 --- a/lib/widgets/composer/overlays/user_overlay.dart +++ b/lib/widgets/composer/overlays/user_overlay.dart @@ -5,7 +5,7 @@ import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/weighted_search.dart"; import "package:nexus/models/content/membership.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; class const UserOverlay( final String query, { diff --git a/lib/widgets/composer/relation_preview.dart b/lib/widgets/composer/relation_preview.dart index 5af01ee..f319d74 100644 --- a/lib/widgets/composer/relation_preview.dart +++ b/lib/widgets/composer/relation_preview.dart @@ -2,7 +2,7 @@ import "package:material_ui/material_ui.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/models/event.dart"; import "package:nexus/models/relation_type.dart"; -import "package:nexus/widgets/event_preview.dart"; +import "package:nexus/widgets/renderers/event_preview.dart"; class const RelationPreview( final Event? relatedEvent, { diff --git a/lib/widgets/composer/typing_indicator.dart b/lib/widgets/composer/typing_indicator.dart index 9624937..9cacb9c 100644 --- a/lib/widgets/composer/typing_indicator.dart +++ b/lib/widgets/composer/typing_indicator.dart @@ -5,8 +5,8 @@ import "package:nexus/controllers/room_typing.dart"; import "package:nexus/controllers/user.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/hooks/tap_recognizer.dart"; -import "package:nexus/widgets/bouncing_dots.dart"; -import "package:nexus/widgets/user_span.dart"; +import "package:nexus/widgets/common/bouncing_dots.dart"; +import "package:nexus/widgets/users/user_span.dart"; class const TypingIndicator(final String roomId, {super.key}) extends HookConsumerWidget { diff --git a/lib/widgets/emoji_picker.dart b/lib/widgets/emoji/emoji_picker.dart similarity index 100% rename from lib/widgets/emoji_picker.dart rename to lib/widgets/emoji/emoji_picker.dart diff --git a/lib/widgets/mxc_emoji.dart b/lib/widgets/emoji/mxc_emoji.dart similarity index 100% rename from lib/widgets/mxc_emoji.dart rename to lib/widgets/emoji/mxc_emoji.dart diff --git a/lib/widgets/sticker_picker.dart b/lib/widgets/emoji/sticker_picker.dart similarity index 100% rename from lib/widgets/sticker_picker.dart rename to lib/widgets/emoji/sticker_picker.dart diff --git a/lib/widgets/recovery_key_sheet.dart b/lib/widgets/encryption/recovery_key_sheet.dart similarity index 100% rename from lib/widgets/recovery_key_sheet.dart rename to lib/widgets/encryption/recovery_key_sheet.dart diff --git a/lib/widgets/reset_encryption_sheet.dart b/lib/widgets/encryption/reset_encryption_sheet.dart similarity index 99% rename from lib/widgets/reset_encryption_sheet.dart rename to lib/widgets/encryption/reset_encryption_sheet.dart index c223b37..40b0074 100644 --- a/lib/widgets/reset_encryption_sheet.dart +++ b/lib/widgets/encryption/reset_encryption_sheet.dart @@ -6,7 +6,7 @@ import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; import "package:nexus/main.dart"; import "package:nexus/models/client_state.dart"; -import "package:nexus/widgets/recovery_key_sheet.dart"; +import "package:nexus/widgets/encryption/recovery_key_sheet.dart"; class const ResetEncryptionSheet({ /// Whether this is shown as a page rather than in a sheet, in which case it diff --git a/lib/widgets/html/html.dart b/lib/widgets/html/html.dart index d717a8a..9236e9a 100644 --- a/lib/widgets/html/html.dart +++ b/lib/widgets/html/html.dart @@ -6,7 +6,7 @@ import "package:html/dom.dart" as dom; import "package:nexus/helpers/extensions/get_link_info.dart"; import "package:nexus/helpers/launch_helper.dart"; import "package:nexus/helpers/mxc_image.dart"; -import "package:nexus/widgets/expandable_image.dart"; +import "package:nexus/widgets/common/expandable_image.dart"; import "package:nexus/widgets/html/mention_chip.dart"; import "package:nexus/widgets/html/spoiler_text.dart"; import "package:nexus/widgets/html/code_block.dart"; diff --git a/lib/widgets/lazy_loading/message_avatar.dart b/lib/widgets/lazy_loading/message_avatar.dart index 0279eca..95f987f 100644 --- a/lib/widgets/lazy_loading/message_avatar.dart +++ b/lib/widgets/lazy_loading/message_avatar.dart @@ -4,7 +4,7 @@ import "package:nexus/controllers/author.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/show_user_popover.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; class const MessageAvatar( final Event event, { diff --git a/lib/widgets/location_map.dart b/lib/widgets/location/location_map.dart similarity index 100% rename from lib/widgets/location_map.dart rename to lib/widgets/location/location_map.dart diff --git a/lib/widgets/location_message.dart b/lib/widgets/location/location_message.dart similarity index 94% rename from lib/widgets/location_message.dart rename to lib/widgets/location/location_message.dart index 2f22b9d..661b7dd 100644 --- a/lib/widgets/location_message.dart +++ b/lib/widgets/location/location_message.dart @@ -2,8 +2,8 @@ import "package:material_ui/material_ui.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/location.dart"; -import "package:nexus/widgets/location_map.dart"; -import "package:nexus/widgets/location_viewer_sheet.dart"; +import "package:nexus/widgets/location/location_map.dart"; +import "package:nexus/widgets/location/location_viewer_sheet.dart"; class const LocationMessage(final LocationMessageContent content, {super.key}) extends StatelessWidget { diff --git a/lib/widgets/location_picker_sheet.dart b/lib/widgets/location/location_picker_sheet.dart similarity index 98% rename from lib/widgets/location_picker_sheet.dart rename to lib/widgets/location/location_picker_sheet.dart index 10b77ae..4fb61bf 100644 --- a/lib/widgets/location_picker_sheet.dart +++ b/lib/widgets/location/location_picker_sheet.dart @@ -7,7 +7,7 @@ import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/helpers/current_location_helper.dart"; import "package:nexus/models/content/message.dart"; import "package:nexus/models/location.dart"; -import "package:nexus/widgets/location_map.dart"; +import "package:nexus/widgets/location/location_map.dart"; /// Chooses a location to share, either the user's own or a pin dropped on the /// map. diff --git a/lib/widgets/location_viewer_sheet.dart b/lib/widgets/location/location_viewer_sheet.dart similarity index 95% rename from lib/widgets/location_viewer_sheet.dart rename to lib/widgets/location/location_viewer_sheet.dart index 48965bc..ca74ab0 100644 --- a/lib/widgets/location_viewer_sheet.dart +++ b/lib/widgets/location/location_viewer_sheet.dart @@ -4,7 +4,7 @@ import "package:material_ui/material_ui.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/helpers/launch_helper.dart"; import "package:nexus/models/location.dart"; -import "package:nexus/widgets/location_map.dart"; +import "package:nexus/widgets/location/location_map.dart"; class const LocationViewerSheet( final LatLng point, { diff --git a/lib/widgets/pages/chat.dart b/lib/widgets/pages/chat.dart index 53d3571..c5d704f 100644 --- a/lib/widgets/pages/chat.dart +++ b/lib/widgets/pages/chat.dart @@ -8,11 +8,11 @@ import "package:nexus/helpers/extensions/open_link_info.dart"; import "package:nexus/main.dart"; import "package:nexus/controllers/selected_room.dart"; import "package:nexus/controllers/notification_request.dart"; -import "package:nexus/widgets/appbar.dart"; -import "package:nexus/widgets/sidebar.dart"; -import "package:nexus/widgets/sync_status_banner.dart"; +import "package:nexus/widgets/common/appbar.dart"; +import "package:nexus/widgets/sidebar/sidebar.dart"; +import "package:nexus/widgets/common/sync_status_banner.dart"; import "package:nexus/widgets/room_chat/room_chat.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/loading.dart"; class const ChatPage({super.key}) extends HookConsumerWidget { @override diff --git a/lib/widgets/pages/explore.dart b/lib/widgets/pages/explore.dart index bc8ab2d..3cd77ea 100644 --- a/lib/widgets/pages/explore.dart +++ b/lib/widgets/pages/explore.dart @@ -14,14 +14,14 @@ import "package:nexus/controllers/settings.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/main.dart"; import "package:nexus/helpers/extensions/room_summary_display.dart"; -import "package:nexus/widgets/add_directory_server_sheet.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; -import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; -import "package:nexus/widgets/m3e_rail_theme.dart"; -import "package:nexus/widgets/room_directory_card.dart"; +import "package:nexus/widgets/rooms/add_directory_server_sheet.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; +import "package:nexus/widgets/common/divider_text.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; +import "package:nexus/widgets/common/m3e_rail_theme.dart"; +import "package:nexus/widgets/rooms/room_directory_card.dart"; class const ExplorePage({super.key}) extends HookConsumerWidget { @override diff --git a/lib/widgets/pages/select_server.dart b/lib/widgets/pages/select_server.dart index 1e20f32..a44e4b8 100644 --- a/lib/widgets/pages/select_server.dart +++ b/lib/widgets/pages/select_server.dart @@ -13,9 +13,9 @@ import "package:nexus/models/gomuks_exception.dart"; import "package:nexus/models/homeserver.dart"; import "package:nexus/models/oauth_auth_code_response.dart"; import "package:nexus/widgets/pages/settings.dart"; -import "package:nexus/widgets/account_switcher.dart"; -import "package:nexus/widgets/appbar.dart"; -import "package:nexus/widgets/divider_text.dart"; +import "package:nexus/widgets/common/account_switcher.dart"; +import "package:nexus/widgets/common/appbar.dart"; +import "package:nexus/widgets/common/divider_text.dart"; class const SelectServerPage({super.key}) extends HookConsumerWidget { @override diff --git a/lib/widgets/pages/settings_category.dart b/lib/widgets/pages/settings_category.dart index 69513b8..0efa68e 100644 --- a/lib/widgets/pages/settings_category.dart +++ b/lib/widgets/pages/settings_category.dart @@ -8,7 +8,7 @@ import "package:hooks_riverpod/misc.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:nexus/models/settings_category.dart"; import "package:nexus/helpers/extensions/better_when.dart"; -import "package:nexus/widgets/highlight_wrapper.dart"; +import "package:nexus/widgets/common/highlight_wrapper.dart"; import "package:super_sliver_list/super_sliver_list.dart"; class const SettingsCategoryPage( diff --git a/lib/widgets/pages/verify.dart b/lib/widgets/pages/verify.dart index 6cf935d..aa342cd 100644 --- a/lib/widgets/pages/verify.dart +++ b/lib/widgets/pages/verify.dart @@ -5,12 +5,12 @@ import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/client_state.dart"; import "package:nexus/models/client_state.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:nexus/widgets/pages/settings.dart"; -import "package:nexus/widgets/account_switcher.dart"; -import "package:nexus/widgets/appbar.dart"; +import "package:nexus/widgets/common/account_switcher.dart"; +import "package:nexus/widgets/common/appbar.dart"; import "package:nexus/helpers/required_validator_helper.dart"; -import "package:nexus/widgets/reset_encryption_sheet.dart"; +import "package:nexus/widgets/encryption/reset_encryption_sheet.dart"; class const VerifyPage({super.key}) extends HookConsumerWidget { @override diff --git a/lib/widgets/reaction_key.dart b/lib/widgets/reactions/reaction_key.dart similarity index 100% rename from lib/widgets/reaction_key.dart rename to lib/widgets/reactions/reaction_key.dart diff --git a/lib/widgets/reaction_row.dart b/lib/widgets/reactions/reaction_row.dart similarity index 96% rename from lib/widgets/reaction_row.dart rename to lib/widgets/reactions/reaction_row.dart index ecf1f9e..6020358 100644 --- a/lib/widgets/reaction_row.dart +++ b/lib/widgets/reactions/reaction_row.dart @@ -7,9 +7,9 @@ import "package:nexus/controllers/reactions.dart"; import "package:nexus/controllers/room_chat.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/reaction_key.dart"; -import "package:nexus/widgets/reactions_popover.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/reactions/reaction_key.dart"; +import "package:nexus/widgets/reactions/reactions_popover.dart"; import "package:nexus/main.dart"; import "package:fast_immutable_collections/fast_immutable_collections.dart"; diff --git a/lib/widgets/reactions_popover.dart b/lib/widgets/reactions/reactions_popover.dart similarity index 97% rename from lib/widgets/reactions_popover.dart rename to lib/widgets/reactions/reactions_popover.dart index 01f2efa..0c7660b 100644 --- a/lib/widgets/reactions_popover.dart +++ b/lib/widgets/reactions/reactions_popover.dart @@ -10,9 +10,9 @@ import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/show_user_popover.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; import "package:nexus/helpers/extensions/show_image_viewer.dart"; -import "package:nexus/widgets/reaction_key.dart"; +import "package:nexus/widgets/reactions/reaction_key.dart"; /// Every reaction to an event in tabs, each listing who reacted with it. class const ReactionsPopover( diff --git a/lib/widgets/read_receipts_row.dart b/lib/widgets/read_receipts/read_receipts_row.dart similarity index 96% rename from lib/widgets/read_receipts_row.dart rename to lib/widgets/read_receipts/read_receipts_row.dart index fb20e3d..156d3f8 100644 --- a/lib/widgets/read_receipts_row.dart +++ b/lib/widgets/read_receipts/read_receipts_row.dart @@ -8,9 +8,9 @@ import "package:nexus/controllers/room_chat.dart"; import "package:nexus/controllers/user.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/show_user_popover.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/avatar_ring.dart"; -import "package:nexus/widgets/read_receipts_sheet.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_ring.dart"; +import "package:nexus/widgets/read_receipts/read_receipts_sheet.dart"; class const ReadReceiptsRow( final String eventId, { diff --git a/lib/widgets/read_receipts_sheet.dart b/lib/widgets/read_receipts/read_receipts_sheet.dart similarity index 96% rename from lib/widgets/read_receipts_sheet.dart rename to lib/widgets/read_receipts/read_receipts_sheet.dart index 135e3fb..3021102 100644 --- a/lib/widgets/read_receipts_sheet.dart +++ b/lib/widgets/read_receipts/read_receipts_sheet.dart @@ -6,7 +6,7 @@ import "package:nexus/controllers/room_chat.dart"; import "package:nexus/controllers/user.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/show_user_popover.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; /// Everyone who has read up to an event, kept up to date while open. class const ReadReceiptsSheet( diff --git a/lib/widgets/renderers/change_line.dart b/lib/widgets/renderers/diffs/change_line.dart similarity index 100% rename from lib/widgets/renderers/change_line.dart rename to lib/widgets/renderers/diffs/change_line.dart diff --git a/lib/widgets/renderers/join_rules_diff.dart b/lib/widgets/renderers/diffs/join_rules_diff.dart similarity index 97% rename from lib/widgets/renderers/join_rules_diff.dart rename to lib/widgets/renderers/diffs/join_rules_diff.dart index 6d41c0b..1698aa0 100644 --- a/lib/widgets/renderers/join_rules_diff.dart +++ b/lib/widgets/renderers/diffs/join_rules_diff.dart @@ -5,7 +5,7 @@ import "package:nexus/controllers/rooms.dart"; import "package:nexus/helpers/extensions/join_rule_name.dart"; import "package:nexus/helpers/extensions/success_scheme.dart"; import "package:nexus/models/content/join_rules.dart"; -import "package:nexus/widgets/renderers/change_line.dart"; +import "package:nexus/widgets/renderers/diffs/change_line.dart"; /// The join rule a join rules event changed to, and for restricted rooms, the /// rooms whose members it let join, or stopped letting join. diff --git a/lib/widgets/renderers/pinned_events_diff.dart b/lib/widgets/renderers/diffs/pinned_events_diff.dart similarity index 100% rename from lib/widgets/renderers/pinned_events_diff.dart rename to lib/widgets/renderers/diffs/pinned_events_diff.dart diff --git a/lib/widgets/renderers/power_levels_diff.dart b/lib/widgets/renderers/diffs/power_levels_diff.dart similarity index 100% rename from lib/widgets/renderers/power_levels_diff.dart rename to lib/widgets/renderers/diffs/power_levels_diff.dart diff --git a/lib/widgets/renderers/server_acl_diff.dart b/lib/widgets/renderers/diffs/server_acl_diff.dart similarity index 97% rename from lib/widgets/renderers/server_acl_diff.dart rename to lib/widgets/renderers/diffs/server_acl_diff.dart index e232614..9364c04 100644 --- a/lib/widgets/renderers/server_acl_diff.dart +++ b/lib/widgets/renderers/diffs/server_acl_diff.dart @@ -2,7 +2,7 @@ import "package:fast_immutable_collections/fast_immutable_collections.dart"; import "package:material_ui/material_ui.dart"; import "package:nexus/helpers/extensions/success_scheme.dart"; import "package:nexus/models/content/server_acl.dart"; -import "package:nexus/widgets/renderers/change_line.dart"; +import "package:nexus/widgets/renderers/diffs/change_line.dart"; /// The servers newly denied (in red) and allowed (in green) by a server ACL /// event, and those no longer denied or allowed, struck through. diff --git a/lib/widgets/renderers/event.dart b/lib/widgets/renderers/event.dart index deff7f7..4e14fad 100644 --- a/lib/widgets/renderers/event.dart +++ b/lib/widgets/renderers/event.dart @@ -32,21 +32,21 @@ import "package:nexus/models/content/server_acl.dart"; import "package:nexus/models/content/tombstone.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/common/error_dialog.dart"; import "package:nexus/widgets/renderers/message.dart"; -import "package:nexus/widgets/reaction_row.dart"; -import "package:nexus/widgets/read_receipts_row.dart"; +import "package:nexus/widgets/reactions/reaction_row.dart"; +import "package:nexus/widgets/read_receipts/read_receipts_row.dart"; import "package:nexus/widgets/renderers/membership.dart"; -import "package:nexus/widgets/renderers/change_line.dart"; +import "package:nexus/widgets/renderers/diffs/change_line.dart"; import "package:nexus/widgets/renderers/generic_event.dart"; -import "package:nexus/widgets/renderers/join_rules_diff.dart"; -import "package:nexus/widgets/renderers/power_levels_diff.dart"; -import "package:nexus/widgets/renderers/pinned_events_diff.dart"; -import "package:nexus/widgets/renderers/server_acl_diff.dart"; -import "package:nexus/widgets/swipe_to_reply.dart"; -import "package:nexus/widgets/thread_summary.dart"; -import "package:nexus/widgets/timestamp.dart"; -import "package:nexus/widgets/user_span.dart"; +import "package:nexus/widgets/renderers/diffs/join_rules_diff.dart"; +import "package:nexus/widgets/renderers/diffs/power_levels_diff.dart"; +import "package:nexus/widgets/renderers/diffs/pinned_events_diff.dart"; +import "package:nexus/widgets/renderers/diffs/server_acl_diff.dart"; +import "package:nexus/widgets/renderers/swipe_to_reply.dart"; +import "package:nexus/widgets/threads/thread_summary.dart"; +import "package:nexus/widgets/common/timestamp.dart"; +import "package:nexus/widgets/users/user_span.dart"; class const EventRenderer( final int eventRowId, { diff --git a/lib/widgets/event_preview.dart b/lib/widgets/renderers/event_preview.dart similarity index 100% rename from lib/widgets/event_preview.dart rename to lib/widgets/renderers/event_preview.dart diff --git a/lib/widgets/file_card.dart b/lib/widgets/renderers/file_card.dart similarity index 100% rename from lib/widgets/file_card.dart rename to lib/widgets/renderers/file_card.dart diff --git a/lib/widgets/renderers/membership.dart b/lib/widgets/renderers/membership.dart index 17f8128..125ea64 100644 --- a/lib/widgets/renderers/membership.dart +++ b/lib/widgets/renderers/membership.dart @@ -6,7 +6,7 @@ import "package:nexus/helpers/hooks/tap_recognizer.dart"; import "package:nexus/models/content/membership.dart"; import "package:nexus/models/event.dart"; import "package:nexus/widgets/renderers/generic_event.dart"; -import "package:nexus/widgets/user_span.dart"; +import "package:nexus/widgets/users/user_span.dart"; class const MembershipRenderer( final Event event, { diff --git a/lib/widgets/renderers/message.dart b/lib/widgets/renderers/message.dart index 4e6a45a..40ee5e7 100644 --- a/lib/widgets/renderers/message.dart +++ b/lib/widgets/renderers/message.dart @@ -12,22 +12,22 @@ import "package:nexus/models/location.dart"; import "package:nexus/models/content/poll_start.dart"; import "package:nexus/models/content/sticker.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/file_card.dart"; +import "package:nexus/widgets/renderers/file_card.dart"; import "package:nexus/widgets/html/html.dart"; import "package:nexus/widgets/lazy_loading/message_avatar.dart"; import "package:nexus/widgets/lazy_loading/message_displayname.dart"; -import "package:nexus/widgets/linkified_text.dart"; -import "package:nexus/widgets/location_message.dart"; -import "package:nexus/widgets/loading.dart"; -import "package:nexus/widgets/message_image.dart"; -import "package:nexus/widgets/reaction_row.dart"; -import "package:nexus/widgets/timestamp.dart"; -import "package:nexus/widgets/url_preview.dart"; -import "package:nexus/widgets/event_preview.dart"; +import "package:nexus/widgets/common/linkified_text.dart"; +import "package:nexus/widgets/location/location_message.dart"; +import "package:nexus/widgets/common/loading.dart"; +import "package:nexus/widgets/renderers/message_image.dart"; +import "package:nexus/widgets/reactions/reaction_row.dart"; +import "package:nexus/widgets/common/timestamp.dart"; +import "package:nexus/widgets/renderers/url_preview.dart"; +import "package:nexus/widgets/renderers/event_preview.dart"; import "package:nexus/widgets/players/video.dart"; import "package:nexus/widgets/players/audio.dart"; import "package:nexus/widgets/renderers/poll.dart"; -import "package:nexus/widgets/thread_summary.dart"; +import "package:nexus/widgets/threads/thread_summary.dart"; class const MessageRenderer( final Event event, { diff --git a/lib/widgets/message_image.dart b/lib/widgets/renderers/message_image.dart similarity index 94% rename from lib/widgets/message_image.dart rename to lib/widgets/renderers/message_image.dart index c0dfa87..a8c44e3 100644 --- a/lib/widgets/message_image.dart +++ b/lib/widgets/renderers/message_image.dart @@ -4,8 +4,8 @@ import "package:flutter_riverpod/flutter_riverpod.dart"; import "package:nexus/helpers/mxc_image.dart"; import "package:nexus/models/info/image.dart" as i; import "package:nexus/models/requests/download_media.dart"; -import "package:nexus/widgets/expandable_image.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/expandable_image.dart"; +import "package:nexus/widgets/common/loading.dart"; final class const MessageImage( final Uri url, { diff --git a/lib/widgets/renderers/poll.dart b/lib/widgets/renderers/poll.dart index d3a8cb0..1f738b5 100644 --- a/lib/widgets/renderers/poll.dart +++ b/lib/widgets/renderers/poll.dart @@ -15,7 +15,7 @@ import "package:nexus/helpers/extensions/event_id_is_fake.dart"; import "package:nexus/main.dart"; import "package:nexus/models/content/poll_start.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/poll_option.dart"; +import "package:nexus/widgets/renderers/poll_option.dart"; class const PollRenderer(final Event event, final PollStart poll, {super.key}) extends HookConsumerWidget { diff --git a/lib/widgets/poll_option.dart b/lib/widgets/renderers/poll_option.dart similarity index 100% rename from lib/widgets/poll_option.dart rename to lib/widgets/renderers/poll_option.dart diff --git a/lib/widgets/swipe_to_reply.dart b/lib/widgets/renderers/swipe_to_reply.dart similarity index 100% rename from lib/widgets/swipe_to_reply.dart rename to lib/widgets/renderers/swipe_to_reply.dart diff --git a/lib/widgets/url_preview.dart b/lib/widgets/renderers/url_preview.dart similarity index 100% rename from lib/widgets/url_preview.dart rename to lib/widgets/renderers/url_preview.dart diff --git a/lib/widgets/room_chat/chat_body.dart b/lib/widgets/room_chat/chat_body.dart index 239ae4b..3b5f752 100644 --- a/lib/widgets/room_chat/chat_body.dart +++ b/lib/widgets/room_chat/chat_body.dart @@ -13,10 +13,10 @@ import "package:nexus/main.dart"; import "package:nexus/models/event.dart"; import "package:nexus/widgets/composer/composer.dart"; import "package:nexus/widgets/composer/typing_indicator.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:nexus/widgets/room_chat/chat_timeline.dart"; -import "package:nexus/widgets/tombstone_banner.dart"; +import "package:nexus/widgets/room_chat/tombstone_banner.dart"; final class const ChatBody({ required final ChatParams chat, diff --git a/lib/widgets/room_chat/chat_timeline.dart b/lib/widgets/room_chat/chat_timeline.dart index 57388b9..d6aaef7 100644 --- a/lib/widgets/room_chat/chat_timeline.dart +++ b/lib/widgets/room_chat/chat_timeline.dart @@ -4,7 +4,7 @@ import "package:nexus/controllers/room_chat.dart"; import "package:nexus/helpers/hooks/chat_scroll.dart"; import "package:nexus/models/event.dart"; import "package:nexus/widgets/renderers/event.dart"; -import "package:nexus/widgets/highlight_wrapper.dart"; +import "package:nexus/widgets/common/highlight_wrapper.dart"; import "package:super_sliver_list/super_sliver_list.dart"; class const ChatTimeline({ diff --git a/lib/widgets/member_list.dart b/lib/widgets/room_chat/member_list.dart similarity index 97% rename from lib/widgets/member_list.dart rename to lib/widgets/room_chat/member_list.dart index 02cc0c6..bf86b9c 100644 --- a/lib/widgets/member_list.dart +++ b/lib/widgets/room_chat/member_list.dart @@ -11,10 +11,10 @@ import "package:nexus/helpers/extensions/show_user_popover.dart"; import "package:nexus/helpers/extensions/displayname_color.dart"; import "package:nexus/models/content/membership.dart"; import "package:nexus/models/membership_status.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/divider_text.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; class const MemberList(final String roomId, {super.key}) extends HookConsumerWidget { diff --git a/lib/widgets/pinned_events_drawer.dart b/lib/widgets/room_chat/pinned_events_drawer.dart similarity index 96% rename from lib/widgets/pinned_events_drawer.dart rename to lib/widgets/room_chat/pinned_events_drawer.dart index cff6ad6..1e0ab6a 100644 --- a/lib/widgets/pinned_events_drawer.dart +++ b/lib/widgets/room_chat/pinned_events_drawer.dart @@ -4,8 +4,8 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:nexus/controllers/pinned_events.dart"; import "package:nexus/helpers/hooks/chat_scroll.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:nexus/widgets/renderers/event.dart"; final class const PinnedEventsDrawer( diff --git a/lib/widgets/room_appbar.dart b/lib/widgets/room_chat/room_appbar.dart similarity index 87% rename from lib/widgets/room_appbar.dart rename to lib/widgets/room_chat/room_appbar.dart index 83a3278..14b9df5 100644 --- a/lib/widgets/room_appbar.dart +++ b/lib/widgets/room_chat/room_appbar.dart @@ -2,13 +2,13 @@ import "package:material_ui/material_ui.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/controllers/rooms.dart"; -import "package:nexus/widgets/appbar.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/count_badge.dart"; -import "package:nexus/widgets/room_menu_button.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; -import "package:nexus/widgets/room_title.dart"; -import "package:nexus/widgets/sidebar.dart"; +import "package:nexus/widgets/common/appbar.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/count_badge.dart"; +import "package:nexus/widgets/rooms/room_menu_button.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; +import "package:nexus/widgets/rooms/room_title.dart"; +import "package:nexus/widgets/sidebar/sidebar.dart"; final class const RoomAppbar({ required final String? roomId, diff --git a/lib/widgets/room_chat/room_chat.dart b/lib/widgets/room_chat/room_chat.dart index 0062450..929be84 100644 --- a/lib/widgets/room_chat/room_chat.dart +++ b/lib/widgets/room_chat/room_chat.dart @@ -10,13 +10,13 @@ import "package:nexus/controllers/room_chat.dart"; import "package:nexus/helpers/hooks/chat_composer.dart"; import "package:nexus/helpers/hooks/chat_scroll.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/pinned_events_drawer.dart"; -import "package:nexus/widgets/member_list.dart"; -import "package:nexus/widgets/room_appbar.dart"; -import "package:nexus/widgets/search_drawer.dart"; -import "package:nexus/widgets/sync_status_banner.dart"; -import "package:nexus/widgets/thread_drawer.dart"; -import "package:nexus/widgets/threads_drawer.dart"; +import "package:nexus/widgets/room_chat/pinned_events_drawer.dart"; +import "package:nexus/widgets/room_chat/member_list.dart"; +import "package:nexus/widgets/room_chat/room_appbar.dart"; +import "package:nexus/widgets/room_chat/search_drawer.dart"; +import "package:nexus/widgets/common/sync_status_banner.dart"; +import "package:nexus/widgets/threads/thread_drawer.dart"; +import "package:nexus/widgets/threads/threads_drawer.dart"; import "package:nexus/widgets/room_chat/chat_body.dart"; import "package:nexus/helpers/extensions/build_event_options.dart"; import "package:nexus/controllers/jump_request.dart"; diff --git a/lib/widgets/search_drawer.dart b/lib/widgets/room_chat/search_drawer.dart similarity index 98% rename from lib/widgets/search_drawer.dart rename to lib/widgets/room_chat/search_drawer.dart index 03418df..2905789 100644 --- a/lib/widgets/search_drawer.dart +++ b/lib/widgets/room_chat/search_drawer.dart @@ -6,8 +6,8 @@ import "package:nexus/controllers/event_search.dart"; import "package:nexus/helpers/hooks/chat_scroll.dart"; import "package:nexus/main.dart"; import "package:nexus/models/event.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:nexus/widgets/renderers/event.dart"; final class const SearchDrawer( diff --git a/lib/widgets/tombstone_banner.dart b/lib/widgets/room_chat/tombstone_banner.dart similarity index 100% rename from lib/widgets/tombstone_banner.dart rename to lib/widgets/room_chat/tombstone_banner.dart diff --git a/lib/widgets/room_list.dart b/lib/widgets/room_list.dart deleted file mode 100644 index bdbf9cd..0000000 --- a/lib/widgets/room_list.dart +++ /dev/null @@ -1,328 +0,0 @@ -import "dart:math"; - -import "package:fast_immutable_collections/fast_immutable_collections.dart"; -import "package:hooks_riverpod/hooks_riverpod.dart"; -import "package:material_ui/material_ui.dart"; -import "package:navigation_rail_m3e/navigation_rail_m3e.dart"; -import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; -import "package:nexus/helpers/extensions/get_all_child_rooms.dart"; -import "package:nexus/helpers/extensions/room_destinations.dart"; -import "package:nexus/widgets/account_switcher.dart"; -import "package:nexus/models/nav_page.dart"; -import "package:nexus/widgets/appbar.dart"; -import "package:nexus/widgets/room_title.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/create_room_sheet.dart"; -import "package:nexus/widgets/start_dm_sheet.dart"; -import "package:nexus/widgets/divider_widget.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/pages/explore.dart"; -import "package:nexus/widgets/pages/settings.dart"; -import "package:nexus/widgets/join_sheet.dart"; -import "package:nexus/widgets/m3e_rail_theme.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; -import "package:nexus/widgets/room_menu_button.dart"; -import "package:nexus/widgets/space_hierarchy_sheet.dart"; -import "package:nexus/controllers/key.dart"; -import "package:nexus/controllers/selected_room.dart"; -import "package:nexus/controllers/selected_space.dart"; -import "package:nexus/controllers/rooms.dart"; -import "package:nexus/controllers/spaces.dart"; - -class const RoomList({super.key}) extends ConsumerWidget implements NavPage { - @override - String get title => "Rooms"; - - @override - IconData get icon => Icons.list; - - @override - int? badgeCount(WidgetRef ref) { - final (notifications, hasUnread) = ref.watch( - RoomsController.provider.select( - (rooms) => rooms.values.fold( - (0, false), - (total, room) => ( - total.$1 + (room.metadata?.unreadNotifications ?? 0), - total.$2 || (room.metadata?.unreadMessages ?? 0) > 0, - ), - ), - ), - ); - - return notifications > 0 - ? notifications - : hasUnread - ? 0 - : null; - } - - @override - Widget build(BuildContext context, WidgetRef ref) { - final spacesAsync = ref.watch(SpacesController.provider); - if (spacesAsync.value == null) { - return switch (spacesAsync) { - AsyncError(:final error, :final stackTrace) => ErrorDialog( - error, - stackTrace, - ), - _ => const Center(child: CircularProgressIndicator()), - }; - } - - return const Row( - children: [ - SpacesRail(), - Expanded(child: RoomsPane()), - ], - ); - } -} - -class const SpacesRail({super.key}) extends ConsumerWidget { - @override - Widget build(BuildContext context, WidgetRef ref) { - final spaces = ref.watch( - SpacesController.provider.select((async) => async.requireValue), - ); - final selectedSpaceId = ref.watch( - KeyController.provider(KeyController.spaceKey) - .select((async) => async.requireValue), - ); - - return M3ERailTheme( - extensions: [ - NavigationRailM3ETheme(itemCollapsedHeight: 48, itemVerticalGap: 0), - ], - builder: (context) => Container( - color: NavigationRailTokensAdapter(context).containerColor, - padding: .only(top: 16), - child: NavigationRailM3E( - type: .alwaysCollapse, - labelBehavior: .alwaysHide, - scrollable: true, - onDestinationSelected: (value) { - ref - .read(KeyController.provider(KeyController.spaceKey).notifier) - .set(spaces[value].id); - ref - .read(KeyController.provider(KeyController.roomKey).notifier) - .set(spaces[value].children.firstOrNull?.metadata?.id); - }, - sections: [ - .new( - destinations: spaces.map((space) { - final notifications = space.allChildRooms.fold( - 0, - (sum, room) => - sum + (room.metadata?.unreadNotifications ?? 0), - ); - - return NavigationRailM3EDestination( - badgeCount: notifications > 0 - ? notifications - : space.allChildRooms.any( - (room) => room.metadata?.unreadMessages != 0, - ) - ? 0 - : null, - short: true, - icon: AvatarOrHash( - dimension: 28, - space.room?.metadata?.avatar, - fallback: space.icon == null ? null : Icon(space.icon), - space.title, - ), - label: space.title, - ); - }).toList(), - ), - ], - selectedIndex: max( - 0, - spaces.indexWhere((space) => space.id == selectedSpaceId), - ), - trailingAtBottom: true, - trailing: Padding( - padding: .only(top: 8), - child: Column( - children: [ - AdaptiveMenuButton( - tooltip: "Add a room", - itemBuilder: (_) => [ - PopupMenuItem( - onTap: () => - context.showAdaptiveSheet((_) => JoinSheet(ref)), - child: const ListTile( - title: Text("Join an existing room (or space)"), - leading: Icon(Icons.numbers), - ), - ), - PopupMenuItem( - onTap: () => context.showAdaptiveSheet( - (_) => const CreateRoomSheet(), - ), - child: const ListTile( - title: Text("Create a new room (or space)"), - leading: Icon(Icons.add), - ), - ), - PopupMenuItem( - onTap: () => context.showAdaptiveSheet( - (_) => const StartDmSheet(), - ), - child: const ListTile( - title: Text("Start a direct message"), - leading: Icon(Icons.person_add), - ), - ), - ], - icon: const Icon(Icons.add), - ), - const AccountSwitcher(), - IconButton( - tooltip: "Explore other rooms", - onPressed: () => Navigator.of(context).push( - MaterialPageRoute(builder: (_) => const ExplorePage()), - ), - icon: const Icon(Icons.explore), - ), - IconButton( - tooltip: "Open settings", - onPressed: () => showDialog( - context: context, - builder: (_) => SettingsPage(), - ), - icon: const Icon(Icons.settings), - ), - ], - ), - ), - ), - ), - ); - } -} - -class const RoomsPane({super.key}) extends ConsumerWidget { - @override - Widget build(BuildContext context, WidgetRef ref) { - final selectedRoomId = ref.watch(SelectedRoomController.provider); - final selectedSpace = ref.watch(SelectedSpaceController.provider)!; - final isDm = selectedSpace.id == "dms"; - final spaceMetadata = selectedSpace.room?.metadata; - // In the order the rail shows them, with the space's own timeline first - final destinationIds = IList([?spaceMetadata?.id]) - .addAll(selectedSpace.allChildRooms.map((room) => room.metadata?.id)); - - return Scaffold( - backgroundColor: Colors.transparent, - appBar: Appbar( - // Home and DMs aren't real spaces, so they don't have a summary. - onTap: spaceMetadata == null - ? null - : () => context.showAdaptiveSheet( - (_) => RoomSummarySheet(.fromMetadata(spaceMetadata)), - ), - windowControls: false, - leading: AvatarOrHash( - spaceMetadata?.avatar, - fallback: selectedSpace.icon == null - ? null - : Icon(selectedSpace.icon), - selectedSpace.title, - ), - title: RoomTitle(selectedSpace.title, topic: spaceMetadata?.topic), - backgroundColor: Colors.transparent, - actions: .new([ - RoomMenuButton( - selectedSpace.room, - children: selectedSpace.allChildRooms, - ), - ]), - ), - body: M3ERailTheme( - extensions: [ - NavigationRailM3ETheme( - itemExpandedHeight: 48, - iconLabelGap: 16, - sectionHeaderSpacingTop: 0, - ), - ], - builder: (context) => Padding( - padding: const .only(top: 4), - child: NavigationRailM3E( - fab: selectedSpace.room == null - ? null - : .new( - icon: const Icon(Icons.explore), - label: "Browse space", - tooltip: "Browse and join rooms in this space", - onPressed: () => context.showAdaptiveSheet( - (_) => SpaceHierarchySheet(selectedSpace.id), - ), - ), - expandedWidth: double.infinity, - scrollable: true, - background: Colors.transparent, - type: .alwaysExpand, - selectedIndex: max(0, destinationIds.indexOf(selectedRoomId)), - sections: [ - if (selectedSpace.room case final room? - when spaceMetadata != null) - .new( - destinations: [ - room.toDestination( - isDm: isDm, - label: "Space timeline", - icon: const Icon(Icons.forum), - ), - ], - ), - .new( - header: selectedSpace.room == null - ? null - : const DividerWidget(Text("Rooms")), - destinations: selectedSpace.children.toDestinations(isDm: isDm), - ), - ...selectedSpace.subSpaces.map( - (subSpace) => NavigationRailM3ESection( - header: DividerWidget( - Row( - mainAxisSize: .min, - spacing: 8, - children: [ - if (subSpace.room.metadata?.avatar != null) - AvatarOrHash( - subSpace.room.metadata?.avatar, - subSpace.room.metadata?.name ?? "Unnamed Room", - dimension: 16, - ), - Flexible( - child: Text( - subSpace.room.metadata?.name ?? "Unnamed Space", - maxLines: 1, - overflow: .ellipsis, - ), - ), - ], - ), - ), - destinations: subSpace.children.toDestinations(isDm: isDm), - ), - ), - ], - onDestinationSelected: (value) { - ref - .read(KeyController.provider(KeyController.roomKey).notifier) - .set(destinationIds[value]); - if (Navigator.of(context).canPop()) { - Navigator.of(context).pop(); - } - }, - ), - ), - ), - ); - } -} diff --git a/lib/widgets/add_directory_server_sheet.dart b/lib/widgets/rooms/add_directory_server_sheet.dart similarity index 100% rename from lib/widgets/add_directory_server_sheet.dart rename to lib/widgets/rooms/add_directory_server_sheet.dart diff --git a/lib/widgets/add_space_rooms_sheet.dart b/lib/widgets/rooms/add_space_rooms_sheet.dart similarity index 99% rename from lib/widgets/add_space_rooms_sheet.dart rename to lib/widgets/rooms/add_space_rooms_sheet.dart index b6d8767..e78ba7a 100644 --- a/lib/widgets/add_space_rooms_sheet.dart +++ b/lib/widgets/rooms/add_space_rooms_sheet.dart @@ -14,7 +14,7 @@ import "package:nexus/helpers/extensions/with_progress_snackbar.dart"; import "package:nexus/main.dart"; import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/space_child.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; import "package:nexus/widgets/settings/search_chooser.dart"; /// Chooses rooms to add to the space [spaceId], then adds them. diff --git a/lib/widgets/create_room_sheet.dart b/lib/widgets/rooms/create_room_sheet.dart similarity index 100% rename from lib/widgets/create_room_sheet.dart rename to lib/widgets/rooms/create_room_sheet.dart diff --git a/lib/widgets/join_sheet.dart b/lib/widgets/rooms/join_sheet.dart similarity index 96% rename from lib/widgets/join_sheet.dart rename to lib/widgets/rooms/join_sheet.dart index 8977814..e9ee719 100644 --- a/lib/widgets/join_sheet.dart +++ b/lib/widgets/rooms/join_sheet.dart @@ -4,7 +4,7 @@ import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/controllers/room_summary.dart"; import "package:nexus/helpers/extensions/get_link_info.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; class const JoinSheet(final WidgetRef ref, {super.key}) extends HookWidget { @override diff --git a/lib/widgets/knock_sheet.dart b/lib/widgets/rooms/knock_sheet.dart similarity index 100% rename from lib/widgets/knock_sheet.dart rename to lib/widgets/rooms/knock_sheet.dart diff --git a/lib/widgets/room_directory_card.dart b/lib/widgets/rooms/room_directory_card.dart similarity index 96% rename from lib/widgets/room_directory_card.dart rename to lib/widgets/rooms/room_directory_card.dart index e8d8bfc..10cc071 100644 --- a/lib/widgets/room_directory_card.dart +++ b/lib/widgets/rooms/room_directory_card.dart @@ -8,9 +8,9 @@ import "package:nexus/helpers/extensions/focus_room.dart"; import "package:nexus/helpers/extensions/join_room.dart"; import "package:nexus/helpers/extensions/room_summary_display.dart"; import "package:nexus/models/room_summary.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/knock_sheet.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/rooms/knock_sheet.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; class const RoomDirectoryCard( final RoomSummary summary, { diff --git a/lib/widgets/room_menu_button.dart b/lib/widgets/rooms/room_menu_button.dart similarity index 100% rename from lib/widgets/room_menu_button.dart rename to lib/widgets/rooms/room_menu_button.dart diff --git a/lib/widgets/room_summary_sheet.dart b/lib/widgets/rooms/room_summary_sheet.dart similarity index 96% rename from lib/widgets/room_summary_sheet.dart rename to lib/widgets/rooms/room_summary_sheet.dart index 5579e59..2195101 100644 --- a/lib/widgets/room_summary_sheet.dart +++ b/lib/widgets/rooms/room_summary_sheet.dart @@ -9,10 +9,10 @@ import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/helpers/extensions/join_room.dart"; import "package:nexus/helpers/extensions/room_summary_display.dart"; import "package:nexus/main.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/expandable_image.dart"; -import "package:nexus/widgets/knock_sheet.dart"; -import "package:nexus/widgets/linkified_text.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/expandable_image.dart"; +import "package:nexus/widgets/rooms/knock_sheet.dart"; +import "package:nexus/widgets/common/linkified_text.dart"; import "package:nexus/models/room_summary.dart"; class const RoomSummarySheet( diff --git a/lib/widgets/room_title.dart b/lib/widgets/rooms/room_title.dart similarity index 100% rename from lib/widgets/room_title.dart rename to lib/widgets/rooms/room_title.dart diff --git a/lib/widgets/space_hierarchy_sheet.dart b/lib/widgets/rooms/space_hierarchy_sheet.dart similarity index 97% rename from lib/widgets/space_hierarchy_sheet.dart rename to lib/widgets/rooms/space_hierarchy_sheet.dart index 613c13c..65fb5da 100644 --- a/lib/widgets/space_hierarchy_sheet.dart +++ b/lib/widgets/rooms/space_hierarchy_sheet.dart @@ -17,12 +17,12 @@ import "package:nexus/main.dart"; import "package:nexus/models/content/content.dart"; import "package:nexus/models/content/create.dart"; import "package:nexus/models/space_hierarchy.dart"; -import "package:nexus/widgets/add_space_rooms_sheet.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/expandable_image.dart"; -import "package:nexus/widgets/knock_sheet.dart"; -import "package:nexus/widgets/loading.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; +import "package:nexus/widgets/rooms/add_space_rooms_sheet.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/expandable_image.dart"; +import "package:nexus/widgets/rooms/knock_sheet.dart"; +import "package:nexus/widgets/common/loading.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; class const SpaceHierarchySheet(final String spaceId, {super.key}) extends ConsumerWidget { diff --git a/lib/widgets/settings/allowed_rooms_sheet.dart b/lib/widgets/settings/allowed_rooms_sheet.dart index 8123c51..63aac8b 100644 --- a/lib/widgets/settings/allowed_rooms_sheet.dart +++ b/lib/widgets/settings/allowed_rooms_sheet.dart @@ -7,7 +7,7 @@ import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/controllers/client.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/main.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; import "package:nexus/widgets/settings/search_chooser.dart"; /// Chooses the rooms whose members can join [roomId] without an invite. diff --git a/lib/widgets/settings/enable_image_packs_sheet.dart b/lib/widgets/settings/enable_image_packs_sheet.dart index 9bc952f..427f7d8 100644 --- a/lib/widgets/settings/enable_image_packs_sheet.dart +++ b/lib/widgets/settings/enable_image_packs_sheet.dart @@ -8,8 +8,8 @@ import "package:nexus/controllers/room_image_packs.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/models/account_data.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/image_pack_avatar.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/image_pack_avatar.dart"; /// Chooses a room, then which of its image packs to use in every room. class const EnableImagePacksSheet({ diff --git a/lib/widgets/settings/image_pack_sheet.dart b/lib/widgets/settings/image_pack_sheet.dart index 2dd394e..d18d3f6 100644 --- a/lib/widgets/settings/image_pack_sheet.dart +++ b/lib/widgets/settings/image_pack_sheet.dart @@ -9,8 +9,8 @@ import "package:nexus/helpers/hooks/saving.dart"; import "package:nexus/main.dart"; import "package:nexus/models/content/image_pack.dart"; import "package:nexus/models/content/message.dart"; -import "package:nexus/widgets/image_pack_avatar.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; +import "package:nexus/widgets/avatars/image_pack_avatar.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; import "package:nexus/widgets/settings/image_usage_chips.dart"; import "package:nexus/widgets/settings/pack_image_sheet.dart"; diff --git a/lib/widgets/settings/member_chooser.dart b/lib/widgets/settings/member_chooser.dart index 18ed2e2..fbaaa8e 100644 --- a/lib/widgets/settings/member_chooser.dart +++ b/lib/widgets/settings/member_chooser.dart @@ -6,7 +6,7 @@ import "package:material_ui/material_ui.dart"; import "package:nexus/controllers/members.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; import "package:nexus/models/content/membership.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; import "package:nexus/widgets/settings/search_chooser.dart"; /// The [chosen] users, above a field searching [roomId]'s members, or taking a user ID, to choose more. diff --git a/lib/widgets/settings/pack_image_sheet.dart b/lib/widgets/settings/pack_image_sheet.dart index da17f38..89ed4f7 100644 --- a/lib/widgets/settings/pack_image_sheet.dart +++ b/lib/widgets/settings/pack_image_sheet.dart @@ -3,7 +3,7 @@ import "package:flutter_hooks/flutter_hooks.dart"; import "package:material_ui/material_ui.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/models/content/image_pack.dart"; -import "package:nexus/widgets/mxc_emoji.dart"; +import "package:nexus/widgets/emoji/mxc_emoji.dart"; import "package:nexus/widgets/settings/image_usage_chips.dart"; /// Edits an image in a pack, or only shows it if [onSave] is null. diff --git a/lib/widgets/settings/settings_layout.dart b/lib/widgets/settings/settings_layout.dart index 9741dcb..de20137 100644 --- a/lib/widgets/settings/settings_layout.dart +++ b/lib/widgets/settings/settings_layout.dart @@ -10,9 +10,9 @@ import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/weighted_search.dart"; import "package:nexus/models/settings_category.dart"; import "package:nexus/widgets/pages/settings_category.dart"; -import "package:nexus/widgets/divider_text.dart"; -import "package:nexus/widgets/highlight_wrapper.dart"; -import "package:nexus/widgets/m3e_rail_theme.dart"; +import "package:nexus/widgets/common/divider_text.dart"; +import "package:nexus/widgets/common/highlight_wrapper.dart"; +import "package:nexus/widgets/common/m3e_rail_theme.dart"; import "package:super_sliver_list/super_sliver_list.dart"; /// A settings screen split into categories: a list of them that opens each diff --git a/lib/widgets/sidebar/invite_card.dart b/lib/widgets/sidebar/invite_card.dart new file mode 100644 index 0000000..239d3c1 --- /dev/null +++ b/lib/widgets/sidebar/invite_card.dart @@ -0,0 +1,52 @@ +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:material_ui/material_ui.dart"; +import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; +import "package:nexus/controllers/invites.dart"; +import "package:nexus/helpers/extensions/get_localpart.dart"; +import "package:nexus/helpers/extensions/room_summary_display.dart"; +import "package:nexus/models/room_summary.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; + +class const InviteCard(final RoomSummary invite, {super.key}) + extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final responding = ref + .watch(InvitesController.respondMutation(invite.roomId)) + .isPending; + final name = invite.name ?? invite.canonicalAlias ?? invite.roomId; + final inviterName = + invite.inviterProfile?.displayName ?? invite.invitedBy?.localpart; + + return Card( + clipBehavior: .antiAlias, + child: ListTile( + onTap: responding + ? null + : () => context.showAdaptiveSheet((_) => RoomSummarySheet(invite)), + trailing: responding + ? const SizedBox.square( + dimension: 24, + child: CircularProgressIndicator(), + ) + : null, + leading: AvatarOrHash( + invite.avatarUrl, + name, + dimension: 40, + fallback: invite.isDirect ? null : Icon(invite.icon), + ), + title: Text(name, maxLines: 1, overflow: .ellipsis), + subtitle: Text( + [ + if (inviterName != null) + "${invite.isDirect ? "Direct message from" : "Invited by"} $inviterName", + ].join("\n"), + maxLines: 2, + overflow: .ellipsis, + ), + ), + ); + } +} diff --git a/lib/widgets/invites_list.dart b/lib/widgets/sidebar/invites_list.dart similarity index 63% rename from lib/widgets/invites_list.dart rename to lib/widgets/sidebar/invites_list.dart index 68d8b3b..18fb5f0 100644 --- a/lib/widgets/invites_list.dart +++ b/lib/widgets/sidebar/invites_list.dart @@ -1,14 +1,10 @@ +import "package:nexus/widgets/sidebar/invite_card.dart"; import "package:hooks_riverpod/hooks_riverpod.dart"; import "package:material_ui/material_ui.dart"; import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; import "package:nexus/controllers/invites.dart"; -import "package:nexus/helpers/extensions/get_localpart.dart"; -import "package:nexus/helpers/extensions/room_summary_display.dart"; import "package:nexus/main.dart"; import "package:nexus/models/nav_page.dart"; -import "package:nexus/models/room_summary.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; -import "package:nexus/widgets/room_summary_sheet.dart"; class const InvitesList({super.key}) extends ConsumerWidget implements NavPage { @override @@ -92,46 +88,3 @@ class const InvitesList({super.key}) extends ConsumerWidget implements NavPage { ); } } - -class const InviteCard(final RoomSummary invite, {super.key}) - extends ConsumerWidget { - @override - Widget build(BuildContext context, WidgetRef ref) { - final responding = ref - .watch(InvitesController.respondMutation(invite.roomId)) - .isPending; - final name = invite.name ?? invite.canonicalAlias ?? invite.roomId; - final inviterName = - invite.inviterProfile?.displayName ?? invite.invitedBy?.localpart; - - return Card( - clipBehavior: .antiAlias, - child: ListTile( - onTap: responding - ? null - : () => context.showAdaptiveSheet((_) => RoomSummarySheet(invite)), - trailing: responding - ? const SizedBox.square( - dimension: 24, - child: CircularProgressIndicator(), - ) - : null, - leading: AvatarOrHash( - invite.avatarUrl, - name, - dimension: 40, - fallback: invite.isDirect ? null : Icon(invite.icon), - ), - title: Text(name, maxLines: 1, overflow: .ellipsis), - subtitle: Text( - [ - if (inviterName != null) - "${invite.isDirect ? "Direct message from" : "Invited by"} $inviterName", - ].join("\n"), - maxLines: 2, - overflow: .ellipsis, - ), - ), - ); - } -} diff --git a/lib/widgets/notifications_list.dart b/lib/widgets/sidebar/notifications_list.dart similarity index 97% rename from lib/widgets/notifications_list.dart rename to lib/widgets/sidebar/notifications_list.dart index 23ff676..f52f944 100644 --- a/lib/widgets/notifications_list.dart +++ b/lib/widgets/sidebar/notifications_list.dart @@ -9,9 +9,9 @@ import "package:nexus/controllers/notifications.dart"; import "package:nexus/helpers/extensions/focus_room.dart"; import "package:nexus/models/event.dart"; import "package:nexus/models/nav_page.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/highlight_wrapper.dart"; -import "package:nexus/widgets/loading.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/highlight_wrapper.dart"; +import "package:nexus/widgets/common/loading.dart"; import "package:nexus/widgets/renderers/event.dart"; import "package:super_sliver_list/super_sliver_list.dart"; diff --git a/lib/widgets/sidebar/room_list.dart b/lib/widgets/sidebar/room_list.dart new file mode 100644 index 0000000..0e94cdb --- /dev/null +++ b/lib/widgets/sidebar/room_list.dart @@ -0,0 +1,59 @@ +import "package:nexus/widgets/sidebar/spaces_rail.dart"; +import "package:nexus/widgets/sidebar/rooms_pane.dart"; + +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:material_ui/material_ui.dart"; +import "package:nexus/models/nav_page.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/controllers/rooms.dart"; +import "package:nexus/controllers/spaces.dart"; + +class const RoomList({super.key}) extends ConsumerWidget implements NavPage { + @override + String get title => "Rooms"; + + @override + IconData get icon => Icons.list; + + @override + int? badgeCount(WidgetRef ref) { + final (notifications, hasUnread) = ref.watch( + RoomsController.provider.select( + (rooms) => rooms.values.fold( + (0, false), + (total, room) => ( + total.$1 + (room.metadata?.unreadNotifications ?? 0), + total.$2 || (room.metadata?.unreadMessages ?? 0) > 0, + ), + ), + ), + ); + + return notifications > 0 + ? notifications + : hasUnread + ? 0 + : null; + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final spacesAsync = ref.watch(SpacesController.provider); + if (spacesAsync.value == null) { + return switch (spacesAsync) { + AsyncError(:final error, :final stackTrace) => ErrorDialog( + error, + stackTrace, + ), + _ => const Center(child: CircularProgressIndicator()), + }; + } + + return const Row( + children: [ + SpacesRail(), + Expanded(child: RoomsPane()), + ], + ); + } +} diff --git a/lib/widgets/sidebar/rooms_pane.dart b/lib/widgets/sidebar/rooms_pane.dart new file mode 100644 index 0000000..aabebbb --- /dev/null +++ b/lib/widgets/sidebar/rooms_pane.dart @@ -0,0 +1,143 @@ +import "dart:math"; + +import "package:fast_immutable_collections/fast_immutable_collections.dart"; +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:material_ui/material_ui.dart"; +import "package:navigation_rail_m3e/navigation_rail_m3e.dart"; +import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; +import "package:nexus/helpers/extensions/get_all_child_rooms.dart"; +import "package:nexus/helpers/extensions/room_destinations.dart"; +import "package:nexus/widgets/common/appbar.dart"; +import "package:nexus/widgets/rooms/room_title.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/common/divider_widget.dart"; +import "package:nexus/widgets/common/m3e_rail_theme.dart"; +import "package:nexus/widgets/rooms/room_summary_sheet.dart"; +import "package:nexus/widgets/rooms/room_menu_button.dart"; +import "package:nexus/widgets/rooms/space_hierarchy_sheet.dart"; +import "package:nexus/controllers/key.dart"; +import "package:nexus/controllers/selected_room.dart"; +import "package:nexus/controllers/selected_space.dart"; + +class const RoomsPane({super.key}) extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final selectedRoomId = ref.watch(SelectedRoomController.provider); + final selectedSpace = ref.watch(SelectedSpaceController.provider)!; + final isDm = selectedSpace.id == "dms"; + final spaceMetadata = selectedSpace.room?.metadata; + // In the order the rail shows them, with the space's own timeline first + final destinationIds = IList([?spaceMetadata?.id]) + .addAll(selectedSpace.allChildRooms.map((room) => room.metadata?.id)); + + return Scaffold( + backgroundColor: Colors.transparent, + appBar: Appbar( + // Home and DMs aren't real spaces, so they don't have a summary. + onTap: spaceMetadata == null + ? null + : () => context.showAdaptiveSheet( + (_) => RoomSummarySheet(.fromMetadata(spaceMetadata)), + ), + windowControls: false, + leading: AvatarOrHash( + spaceMetadata?.avatar, + fallback: selectedSpace.icon == null + ? null + : Icon(selectedSpace.icon), + selectedSpace.title, + ), + title: RoomTitle(selectedSpace.title, topic: spaceMetadata?.topic), + backgroundColor: Colors.transparent, + actions: .new([ + RoomMenuButton( + selectedSpace.room, + children: selectedSpace.allChildRooms, + ), + ]), + ), + body: M3ERailTheme( + extensions: [ + NavigationRailM3ETheme( + itemExpandedHeight: 48, + iconLabelGap: 16, + sectionHeaderSpacingTop: 0, + ), + ], + builder: (context) => Padding( + padding: const .only(top: 4), + child: NavigationRailM3E( + fab: selectedSpace.room == null + ? null + : .new( + icon: const Icon(Icons.explore), + label: "Browse space", + tooltip: "Browse and join rooms in this space", + onPressed: () => context.showAdaptiveSheet( + (_) => SpaceHierarchySheet(selectedSpace.id), + ), + ), + expandedWidth: double.infinity, + scrollable: true, + background: Colors.transparent, + type: .alwaysExpand, + selectedIndex: max(0, destinationIds.indexOf(selectedRoomId)), + sections: [ + if (selectedSpace.room case final room? + when spaceMetadata != null) + .new( + destinations: [ + room.toDestination( + isDm: isDm, + label: "Space timeline", + icon: const Icon(Icons.forum), + ), + ], + ), + .new( + header: selectedSpace.room == null + ? null + : const DividerWidget(Text("Rooms")), + destinations: selectedSpace.children.toDestinations(isDm: isDm), + ), + ...selectedSpace.subSpaces.map( + (subSpace) => NavigationRailM3ESection( + header: DividerWidget( + Row( + mainAxisSize: .min, + spacing: 8, + children: [ + if (subSpace.room.metadata?.avatar != null) + AvatarOrHash( + subSpace.room.metadata?.avatar, + subSpace.room.metadata?.name ?? "Unnamed Room", + dimension: 16, + ), + Flexible( + child: Text( + subSpace.room.metadata?.name ?? "Unnamed Space", + maxLines: 1, + overflow: .ellipsis, + ), + ), + ], + ), + ), + destinations: subSpace.children.toDestinations(isDm: isDm), + ), + ), + ], + onDestinationSelected: (value) { + ref + .read(KeyController.provider(KeyController.roomKey).notifier) + .set(destinationIds[value]); + if (Navigator.of(context).canPop()) { + Navigator.of(context).pop(); + } + }, + ), + ), + ), + ); + } +} diff --git a/lib/widgets/sidebar.dart b/lib/widgets/sidebar/sidebar.dart similarity index 88% rename from lib/widgets/sidebar.dart rename to lib/widgets/sidebar/sidebar.dart index 3ed8daa..d8f98cb 100644 --- a/lib/widgets/sidebar.dart +++ b/lib/widgets/sidebar/sidebar.dart @@ -4,10 +4,10 @@ import "package:material_ui/material_ui.dart"; import "package:nexus/controllers/sidebar_page.dart"; import "package:nexus/models/nav_page.dart"; import "package:nexus/models/sidebar_page.dart"; -import "package:nexus/widgets/count_badge.dart"; -import "package:nexus/widgets/invites_list.dart"; -import "package:nexus/widgets/notifications_list.dart"; -import "package:nexus/widgets/room_list.dart"; +import "package:nexus/widgets/common/count_badge.dart"; +import "package:nexus/widgets/sidebar/invites_list.dart"; +import "package:nexus/widgets/sidebar/notifications_list.dart"; +import "package:nexus/widgets/sidebar/room_list.dart"; class const Sidebar({super.key}) extends ConsumerWidget { static NavPage pageFor(SidebarPage page) => switch (page) { diff --git a/lib/widgets/sidebar/spaces_rail.dart b/lib/widgets/sidebar/spaces_rail.dart new file mode 100644 index 0000000..d84a40a --- /dev/null +++ b/lib/widgets/sidebar/spaces_rail.dart @@ -0,0 +1,142 @@ +import "dart:math"; + +import "package:hooks_riverpod/hooks_riverpod.dart"; +import "package:material_ui/material_ui.dart"; +import "package:navigation_rail_m3e/navigation_rail_m3e.dart"; +import "package:material_adaptive_sheets/material_adaptive_sheets.dart"; +import "package:nexus/helpers/extensions/get_all_child_rooms.dart"; +import "package:nexus/widgets/common/account_switcher.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; +import "package:nexus/widgets/rooms/create_room_sheet.dart"; +import "package:nexus/widgets/users/start_dm_sheet.dart"; +import "package:nexus/widgets/pages/explore.dart"; +import "package:nexus/widgets/pages/settings.dart"; +import "package:nexus/widgets/rooms/join_sheet.dart"; +import "package:nexus/widgets/common/m3e_rail_theme.dart"; +import "package:nexus/controllers/key.dart"; +import "package:nexus/controllers/spaces.dart"; + +class const SpacesRail({super.key}) extends ConsumerWidget { + @override + Widget build(BuildContext context, WidgetRef ref) { + final spaces = ref.watch( + SpacesController.provider.select((async) => async.requireValue), + ); + final selectedSpaceId = ref.watch( + KeyController.provider(KeyController.spaceKey) + .select((async) => async.requireValue), + ); + + return M3ERailTheme( + extensions: [ + NavigationRailM3ETheme(itemCollapsedHeight: 48, itemVerticalGap: 0), + ], + builder: (context) => Container( + color: NavigationRailTokensAdapter(context).containerColor, + padding: .only(top: 16), + child: NavigationRailM3E( + type: .alwaysCollapse, + labelBehavior: .alwaysHide, + scrollable: true, + onDestinationSelected: (value) { + ref + .read(KeyController.provider(KeyController.spaceKey).notifier) + .set(spaces[value].id); + ref + .read(KeyController.provider(KeyController.roomKey).notifier) + .set(spaces[value].children.firstOrNull?.metadata?.id); + }, + sections: [ + .new( + destinations: spaces.map((space) { + final notifications = space.allChildRooms.fold( + 0, + (sum, room) => + sum + (room.metadata?.unreadNotifications ?? 0), + ); + + return NavigationRailM3EDestination( + badgeCount: notifications > 0 + ? notifications + : space.allChildRooms.any( + (room) => room.metadata?.unreadMessages != 0, + ) + ? 0 + : null, + short: true, + icon: AvatarOrHash( + dimension: 28, + space.room?.metadata?.avatar, + fallback: space.icon == null ? null : Icon(space.icon), + space.title, + ), + label: space.title, + ); + }).toList(), + ), + ], + selectedIndex: max( + 0, + spaces.indexWhere((space) => space.id == selectedSpaceId), + ), + trailingAtBottom: true, + trailing: Padding( + padding: .only(top: 8), + child: Column( + children: [ + AdaptiveMenuButton( + tooltip: "Add a room", + itemBuilder: (_) => [ + PopupMenuItem( + onTap: () => + context.showAdaptiveSheet((_) => JoinSheet(ref)), + child: const ListTile( + title: Text("Join an existing room (or space)"), + leading: Icon(Icons.numbers), + ), + ), + PopupMenuItem( + onTap: () => context.showAdaptiveSheet( + (_) => const CreateRoomSheet(), + ), + child: const ListTile( + title: Text("Create a new room (or space)"), + leading: Icon(Icons.add), + ), + ), + PopupMenuItem( + onTap: () => context.showAdaptiveSheet( + (_) => const StartDmSheet(), + ), + child: const ListTile( + title: Text("Start a direct message"), + leading: Icon(Icons.person_add), + ), + ), + ], + icon: const Icon(Icons.add), + ), + const AccountSwitcher(), + IconButton( + tooltip: "Explore other rooms", + onPressed: () => Navigator.of(context).push( + MaterialPageRoute(builder: (_) => const ExplorePage()), + ), + icon: const Icon(Icons.explore), + ), + IconButton( + tooltip: "Open settings", + onPressed: () => showDialog( + context: context, + builder: (_) => SettingsPage(), + ), + icon: const Icon(Icons.settings), + ), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/widgets/thread_drawer.dart b/lib/widgets/threads/thread_drawer.dart similarity index 100% rename from lib/widgets/thread_drawer.dart rename to lib/widgets/threads/thread_drawer.dart diff --git a/lib/widgets/thread_summary.dart b/lib/widgets/threads/thread_summary.dart similarity index 100% rename from lib/widgets/thread_summary.dart rename to lib/widgets/threads/thread_summary.dart diff --git a/lib/widgets/threads_drawer.dart b/lib/widgets/threads/threads_drawer.dart similarity index 96% rename from lib/widgets/threads_drawer.dart rename to lib/widgets/threads/threads_drawer.dart index a2ff127..e7931da 100644 --- a/lib/widgets/threads_drawer.dart +++ b/lib/widgets/threads/threads_drawer.dart @@ -4,10 +4,10 @@ import "package:nexus/controllers/thread_list.dart"; import "package:nexus/controllers/rooms.dart"; import "package:nexus/helpers/extensions/thread_events.dart"; import "package:nexus/main.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; -import "package:nexus/widgets/event_preview.dart"; -import "package:nexus/widgets/timestamp.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; +import "package:nexus/widgets/renderers/event_preview.dart"; +import "package:nexus/widgets/common/timestamp.dart"; final class const ThreadsDrawer( final String roomId, { diff --git a/lib/widgets/mutual_rooms_sheet.dart b/lib/widgets/users/mutual_rooms_sheet.dart similarity index 97% rename from lib/widgets/mutual_rooms_sheet.dart rename to lib/widgets/users/mutual_rooms_sheet.dart index 4c47577..16066b0 100644 --- a/lib/widgets/mutual_rooms_sheet.dart +++ b/lib/widgets/users/mutual_rooms_sheet.dart @@ -7,7 +7,7 @@ import "package:nexus/controllers/rooms.dart"; import "package:nexus/controllers/sidebar_page.dart"; import "package:nexus/helpers/extensions/better_when.dart"; import "package:nexus/helpers/extensions/focus_room.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; /// The rooms the user shares with [userId]. class const MutualRoomsSheet(final String userId, {super.key}) diff --git a/lib/widgets/start_dm_sheet.dart b/lib/widgets/users/start_dm_sheet.dart similarity index 100% rename from lib/widgets/start_dm_sheet.dart rename to lib/widgets/users/start_dm_sheet.dart diff --git a/lib/widgets/timezone_field.dart b/lib/widgets/users/timezone_field.dart similarity index 100% rename from lib/widgets/timezone_field.dart rename to lib/widgets/users/timezone_field.dart diff --git a/lib/widgets/user_bottom_sheet.dart b/lib/widgets/users/user_bottom_sheet.dart similarity index 97% rename from lib/widgets/user_bottom_sheet.dart rename to lib/widgets/users/user_bottom_sheet.dart index 373ed52..12e0e24 100644 --- a/lib/widgets/user_bottom_sheet.dart +++ b/lib/widgets/users/user_bottom_sheet.dart @@ -19,19 +19,19 @@ import "package:nexus/helpers/extensions/create_room.dart"; import "package:nexus/helpers/extensions/success_scheme.dart"; import "package:nexus/helpers/extensions/with_progress_snackbar.dart"; import "package:nexus/helpers/extensions/get_localpart.dart"; -import "package:nexus/widgets/error_dialog.dart"; -import "package:nexus/widgets/loading.dart"; -import "package:nexus/widgets/mutual_rooms_sheet.dart"; +import "package:nexus/widgets/common/error_dialog.dart"; +import "package:nexus/widgets/common/loading.dart"; +import "package:nexus/widgets/users/mutual_rooms_sheet.dart"; import "package:nexus/models/content/membership.dart"; import "package:nexus/models/membership_action.dart"; import "package:nexus/models/profile_response.dart"; -import "package:nexus/widgets/avatar_or_hash.dart"; +import "package:nexus/widgets/avatars/avatar_or_hash.dart"; import "package:nexus/main.dart"; -import "package:nexus/widgets/editable_avatar.dart"; -import "package:nexus/widgets/expandable_image.dart"; +import "package:nexus/widgets/avatars/editable_avatar.dart"; +import "package:nexus/widgets/common/expandable_image.dart"; import "package:nexus/widgets/settings/inline_text_field.dart"; -import "package:nexus/widgets/start_dm_sheet.dart"; -import "package:nexus/widgets/timezone_field.dart"; +import "package:nexus/widgets/users/start_dm_sheet.dart"; +import "package:nexus/widgets/users/timezone_field.dart"; final class const UserBottomSheet( final String userId, { diff --git a/lib/widgets/user_span.dart b/lib/widgets/users/user_span.dart similarity index 100% rename from lib/widgets/user_span.dart rename to lib/widgets/users/user_span.dart