Browse Source

neon: make move appBar to it's own widget

pull/397/head
Nikolas Rimikis 2 years ago
parent
commit
7fd221ad9b
No known key found for this signature in database
GPG Key ID: 85ED1DE9786A4FF2
  1. 1
      packages/neon/neon/lib/neon.dart
  2. 131
      packages/neon/neon/lib/src/pages/home.dart
  3. 194
      packages/neon/neon/lib/src/widgets/app_bar.dart

1
packages/neon/neon/lib/neon.dart

@ -26,6 +26,7 @@ import 'package:neon/src/blocs/blocs.dart';
import 'package:neon/src/models/account.dart';
import 'package:neon/src/models/push_notification.dart';
import 'package:neon/src/router.dart';
import 'package:neon/src/widgets/app_bar.dart';
import 'package:neon/src/widgets/drawer.dart';
import 'package:neon/src/widgets/drawer_destination.dart';
import 'package:nextcloud/nextcloud.dart';

131
packages/neon/neon/lib/src/pages/home.dart

@ -31,17 +31,6 @@ class _HomePageState extends State<HomePage> {
_appsBloc = _accountsBloc.activeAppsBloc;
_capabilitiesBloc = _accountsBloc.activeCapabilitiesBloc;
_appsBloc.openNotifications.listen((final _) async {
final notificationsAppImplementation = _appsBloc.notificationsAppImplementation.valueOrNull;
if (notificationsAppImplementation != null) {
await _openNotifications(
notificationsAppImplementation.data!,
_accountsBloc.accounts.value,
_accountsBloc.activeAccount.value!,
);
}
});
_appsBloc.appVersions.listen((final values) {
if (values == null || !mounted) {
return;
@ -108,40 +97,6 @@ class _HomePageState extends State<HomePage> {
);
}
Future _openNotifications(
final NotificationsAppInterface app,
final List<Account> accounts,
final Account account,
) async {
final page = Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(app.name(context)),
if (accounts.length > 1) ...[
Text(
account.client.humanReadableID,
style: Theme.of(context).textTheme.bodySmall,
),
],
],
),
),
body: app.page,
);
await Navigator.of(context).push(
MaterialPageRoute(
builder: (final context) => Provider<NotificationsBlocInterface>(
create: (final context) => app.getBloc(account),
child: page,
),
),
);
}
@override
void dispose() {
drawerScrollController.dispose();
@ -172,91 +127,7 @@ class _HomePageState extends State<HomePage> {
final drawerAlwaysVisible = navigationMode == NavigationMode.drawerAlwaysVisible;
const drawer = NeonDrawer();
final appBar = AppBar(
automaticallyImplyLeading: !drawerAlwaysVisible,
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
if (appImplementations.data != null && activeAppIDSnapshot.hasData) ...[
Flexible(
child: Text(
appImplementations.data!.find(activeAppIDSnapshot.data!)!.name(context),
),
),
],
if (appImplementations.hasError) ...[
const SizedBox(
width: 8,
),
NeonException(
appImplementations.error,
onRetry: _appsBloc.refresh,
onlyIcon: true,
),
],
if (appImplementations.isLoading) ...[
const SizedBox(
width: 8,
),
Expanded(
child: NeonLinearProgressIndicator(
color: Theme.of(context).appBarTheme.foregroundColor,
),
),
],
],
),
if (accounts.length > 1) ...[
Text(
account.client.humanReadableID,
style: Theme.of(context).textTheme.bodySmall,
),
],
],
),
actions: [
if (notificationsAppImplementation.data != null) ...[
StreamBuilder<int>(
stream: notificationsAppImplementation.data!
.getUnreadCounter(notificationsAppImplementation.data!.getBloc(account)),
builder: (final context, final unreadCounterSnapshot) {
final unreadCount = unreadCounterSnapshot.data ?? 0;
return IconButton(
key: Key('app-${notificationsAppImplementation.data!.id}'),
onPressed: () async {
await _openNotifications(
notificationsAppImplementation.data!,
accounts,
account,
);
},
tooltip: AppLocalizations.of(context)
.appImplementationName(notificationsAppImplementation.data!.id),
icon: NeonAppImplementationIcon(
appImplementation: notificationsAppImplementation.data!,
unreadCount: unreadCount,
color: unreadCount > 0
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onBackground,
size: const Size.square(kAvatarSize * 2 / 3),
),
);
},
),
],
IconButton(
onPressed: () {
AccountSettingsRoute(accountid: account.id).go(context);
},
tooltip: AppLocalizations.of(context).settingsAccount,
icon: NeonUserAvatar(
account: account,
),
),
],
);
const appBar = NeonAppBar();
Widget body = Builder(
builder: (final context) => Column(

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

@ -0,0 +1,194 @@
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:meta/meta.dart';
import 'package:neon/l10n/localizations.dart';
import 'package:neon/neon.dart';
import 'package:neon/src/router.dart';
import 'package:provider/provider.dart';
@internal
class NeonAppBar extends StatelessWidget implements PreferredSizeWidget {
const NeonAppBar({super.key});
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
@override
Widget build(final BuildContext context) {
final accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
final accounts = accountsBloc.accounts.value;
final account = accountsBloc.activeAccount.value!;
final appsBloc = accountsBloc.activeAppsBloc;
return ResultBuilder<Iterable<AppImplementation>>.behaviorSubject(
stream: appsBloc.appImplementations,
builder: (final context, final appImplementations) => StreamBuilder<String?>(
stream: appsBloc.activeAppID,
builder: (final context, final activeAppIDSnapshot) => AppBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Row(
children: [
if (appImplementations.data != null && activeAppIDSnapshot.hasData) ...[
Flexible(
child: Text(
appImplementations.data!.find(activeAppIDSnapshot.data!)!.name(context),
),
),
],
if (appImplementations.error != null) ...[
const SizedBox(
width: 8,
),
NeonException(
appImplementations.error,
onRetry: appsBloc.refresh,
onlyIcon: true,
),
],
if (appImplementations.isLoading) ...[
const SizedBox(
width: 8,
),
Expanded(
child: NeonLinearProgressIndicator(
color: Theme.of(context).appBarTheme.foregroundColor,
),
),
],
],
),
if (accounts.length > 1) ...[
Text(
account.client.humanReadableID,
style: Theme.of(context).textTheme.bodySmall,
),
],
],
),
actions: [
const NotificationIconButton(),
IconButton(
onPressed: () {
AccountSettingsRoute(accountid: account.id).go(context);
},
tooltip: AppLocalizations.of(context).settingsAccount,
icon: NeonUserAvatar(
account: account,
),
),
],
),
),
);
}
}
@internal
class NotificationIconButton extends StatefulWidget {
const NotificationIconButton({
super.key,
});
@override
State<NotificationIconButton> createState() => _NotificationIconButtonState();
}
class _NotificationIconButtonState extends State<NotificationIconButton> {
late AccountsBloc _accountsBloc;
late AppsBloc _appsBloc;
late List<Account> _accounts;
late Account _account;
late StreamSubscription notificationSubscription;
@override
void initState() {
super.initState();
_accountsBloc = Provider.of<AccountsBloc>(context, listen: false);
_appsBloc = _accountsBloc.activeAppsBloc;
_accounts = _accountsBloc.accounts.value;
_account = _accountsBloc.activeAccount.value!;
notificationSubscription = _appsBloc.openNotifications.listen((final _) async {
final notificationsAppImplementation = _appsBloc.notificationsAppImplementation.valueOrNull;
if (notificationsAppImplementation != null) {
await _openNotifications(notificationsAppImplementation.data!);
}
});
}
@override
void dispose() {
unawaited(notificationSubscription.cancel());
super.dispose();
}
// TODO: migrate to go_router with a separate page
Future<void> _openNotifications(
final NotificationsAppInterface app,
) async {
final page = Scaffold(
resizeToAvoidBottomInset: false,
appBar: AppBar(
title: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(app.name(context)),
if (_accounts.length > 1) ...[
Text(
_account.client.humanReadableID,
style: Theme.of(context).textTheme.bodySmall,
),
],
],
),
),
body: app.page,
);
await Navigator.of(context).push(
MaterialPageRoute(
builder: (final context) => Provider<NotificationsBlocInterface>(
create: (final context) => app.getBloc(_account),
child: page,
),
),
);
}
@override
Widget build(final BuildContext context) => ResultBuilder<NotificationsAppInterface?>.behaviorSubject(
stream: _appsBloc.notificationsAppImplementation,
builder: (final context, final notificationsAppImplementation) {
if (notificationsAppImplementation.data == null) {
return const SizedBox.shrink();
}
return StreamBuilder<int>(
stream: notificationsAppImplementation.data!
.getUnreadCounter(notificationsAppImplementation.data!.getBloc(_account)),
builder: (final context, final unreadCounterSnapshot) {
final unreadCount = unreadCounterSnapshot.data ?? 0;
return IconButton(
key: Key('app-${notificationsAppImplementation.data!.id}'),
onPressed: () async {
await _openNotifications(notificationsAppImplementation.data!);
},
tooltip: AppLocalizations.of(context).appImplementationName(notificationsAppImplementation.data!.id),
icon: NeonAppImplementationIcon(
appImplementation: notificationsAppImplementation.data!,
unreadCount: unreadCount,
color: unreadCount > 0
? Theme.of(context).colorScheme.primary
: Theme.of(context).colorScheme.onBackground,
size: const Size.square(kAvatarSize * 2 / 3),
),
);
},
);
},
);
}
Loading…
Cancel
Save