2024-12-05 00:43:57 +08:00
|
|
|
import 'dart:io';
|
|
|
|
|
|
|
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
|
|
|
import 'package:flutter/foundation.dart';
|
2024-11-09 00:09:46 +08:00
|
|
|
import 'package:flutter/material.dart';
|
2024-11-09 18:28:45 +08:00
|
|
|
import 'package:go_router/go_router.dart';
|
2024-12-08 19:11:37 +08:00
|
|
|
import 'package:google_fonts/google_fonts.dart';
|
2025-01-06 22:57:44 +08:00
|
|
|
import 'package:provider/provider.dart';
|
2024-11-09 00:09:46 +08:00
|
|
|
import 'package:responsive_framework/responsive_framework.dart';
|
2024-12-08 19:11:37 +08:00
|
|
|
import 'package:styled_widget/styled_widget.dart';
|
2025-01-06 22:57:44 +08:00
|
|
|
import 'package:surface/providers/config.dart';
|
2024-11-15 23:08:29 +08:00
|
|
|
import 'package:surface/providers/navigation.dart';
|
2024-11-15 00:52:31 +08:00
|
|
|
import 'package:surface/widgets/connection_indicator.dart';
|
2024-11-09 00:09:46 +08:00
|
|
|
import 'package:surface/widgets/navigation/app_background.dart';
|
|
|
|
import 'package:surface/widgets/navigation/app_bottom_navigation.dart';
|
2024-11-14 00:08:09 +08:00
|
|
|
import 'package:surface/widgets/navigation/app_drawer_navigation.dart';
|
2024-11-14 22:21:13 +08:00
|
|
|
import 'package:surface/widgets/navigation/app_rail_navigation.dart';
|
2025-01-20 16:52:53 +08:00
|
|
|
import 'package:surface/widgets/notify_indicator.dart';
|
2024-11-09 00:09:46 +08:00
|
|
|
|
2024-12-05 00:02:32 +08:00
|
|
|
final globalRootScaffoldKey = GlobalKey<ScaffoldState>();
|
|
|
|
|
2025-01-21 20:35:04 +08:00
|
|
|
class AppScaffold extends StatelessWidget {
|
|
|
|
final Widget? body;
|
|
|
|
final PreferredSizeWidget? bottomNavigationBar;
|
|
|
|
final PreferredSizeWidget? bottomSheet;
|
|
|
|
final Drawer? drawer;
|
|
|
|
final Widget? endDrawer;
|
|
|
|
final FloatingActionButtonAnimator? floatingActionButtonAnimator;
|
|
|
|
final FloatingActionButtonLocation? floatingActionButtonLocation;
|
|
|
|
final Widget? floatingActionButton;
|
|
|
|
final AppBar? appBar;
|
|
|
|
final DrawerCallback? onDrawerChanged;
|
|
|
|
final DrawerCallback? onEndDrawerChanged;
|
|
|
|
|
|
|
|
const AppScaffold({
|
|
|
|
super.key,
|
|
|
|
this.appBar,
|
|
|
|
this.body,
|
|
|
|
this.floatingActionButton,
|
|
|
|
this.floatingActionButtonLocation,
|
|
|
|
this.floatingActionButtonAnimator,
|
|
|
|
this.bottomNavigationBar,
|
|
|
|
this.bottomSheet,
|
|
|
|
this.drawer,
|
|
|
|
this.endDrawer,
|
|
|
|
this.onDrawerChanged,
|
|
|
|
this.onEndDrawerChanged,
|
|
|
|
});
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
final appBarHeight = appBar?.preferredSize.height ?? 0;
|
|
|
|
final safeTop = MediaQuery.of(context).padding.top;
|
|
|
|
|
|
|
|
return Scaffold(
|
|
|
|
extendBody: true,
|
|
|
|
extendBodyBehindAppBar: true,
|
|
|
|
backgroundColor: Theme.of(context).scaffoldBackgroundColor,
|
|
|
|
body: SizedBox.expand(
|
|
|
|
child: AppBackground(
|
2025-02-11 21:31:53 +08:00
|
|
|
isRoot: true,
|
2025-01-21 20:35:04 +08:00
|
|
|
child: Column(
|
|
|
|
children: [
|
|
|
|
IgnorePointer(child: SizedBox(height: appBar != null ? appBarHeight + safeTop : 0)),
|
|
|
|
if (body != null) Expanded(child: body!),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
appBar: appBar,
|
|
|
|
bottomNavigationBar: bottomNavigationBar,
|
|
|
|
bottomSheet: bottomSheet,
|
|
|
|
drawer: drawer,
|
|
|
|
endDrawer: endDrawer,
|
|
|
|
floatingActionButton: floatingActionButton,
|
|
|
|
floatingActionButtonAnimator: floatingActionButtonAnimator,
|
|
|
|
floatingActionButtonLocation: floatingActionButtonLocation,
|
|
|
|
onDrawerChanged: onDrawerChanged,
|
|
|
|
onEndDrawerChanged: onEndDrawerChanged,
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
class PageBackButton extends StatelessWidget {
|
|
|
|
const PageBackButton({super.key});
|
|
|
|
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
return BackButton(
|
|
|
|
onPressed: () {
|
|
|
|
GoRouter.of(context).pop();
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2024-11-14 22:21:13 +08:00
|
|
|
class AppRootScaffold extends StatelessWidget {
|
|
|
|
final Widget body;
|
2024-12-08 19:59:04 +08:00
|
|
|
|
2024-11-14 22:21:13 +08:00
|
|
|
const AppRootScaffold({super.key, required this.body});
|
2024-11-14 13:02:42 +08:00
|
|
|
|
2024-11-14 22:21:13 +08:00
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
2025-01-06 22:57:44 +08:00
|
|
|
final cfg = context.watch<ConfigProvider>();
|
2024-11-14 22:21:13 +08:00
|
|
|
final devicePixelRatio = MediaQuery.of(context).devicePixelRatio;
|
|
|
|
|
2025-01-06 22:57:44 +08:00
|
|
|
final isCollapseDrawer = cfg.drawerIsCollapsed;
|
|
|
|
final isExpandedDrawer = cfg.drawerIsExpanded;
|
2024-11-14 22:21:13 +08:00
|
|
|
|
2024-12-08 19:59:04 +08:00
|
|
|
final routeName = GoRouter.of(context).routerDelegate.currentConfiguration.last.route.name;
|
|
|
|
final isShowBottomNavigation = NavigationProvider.kShowBottomNavScreen.contains(routeName)
|
|
|
|
? ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE)
|
|
|
|
: false;
|
|
|
|
final isPopable = !NavigationProvider.kAllDestination.map((ele) => ele.screen).contains(routeName);
|
2024-11-15 23:08:29 +08:00
|
|
|
|
2024-11-14 22:21:13 +08:00
|
|
|
final innerWidget = isCollapseDrawer
|
|
|
|
? body
|
|
|
|
: Row(
|
|
|
|
children: [
|
|
|
|
Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
border: Border(
|
|
|
|
right: BorderSide(
|
|
|
|
color: Theme.of(context).dividerColor,
|
|
|
|
width: 1 / devicePixelRatio,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2025-01-06 22:57:44 +08:00
|
|
|
child: isExpandedDrawer ? AppNavigationDrawer(elevation: 0) : AppRailNavigation(),
|
2024-11-14 22:21:13 +08:00
|
|
|
),
|
|
|
|
Expanded(child: body),
|
|
|
|
],
|
|
|
|
);
|
2024-11-14 00:20:59 +08:00
|
|
|
|
2024-12-08 19:11:37 +08:00
|
|
|
final windowButtonColor = WindowButtonColors(
|
|
|
|
iconNormal: Theme.of(context).colorScheme.primary,
|
|
|
|
mouseOver: Theme.of(context).colorScheme.primaryContainer,
|
|
|
|
mouseDown: Theme.of(context).colorScheme.onPrimaryContainer,
|
|
|
|
iconMouseOver: Theme.of(context).colorScheme.primary,
|
|
|
|
iconMouseDown: Theme.of(context).colorScheme.primary,
|
|
|
|
);
|
|
|
|
|
2025-01-20 14:40:26 +08:00
|
|
|
final safeTop = MediaQuery.of(context).padding.top;
|
2025-01-31 21:50:18 +08:00
|
|
|
final safeBottom = MediaQuery.of(context).padding.bottom;
|
2025-01-20 14:40:26 +08:00
|
|
|
|
2025-01-21 20:35:04 +08:00
|
|
|
return Scaffold(
|
|
|
|
key: globalRootScaffoldKey,
|
|
|
|
backgroundColor: Theme.of(context).colorScheme.surface,
|
|
|
|
body: Stack(
|
|
|
|
children: [
|
|
|
|
Column(
|
|
|
|
children: [
|
|
|
|
if (!kIsWeb && (Platform.isWindows || Platform.isLinux || Platform.isMacOS))
|
|
|
|
WindowTitleBarBox(
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
border: Border(
|
|
|
|
bottom: BorderSide(
|
|
|
|
color: Theme.of(context).dividerColor,
|
|
|
|
width: 1 / devicePixelRatio,
|
2025-01-20 14:40:26 +08:00
|
|
|
),
|
2024-12-08 19:11:37 +08:00
|
|
|
),
|
2025-01-21 20:35:04 +08:00
|
|
|
),
|
|
|
|
child: MoveWindow(
|
|
|
|
child: Row(
|
|
|
|
crossAxisAlignment: CrossAxisAlignment.center,
|
|
|
|
mainAxisAlignment: Platform.isMacOS ? MainAxisAlignment.center : MainAxisAlignment.start,
|
|
|
|
children: [
|
|
|
|
Text(
|
|
|
|
'Solar Network',
|
|
|
|
style: GoogleFonts.spaceGrotesk(),
|
|
|
|
).padding(horizontal: 12, vertical: 5),
|
|
|
|
if (!Platform.isMacOS)
|
|
|
|
Row(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: [
|
|
|
|
Expanded(child: MoveWindow()),
|
|
|
|
Row(
|
|
|
|
children: [
|
|
|
|
MinimizeWindowButton(colors: windowButtonColor),
|
|
|
|
MaximizeWindowButton(colors: windowButtonColor),
|
|
|
|
CloseWindowButton(colors: windowButtonColor),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
],
|
2025-01-21 15:04:55 +08:00
|
|
|
),
|
2025-01-20 14:40:26 +08:00
|
|
|
),
|
|
|
|
),
|
2025-01-21 20:35:04 +08:00
|
|
|
),
|
|
|
|
Expanded(child: innerWidget),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
Positioned(top: safeTop > 0 ? safeTop : 16, right: 8, child: NotifyIndicator()),
|
2025-01-31 21:50:18 +08:00
|
|
|
if (ResponsiveBreakpoints.of(context).smallerOrEqualTo(MOBILE))
|
|
|
|
Positioned(bottom: safeBottom > 0 ? safeBottom : 16, left: 0, right: 0, child: ConnectionIndicator())
|
|
|
|
else
|
|
|
|
Positioned(top: safeTop > 0 ? safeTop : 16, left: 0, right: 0, child: ConnectionIndicator()),
|
2025-01-21 20:35:04 +08:00
|
|
|
],
|
2024-11-14 22:21:13 +08:00
|
|
|
),
|
2025-01-21 20:35:04 +08:00
|
|
|
drawer: !isExpandedDrawer ? AppNavigationDrawer() : null,
|
|
|
|
drawerEdgeDragWidth: isPopable ? 0 : null,
|
|
|
|
bottomNavigationBar: isShowBottomNavigation ? AppBottomNavigationBar() : null,
|
2024-11-14 22:21:13 +08:00
|
|
|
);
|
2024-11-09 00:09:46 +08:00
|
|
|
}
|
|
|
|
}
|