mirror of
https://github.com/KRTirtho/spotube.git
synced 2025-09-13 07:55:18 +00:00
193 lines
6.2 KiB
Dart
193 lines
6.2 KiB
Dart
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
import 'package:go_router/go_router.dart';
|
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'package:spotube/collections/assets.gen.dart';
|
|
import 'package:spotube/collections/side_bar_tiles.dart';
|
|
import 'package:spotube/collections/spotube_icons.dart';
|
|
import 'package:spotube/components/shared/image/universal_image.dart';
|
|
import 'package:spotube/hooks/use_breakpoints.dart';
|
|
import 'package:spotube/provider/authentication_provider.dart';
|
|
import 'package:spotube/provider/downloader_provider.dart';
|
|
|
|
import 'package:spotube/provider/user_preferences_provider.dart';
|
|
import 'package:spotube/services/queries/queries.dart';
|
|
import 'package:spotube/utils/platform.dart';
|
|
import 'package:spotube/utils/type_conversion_utils.dart';
|
|
|
|
class Sidebar extends HookConsumerWidget {
|
|
final int selectedIndex;
|
|
final void Function(int) onSelectedIndexChanged;
|
|
final Widget child;
|
|
|
|
const Sidebar({
|
|
required this.selectedIndex,
|
|
required this.onSelectedIndexChanged,
|
|
required this.child,
|
|
Key? key,
|
|
}) : super(key: key);
|
|
|
|
static Widget brandLogo() {
|
|
return Container(
|
|
decoration: BoxDecoration(
|
|
color: Colors.black,
|
|
borderRadius: BorderRadius.circular(50),
|
|
),
|
|
child: Assets.spotubeLogoPng.image(height: 50),
|
|
);
|
|
}
|
|
|
|
static Widget macSpacer = const SizedBox(height: 25);
|
|
|
|
static void goToSettings(BuildContext context) {
|
|
GoRouter.of(context).go("/settings");
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context, WidgetRef ref) {
|
|
final breakpoints = useBreakpoints();
|
|
|
|
final downloadCount = ref.watch(
|
|
downloaderProvider.select((s) => s.currentlyRunning),
|
|
);
|
|
|
|
final layoutMode =
|
|
ref.watch(userPreferencesProvider.select((s) => s.layoutMode));
|
|
|
|
if (layoutMode == LayoutMode.compact ||
|
|
(breakpoints.isSm && layoutMode == LayoutMode.adaptive)) {
|
|
return Scaffold(body: child);
|
|
}
|
|
|
|
return Row(
|
|
children: [
|
|
NavigationRail(
|
|
selectedIndex: selectedIndex,
|
|
onDestinationSelected: onSelectedIndexChanged,
|
|
destinations: sidebarTileList.map(
|
|
(e) {
|
|
return NavigationRailDestination(
|
|
icon: Badge(
|
|
backgroundColor: Theme.of(context).primaryColor,
|
|
isLabelVisible: e.title == "Library" && downloadCount > 0,
|
|
label: Text(
|
|
downloadCount.toString(),
|
|
style: const TextStyle(
|
|
color: Colors.white,
|
|
fontSize: 10,
|
|
),
|
|
),
|
|
child: Icon(e.icon),
|
|
),
|
|
label: Text(
|
|
e.title,
|
|
style: const TextStyle(
|
|
fontWeight: FontWeight.bold,
|
|
fontSize: 16,
|
|
),
|
|
),
|
|
);
|
|
},
|
|
).toList(),
|
|
extended: true,
|
|
leading: Padding(
|
|
padding: const EdgeInsets.all(8.0),
|
|
child: Column(
|
|
children: [
|
|
if (kIsMacOS) macSpacer,
|
|
Row(
|
|
children: [
|
|
brandLogo(),
|
|
const SizedBox(width: 10),
|
|
Text(
|
|
"Spotube",
|
|
style: Theme.of(context).textTheme.titleLarge,
|
|
),
|
|
],
|
|
),
|
|
],
|
|
),
|
|
),
|
|
trailing: const SidebarFooter(),
|
|
),
|
|
Expanded(child: child)
|
|
],
|
|
);
|
|
}
|
|
}
|
|
|
|
class SidebarFooter extends HookConsumerWidget {
|
|
const SidebarFooter({
|
|
Key? key,
|
|
}) : super(key: key);
|
|
|
|
@override
|
|
Widget build(BuildContext context, ref) {
|
|
return SizedBox(
|
|
width: 256,
|
|
child: HookBuilder(
|
|
builder: (context) {
|
|
final me = useQueries.user.me(ref);
|
|
final data = me.data;
|
|
|
|
final avatarImg = TypeConversionUtils.image_X_UrlString(
|
|
data?.images,
|
|
index: (data?.images?.length ?? 1) - 1,
|
|
placeholder: ImagePlaceholder.artist,
|
|
);
|
|
|
|
final auth = ref.watch(AuthenticationNotifier.provider);
|
|
|
|
return Padding(
|
|
padding: const EdgeInsets.all(16).copyWith(left: 0),
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
|
children: [
|
|
if (auth != null && data == null)
|
|
const Center(
|
|
child: CircularProgressIndicator(),
|
|
)
|
|
else if (data != null)
|
|
Flexible(
|
|
child: Row(
|
|
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
|
children: [
|
|
CircleAvatar(
|
|
backgroundImage:
|
|
UniversalImage.imageProvider(avatarImg),
|
|
onBackgroundImageError: (exception, stackTrace) =>
|
|
Assets.userPlaceholder.image(
|
|
height: 16,
|
|
width: 16,
|
|
),
|
|
),
|
|
const SizedBox(
|
|
width: 10,
|
|
),
|
|
Flexible(
|
|
child: Text(
|
|
data.displayName ?? "Guest",
|
|
maxLines: 1,
|
|
softWrap: false,
|
|
overflow: TextOverflow.fade,
|
|
style: Theme.of(context)
|
|
.textTheme
|
|
.bodyMedium
|
|
?.copyWith(fontWeight: FontWeight.bold),
|
|
),
|
|
),
|
|
],
|
|
),
|
|
),
|
|
IconButton(
|
|
icon: const Icon(SpotubeIcons.settings),
|
|
onPressed: () => Sidebar.goToSettings(context)),
|
|
],
|
|
));
|
|
},
|
|
),
|
|
);
|
|
}
|
|
}
|