Browse Source

perf(neon): do not use the spread operator for building lists

Signed-off-by: Nikolas Rimikis <leptopoda@users.noreply.github.com>
pull/1094/head
Nikolas Rimikis 1 year ago
parent
commit
550aaf81e5
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 6
      packages/neon/neon/lib/src/app.dart
  2. 35
      packages/neon/neon/lib/src/pages/login.dart
  3. 3
      packages/neon/neon/lib/src/pages/login_check_account.dart
  4. 3
      packages/neon/neon/lib/src/pages/login_check_server_status.dart
  5. 43
      packages/neon/neon/lib/src/pages/login_flow.dart
  6. 39
      packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart
  7. 281
      packages/neon/neon/lib/src/pages/settings.dart
  8. 7
      packages/neon/neon/lib/src/widgets/account_tile.dart
  9. 70
      packages/neon/neon/lib/src/widgets/app_bar.dart
  10. 6
      packages/neon/neon/lib/src/widgets/unified_search_results.dart

6
packages/neon/neon/lib/src/app.dart

@ -120,13 +120,13 @@ class _NeonAppState extends State<NeonApp> with WidgetsBindingObserver, tray.Tra
await tray.trayManager.setContextMenu( await tray.trayManager.setContextMenu(
tray.Menu( tray.Menu(
items: [ items: [
for (final app in _appImplementations) ...[ ..._appImplementations.map(
tray.MenuItem( (final app) => tray.MenuItem(
key: 'app_${app.id}', key: 'app_${app.id}',
label: app.nameFromLocalization(localizations), label: app.nameFromLocalization(localizations),
// TODO: Add icons which should work on macOS and Windows // TODO: Add icons which should work on macOS and Windows
), ),
], ),
tray.MenuItem.separator(), tray.MenuItem.separator(),
tray.MenuItem( tray.MenuItem(
key: 'show_hide', key: 'show_hide',

35
packages/neon/neon/lib/src/pages/login.dart

@ -67,23 +67,22 @@ class _LoginPageState extends State<LoginPage> {
branding.name, branding.name,
style: Theme.of(context).textTheme.titleLarge, style: Theme.of(context).textTheme.titleLarge,
), ),
if (branding.showLoginWithNextcloud) ...[ if (branding.showLoginWithNextcloud)
const SizedBox( Padding(
height: 10, padding: const EdgeInsets.only(top: 10),
), child: Text(NeonLocalizations.of(context).loginWorksWith),
Text(NeonLocalizations.of(context).loginWorksWith), ),
const SizedBox( if (branding.showLoginWithNextcloud)
height: 10, Padding(
), padding: const EdgeInsets.only(top: 10),
Semantics( child: Semantics(
label: NeonLocalizations.of(context).nextcloud, label: NeonLocalizations.of(context).nextcloud,
child: const NextcloudLogo(), child: const NextcloudLogo(),
), ),
],
const SizedBox(
height: 50,
), ),
Form( Padding(
padding: const EdgeInsets.only(top: 50),
child: Form(
key: _formKey, key: _formKey,
child: TextFormField( child: TextFormField(
focusNode: _focusNode, focusNode: _focusNode,
@ -104,11 +103,11 @@ class _LoginPageState extends State<LoginPage> {
autofillHints: const [AutofillHints.url], autofillHints: const [AutofillHints.url],
), ),
), ),
if (NeonPlatform.instance.canUseCamera) ...[
const SizedBox(
height: 50,
), ),
IconButton( if (NeonPlatform.instance.canUseCamera)
Padding(
padding: const EdgeInsets.only(top: 50),
child: IconButton(
tooltip: NeonLocalizations.of(context).loginUsingQRcode, tooltip: NeonLocalizations.of(context).loginUsingQRcode,
icon: const Icon( icon: const Icon(
Icons.qr_code_scanner_rounded, Icons.qr_code_scanner_rounded,
@ -116,7 +115,7 @@ class _LoginPageState extends State<LoginPage> {
), ),
onPressed: () => const LoginQRcodeRoute().go(context), onPressed: () => const LoginQRcodeRoute().go(context),
), ),
], ),
], ],
), ),
), ),

3
packages/neon/neon/lib/src/pages/login_check_account.dart

@ -65,7 +65,7 @@ class _LoginCheckAccountPageState extends State<LoginCheckAccountPage> {
builder: (final context, final state) => Column( builder: (final context, final state) => Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (state.hasError) ...[ if (state.hasError)
Builder( Builder(
builder: (final context) { builder: (final context) {
final details = NeonError.getDetails(state.error); final details = NeonError.getDetails(state.error);
@ -77,7 +77,6 @@ class _LoginCheckAccountPageState extends State<LoginCheckAccountPage> {
); );
}, },
), ),
],
_buildAccountTile(state), _buildAccountTile(state),
Align( Align(
alignment: Alignment.bottomRight, alignment: Alignment.bottomRight,

3
packages/neon/neon/lib/src/pages/login_check_server_status.dart

@ -65,12 +65,11 @@ class _LoginCheckServerStatusPageState extends State<LoginCheckServerStatusPage>
return Column( return Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: [
if (state.hasError) ...[ if (state.hasError)
NeonValidationTile( NeonValidationTile(
title: NeonError.getDetails(state.error).getText(context), title: NeonError.getDetails(state.error).getText(context),
state: ValidationState.failure, state: ValidationState.failure,
), ),
],
_buildServerVersionTile(state), _buildServerVersionTile(state),
_buildMaintenanceModeTile(state), _buildMaintenanceModeTile(state),
Align( Align(

43
packages/neon/neon/lib/src/pages/login_flow.dart

@ -6,6 +6,7 @@ import 'package:neon/src/blocs/login_flow.dart';
import 'package:neon/src/router.dart'; import 'package:neon/src/router.dart';
import 'package:neon/src/widgets/error.dart'; import 'package:neon/src/widgets/error.dart';
import 'package:neon/src/widgets/linear_progress_indicator.dart'; import 'package:neon/src/widgets/linear_progress_indicator.dart';
import 'package:nextcloud/core.dart' as core;
import 'package:url_launcher/url_launcher_string.dart'; import 'package:url_launcher/url_launcher_string.dart';
@internal @internal
@ -65,29 +66,35 @@ class _LoginFlowPageState extends State<LoginFlowPage> {
subject: bloc.init, subject: bloc.init,
builder: (final context, final init) => Column( builder: (final context, final init) => Column(
mainAxisAlignment: MainAxisAlignment.center, mainAxisAlignment: MainAxisAlignment.center,
children: [ children: _buildChildren(init).toList(),
NeonLinearProgressIndicator(
visible: init.isLoading,
),
NeonError(
init.error,
onRetry: bloc.refresh,
), ),
if (init.hasData) ...[
Text(NeonLocalizations.of(context).loginSwitchToBrowserWindow),
const SizedBox(
height: 10,
),
ElevatedButton(
onPressed: bloc.refresh,
child: Text(NeonLocalizations.of(context).loginOpenAgain),
),
],
],
), ),
), ),
), ),
), ),
);
Iterable<Widget> _buildChildren(final Result<core.LoginFlowV2> init) sync* {
yield NeonLinearProgressIndicator(
visible: init.isLoading,
);
if (init.hasError) {
yield NeonError(
init.error,
onRetry: bloc.refresh,
);
}
if (init.hasData) {
yield Text(NeonLocalizations.of(context).loginSwitchToBrowserWindow);
yield Padding(
padding: const EdgeInsets.only(top: 10),
child: ElevatedButton(
onPressed: bloc.refresh,
child: Text(NeonLocalizations.of(context).loginOpenAgain),
), ),
); );
}
}
} }

39
packages/neon/neon/lib/src/pages/nextcloud_app_settings.dart

@ -39,23 +39,7 @@ class NextcloudAppSettingsPage extends StatelessWidget {
); );
final body = SettingsList( final body = SettingsList(
categories: [ categories: _buildCategories(context).toList(),
for (final category in [...appImplementation.options.categories, null]) ...[
if (appImplementation.options.options.where((final option) => option.category == category).isNotEmpty) ...[
SettingsCategory(
title: Text(
category != null ? category.name(context) : NeonLocalizations.of(context).optionsCategoryOther,
),
tiles: [
for (final option
in appImplementation.options.options.where((final option) => option.category == category)) ...[
OptionSettingsTile(option: option),
],
],
),
],
],
],
); );
return Scaffold( return Scaffold(
@ -71,4 +55,25 @@ class NextcloudAppSettingsPage extends StatelessWidget {
), ),
); );
} }
Iterable<Widget> _buildCategories(final BuildContext context) sync* {
final appOptions = appImplementation.options;
final categories = [...appOptions.categories, null];
for (final category in categories) {
final matchedOptions = appOptions.options.where((final option) => option.category == category);
if (matchedOptions.isNotEmpty) {
yield SettingsCategory(
title: Text(
category != null ? category.name(context) : NeonLocalizations.of(context).optionsCategoryOther,
),
tiles: [
...matchedOptions.map(
(final option) => OptionSettingsTile(option: option),
),
],
);
}
}
}
} }

281
packages/neon/neon/lib/src/pages/settings.dart

@ -14,7 +14,6 @@ import 'package:neon/src/settings/widgets/custom_settings_tile.dart';
import 'package:neon/src/settings/widgets/option_settings_tile.dart'; import 'package:neon/src/settings/widgets/option_settings_tile.dart';
import 'package:neon/src/settings/widgets/settings_category.dart'; import 'package:neon/src/settings/widgets/settings_category.dart';
import 'package:neon/src/settings/widgets/settings_list.dart'; import 'package:neon/src/settings/widgets/settings_list.dart';
import 'package:neon/src/settings/widgets/settings_tile.dart';
import 'package:neon/src/settings/widgets/text_settings_tile.dart'; import 'package:neon/src/settings/widgets/text_settings_tile.dart';
import 'package:neon/src/theme/branding.dart'; import 'package:neon/src/theme/branding.dart';
import 'package:neon/src/theme/dialog.dart'; import 'package:neon/src/theme/dialog.dart';
@ -89,7 +88,6 @@ class _SettingsPageState extends State<SettingsPage> {
final globalOptions = NeonProvider.of<GlobalOptions>(context); final globalOptions = NeonProvider.of<GlobalOptions>(context);
final accountsBloc = NeonProvider.of<AccountsBloc>(context); final accountsBloc = NeonProvider.of<AccountsBloc>(context);
final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context); final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final branding = Branding.of(context);
final appBar = AppBar( final appBar = AppBar(
title: Text(NeonLocalizations.of(context).settings), title: Text(NeonLocalizations.of(context).settings),
@ -116,24 +114,7 @@ class _SettingsPageState extends State<SettingsPage> {
final body = SettingsList( final body = SettingsList(
initialCategory: widget.initialCategory?.name, initialCategory: widget.initialCategory?.name,
categories: [ categories: [
SettingsCategory( buildAppCategory(),
hasLeading: true,
title: Text(NeonLocalizations.of(context).settingsApps),
key: ValueKey(SettingsCategories.apps.name),
tiles: <SettingsTile>[
for (final appImplementation in appImplementations) ...[
if (appImplementation.options.options.isNotEmpty) ...[
CustomSettingsTile(
leading: appImplementation.buildIcon(),
title: Text(appImplementation.name(context)),
onTap: () {
NextcloudAppSettingsRoute(appid: appImplementation.id).go(context);
},
),
],
],
],
),
SettingsCategory( SettingsCategory(
title: Text(NeonLocalizations.of(context).optionsCategoryTheme), title: Text(NeonLocalizations.of(context).optionsCategoryTheme),
key: ValueKey(SettingsCategories.theme.name), key: ValueKey(SettingsCategories.theme.name),
@ -159,7 +140,7 @@ class _SettingsPageState extends State<SettingsPage> {
], ],
), ),
if (NeonPlatform.instance.canUsePushNotifications) buildNotificationsCategory(), if (NeonPlatform.instance.canUsePushNotifications) buildNotificationsCategory(),
if (NeonPlatform.instance.canUseWindowManager) ...[ if (NeonPlatform.instance.canUseWindowManager)
SettingsCategory( SettingsCategory(
title: Text(NeonLocalizations.of(context).optionsCategoryStartup), title: Text(NeonLocalizations.of(context).optionsCategoryStartup),
key: ValueKey(SettingsCategories.startup.name), key: ValueKey(SettingsCategories.startup.name),
@ -172,8 +153,7 @@ class _SettingsPageState extends State<SettingsPage> {
), ),
], ],
), ),
], if (NeonPlatform.instance.canUseWindowManager && NeonPlatform.instance.canUseSystemTray)
if (NeonPlatform.instance.canUseWindowManager && NeonPlatform.instance.canUseSystemTray) ...[
SettingsCategory( SettingsCategory(
title: Text(NeonLocalizations.of(context).optionsCategorySystemTray), title: Text(NeonLocalizations.of(context).optionsCategorySystemTray),
key: ValueKey(SettingsCategories.systemTray.name), key: ValueKey(SettingsCategories.systemTray.name),
@ -186,120 +166,8 @@ class _SettingsPageState extends State<SettingsPage> {
), ),
], ],
), ),
],
...buildAccountCategory(), ...buildAccountCategory(),
SettingsCategory( buildOtherCategory(),
hasLeading: true,
title: Text(NeonLocalizations.of(context).optionsCategoryOther),
key: ValueKey(SettingsCategories.other.name),
tiles: [
if (branding.sourceCodeURL != null)
CustomSettingsTile(
leading: Icon(
Icons.code,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).sourceCode),
onTap: () async {
await launchUrlString(
branding.sourceCodeURL!,
mode: LaunchMode.externalApplication,
);
},
),
if (branding.issueTrackerURL != null)
CustomSettingsTile(
leading: Icon(
MdiIcons.textBoxEditOutline,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).issueTracker),
onTap: () async {
await launchUrlString(
branding.issueTrackerURL!,
mode: LaunchMode.externalApplication,
);
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.scriptText,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).licenses),
onTap: () async {
showLicensePage(
context: context,
applicationName: branding.name,
applicationIcon: branding.logo,
applicationLegalese: branding.legalese,
applicationVersion: NeonProvider.of<PackageInfo>(context).version,
);
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.export,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).settingsExport),
onTap: () async {
final settingsExportHelper = _buildSettingsExportHelper(context);
try {
final fileName = 'nextcloud-neon-settings-${DateTime.now().millisecondsSinceEpoch ~/ 1000}.json';
final data = settingsExportHelper.exportToFile();
await saveFileWithPickDialog(fileName, data);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
if (mounted) {
NeonError.showSnackbar(context, e);
}
}
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.import,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).settingsImport),
onTap: () async {
final settingsExportHelper = _buildSettingsExportHelper(context);
try {
final result = await FilePicker.platform.pickFiles(
withReadStream: true,
);
if (result == null) {
return;
}
if (!result.files.single.path!.endsWith('.json')) {
if (mounted) {
NeonError.showSnackbar(
context,
NeonLocalizations.of(context).settingsImportWrongFileExtension,
);
}
return;
}
await settingsExportHelper.applyFromFile(result.files.single.readStream);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
if (mounted) {
NeonError.showSnackbar(context, e);
}
}
},
),
],
),
], ],
); );
@ -317,6 +185,30 @@ class _SettingsPageState extends State<SettingsPage> {
); );
} }
Widget buildAppCategory() {
final appImplementations = NeonProvider.of<Iterable<AppImplementation>>(context);
final appsWithOptions = appImplementations.where(
(final app) => app.options.options.isNotEmpty,
);
final tiles = appsWithOptions.map(
(final appImplementation) => CustomSettingsTile(
leading: appImplementation.buildIcon(),
title: Text(appImplementation.name(context)),
onTap: () {
NextcloudAppSettingsRoute(appid: appImplementation.id).go(context);
},
),
);
return SettingsCategory(
hasLeading: true,
title: Text(NeonLocalizations.of(context).settingsApps),
key: ValueKey(SettingsCategories.apps.name),
tiles: tiles.toList(),
);
}
Widget buildNotificationsCategory() { Widget buildNotificationsCategory() {
final globalOptions = NeonProvider.of<GlobalOptions>(context); final globalOptions = NeonProvider.of<GlobalOptions>(context);
@ -416,6 +308,123 @@ class _SettingsPageState extends State<SettingsPage> {
} }
} }
Widget buildOtherCategory() {
final branding = Branding.of(context);
return SettingsCategory(
hasLeading: true,
title: Text(NeonLocalizations.of(context).optionsCategoryOther),
key: ValueKey(SettingsCategories.other.name),
tiles: [
if (branding.sourceCodeURL != null)
CustomSettingsTile(
leading: Icon(
Icons.code,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).sourceCode),
onTap: () async {
await launchUrlString(
branding.sourceCodeURL!,
mode: LaunchMode.externalApplication,
);
},
),
if (branding.issueTrackerURL != null)
CustomSettingsTile(
leading: Icon(
MdiIcons.textBoxEditOutline,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).issueTracker),
onTap: () async {
await launchUrlString(
branding.issueTrackerURL!,
mode: LaunchMode.externalApplication,
);
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.scriptText,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).licenses),
onTap: () async {
showLicensePage(
context: context,
applicationName: branding.name,
applicationIcon: branding.logo,
applicationLegalese: branding.legalese,
applicationVersion: NeonProvider.of<PackageInfo>(context).version,
);
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.export,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).settingsExport),
onTap: () async {
final settingsExportHelper = _buildSettingsExportHelper(context);
try {
final fileName = 'nextcloud-neon-settings-${DateTime.now().millisecondsSinceEpoch ~/ 1000}.json';
final data = settingsExportHelper.exportToFile();
await saveFileWithPickDialog(fileName, data);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
if (mounted) {
NeonError.showSnackbar(context, e);
}
}
},
),
CustomSettingsTile(
leading: Icon(
MdiIcons.import,
color: Theme.of(context).colorScheme.primary,
),
title: Text(NeonLocalizations.of(context).settingsImport),
onTap: () async {
final settingsExportHelper = _buildSettingsExportHelper(context);
try {
final result = await FilePicker.platform.pickFiles(
withReadStream: true,
);
if (result == null) {
return;
}
if (!result.files.single.path!.endsWith('.json')) {
if (mounted) {
NeonError.showSnackbar(
context,
NeonLocalizations.of(context).settingsImportWrongFileExtension,
);
}
return;
}
await settingsExportHelper.applyFromFile(result.files.single.readStream);
} catch (e, s) {
debugPrint(e.toString());
debugPrint(s.toString());
if (mounted) {
NeonError.showSnackbar(context, e);
}
}
},
),
],
);
}
SettingsExportHelper _buildSettingsExportHelper(final BuildContext context) { SettingsExportHelper _buildSettingsExportHelper(final BuildContext context) {
final globalOptions = NeonProvider.of<GlobalOptions>(context); final globalOptions = NeonProvider.of<GlobalOptions>(context);
final accountsBloc = NeonProvider.of<AccountsBloc>(context); final accountsBloc = NeonProvider.of<AccountsBloc>(context);

7
packages/neon/neon/lib/src/widgets/account_tile.dart

@ -64,9 +64,10 @@ class NeonAccountTile extends StatelessWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
), ),
if (userDetails.isLoading) Expanded(
const Expanded( child: NeonLinearProgressIndicator(
child: NeonLinearProgressIndicator(), visible: userDetails.isLoading,
),
), ),
if (userDetails.hasError) if (userDetails.hasError)
NeonError( NeonError(

70
packages/neon/neon/lib/src/widgets/app_bar.dart

@ -1,6 +1,7 @@
import 'dart:async'; import 'dart:async';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:intersperse/intersperse.dart';
import 'package:meta/meta.dart'; import 'package:meta/meta.dart';
import 'package:neon/l10n/localizations.dart'; import 'package:neon/l10n/localizations.dart';
import 'package:neon/src/bloc/result.dart'; import 'package:neon/src/bloc/result.dart';
@ -72,53 +73,47 @@ class _NeonAppBarState extends State<NeonAppBar> {
stream: unifiedSearchBloc.enabled, stream: unifiedSearchBloc.enabled,
builder: (final context, final unifiedSearchEnabledSnapshot) { builder: (final context, final unifiedSearchEnabledSnapshot) {
final unifiedSearchEnabled = unifiedSearchEnabledSnapshot.data ?? false; final unifiedSearchEnabled = unifiedSearchEnabledSnapshot.data ?? false;
return AppBar(
title: unifiedSearchEnabled Widget header = Row(
? null
: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [ children: [
if (activeAppSnapshot.hasData) ...[ if (activeAppSnapshot.hasData)
Flexible( Flexible(
child: Text( child: Text(
activeAppSnapshot.requireData.name(context), activeAppSnapshot.requireData.name(context),
), ),
), ),
], if (appImplementations.hasError)
if (appImplementations.hasError) ...[
const SizedBox(
width: 8,
),
NeonError( NeonError(
appImplementations.error, appImplementations.error,
onRetry: appsBloc.refresh, onRetry: appsBloc.refresh,
type: NeonErrorType.iconOnly, type: NeonErrorType.iconOnly,
), ),
], if (appImplementations.isLoading)
if (appImplementations.isLoading) ...[
const SizedBox(
width: 8,
),
Expanded( Expanded(
child: NeonLinearProgressIndicator( child: NeonLinearProgressIndicator(
color: Theme.of(context).appBarTheme.foregroundColor, color: Theme.of(context).appBarTheme.foregroundColor,
), ),
), ),
], ].intersperse(const SizedBox(width: 8)).toList(),
], );
),
if (accounts.length > 1) ...[ if (accounts.length > 1) {
header = Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
header,
Text( Text(
account.humanReadableID, account.humanReadableID,
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],
], );
), }
return AppBar(
title: unifiedSearchEnabled ? null : header,
actions: [ actions: [
if (unifiedSearchEnabled) ...[ if (unifiedSearchEnabled)
Flexible( Flexible(
child: SearchBar( child: SearchBar(
focusNode: _searchBarFocusNode, focusNode: _searchBarFocusNode,
@ -137,10 +132,9 @@ class _NeonAppBarState extends State<NeonAppBar> {
), ),
], ],
), ),
), )
] else ...[ else
const SearchIconButton(), const SearchIconButton(),
],
const NotificationIconButton(), const NotificationIconButton(),
const AccountSwitcherButton(), const AccountSwitcherButton(),
], ],
@ -217,21 +211,25 @@ class _NotificationIconButtonState extends State<NotificationIconButton> {
Future<void> _openNotifications( Future<void> _openNotifications(
final NotificationsAppInterface app, final NotificationsAppInterface app,
) async { ) async {
final page = Scaffold( Widget title = Text(app.name(context));
resizeToAvoidBottomInset: false,
appBar: AppBar( if (_accounts.length > 1) {
title: Column( title = Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(app.name(context)), title,
if (_accounts.length > 1) ...[
Text( Text(
_account.humanReadableID, _account.humanReadableID,
style: Theme.of(context).textTheme.bodySmall, style: Theme.of(context).textTheme.bodySmall,
), ),
], ],
], );
), }
final page = Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: title,
), ),
body: SafeArea( body: SafeArea(
child: app.page, child: app.page,

6
packages/neon/neon/lib/src/widgets/unified_search_results.dart

@ -81,7 +81,7 @@ class NeonUnifiedSearchResults extends StatelessWidget {
NeonLinearProgressIndicator( NeonLinearProgressIndicator(
visible: result.isLoading, visible: result.isLoading,
), ),
if (entries.isEmpty) ...[ if (entries.isEmpty)
AdaptiveListTile( AdaptiveListTile(
leading: const Icon( leading: const Icon(
Icons.close, Icons.close,
@ -89,8 +89,7 @@ class NeonUnifiedSearchResults extends StatelessWidget {
), ),
title: Text(NeonLocalizations.of(context).searchNoResults), title: Text(NeonLocalizations.of(context).searchNoResults),
), ),
], for (final entry in entries)
for (final entry in entries) ...[
AdaptiveListTile( AdaptiveListTile(
leading: NeonImageWrapper( leading: NeonImageWrapper(
size: const Size.square(largeIconSize), size: const Size.square(largeIconSize),
@ -103,7 +102,6 @@ class NeonUnifiedSearchResults extends StatelessWidget {
}, },
), ),
], ],
],
), ),
), ),
); );

Loading…
Cancel
Save