SimpleCloudNotifier/flutter/lib/components/layout/app_bar.dart

183 lines
5.6 KiB
Dart
Raw Normal View History

2024-05-21 23:20:34 +02:00
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:provider/provider.dart';
2024-06-16 00:46:46 +02:00
import 'package:simplecloudnotifier/components/layout/app_bar_filter_dialog.dart';
import 'package:simplecloudnotifier/components/layout/app_bar_progress_indicator.dart';
2024-05-23 17:41:51 +02:00
import 'package:simplecloudnotifier/pages/debug/debug_main.dart';
2024-06-15 21:29:51 +02:00
import 'package:simplecloudnotifier/settings/app_settings.dart';
2024-06-16 00:46:46 +02:00
import 'package:simplecloudnotifier/state/app_bar_state.dart';
import 'package:simplecloudnotifier/state/app_events.dart';
2024-05-21 23:20:34 +02:00
import 'package:simplecloudnotifier/state/app_theme.dart';
import 'package:simplecloudnotifier/utils/navi.dart';
2024-05-21 23:20:34 +02:00
2024-06-16 00:46:46 +02:00
class SCNAppBar extends StatefulWidget implements PreferredSizeWidget {
SCNAppBar({
2024-05-23 17:41:51 +02:00
Key? key,
required this.title,
required this.showThemeSwitch,
required this.showSearch,
2024-06-08 20:01:23 +02:00
required this.showShare,
this.onShare = null,
2024-05-23 17:41:51 +02:00
}) : super(key: key);
2024-05-21 23:20:34 +02:00
final String? title;
2024-05-23 17:41:51 +02:00
final bool showThemeSwitch;
final bool showSearch;
2024-06-08 20:01:23 +02:00
final bool showShare;
final void Function()? onShare;
2024-05-21 23:20:34 +02:00
2024-06-16 00:46:46 +02:00
@override
Size get preferredSize => const Size.fromHeight(kToolbarHeight);
@override
State<SCNAppBar> createState() => _SCNAppBarState();
}
class _SCNAppBarState extends State<SCNAppBar> {
final TextEditingController _ctrlSearchField = TextEditingController();
@override
void dispose() {
_ctrlSearchField.dispose();
super.dispose();
}
2024-05-21 23:20:34 +02:00
@override
Widget build(BuildContext context) {
2024-06-15 21:29:51 +02:00
final cfg = Provider.of<AppSettings>(context);
2024-06-08 20:01:23 +02:00
var actions = <Widget>[];
2024-06-15 21:29:51 +02:00
if (cfg.showDebugButton) {
actions.add(IconButton(
icon: const Icon(FontAwesomeIcons.solidSpiderBlackWidow),
tooltip: 'Debug',
onPressed: () {
Navi.push(context, () => DebugMainPage());
},
));
}
2024-06-16 00:46:46 +02:00
if (widget.showThemeSwitch) {
2024-06-08 20:01:23 +02:00
actions.add(Consumer<AppTheme>(
builder: (context, appTheme, child) => IconButton(
icon: Icon(appTheme.darkMode ? FontAwesomeIcons.solidSun : FontAwesomeIcons.solidMoon),
tooltip: appTheme.darkMode ? 'Light mode' : 'Dark mode',
onPressed: appTheme.switchDarkMode,
),
));
} else {
2024-06-16 00:46:46 +02:00
actions.add(_buildSpacer());
2024-06-08 20:01:23 +02:00
}
2024-06-16 00:46:46 +02:00
if (widget.showSearch) {
actions.add(IconButton(
icon: const Icon(FontAwesomeIcons.solidFilter),
tooltip: 'Filter',
onPressed: () => _showFilterDialog(context),
));
2024-06-08 20:01:23 +02:00
actions.add(IconButton(
icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass),
tooltip: 'Search',
2024-06-16 00:46:46 +02:00
onPressed: () => AppBarState().setShowSearchField(true),
2024-06-08 20:01:23 +02:00
));
2024-06-16 00:46:46 +02:00
} else if (widget.showShare) {
actions.add(_buildSpacer());
2024-06-08 20:01:23 +02:00
actions.add(IconButton(
icon: const Icon(FontAwesomeIcons.solidShareNodes),
tooltip: 'Share',
2024-06-16 00:46:46 +02:00
onPressed: widget.onShare ?? () {},
2024-06-08 20:01:23 +02:00
));
} else {
2024-06-16 00:46:46 +02:00
actions.add(_buildSpacer());
2024-06-25 12:00:34 +02:00
actions.add(_buildSpacer());
2024-06-08 20:01:23 +02:00
}
2024-06-16 00:46:46 +02:00
return Consumer<AppBarState>(builder: (context, value, child) {
if (value.showSearchField) {
return AppBar(
leading: IconButton(
icon: const Icon(FontAwesomeIcons.solidArrowLeft),
onPressed: () {
value.setShowSearchField(false);
},
),
title: _buildSearchTextField(context),
actions: [
IconButton(
icon: const Icon(FontAwesomeIcons.solidMagnifyingGlass),
onPressed: () {
value.setShowSearchField(false);
AppEvents().notifySearchListeners(_ctrlSearchField.text);
2024-06-16 00:46:46 +02:00
_ctrlSearchField.clear();
},
),
],
backgroundColor: Theme.of(context).secondaryHeaderColor,
bottom: PreferredSize(
preferredSize: Size(double.infinity, 1.0),
child: AppBarProgressIndicator(show: value.loadingIndeterminate),
),
);
} else {
return AppBar(
title: Text(widget.title ?? 'SCN'),
actions: actions,
backgroundColor: Theme.of(context).secondaryHeaderColor,
bottom: PreferredSize(
preferredSize: Size(double.infinity, 1.0),
child: AppBarProgressIndicator(show: value.loadingIndeterminate),
),
);
}
});
}
Visibility _buildSpacer() {
return Visibility(
visible: false,
maintainSize: true,
maintainAnimation: true,
maintainState: true,
child: IconButton(
icon: const Icon(FontAwesomeIcons.square),
onPressed: () {/* NO-OP */},
),
2024-05-21 23:20:34 +02:00
);
}
2024-06-16 00:46:46 +02:00
Widget _buildSearchTextField(BuildContext context) {
return TextField(
controller: _ctrlSearchField,
autofocus: true,
style: TextStyle(fontSize: 20),
textInputAction: TextInputAction.search,
decoration: InputDecoration(
hintText: 'Search',
),
onSubmitted: (value) {
AppBarState().setShowSearchField(false);
AppEvents().notifySearchListeners(_ctrlSearchField.text);
2024-06-16 00:46:46 +02:00
_ctrlSearchField.clear();
},
);
}
void _showFilterDialog(BuildContext context) {
showDialog<void>(
context: context,
barrierDismissible: true,
barrierColor: Colors.transparent,
builder: (BuildContext context) {
return Dialog(
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(0)),
alignment: Alignment.topCenter,
insetPadding: EdgeInsets.fromLTRB(0, this.widget.preferredSize.height, 0, 0),
backgroundColor: Colors.transparent,
child: AppBarFilterDialog(),
);
},
);
}
2024-05-21 23:20:34 +02:00
}