move app bar to bottom screen
This commit is contained in:
@@ -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> {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user