Skip to content

Commit

Permalink
feat: initial right panel support
Browse files Browse the repository at this point in the history
  • Loading branch information
MuZhou233 committed Oct 21, 2023
1 parent 449d86f commit 2281afb
Show file tree
Hide file tree
Showing 9 changed files with 426 additions and 251 deletions.
7 changes: 7 additions & 0 deletions lib/repo/yesod/yesod_local_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,11 @@ class YesodLocalSource implements YesodSource {
Future<List<String>> getFeedCategories() {
throw UnimplementedError();
}

@override
Future<List<ListFeedConfigsResponse_FeedWithConfig>> listFeedConfigs(
Iterable<InternalID>? ids) {
// TODO: implement listFeedConfigs
throw UnimplementedError();
}
}
20 changes: 20 additions & 0 deletions lib/repo/yesod/yesod_remote_source.dart
Original file line number Diff line number Diff line change
Expand Up @@ -35,4 +35,24 @@ class YesodRemoteSource implements YesodSource {
);
return response.data?.categories ?? [];
}

@override
Future<List<ListFeedConfigsResponse_FeedWithConfig>> listFeedConfigs(
Iterable<InternalID>? ids) async {
final response = await GetIt.I<ApiHelper>().doRequest(
(client, option) {
return client.listFeedConfigs(
ListFeedConfigsRequest(
paging: PagingRequest(
pageSize: ids?.length ?? 1,
pageNum: 1,
),
idFilter: ids,
),
options: option,
);
},
);
return response.data?.feedsWithConfig ?? [];
}
}
15 changes: 15 additions & 0 deletions lib/repo/yesod/yesod_repo.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,9 @@ part 'yesod_remote_source.dart';

abstract class YesodSource {
Future<List<FeedItem>> getBatchFeedItems(Iterable<InternalID>? ids);
Future<List<ListFeedConfigsResponse_FeedWithConfig>> listFeedConfigs(
Iterable<InternalID>? ids);

Future<List<String>> getFeedCategories();
}

Expand All @@ -37,6 +40,18 @@ class YesodRepo {
return [...cachedItems, ...remoteItems];
}

Future<ListFeedConfigsResponse_FeedWithConfig> getFeedConfig(
InternalID id) async {
final item = await getBatchFeedConfigs([id].reversed);
return item[0];
}

Future<List<ListFeedConfigsResponse_FeedWithConfig>> getBatchFeedConfigs(
Iterable<InternalID>? ids) async {
final remoteItems = await _remoteSource.listFeedConfigs(ids);
return remoteItems;
}

Future<List<String>> getFeedCategories() async {
return _remoteSource.getFeedCategories();
}
Expand Down
20 changes: 17 additions & 3 deletions lib/route.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:get_it/get_it.dart';
import 'package:go_router/go_router.dart';
import 'view/pages/yesod/yesod_config_edit_page.dart';

import 'bloc/api_request/api_request_bloc.dart';
import 'bloc/app_setting/app_setting_bloc.dart';
Expand Down Expand Up @@ -129,13 +130,26 @@ GoRouter getRouter() {
'config': const YesodConfigPage()
};
final function = state.pathParameters['function'] ?? 'recent';
final id = state.uri.queryParameters['id'];
final feedConfigID = id != null ? int.tryParse(id) : null;

final yesodRight = {
'config': feedConfigID != null
? YesodConfigEditPage(
key: ValueKey(feedConfigID),
feedConfigID: feedConfigID)
: const SizedBox(),
};
debugPrint(id);
return NoTransitionPage(
child: FramePage(
selectedNav: 'Yesod',
leftPart: YesodNav(
function: function,
),
rightPart: yesodPages[function],
middlePart: yesodPages[function],
rightPart: yesodRight[function],
gestureRight: false,
),
);
},
Expand Down Expand Up @@ -165,7 +179,7 @@ GoRouter getRouter() {
function: function,
selectedAppID: id,
),
rightPart: function == 'store'
middlePart: function == 'store'
? const GeburaStorePage()
: GeburaLibraryDetailPage(appID: appID),
),
Expand Down Expand Up @@ -199,7 +213,7 @@ GoRouter getRouter() {
leftPart: SettingsNav(
function: function,
),
rightPart: settingsPages[function] ?? const SizedBox(),
middlePart: settingsPages[function] ?? const SizedBox(),
),
);
},
Expand Down
50 changes: 36 additions & 14 deletions lib/view/layout/overlapping_panels.dart
Original file line number Diff line number Diff line change
Expand Up @@ -27,16 +27,25 @@ class OverlappingPanels extends StatefulWidget {
/// panel is revealed.
final double restWidth;

/// Allow reveal to left
final bool gestureLeft;

/// Allow reveal to right
final bool gestureRight;

/// A callback to notify when a panel reveal has completed.
final ValueChanged<RevealSide>? onSideChange;

const OverlappingPanels(
{this.left,
required this.main,
this.right,
this.restWidth = 40,
this.onSideChange,
super.key});
const OverlappingPanels({
this.left,
required this.main,
this.right,
this.restWidth = 40,
this.onSideChange,
this.gestureLeft = true,
this.gestureRight = true,
super.key,
});

static OverlappingPanelsState? of(BuildContext context) {
return context.findAncestorStateOfType<OverlappingPanelsState>();
Expand Down Expand Up @@ -70,7 +79,7 @@ class OverlappingPanelsState extends State<OverlappingPanels>
return (multiplier * width) + (-multiplier * widget.restWidth);
}

void _onApplyTranslation(Offset pixelsPerSecond) {
void _onApplyTranslation(Offset pixelsPerSecond, bool gestureEnd) {
final animationController = AnimationController(
vsync: this, duration: const Duration(milliseconds: 160));

Expand Down Expand Up @@ -103,6 +112,9 @@ class OverlappingPanelsState extends State<OverlappingPanels>
if (widget.left == null && goal > 0) goal = 0;
if (widget.right == null && goal < 0) goal = 0;

if (!widget.gestureLeft && gestureEnd && goal > 0) goal = 0;
if (!widget.gestureRight && gestureEnd && goal < 0) goal = 0;

final Tween<double> tween = Tween<double>(begin: translate, end: goal);

final animation = tween.animate(CurvedAnimation(
Expand All @@ -116,7 +128,6 @@ class OverlappingPanelsState extends State<OverlappingPanels>
lastTranslate = animation.value;
});
});
debugPrint('pixels ${pixelsPerSecond.dx} $translate $lastTranslate');

animationController.forward();
}
Expand All @@ -134,7 +145,7 @@ class OverlappingPanelsState extends State<OverlappingPanels>

animationController.addStatusListener((status) {
if (status == AnimationStatus.completed) {
_onApplyTranslation(Offset.zero);
_onApplyTranslation(Offset.zero, false);
animationController.dispose();
}
});
Expand All @@ -154,8 +165,8 @@ class OverlappingPanelsState extends State<OverlappingPanels>
void _onTranslate(double delta) {
setState(() {
final translate = this.translate + delta;
if (translate < 0 && widget.right != null ||
translate > 0 && widget.left != null) {
if ((widget.gestureRight && translate < 0 && widget.right != null) ||
(widget.gestureLeft && translate > 0 && widget.left != null)) {
this.translate = translate;
}
});
Expand Down Expand Up @@ -188,15 +199,26 @@ class OverlappingPanelsState extends State<OverlappingPanels>
),
Transform.translate(
offset: Offset(translate, 0),
child: widget.main,
child: GestureDetector(
behavior: HitTestBehavior.translucent,
onTap: () {
if (translate != 0) {
reveal(RevealSide.main);
}
},
child: IgnorePointer(
ignoring: translate != 0,
child: widget.main,
),
),
),
GestureDetector(
behavior: HitTestBehavior.translucent,
onHorizontalDragUpdate: (details) {
_onTranslate(details.delta.dx);
},
onHorizontalDragEnd: (details) {
_onApplyTranslation(details.velocity.pixelsPerSecond);
_onApplyTranslation(details.velocity.pixelsPerSecond, true);
},
),
]),
Expand Down
87 changes: 70 additions & 17 deletions lib/view/pages/frame_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,40 @@ import '../specialized/nav_rail.dart';
import '../specialized/theme_mode_toggle.dart';
import '../specialized/title_bar.dart';

class FramePage extends StatelessWidget {
class FramePage extends StatefulWidget {
const FramePage({
super.key,
required this.selectedNav,
required this.leftPart,
this.rightPart,
this.leftPartWidth,
this.middlePart,
this.rightPart,
this.rightPartWidth,
this.gestureRight = true,
});

final String selectedNav;
final Widget leftPart;
final Widget? rightPart;
final double? leftPartWidth;
final Widget? middlePart;
final Widget? rightPart;
final double? rightPartWidth;
final bool gestureRight;

static FramePageState? of(BuildContext context) {
return context.findAncestorStateOfType<FramePageState>();
}

@override
State<StatefulWidget> createState() => FramePageState();
}

class FramePageState extends State<FramePage> {
void openDrawer() {
_frameScaffold.currentState?.openEndDrawer();
}

final GlobalKey<ScaffoldState> _frameScaffold = GlobalKey();

@override
Widget build(BuildContext context) {
Expand All @@ -31,34 +52,37 @@ class FramePage extends StatelessWidget {
builder: (context, constraints) {
final width = constraints.biggest.width;

Widget content = rightPart != null
Widget content = widget.middlePart != null
? Row(
children: [
_Nav(selectedNav: selectedNav),
_Nav(selectedNav: widget.selectedNav),
SizedBox(
width: leftPartWidth != null ? leftPartWidth! - 64 : 256,
child: leftPart,
width: widget.leftPartWidth != null
? widget.leftPartWidth! - 64
: 256,
child: widget.leftPart,
),
Expanded(child: rightPart!),
Expanded(child: widget.middlePart!),
],
)
: Row(
children: [
_Nav(selectedNav: selectedNav),
Expanded(child: leftPart),
_Nav(selectedNav: widget.selectedNav),
Expanded(child: widget.leftPart),
],
);

if (width <= BootstrapBreakpoints.sm) {
content = rightPart != null
if (width <= BootstrapBreakpoints.md) {
content = widget.middlePart != null
? OverlappingPanels(
restWidth: restWidth,
gestureRight: widget.gestureRight,
left: Row(
children: [
_Nav(selectedNav: selectedNav),
_Nav(selectedNav: widget.selectedNav),
SizedBox(
width: width - 64 - restWidth,
child: leftPart,
child: widget.leftPart,
),
],
),
Expand All @@ -67,23 +91,43 @@ class FramePage extends StatelessWidget {
color: Theme.of(context).colorScheme.surfaceVariant,
borderRadius: BorderRadius.circular(12),
),
child: rightPart,
child: widget.middlePart,
),
right: widget.rightPart != null
? Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: width - 8 - restWidth,
child: widget.rightPart,
),
)
: null,
)
: OverlappingPanels(
gestureRight: widget.gestureRight,
main: Row(
children: [
_Nav(selectedNav: selectedNav),
_Nav(selectedNav: widget.selectedNav),
SizedBox(
width: width - 64,
child: leftPart,
child: widget.leftPart,
),
],
),
right: widget.rightPart != null
? Align(
alignment: Alignment.centerRight,
child: SizedBox(
width: width - 8 - restWidth,
child: widget.rightPart,
),
)
: null,
);
}

return Scaffold(
key: _frameScaffold,
body: SafeArea(
maintainBottomViewPadding: true,
child: Column(
Expand All @@ -98,6 +142,15 @@ class FramePage extends StatelessWidget {
],
),
),
endDrawer: width > BootstrapBreakpoints.md && widget.rightPart != null
? Drawer(
width: widget.rightPartWidth ?? 512,
child: SafeArea(
maintainBottomViewPadding: true,
child: widget.rightPart!,
),
)
: null,
);
},
);
Expand Down
Loading

0 comments on commit 2281afb

Please sign in to comment.