fluffychat/lib/pangea/spaces/space_navigation_column.dart

200 lines
6 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:cached_network_image/cached_network_image.dart';
import 'package:go_router/go_router.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/config/themes.dart';
import 'package:fluffychat/pages/chat_list/chat_list.dart';
import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/pangea/analytics_details_popup/analytics_details_popup.dart';
import 'package:fluffychat/pangea/analytics_misc/construct_type_enum.dart';
import 'package:fluffychat/pangea/analytics_page/activity_archive.dart';
import 'package:fluffychat/pangea/analytics_summary/level_analytics_details_content.dart';
import 'package:fluffychat/pangea/spaces/space_constants.dart';
import 'package:fluffychat/widgets/hover_builder.dart';
import 'package:fluffychat/widgets/navigation_rail.dart';
class SpaceNavigationColumn extends StatefulWidget {
final GoRouterState state;
final bool showNavRail;
const SpaceNavigationColumn({
required this.state,
required this.showNavRail,
super.key,
});
@override
State<SpaceNavigationColumn> createState() => SpaceNavigationColumnState();
}
class SpaceNavigationColumnState extends State<SpaceNavigationColumn> {
bool _expanded = false;
Timer? _debounceTimer;
@override
void dispose() {
_debounceTimer?.cancel();
_debounceTimer = null;
super.dispose();
}
void _expand() {
if (_debounceTimer?.isActive == true) return;
if (!_expanded) {
setState(() => _expanded = true);
}
}
void _collapse() {
if (_expanded) {
setState(() {
_expanded = false;
_debounce();
});
}
}
void _debounce() {
_debounceTimer?.cancel();
_debounceTimer = Timer(const Duration(milliseconds: 300), () {
_debounceTimer?.cancel();
_debounceTimer = null;
});
}
@override
Widget build(BuildContext context) {
final theme = Theme.of(context);
final isColumnMode = FluffyThemes.isColumnMode(context);
final navRailWidth = isColumnMode
? FluffyThemes.navRailWidth
: FluffyThemes.navRailWidth - 8.0;
final double navRailExtraWidth = widget.showNavRail ? 250.0 : 0.0;
final double columnWidth =
isColumnMode ? FluffyThemes.columnWidth + 1.0 : 0;
final double railWidth = widget.showNavRail ? navRailWidth + 1.0 : 0;
final double baseWidth = columnWidth + railWidth;
final double expandedWidth = baseWidth < navRailExtraWidth
? navRailExtraWidth + railWidth
: baseWidth;
return AnimatedContainer(
duration: FluffyThemes.animationDuration,
width: _expanded ? expandedWidth : baseWidth,
child: Stack(
children: [
if (isColumnMode)
Positioned(
left: navRailWidth + 1.0,
child: SizedBox(
height: MediaQuery.heightOf(context),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Container(
clipBehavior: Clip.antiAlias,
decoration: const BoxDecoration(),
width: FluffyThemes.columnWidth,
child: _MainView(state: widget.state),
),
Container(
width: 1.0,
color: theme.dividerColor,
),
],
),
),
),
if (widget.showNavRail)
HoverBuilder(
builder: (context, hovered) {
WidgetsBinding.instance.addPostFrameCallback((_) {
hovered ? _expand() : _collapse();
});
return Row(
mainAxisSize: MainAxisSize.min,
children: [
SpacesNavigationRail(
activeSpaceId: widget.state.pathParameters['spaceid'],
path: widget.state.fullPath,
railWidth: _expanded
? navRailWidth + navRailExtraWidth
: navRailWidth,
expanded: _expanded,
collapse: _collapse,
),
Container(
width: 1,
color: Theme.of(context).dividerColor,
),
],
);
},
),
],
),
);
}
}
class _MainView extends StatelessWidget {
final GoRouterState state;
const _MainView({
required this.state,
});
@override
Widget build(BuildContext context) {
final path = state.fullPath;
if (path == null) {
return ChatList(
activeChat: state.pathParameters['roomid'],
activeSpaceId: state.pathParameters['spaceid'],
);
}
if (path.contains("analytics")) {
if (path.contains("analytics/level")) {
return const LevelAnalyticsDetailsContent();
} else if (path.contains("analytics/activities")) {
return const ActivityArchive();
} else if (path.contains("analytics/${ConstructTypeEnum.morph.string}")) {
return const ConstructAnalyticsView(view: ConstructTypeEnum.morph);
}
return const ConstructAnalyticsView(view: ConstructTypeEnum.vocab);
}
if (path.contains("settings")) {
return Settings(key: state.pageKey);
}
if (path.contains('course')) {
return Center(
child: SizedBox(
width: 250.0,
child: CachedNetworkImage(
imageUrl:
"${AppConfig.assetsBaseURL}/${SpaceConstants.sideBearFileName}",
errorWidget: (context, url, error) => const SizedBox(),
placeholder: (context, url) => const Center(
child: CircularProgressIndicator.adaptive(),
),
),
),
);
}
return ChatList(
activeChat: state.pathParameters['roomid'],
activeSpaceId: state.pathParameters['spaceid'],
);
}
}