refactor: logs page to shadcn

This commit is contained in:
Kingkor Roy Tirtho 2025-01-19 21:00:49 +06:00
parent e470f50e81
commit 74a328e529
6 changed files with 144 additions and 81 deletions

View File

@ -414,5 +414,6 @@
"no_tracks": "Looks like there are no tracks here", "no_tracks": "Looks like there are no tracks here",
"no_tracks_listened_yet": "Looks like you haven't listened to anything yet", "no_tracks_listened_yet": "Looks like you haven't listened to anything yet",
"not_following_artists": "You're not following any artists", "not_following_artists": "You're not following any artists",
"no_favorite_albums_yet": "Looks like you haven't added any albums to your favorites yet" "no_favorite_albums_yet": "Looks like you haven't added any albums to your favorites yet",
"no_logs_found": "No logs found"
} }

View File

@ -1,8 +1,11 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_hooks/flutter_hooks.dart'; import 'package:flutter_hooks/flutter_hooks.dart';
import 'package:flutter_undraw/flutter_undraw.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart';
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/components/button/back_button.dart';
import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart'; import 'package:spotube/components/inter_scrollbar/inter_scrollbar.dart';
import 'package:spotube/components/titlebar/titlebar.dart'; import 'package:spotube/components/titlebar/titlebar.dart';
import 'package:spotube/extensions/context.dart'; import 'package:spotube/extensions/context.dart';
@ -21,54 +24,73 @@ class LogsPage extends HookConsumerWidget {
final logsQuery = ref.watch(logsProvider); final logsQuery = ref.watch(logsProvider);
return Scaffold( return Scaffold(
appBar: TitleBar( headers: [
title: Text(context.l10n.logs), TitleBar(
leading: const [BackButton()], title: Text(context.l10n.logs),
trailing: [ leading: const [BackButton()],
IconButton( trailing: [
icon: const Icon(SpotubeIcons.clipboard), IconButton.ghost(
iconSize: 16, icon: const Icon(SpotubeIcons.clipboard, size: 16),
onPressed: () async { onPressed: () async {
final logsSnapshot = await ref.read(logsProvider.future); final logsSnapshot = await ref.read(logsProvider.future);
await Clipboard.setData(ClipboardData(text: logsSnapshot)); await Clipboard.setData(ClipboardData(text: logsSnapshot));
if (context.mounted) { if (context.mounted) {
ScaffoldMessenger.of(context).showSnackBar( showToast(
SnackBar( context: context,
content: Text(context.l10n.copied_to_clipboard("")), location: ToastLocation.topRight,
), builder: (context, overlay) {
); return SurfaceCard(
} child: Basic(
}, title: Text(context.l10n.copied_to_clipboard("")),
), ),
IconButton( );
icon: const Icon(SpotubeIcons.trash), },
iconSize: 16, );
onPressed: () async { }
ref.invalidate(logsProvider); },
),
IconButton.ghost(
icon: const Icon(
SpotubeIcons.trash,
size: 16,
),
onPressed: () async {
ref.invalidate(logsProvider);
final logsFile = await AppLogger.getLogsPath(); final logsFile = await AppLogger.getLogsPath();
await logsFile.writeAsString(""); await logsFile.writeAsString("");
}, },
) )
], ],
), )
body: SafeArea( ],
child: SafeArea(
child: switch (logsQuery) { child: switch (logsQuery) {
AsyncData(:final value) => Card( AsyncData(:final value) => InterScrollbar(
child: InterScrollbar( controller: controller,
child: SingleChildScrollView(
padding: const EdgeInsets.all(8.0),
controller: controller, controller: controller,
child: Padding( child: Card(child: SelectableText(value)),
padding: const EdgeInsets.all(8.0),
child: SingleChildScrollView(
controller: controller,
child: Text(value),
),
),
), ),
), ),
AsyncError(:final error) => Center(child: Text(error.toString())), AsyncError(:final error) => switch (error) {
StateError() => Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Undraw(
illustration: UndrawIllustration.noData,
height: 200 * context.theme.scaling,
width: 200 * context.theme.scaling,
color: context.theme.colorScheme.primary,
),
Text(context.l10n.no_logs_found).muted().small(),
],
),
_ => Center(child: Text(error.toString())),
},
_ => const Center(child: CircularProgressIndicator()), _ => const Center(child: CircularProgressIndicator()),
}, },
), ),

View File

@ -1,9 +1,8 @@
import 'package:auto_size_text/auto_size_text.dart'; import 'package:auto_size_text/auto_size_text.dart';
import 'package:flutter/material.dart' show FilledButton, ButtonStyle, ListTile; import 'package:flutter/material.dart' show ListTile;
import 'package:go_router/go_router.dart'; import 'package:go_router/go_router.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:shadcn_flutter/shadcn_flutter.dart' hide ButtonStyle; import 'package:shadcn_flutter/shadcn_flutter.dart' hide ButtonStyle;
import 'package:shadcn_flutter/shadcn_flutter_extension.dart';
import 'package:spotube/collections/env.dart'; import 'package:spotube/collections/env.dart';
import 'package:spotube/collections/spotube_icons.dart'; import 'package:spotube/collections/spotube_icons.dart';
import 'package:spotube/modules/settings/section_card_with_heading.dart'; import 'package:spotube/modules/settings/section_card_with_heading.dart';
@ -44,16 +43,25 @@ class SettingsAboutSection extends HookConsumerWidget {
), ),
), ),
), ),
trailing: (context, update) => FilledButton( trailing: (context, update) => Button(
style: ButtonStyle( style: ButtonVariance.primary.copyWith(
backgroundColor: WidgetStatePropertyAll(Colors.red[100]), decoration: (context, states, value) {
foregroundColor: const WidgetStatePropertyAll(Colors.pink), final decoration = ButtonVariance.primary
padding: const WidgetStatePropertyAll(EdgeInsets.all(15)), .decoration(context, states) as BoxDecoration;
shape: WidgetStatePropertyAll(
RoundedRectangleBorder( if (states.contains(WidgetState.hovered)) {
borderRadius: context.theme.borderRadiusLg, return decoration.copyWith(color: Colors.pink[400]);
), } else if (states.contains(WidgetState.focused)) {
), return decoration.copyWith(color: Colors.pink[300]);
} else if (states.isNotEmpty) {
return decoration;
}
return decoration.copyWith(color: Colors.pink);
},
textStyle: (context, states, value) => ButtonVariance.primary
.textStyle(context, states)
.copyWith(color: Colors.white),
), ),
onPressed: () { onPressed: () {
launchUrlString( launchUrlString(

View File

@ -6,6 +6,11 @@ import 'package:spotube/services/logger/logger.dart';
final logsProvider = StreamProvider.autoDispose((ref) async* { final logsProvider = StreamProvider.autoDispose((ref) async* {
final file = await AppLogger.getLogsPath(); final file = await AppLogger.getLogsPath();
final stream = file.openRead().transform(utf8.decoder); final stream = file.openRead().transform(utf8.decoder);
if (await stream.isEmpty) {
throw StateError('No logs found');
}
await for (final line in stream) { await for (final line in stream) {
yield line; yield line;
} }

View File

@ -188,6 +188,7 @@ flutter:
- packages/flutter_undraw/assets/undraw/follow_me_drone.svg - packages/flutter_undraw/assets/undraw/follow_me_drone.svg
- packages/flutter_undraw/assets/undraw/taken.svg - packages/flutter_undraw/assets/undraw/taken.svg
- packages/flutter_undraw/assets/undraw/empty.svg - packages/flutter_undraw/assets/undraw/empty.svg
- packages/flutter_undraw/assets/undraw/no_data.svg
fonts: fonts:
- family: GeistSans - family: GeistSans
fonts: fonts:

View File

@ -14,7 +14,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"bn": [ "bn": [
@ -32,7 +33,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ca": [ "ca": [
@ -50,7 +52,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"cs": [ "cs": [
@ -68,7 +71,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"de": [ "de": [
@ -86,7 +90,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"es": [ "es": [
@ -104,7 +109,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"eu": [ "eu": [
@ -122,7 +128,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"fa": [ "fa": [
@ -140,7 +147,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"fi": [ "fi": [
@ -158,7 +166,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"fr": [ "fr": [
@ -176,7 +185,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"hi": [ "hi": [
@ -194,7 +204,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"id": [ "id": [
@ -212,7 +223,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"it": [ "it": [
@ -230,7 +242,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ja": [ "ja": [
@ -248,7 +261,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ka": [ "ka": [
@ -266,7 +280,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ko": [ "ko": [
@ -284,7 +299,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ne": [ "ne": [
@ -302,7 +318,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"nl": [ "nl": [
@ -320,7 +337,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"pl": [ "pl": [
@ -338,7 +356,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"pt": [ "pt": [
@ -356,7 +375,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"ru": [ "ru": [
@ -374,7 +394,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"th": [ "th": [
@ -392,7 +413,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"tr": [ "tr": [
@ -410,7 +432,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"uk": [ "uk": [
@ -428,7 +451,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"vi": [ "vi": [
@ -446,7 +470,8 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
], ],
"zh": [ "zh": [
@ -464,6 +489,7 @@
"no_tracks", "no_tracks",
"no_tracks_listened_yet", "no_tracks_listened_yet",
"not_following_artists", "not_following_artists",
"no_favorite_albums_yet" "no_favorite_albums_yet",
"no_logs_found"
] ]
} }