diff --git a/packages/neon/neon/lib/src/models/app_implementation.dart b/packages/neon/neon/lib/src/models/app_implementation.dart index 7b0c628d..4ea33c1a 100644 --- a/packages/neon/neon/lib/src/models/app_implementation.dart +++ b/packages/neon/neon/lib/src/models/app_implementation.dart @@ -91,20 +91,23 @@ abstract class AppImplementation } Widget buildIcon({ - final Size size = const Size.square(32), + final double? size, final Color? color, }) => Builder( - builder: (final context) => VectorGraphic( - width: size.width, - height: size.height, - colorFilter: ColorFilter.mode(color ?? Theme.of(context).colorScheme.primary, BlendMode.srcIn), - loader: AssetBytesLoader( - 'assets/app.svg.vec', - packageName: 'neon_$id', - ), - semanticsLabel: AppLocalizations.of(context).nextcloudLogo, - ), + builder: (final context) { + final realSize = size ?? IconTheme.of(context).size; + return VectorGraphic( + width: realSize, + height: realSize, + colorFilter: ColorFilter.mode(color ?? Theme.of(context).colorScheme.primary, BlendMode.srcIn), + loader: AssetBytesLoader( + 'assets/app.svg.vec', + packageName: 'neon_$id', + ), + semanticsLabel: AppLocalizations.of(context).nextcloudLogo, + ); + }, ); @mustCallSuper diff --git a/packages/neon/neon/lib/src/pages/home.dart b/packages/neon/neon/lib/src/pages/home.dart index 5f9fad0e..a76f932a 100644 --- a/packages/neon/neon/lib/src/pages/home.dart +++ b/packages/neon/neon/lib/src/pages/home.dart @@ -14,11 +14,8 @@ import 'package:neon/src/widgets/app_bar.dart'; import 'package:neon/src/widgets/drawer.dart'; import 'package:neon/src/widgets/exception.dart'; import 'package:neon/src/widgets/unified_search_results.dart'; -import 'package:neon/src/widgets/user_avatar.dart'; import 'package:provider/provider.dart'; -const kQuickBarWidth = kAvatarSize + 20; - class HomePage extends StatefulWidget { const HomePage({ super.key, diff --git a/packages/neon/neon/lib/src/theme/sizes.dart b/packages/neon/neon/lib/src/theme/sizes.dart new file mode 100644 index 00000000..b5e6c9eb --- /dev/null +++ b/packages/neon/neon/lib/src/theme/sizes.dart @@ -0,0 +1,5 @@ +/// Used for large icons e.g. in the leading part of a ListTile. +const largeIconSize = 40.0; + +/// Use for small icons e.g. in the subtitle part of a ListTile. +const smallIconSize = 16.0; diff --git a/packages/neon/neon/lib/src/widgets/app_bar.dart b/packages/neon/neon/lib/src/widgets/app_bar.dart index 66782d4a..c6a15f39 100644 --- a/packages/neon/neon/lib/src/widgets/app_bar.dart +++ b/packages/neon/neon/lib/src/widgets/app_bar.dart @@ -13,7 +13,6 @@ import 'package:neon/src/widgets/account_switcher_button.dart'; import 'package:neon/src/widgets/app_implementation_icon.dart'; import 'package:neon/src/widgets/exception.dart'; import 'package:neon/src/widgets/linear_progress_indicator.dart'; -import 'package:neon/src/widgets/user_avatar.dart'; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart'; @@ -131,7 +130,6 @@ class _NeonAppBarState extends State { tooltip: AppLocalizations.of(context).searchCancel, icon: const Icon( Icons.close, - size: kAvatarSize * 2 / 3, ), ), ], @@ -164,7 +162,6 @@ class SearchIconButton extends StatelessWidget { tooltip: AppLocalizations.of(context).search, icon: const Icon( Icons.search, - size: kAvatarSize * 2 / 3, ), ); } @@ -269,7 +266,6 @@ class _NotificationIconButtonState extends State { color: unreadCount > 0 ? Theme.of(context).colorScheme.primary : Theme.of(context).colorScheme.onBackground, - size: const Size.square(kAvatarSize * 2 / 3), ), ); }, diff --git a/packages/neon/neon/lib/src/widgets/app_implementation_icon.dart b/packages/neon/neon/lib/src/widgets/app_implementation_icon.dart index 457f35b2..240584f7 100644 --- a/packages/neon/neon/lib/src/widgets/app_implementation_icon.dart +++ b/packages/neon/neon/lib/src/widgets/app_implementation_icon.dart @@ -1,7 +1,6 @@ import 'package:flutter/widgets.dart'; import 'package:meta/meta.dart'; import 'package:neon/src/models/app_implementation.dart'; -import 'package:neon/src/widgets/user_avatar.dart'; @internal class NeonAppImplementationIcon extends StatelessWidget { @@ -9,7 +8,7 @@ class NeonAppImplementationIcon extends StatelessWidget { required this.appImplementation, this.unreadCount = 0, this.color, - this.size = const Size.square(kAvatarSize), + this.size, super.key, }); @@ -19,7 +18,7 @@ class NeonAppImplementationIcon extends StatelessWidget { final Color? color; - final Size size; + final double? size; @override Widget build(final BuildContext context) => Stack( diff --git a/packages/neon/neon/lib/src/widgets/drawer_destination.dart b/packages/neon/neon/lib/src/widgets/drawer_destination.dart index 57e3bc62..ddc1e98b 100644 --- a/packages/neon/neon/lib/src/widgets/drawer_destination.dart +++ b/packages/neon/neon/lib/src/widgets/drawer_destination.dart @@ -1,10 +1,9 @@ import 'package:flutter/material.dart'; import 'package:meta/meta.dart'; -import 'package:neon/src/widgets/user_avatar.dart'; import 'package:rxdart/subjects.dart'; @internal -typedef DestinationIconBuilder = Widget Function({Size size, Color color}); +typedef DestinationIconBuilder = Widget Function({double? size, Color color}); @internal class NeonNavigationDestination { @@ -34,18 +33,17 @@ extension NavigationDestinationExtension on NavigationDestination { @internal extension NavigationRailDestinationExtension on NavigationRailDestination { static NavigationRailDestination fromNeonDestination(final NeonNavigationDestination neonDestination) { - final iconWIdget = StreamBuilder( + final iconWidget = StreamBuilder( stream: neonDestination.notificationCount, initialData: 0, builder: (final context, final snapshot) { final colorScheme = Theme.of(context).colorScheme; final color = snapshot.requireData > 0 ? colorScheme.primary : colorScheme.onBackground; - const size = Size.square(kAvatarSize * 2 / 3); final icon = Container( margin: const EdgeInsets.all(5), - child: neonDestination.icon(size: size, color: color), + child: neonDestination.icon(color: color), ); if (snapshot.requireData <= 0) { @@ -78,7 +76,7 @@ extension NavigationRailDestinationExtension on NavigationRailDestination { return NavigationRailDestination( label: Text(neonDestination.label), - icon: iconWIdget, + icon: iconWidget, selectedIcon: neonDestination.selectedIcon, ); } diff --git a/packages/neon/neon/lib/src/widgets/unified_search_results.dart b/packages/neon/neon/lib/src/widgets/unified_search_results.dart index a496380d..2404c45e 100644 --- a/packages/neon/neon/lib/src/widgets/unified_search_results.dart +++ b/packages/neon/neon/lib/src/widgets/unified_search_results.dart @@ -7,13 +7,13 @@ import 'package:neon/src/bloc/result_builder.dart'; import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/blocs/unified_search.dart'; import 'package:neon/src/models/account.dart'; +import 'package:neon/src/theme/sizes.dart'; import 'package:neon/src/widgets/cached_image.dart'; import 'package:neon/src/widgets/exception.dart'; import 'package:neon/src/widgets/image_wrapper.dart'; import 'package:neon/src/widgets/linear_progress_indicator.dart'; import 'package:neon/src/widgets/list_view.dart'; import 'package:neon/src/widgets/server_icon.dart'; -import 'package:neon/src/widgets/user_avatar.dart'; import 'package:nextcloud/nextcloud.dart'; import 'package:provider/provider.dart'; @@ -77,7 +77,7 @@ class NeonUnifiedSearchResults extends StatelessWidget { ListTile( leading: const Icon( Icons.close, - size: kAvatarSize, + size: largeIconSize, ), title: Text(AppLocalizations.of(context).searchNoResults), ), @@ -85,7 +85,7 @@ class NeonUnifiedSearchResults extends StatelessWidget { for (final entry in entries) ...[ ListTile( leading: NeonImageWrapper( - size: const Size.square(kAvatarSize), + size: const Size.square(largeIconSize), borderRadius: const BorderRadius.all(Radius.circular(8)), child: _buildThumbnail(context, accountsBloc.activeAccount.value!, entry), ), @@ -105,7 +105,7 @@ class NeonUnifiedSearchResults extends StatelessWidget { Widget _buildThumbnail(final BuildContext context, final Account account, final CoreUnifiedSearchResultEntry entry) { if (entry.thumbnailUrl.isNotEmpty) { return NeonCachedImage.url( - size: const Size.square(kAvatarSize), + size: const Size.square(largeIconSize), url: entry.thumbnailUrl, account: account, // The thumbnail URL might be set but a 404 is returned because there is no preview available @@ -121,7 +121,7 @@ class NeonUnifiedSearchResults extends StatelessWidget { final Account account, final CoreUnifiedSearchResultEntry entry, ) { - const size = Size.square(kAvatarSize * 2 / 3); + final size = Size.square(IconTheme.of(context).size!); if (entry.icon.startsWith('/')) { return NeonCachedImage.url( size: size, diff --git a/packages/neon/neon/lib/src/widgets/user_avatar.dart b/packages/neon/neon/lib/src/widgets/user_avatar.dart index 65949cd5..d5b0f0c3 100644 --- a/packages/neon/neon/lib/src/widgets/user_avatar.dart +++ b/packages/neon/neon/lib/src/widgets/user_avatar.dart @@ -8,20 +8,19 @@ import 'package:neon/src/bloc/result.dart'; import 'package:neon/src/bloc/result_builder.dart'; import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/models/account.dart'; +import 'package:neon/src/theme/sizes.dart'; import 'package:neon/src/widgets/cached_image.dart'; import 'package:neon/src/widgets/server_icon.dart'; import 'package:nextcloud/nextcloud.dart'; import 'package:provider/provider.dart'; import 'package:rxdart/rxdart.dart'; -const kAvatarSize = 40.0; - class NeonUserAvatar extends StatefulWidget { NeonUserAvatar({ required this.account, final String? username, this.showStatus = true, - this.size = kAvatarSize, + this.size, this.backgroundColor, this.foregroundColor, super.key, @@ -30,7 +29,7 @@ class NeonUserAvatar extends StatefulWidget { final Account account; final String username; final bool showStatus; - final double size; + final double? size; final Color? backgroundColor; final Color? foregroundColor; @@ -55,7 +54,7 @@ class _UserAvatarState extends State { Widget build(final BuildContext context) => LayoutBuilder( builder: (final context, final constraints) { final brightness = Theme.of(context).brightness; - size = constraints.constrain(Size.square(widget.size)).shortestSide; + size = constraints.constrain(Size.square(widget.size ?? largeIconSize)).shortestSide; final pixelSize = (size * MediaQuery.of(context).devicePixelRatio).toInt(); return Stack( alignment: Alignment.center, diff --git a/packages/neon/neon/lib/theme.dart b/packages/neon/neon/lib/theme.dart index 8b4281ab..71bd3452 100644 --- a/packages/neon/neon/lib/theme.dart +++ b/packages/neon/neon/lib/theme.dart @@ -3,3 +3,4 @@ export 'src/theme/color_scheme.dart'; export 'src/theme/colors.dart'; export 'src/theme/dialog.dart'; export 'src/theme/neon.dart'; +export 'src/theme/sizes.dart'; diff --git a/packages/neon/neon_files/lib/neon_files.dart b/packages/neon/neon_files/lib/neon_files.dart index 1c63d961..026b2165 100644 --- a/packages/neon/neon_files/lib/neon_files.dart +++ b/packages/neon/neon_files/lib/neon_files.dart @@ -18,6 +18,7 @@ import 'package:neon/nextcloud.dart'; import 'package:neon/platform.dart'; import 'package:neon/settings.dart'; import 'package:neon/sort_box.dart'; +import 'package:neon/theme.dart'; import 'package:neon/utils.dart'; import 'package:neon/widgets.dart'; import 'package:neon_files/l10n/localizations.dart'; diff --git a/packages/neon/neon_files/lib/widgets/browser_view.dart b/packages/neon/neon_files/lib/widgets/browser_view.dart index fe2ef75e..3f2e4d4f 100644 --- a/packages/neon/neon_files/lib/widgets/browser_view.dart +++ b/packages/neon/neon_files/lib/widgets/browser_view.dart @@ -130,14 +130,9 @@ class _FilesBrowserViewState extends State { children: [ IconButton( padding: EdgeInsets.zero, - visualDensity: const VisualDensity( - horizontal: VisualDensity.minimumDensity, - vertical: VisualDensity.minimumDensity, - ), tooltip: AppLocalizations.of(context).goToPath(''), icon: const Icon( Icons.house, - size: 30, ), onPressed: () { widget.bloc.setPath([]); @@ -167,7 +162,6 @@ class _FilesBrowserViewState extends State { .intersperse( const Icon( Icons.keyboard_arrow_right, - size: 30, ), ) .toList(), diff --git a/packages/neon/neon_files/lib/widgets/file_list_tile.dart b/packages/neon/neon_files/lib/widgets/file_list_tile.dart index f44db77e..a9d09c4a 100644 --- a/packages/neon/neon_files/lib/widgets/file_list_tile.dart +++ b/packages/neon/neon_files/lib/widgets/file_list_tile.dart @@ -1,6 +1,7 @@ import 'package:filesize/filesize.dart'; import 'package:flutter/material.dart'; import 'package:flutter_material_design_icons/flutter_material_design_icons.dart'; +import 'package:neon/theme.dart'; import 'package:neon/utils.dart'; import 'package:neon/widgets.dart'; import 'package:neon_files/l10n/localizations.dart'; @@ -75,7 +76,7 @@ class FileListTile extends StatelessWidget { trailing: !details.hasTask && mode != FilesBrowserMode.noActions ? FileActions(details: details) : const SizedBox.square( - dimension: 48, + dimension: largeIconSize, ), ); } @@ -126,7 +127,7 @@ class _FileIcon extends StatelessWidget { alignment: Alignment.bottomRight, child: Icon( Icons.star, - size: 14, + size: smallIconSize, color: Colors.yellow, ), ), @@ -135,7 +136,7 @@ class _FileIcon extends StatelessWidget { } return SizedBox.square( - dimension: 40, + dimension: largeIconSize, child: icon, ); } diff --git a/packages/neon/neon_files/lib/widgets/file_preview.dart b/packages/neon/neon_files/lib/widgets/file_preview.dart index 118a474f..f1cebde2 100644 --- a/packages/neon/neon_files/lib/widgets/file_preview.dart +++ b/packages/neon/neon_files/lib/widgets/file_preview.dart @@ -4,7 +4,7 @@ class FilePreview extends StatelessWidget { const FilePreview({ required this.bloc, required this.details, - this.size = const Size.square(40), + this.size = const Size.square(largeIconSize), this.color, this.borderRadius, this.withBackground = false, diff --git a/packages/neon/neon_news/lib/neon_news.dart b/packages/neon/neon_news/lib/neon_news.dart index de7c26c7..f8d999db 100644 --- a/packages/neon/neon_news/lib/neon_news.dart +++ b/packages/neon/neon_news/lib/neon_news.dart @@ -15,6 +15,7 @@ import 'package:neon/nextcloud.dart'; import 'package:neon/platform.dart'; import 'package:neon/settings.dart'; import 'package:neon/sort_box.dart'; +import 'package:neon/theme.dart'; import 'package:neon/utils.dart'; import 'package:neon/widgets.dart'; import 'package:neon_news/l10n/localizations.dart'; diff --git a/packages/neon/neon_news/lib/widgets/articles_view.dart b/packages/neon/neon_news/lib/widgets/articles_view.dart index e9d9abb9..1a5fab1e 100644 --- a/packages/neon/neon_news/lib/widgets/articles_view.dart +++ b/packages/neon/neon_news/lib/widgets/articles_view.dart @@ -131,7 +131,7 @@ class _NewsArticlesViewState extends State { ), child: NewsFeedIcon( feed: feed, - size: 16, + size: smallIconSize, borderRadius: const BorderRadius.all(Radius.circular(2)), ), ), diff --git a/packages/neon/neon_news/lib/widgets/feed_icon.dart b/packages/neon/neon_news/lib/widgets/feed_icon.dart index ea336f30..f47c7058 100644 --- a/packages/neon/neon_news/lib/widgets/feed_icon.dart +++ b/packages/neon/neon_news/lib/widgets/feed_icon.dart @@ -3,7 +3,7 @@ part of '../neon_news.dart'; class NewsFeedIcon extends StatelessWidget { const NewsFeedIcon({ required this.feed, - this.size = 48, + this.size = largeIconSize, this.borderRadius, super.key, }); diff --git a/packages/neon/neon_news/lib/widgets/folders_view.dart b/packages/neon/neon_news/lib/widgets/folders_view.dart index 058f70d0..b85a76ff 100644 --- a/packages/neon/neon_news/lib/widgets/folders_view.dart +++ b/packages/neon/neon_news/lib/widgets/folders_view.dart @@ -53,12 +53,12 @@ class NewsFoldersView extends StatelessWidget { ), subtitle: unreadCount > 0 ? Text(AppLocalizations.of(context).articlesUnread(unreadCount)) : const SizedBox(), leading: SizedBox.square( - dimension: 48, + dimension: largeIconSize, child: Stack( children: [ Icon( Icons.folder, - size: 48, + size: largeIconSize, color: Theme.of(context).colorScheme.primary, ), Center( diff --git a/packages/neon/neon_notes/lib/neon_notes.dart b/packages/neon/neon_notes/lib/neon_notes.dart index 6ebd227b..32309451 100644 --- a/packages/neon/neon_notes/lib/neon_notes.dart +++ b/packages/neon/neon_notes/lib/neon_notes.dart @@ -14,6 +14,7 @@ import 'package:neon/models.dart'; import 'package:neon/nextcloud.dart'; import 'package:neon/settings.dart'; import 'package:neon/sort_box.dart'; +import 'package:neon/theme.dart'; import 'package:neon/utils.dart'; import 'package:neon/widgets.dart'; import 'package:neon_notes/l10n/localizations.dart'; diff --git a/packages/neon/neon_notes/lib/widgets/categories_view.dart b/packages/neon/neon_notes/lib/widgets/categories_view.dart index 2522cab6..2c1a741b 100644 --- a/packages/neon/neon_notes/lib/widgets/categories_view.dart +++ b/packages/neon/neon_notes/lib/widgets/categories_view.dart @@ -46,10 +46,10 @@ class NotesCategoriesView extends StatelessWidget { leading: category.name.isNotEmpty ? Icon( MdiIcons.tag, - size: 40, + size: largeIconSize, color: NotesCategoryColor.compute(category.name), ) - : const SizedBox.square(dimension: 40), + : const SizedBox.square(dimension: largeIconSize), onTap: () async { await Navigator.of(context).push( MaterialPageRoute( diff --git a/packages/neon/neon_notes/lib/widgets/notes_view.dart b/packages/neon/neon_notes/lib/widgets/notes_view.dart index 03ef7266..ecebf9bf 100644 --- a/packages/neon/neon_notes/lib/widgets/notes_view.dart +++ b/packages/neon/neon_notes/lib/widgets/notes_view.dart @@ -50,7 +50,7 @@ class NotesView extends StatelessWidget { ), Icon( MdiIcons.tag, - size: 14, + size: smallIconSize, color: NotesCategoryColor.compute(note.category), ), const SizedBox( diff --git a/packages/neon/neon_notifications/lib/neon_notifications.dart b/packages/neon/neon_notifications/lib/neon_notifications.dart index c2a5d210..a795f8a7 100644 --- a/packages/neon/neon_notifications/lib/neon_notifications.dart +++ b/packages/neon/neon_notifications/lib/neon_notifications.dart @@ -9,6 +9,7 @@ import 'package:neon/blocs.dart'; import 'package:neon/models.dart'; import 'package:neon/nextcloud.dart'; import 'package:neon/settings.dart'; +import 'package:neon/theme.dart'; import 'package:neon/utils.dart'; import 'package:neon/widgets.dart'; import 'package:neon_notifications/l10n/localizations.dart'; diff --git a/packages/neon/neon_notifications/lib/pages/main.dart b/packages/neon/neon_notifications/lib/pages/main.dart index 0d2172c5..39cdd284 100644 --- a/packages/neon/neon_notifications/lib/pages/main.dart +++ b/packages/neon/neon_notifications/lib/pages/main.dart @@ -74,13 +74,13 @@ class _NotificationsMainPageState extends State { ), leading: app != null ? app.buildIcon( - size: const Size.square(40), + size: largeIconSize, ) : SizedBox.fromSize( - size: const Size.square(40), + size: const Size.square(largeIconSize), child: NeonCachedImage.url( url: notification.icon!, - size: const Size.square(40), + size: const Size.square(largeIconSize), svgColor: Theme.of(context).colorScheme.primary, ), ),