[client] streamline layouts

This commit is contained in:
Abhishek Shroff
2024-11-13 12:58:43 +05:30
parent 796e06d53c
commit 7deccb421c
4 changed files with 63 additions and 121 deletions

View File

@@ -3,41 +3,31 @@ import 'package:flutter_state_notifier/flutter_state_notifier.dart';
import 'package:phylum/libphylum/phylum_account.dart';
import 'package:phylum/ui/app/app_actions.dart';
import 'package:phylum/ui/app/fab_action.dart';
import 'package:phylum/ui/app/app_layout_manager.dart';
import 'package:phylum/ui/app/nav_list.dart';
import 'package:phylum/ui/explorer/explorer_view.dart';
import 'package:phylum/ui/explorer/explorer_view_controller.dart';
import 'package:phylum/ui/explorer/path_view.dart';
import 'package:phylum/ui/explorer/resource_info_view.dart';
import 'package:provider/provider.dart';
class AppLayout extends StatelessWidget {
const AppLayout({super.key});
class AppLayout {
const AppLayout();
static Widget create(String folderId) {
return MultiProvider(
providers: [
StateNotifierProvider<AppLayoutManager, AppLayoutState>(create: (context) => AppLayoutManager()),
StateNotifierProvider<ExplorerViewController, ExplorerViewState>(
create: (context) => ExplorerViewController(account: context.read<PhylumAccount>(), folderId: folderId),
),
],
builder: (context, child) {
final manager = context.read<AppLayoutManager>();
final platform = Theme.of(context).platform;
// final platform = Theme.of(context).platform;
final size = MediaQuery.sizeOf(context);
Future.microtask(() => manager.update(platform, size));
return child!;
},
child: AppActions(child: AppLayout()),
);
}
@override
Widget build(BuildContext context) {
return Builder(builder: (context) {
final layout = context.watch<AppLayoutState>();
return layout.type.isExpanded ? ExpandedAppLayout() : CollapsedAppLayout();
});
final layout = size.width <= 600 ? CollapsedAppLayout() : ExpandedAppLayout(large: size.width > 1200);
return AppActions(child: layout);
},
);
}
}
@@ -82,12 +72,13 @@ class CollapsedAppLayout extends StatelessWidget {
}
class ExpandedAppLayout extends StatelessWidget {
const ExpandedAppLayout({super.key});
final bool large;
const ExpandedAppLayout({super.key, required this.large});
@override
Widget build(BuildContext context) {
final layout = context.watch<AppLayoutState>();
final sidebarWidth = layout.type == LayoutType.expandedLarge ? 300.0 : 240.0;
final sidebarWidth = large ? 288.0 : 216.0;
final infoWidth = large ? 360.0 : 264.0;
return Scaffold(
appBar: AppBar(
@@ -100,13 +91,29 @@ class ExpandedAppLayout extends StatelessWidget {
),
body: Row(
children: [
SizedBox(width: sidebarWidth, child: NavList(showFab: true)),
SizedBox(
width: sidebarWidth,
child: Card(
elevation: 0,
margin: const EdgeInsets.only(left: 16, bottom: 16),
child: NavList(showFab: true),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
child: Card(
elevation: 0,
margin: const EdgeInsets.only(left: 16, right: 16, bottom: 16),
child: const ExplorerView(),
),
),
SizedBox(
width: infoWidth,
child: Card(
elevation: 0,
margin: const EdgeInsets.only(right: 16, bottom: 16),
child: ResourceInfoView(),
),
),
],
),
);

View File

@@ -1,41 +0,0 @@
import 'dart:ui';
import 'package:flutter/foundation.dart';
import 'package:state_notifier/state_notifier.dart';
enum LayoutType {
collapsed,
expandedSmall,
expandedLarge;
bool get isExpanded => this == LayoutType.expandedSmall || this == LayoutType.expandedLarge;
}
class AppLayoutState {
final LayoutType type;
final bool touchUi;
AppLayoutState({required this.type, required this.touchUi});
@override
bool operator ==(Object other) {
return other is AppLayoutState && other.type == type && other.touchUi == touchUi;
}
@override
int get hashCode => type.hashCode ^ touchUi.hashCode;
}
class AppLayoutManager extends StateNotifier<AppLayoutState> {
AppLayoutManager() : super(AppLayoutState(type: LayoutType.collapsed, touchUi: true));
void update(TargetPlatform platform, Size size) {
final type = size.width < 600
? LayoutType.collapsed
: size.width <= 1200
? LayoutType.expandedSmall
: LayoutType.expandedLarge;
final touchUi = platform == TargetPlatform.android || platform == TargetPlatform.iOS;
state = AppLayoutState(type: type, touchUi: touchUi);
}
}

View File

@@ -11,46 +11,39 @@ class NavList extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ExcludeFocusTraversal(
child: Card(
elevation: 0,
margin: const EdgeInsets.only(left: 16, bottom: 16),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: ListView(
children: [
if (showFab)
Padding(
padding: const EdgeInsets.only(bottom: 16),
child: PopupMenuButton(
tooltip: 'Create',
position: PopupMenuPosition.under,
itemBuilder: (context) => [
for (final action in popupMenuActions)
if (action == null)
const PopupMenuItem(enabled: false, height: 16, child: Divider())
else
PopupMenuItem(child: Text(action.descripiton), onTap: () => Actions.maybeInvoke(context, action.intent)),
],
child: FloatingActionButton.extended(
icon: const Icon(Icons.add), label: const Text('New'), elevation: 0, enableFeedback: false, onPressed: null),
),
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('Home'),
onTap: () => Actions.maybeInvoke(context, const NavHomeIntent()),
child: ListView(
children: [
if (showFab)
Padding(
padding: const EdgeInsets.all(16),
child: PopupMenuButton(
tooltip: 'Create',
position: PopupMenuPosition.under,
itemBuilder: (context) => [
for (final action in popupMenuActions)
if (action == null)
const PopupMenuItem(enabled: false, height: 16, child: Divider())
else
PopupMenuItem(child: Text(action.descripiton), onTap: () => Actions.maybeInvoke(context, action.intent)),
],
child: FloatingActionButton.extended(
icon: const Icon(Icons.add), label: const Text('New'), elevation: 0, enableFeedback: false, onPressed: null),
),
const Divider(),
const DownloadButton(),
const ServerStatusButton(),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Settings'),
onTap: () {},
),
],
),
ListTile(
leading: const Icon(Icons.home),
title: const Text('Home'),
onTap: () => Actions.maybeInvoke(context, const NavHomeIntent()),
),
),
const Divider(),
const DownloadButton(),
const ServerStatusButton(),
ListTile(
leading: const Icon(Icons.settings),
title: const Text('Settings'),
onTap: () {},
),
],
),
);
}

View File

@@ -1,8 +1,6 @@
import 'package:flutter/material.dart';
import 'package:phylum/app_shortcuts.dart';
import 'package:phylum/ui/app/app_layout_manager.dart';
import 'package:phylum/ui/explorer/paste_action_handler.dart';
import 'package:phylum/ui/explorer/resource_info_view.dart';
import 'package:provider/provider.dart';
import 'explorer_view_controller.dart';
@@ -14,28 +12,13 @@ class ExplorerView extends StatelessWidget {
@override
Widget build(BuildContext context) {
final layout = context.watch<AppLayoutState>();
return Actions(
actions: {
NextFocusIntent: CallbackAction<NextFocusIntent>(onInvoke: (i) => null),
PreviousFocusIntent: CallbackAction<PreviousFocusIntent>(onInvoke: (i) => null),
PasteFromClipboardIntent: CallbackAction<PasteFromClipboardIntent>(onInvoke: (PasteFromClipboardIntent i) => handlePasteAction(i, context)),
},
child: layout.type.isExpanded
? Row(
children: [
Expanded(child: Card(elevation: 0, child: buildPage(context))),
SizedBox(
width: layout.type == LayoutType.expandedLarge ? 360 : 300,
child: Card(
elevation: 0,
margin: EdgeInsets.only(left: 16),
child: ResourceInfoView(),
),
)
],
)
: buildPage(context),
child: buildPage(context),
);
}