move app bar to bottom screen

This commit is contained in:
Fabian Freund
2024-06-06 05:30:32 +02:00
parent bb23870bf8
commit 063a118f90
2 changed files with 201 additions and 184 deletions
@@ -40,6 +40,8 @@ class KagiScreen extends HookConsumerWidget {
), ),
); );
final menuController = useMemoized(() => MenuController());
final lastBackButtonPress = useRef<DateTime?>(null); final lastBackButtonPress = useRef<DateTime?>(null);
final webViewController = useRef<InAppWebViewController?>(null); final webViewController = useRef<InAppWebViewController?>(null);
@@ -67,7 +69,10 @@ class KagiScreen extends HookConsumerWidget {
); );
return Scaffold( return Scaffold(
appBar: AppBar( bottomNavigationBar: BottomAppBar(
height: AppBar().preferredSize.height,
padding: EdgeInsets.zero,
child: AppBar(
automaticallyImplyLeading: false, automaticallyImplyLeading: false,
title: AppBarTitle( title: AppBarTitle(
onTap: () { onTap: () {
@@ -96,6 +101,7 @@ class KagiScreen extends HookConsumerWidget {
}, },
), ),
MenuAnchor( MenuAnchor(
controller: menuController,
builder: (context, controller, child) { builder: (context, controller, child) {
return IconButton( return IconButton(
onPressed: () { onPressed: () {
@@ -109,9 +115,94 @@ class KagiScreen extends HookConsumerWidget {
); );
}, },
menuChildren: [ menuChildren: [
MenuItemButton(
onPressed: () async {
await context.push(AboutRoute().location);
},
leadingIcon: const Icon(Icons.info),
child: const Text('About'),
),
const Divider(),
MenuItemButton(
onPressed: () async {
await context.push(SettingsRoute().location);
},
leadingIcon: const Icon(Icons.settings),
child: const Text('Settings'),
),
if (showEarlyAccessFeatures) const Divider(),
if (showEarlyAccessFeatures)
MenuItemButton(
onPressed: () async {
await context.push(ChatArchiveListRoute().location);
},
leadingIcon: const Icon(MdiIcons.archive),
child: const Text('Chat Archive'),
),
const Divider(),
if (showEarlyAccessFeatures)
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.assistant),
);
},
leadingIcon: const Icon(MdiIcons.brain),
child: const Text('Assistant'),
),
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.summarizer),
);
},
leadingIcon: const Icon(MdiIcons.text),
child: const Text('Summarizer'),
),
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.search),
);
},
leadingIcon: const Icon(MdiIcons.searchWeb),
child: const Text('Search'),
),
const Divider(),
MenuItemButton(
onPressed: () async {
final url = await webViewController.value?.getUrl();
if (url != null) {
// ignore: use_build_context_synchronously
await ui_helper.launchUrlFeedback(context, url);
}
},
leadingIcon: const Icon(Icons.open_in_browser),
child: const Text('Launch External'),
),
MenuItemButton(
onPressed: () async {
final url = await webViewController.value?.getUrl();
if (url != null) {
await Share.shareUri(url);
}
},
leadingIcon: const Icon(Icons.share),
child: const Text('Share'),
),
const Divider(),
MenuItemButton(
onPressed: () async {
await webViewController.value?.reload();
},
leadingIcon: const Icon(Icons.refresh),
child: const Text('Reload'),
),
const Divider(),
HookConsumer( HookConsumer(
builder: (context, ref, child) { builder: (context, ref, child) {
final activeWebView = ref.watch(webViewTabControllerProvider); final activeWebView =
ref.watch(webViewTabControllerProvider);
final history = useListenableSelector( final history = useListenableSelector(
activeWebView?.page, activeWebView?.page,
() => () =>
@@ -126,6 +217,7 @@ class KagiScreen extends HookConsumerWidget {
onPressed: (history.canGoBack) onPressed: (history.canGoBack)
? () async { ? () async {
await webViewController.value?.goBack(); await webViewController.value?.goBack();
menuController.close();
} }
: null, : null,
icon: const Icon(Icons.arrow_back), icon: const Icon(Icons.arrow_back),
@@ -137,6 +229,7 @@ class KagiScreen extends HookConsumerWidget {
onPressed: (history.canGoForward) onPressed: (history.canGoForward)
? () async { ? () async {
await webViewController.value?.goForward(); await webViewController.value?.goForward();
menuController.close();
} }
: null, : null,
icon: const Icon(Icons.arrow_forward), icon: const Icon(Icons.arrow_forward),
@@ -146,94 +239,11 @@ class KagiScreen extends HookConsumerWidget {
); );
}, },
), ),
const Divider(),
MenuItemButton(
onPressed: () async {
await webViewController.value?.reload();
},
leadingIcon: const Icon(Icons.refresh),
child: const Text('Reload'),
),
const Divider(),
MenuItemButton(
onPressed: () async {
await context.push(SettingsRoute().location);
},
leadingIcon: const Icon(Icons.settings),
child: const Text('Settings'),
),
const Divider(),
MenuItemButton(
onPressed: () async {
final url = await webViewController.value?.getUrl();
if (url != null) {
await Share.shareUri(url);
}
},
leadingIcon: const Icon(Icons.share),
child: const Text('Share'),
),
MenuItemButton(
onPressed: () async {
final url = await webViewController.value?.getUrl();
if (url != null) {
// ignore: use_build_context_synchronously
await ui_helper.launchUrlFeedback(context, url);
}
},
leadingIcon: const Icon(Icons.open_in_browser),
child: const Text('Launch External'),
),
const Divider(),
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.search),
);
},
leadingIcon: const Icon(MdiIcons.searchWeb),
child: const Text('Search'),
),
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.summarizer),
);
},
leadingIcon: const Icon(MdiIcons.text),
child: const Text('Summarizer'),
),
if (showEarlyAccessFeatures)
MenuItemButton(
onPressed: () {
ref.read(createTabStreamProvider.notifier).createTab(
CreateTab(preferredTool: KagiTool.assistant),
);
},
leadingIcon: const Icon(MdiIcons.brain),
child: const Text('Assistant'),
),
const Divider(),
if (showEarlyAccessFeatures)
MenuItemButton(
onPressed: () async {
await context.push(ChatArchiveListRoute().location);
},
leadingIcon: const Icon(MdiIcons.archive),
child: const Text('Chat Archive'),
),
if (showEarlyAccessFeatures) const Divider(),
MenuItemButton(
onPressed: () async {
await context.push(AboutRoute().location);
},
leadingIcon: const Icon(Icons.info),
child: const Text('About'),
),
], ],
), ),
], ],
), ),
),
body: OverlayPortal( body: OverlayPortal(
controller: overlayController, controller: overlayController,
overlayChildBuilder: (context) { overlayChildBuilder: (context) {
@@ -305,6 +315,7 @@ class KagiScreen extends HookConsumerWidget {
return true; return true;
} }
}, },
child: SafeArea(
child: AnimatedIndexedStack( child: AnimatedIndexedStack(
duration: const Duration(milliseconds: 250), duration: const Duration(milliseconds: 250),
transitionBuilder: (child, animation, secondaryAnimation) => transitionBuilder: (child, animation, secondaryAnimation) =>
@@ -329,6 +340,7 @@ class KagiScreen extends HookConsumerWidget {
: 0, : 0,
children: [const LandingContent(), ...webViews.values], children: [const LandingContent(), ...webViews.values],
), ),
),
); );
}, },
), ),
@@ -373,7 +373,11 @@ class _WebViewState extends ConsumerState<WebView> {
} }
}, },
), ),
HookBuilder( Positioned(
bottom: 0,
left: 0,
right: 0,
child: HookBuilder(
builder: (context) { builder: (context) {
final value = useValueListenable(webViewProgress); final value = useValueListenable(webViewProgress);
@@ -385,6 +389,7 @@ class _WebViewState extends ConsumerState<WebView> {
); );
}, },
), ),
),
], ],
); );
} }