Skip to content
Snippets Groups Projects
Commit 03f85461 authored by Benoît Harrault's avatar Benoît Harrault
Browse files

Add navigation bar, split charts in pages

parent 61f44446
No related branches found
No related tags found
1 merge request!23Resolve "Add navigation bottom bar"
Pipeline #4545 passed
Showing
with 294 additions and 27 deletions
org.gradle.jvmargs=-Xmx1536M org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
app.versionName=0.0.21 app.versionName=0.0.22
app.versionCode=21 app.versionCode=22
{ {
"app_name": "Scrobbles", "app_name": "Scrobbles",
"bottom_nav_home": "Home",
"bottom_nav_discoveries": "Discoveries",
"bottom_nav_repartition": "Statistics",
"global_statistics": "Global statistics", "global_statistics": "Global statistics",
"statistics_total_scrobbles_count": "Total scrobbles count: {count}", "statistics_total_scrobbles_count": "Total scrobbles count: {count}",
"statistics_last_scrobble": "Last scrobble: {datetime}", "statistics_last_scrobble": "Last scrobble: {datetime}",
......
{ {
"app_name": "Scrobbles", "app_name": "Scrobbles",
"bottom_nav_home": "Accueil",
"bottom_nav_discoveries": "Découvertes",
"bottom_nav_repartition": "Statistiques",
"global_statistics": "Statistiques globales d'écoutes", "global_statistics": "Statistiques globales d'écoutes",
"statistics_total_scrobbles_count": "Nombre total d'écoutes : {count}", "statistics_total_scrobbles_count": "Nombre total d'écoutes : {count}",
"statistics_last_scrobble": "Dernière écoute : {datetime}", "statistics_last_scrobble": "Dernière écoute : {datetime}",
......
Add navigation bar, split charts in pages.
Ajout d'une barre de navigation, séparation des graphiques en plusieurs pages.
import 'package:hydrated_bloc/hydrated_bloc.dart';
class BottomNavCubit extends HydratedCubit<int> {
BottomNavCubit() : super(0);
void updateIndex(int index) => emit(index);
void getHomePage() => emit(0);
void getDiscoveriesPage() => emit(1);
void getStatisticsPage() => emit(2);
@override
int? fromJson(Map<String, dynamic> json) {
return json['pageIndex'] as int?;
}
@override
Map<String, dynamic>? toJson(int state) {
return <String, int>{'pageIndex': state};
}
}
import 'dart:io';
import 'package:easy_localization/easy_localization.dart'; import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:hive/hive.dart';
import 'package:hydrated_bloc/hydrated_bloc.dart';
import 'package:path_provider/path_provider.dart';
import 'config/theme.dart'; import 'config/theme.dart';
import 'ui/screens/skeleton_screen.dart'; import 'ui/screens/skeleton_screen.dart';
void main() async { void main() async {
/// Initialize packages
WidgetsFlutterBinding.ensureInitialized(); WidgetsFlutterBinding.ensureInitialized();
await EasyLocalization.ensureInitialized(); await EasyLocalization.ensureInitialized();
final Directory tmpDir = await getTemporaryDirectory();
Hive.init(tmpDir.toString());
HydratedBloc.storage = await HydratedStorage.build(
storageDirectory: tmpDir,
);
runApp( runApp(
EasyLocalization( EasyLocalization(
......
import 'package:flutter/material.dart';
import '../widgets/main_screen/discoveries_card.dart';
class DiscoveriesScreen extends StatefulWidget {
const DiscoveriesScreen({super.key});
@override
State<DiscoveriesScreen> createState() => _DiscoveriesScreenState();
}
class _DiscoveriesScreenState extends State<DiscoveriesScreen> {
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).colorScheme.background,
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 4),
physics: const BouncingScrollPhysics(),
children: <Widget>[
const SizedBox(height: 8),
const ChartDiscoveriesCard(),
const SizedBox(height: 36),
],
),
);
}
}
import 'package:flutter/material.dart';
import '../widgets/main_screen/statistics_card.dart';
import '../widgets/main_screen/timeline_card.dart';
class HomeScreen extends StatefulWidget {
const HomeScreen({super.key});
@override
State<HomeScreen> createState() => _HomeScreenState();
}
class _HomeScreenState extends State<HomeScreen> {
@override
Widget build(BuildContext context) {
return Material(
color: Theme.of(context).colorScheme.background,
child: ListView(
padding: const EdgeInsets.symmetric(horizontal: 4),
physics: const BouncingScrollPhysics(),
children: <Widget>[
const SizedBox(height: 8),
const StatisticsCard(),
const SizedBox(height: 6),
const ChartTimelineCard(),
const SizedBox(height: 36),
],
),
);
}
}
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'main_screen.dart'; import '../../cubit/bottom_nav_cubit.dart';
import '../widgets/app_bar.dart'; import '../widgets/app_bar.dart';
import '../widgets/bottom_nav_bar.dart';
import 'discoveries_screen.dart';
import 'home_screen.dart';
import 'statistics_screen.dart';
class SkeletonScreen extends StatefulWidget { class SkeletonScreen extends StatefulWidget {
const SkeletonScreen({super.key}); const SkeletonScreen({super.key});
...@@ -13,11 +19,27 @@ class SkeletonScreen extends StatefulWidget { ...@@ -13,11 +19,27 @@ class SkeletonScreen extends StatefulWidget {
class _SkeletonScreenState extends State<SkeletonScreen> { class _SkeletonScreenState extends State<SkeletonScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( const List<Widget> pageNavigation = <Widget>[
const HomeScreen(),
const DiscoveriesScreen(),
const StatisticsScreen(),
];
return BlocProvider<BottomNavCubit>(
create: (BuildContext context) => BottomNavCubit(),
child: Scaffold(
appBar: StandardAppBar(notifyParent: refresh), appBar: StandardAppBar(notifyParent: refresh),
extendBodyBehindAppBar: true, extendBodyBehindAppBar: false,
body: const MainScreen(), body: BlocBuilder<BottomNavCubit, int>(
builder: (BuildContext context, int state) {
return AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: pageNavigation.elementAt(state));
},
),
bottomNavigationBar: const BottomNavBar(),
backgroundColor: Theme.of(context).colorScheme.background, backgroundColor: Theme.of(context).colorScheme.background,
),
); );
} }
......
...@@ -2,18 +2,15 @@ import 'package:flutter/material.dart'; ...@@ -2,18 +2,15 @@ import 'package:flutter/material.dart';
import '../widgets/main_screen/counts_by_day_card.dart'; import '../widgets/main_screen/counts_by_day_card.dart';
import '../widgets/main_screen/counts_by_hour_card.dart'; import '../widgets/main_screen/counts_by_hour_card.dart';
import '../widgets/main_screen/discoveries_card.dart';
import '../widgets/main_screen/statistics_card.dart';
import '../widgets/main_screen/timeline_card.dart';
class MainScreen extends StatefulWidget { class StatisticsScreen extends StatefulWidget {
const MainScreen({super.key}); const StatisticsScreen({super.key});
@override @override
State<MainScreen> createState() => _MainScreenState(); State<StatisticsScreen> createState() => _StatisticsScreenState();
} }
class _MainScreenState extends State<MainScreen> { class _StatisticsScreenState extends State<StatisticsScreen> {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Material( return Material(
...@@ -22,13 +19,7 @@ class _MainScreenState extends State<MainScreen> { ...@@ -22,13 +19,7 @@ class _MainScreenState extends State<MainScreen> {
padding: const EdgeInsets.symmetric(horizontal: 4), padding: const EdgeInsets.symmetric(horizontal: 4),
physics: const BouncingScrollPhysics(), physics: const BouncingScrollPhysics(),
children: <Widget>[ children: <Widget>[
const SizedBox(height: 90), const SizedBox(height: 8),
const StatisticsCard(),
const SizedBox(height: 6),
const ChartTimelineCard(),
const SizedBox(height: 6),
const ChartDiscoveriesCard(),
const SizedBox(height: 6),
const ChartCountsByDayCard(), const ChartCountsByDayCard(),
const SizedBox(height: 6), const SizedBox(height: 6),
const ChartCountsByHourCard(), const ChartCountsByHourCard(),
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:ionicons/ionicons.dart';
import '../../cubit/bottom_nav_cubit.dart';
class BottomNavBar extends StatelessWidget {
const BottomNavBar({super.key});
@override
Widget build(BuildContext context) {
return Card(
margin: const EdgeInsets.only(top: 1, right: 4, left: 4),
elevation: 4,
shadowColor: Theme.of(context).colorScheme.shadow,
color: Theme.of(context).colorScheme.surfaceVariant,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.only(
topLeft: Radius.circular(16),
topRight: Radius.circular(16),
),
),
child: BlocBuilder<BottomNavCubit, int>(builder: (BuildContext context, int state) {
return BottomNavigationBar(
currentIndex: state,
onTap: (int index) => context.read<BottomNavCubit>().updateIndex(index),
type: BottomNavigationBarType.fixed,
elevation: 0,
backgroundColor: Colors.transparent,
selectedItemColor: Theme.of(context).colorScheme.primary,
unselectedItemColor: Theme.of(context).textTheme.bodySmall!.color,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: const Icon(Ionicons.home_outline),
label: tr('bottom_nav_home'),
),
BottomNavigationBarItem(
icon: const Icon(Ionicons.star_outline),
label: tr('bottom_nav_discoveries'),
),
BottomNavigationBarItem(
icon: const Icon(Ionicons.bar_chart_outline),
label: tr('bottom_nav_repartition'),
),
],
);
}),
);
}
}
...@@ -8,7 +8,7 @@ import '../../../utils/color_extensions.dart'; ...@@ -8,7 +8,7 @@ import '../../../utils/color_extensions.dart';
class CustomBarChart extends StatelessWidget { class CustomBarChart extends StatelessWidget {
CustomBarChart({super.key}); CustomBarChart({super.key});
final double chartHeight = 120.0; final double chartHeight = 150.0;
final double verticalTicksInterval = 10; final double verticalTicksInterval = 10;
final String verticalAxisTitleSuffix = ''; final String verticalAxisTitleSuffix = '';
final double titleFontSize = 10; final double titleFontSize = 10;
......
...@@ -6,7 +6,7 @@ import '../../../config/app_colors.dart'; ...@@ -6,7 +6,7 @@ import '../../../config/app_colors.dart';
class CustomLineChart extends StatelessWidget { class CustomLineChart extends StatelessWidget {
CustomLineChart({super.key}); CustomLineChart({super.key});
final double chartHeight = 120.0; final double chartHeight = 150.0;
final double titleFontSize = 10; final double titleFontSize = 10;
@override @override
......
...@@ -17,6 +17,14 @@ packages: ...@@ -17,6 +17,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.11.0" version: "2.11.0"
bloc:
dependency: transitive
description:
name: bloc
sha256: "3820f15f502372d979121de1f6b97bfcf1630ebff8fe1d52fb2b0bfa49be5b49"
url: "https://pub.dev"
source: hosted
version: "8.1.2"
characters: characters:
dependency: transitive dependency: transitive
description: description:
...@@ -41,6 +49,14 @@ packages: ...@@ -41,6 +49,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.17.2" version: "1.17.2"
crypto:
dependency: transitive
description:
name: crypto
sha256: ff625774173754681d66daaf4a448684fb04b78f902da9cb3d308c19cc5e8bab
url: "https://pub.dev"
source: hosted
version: "3.0.3"
easy_localization: easy_localization:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -58,7 +74,7 @@ packages: ...@@ -58,7 +74,7 @@ packages:
source: hosted source: hosted
version: "0.0.2" version: "0.0.2"
equatable: equatable:
dependency: transitive dependency: "direct main"
description: description:
name: equatable name: equatable
sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2 sha256: c2b87cb7756efdf69892005af546c56c0b5037f54d2a88269b4f347a505e3ca2
...@@ -94,6 +110,14 @@ packages: ...@@ -94,6 +110,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
flutter_bloc:
dependency: "direct main"
description:
name: flutter_bloc
sha256: e74efb89ee6945bcbce74a5b3a5a3376b088e5f21f55c263fc38cbdc6237faae
url: "https://pub.dev"
source: hosted
version: "8.1.3"
flutter_localizations: flutter_localizations:
dependency: transitive dependency: transitive
description: flutter description: flutter
...@@ -104,6 +128,14 @@ packages: ...@@ -104,6 +128,14 @@ packages:
description: flutter description: flutter
source: sdk source: sdk
version: "0.0.0" version: "0.0.0"
hive:
dependency: transitive
description:
name: hive
sha256: "8dcf6db979d7933da8217edcec84e9df1bdb4e4edc7fc77dbd5aa74356d6d941"
url: "https://pub.dev"
source: hosted
version: "2.2.3"
http: http:
dependency: "direct main" dependency: "direct main"
description: description:
...@@ -120,6 +152,14 @@ packages: ...@@ -120,6 +152,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.2" version: "4.0.2"
hydrated_bloc:
dependency: "direct main"
description:
name: hydrated_bloc
sha256: "24994e61f64904d911683cce1a31dc4ef611619da5253f1de2b7b8fc6f79a118"
url: "https://pub.dev"
source: hosted
version: "9.1.2"
intl: intl:
dependency: transitive dependency: transitive
description: description:
...@@ -128,6 +168,14 @@ packages: ...@@ -128,6 +168,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.18.1" version: "0.18.1"
ionicons:
dependency: "direct main"
description:
name: ionicons
sha256: "5496bc65a16115ecf05b15b78f494ee4a8869504357668f0a11d689e970523cf"
url: "https://pub.dev"
source: hosted
version: "0.2.2"
material_color_utilities: material_color_utilities:
dependency: transitive dependency: transitive
description: description:
...@@ -144,6 +192,14 @@ packages: ...@@ -144,6 +192,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.9.1" version: "1.9.1"
nested:
dependency: transitive
description:
name: nested
sha256: "03bac4c528c64c95c722ec99280375a6f2fc708eec17c7b3f07253b626cd2a20"
url: "https://pub.dev"
source: hosted
version: "1.0.0"
path: path:
dependency: transitive dependency: transitive
description: description:
...@@ -152,6 +208,30 @@ packages: ...@@ -152,6 +208,30 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.8.3" version: "1.8.3"
path_provider:
dependency: "direct main"
description:
name: path_provider
sha256: a1aa8aaa2542a6bc57e381f132af822420216c80d4781f7aa085ca3229208aaa
url: "https://pub.dev"
source: hosted
version: "2.1.1"
path_provider_android:
dependency: transitive
description:
name: path_provider_android
sha256: e595b98692943b4881b219f0a9e3945118d3c16bd7e2813f98ec6e532d905f72
url: "https://pub.dev"
source: hosted
version: "2.2.1"
path_provider_foundation:
dependency: transitive
description:
name: path_provider_foundation
sha256: "19314d595120f82aca0ba62787d58dde2cc6b5df7d2f0daf72489e38d1b57f2d"
url: "https://pub.dev"
source: hosted
version: "2.3.1"
path_provider_linux: path_provider_linux:
dependency: transitive dependency: transitive
description: description:
...@@ -192,6 +272,14 @@ packages: ...@@ -192,6 +272,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.1.6" version: "2.1.6"
provider:
dependency: transitive
description:
name: provider
sha256: cdbe7530b12ecd9eb455bdaa2fcb8d4dad22e80b8afb4798b41479d5ce26847f
url: "https://pub.dev"
source: hosted
version: "6.0.5"
shared_preferences: shared_preferences:
dependency: transitive dependency: transitive
description: description:
...@@ -269,6 +357,14 @@ packages: ...@@ -269,6 +357,14 @@ packages:
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.2.0" version: "1.2.0"
synchronized:
dependency: transitive
description:
name: synchronized
sha256: "5fcbd27688af6082f5abd611af56ee575342c30e87541d0245f7ff99faa02c60"
url: "https://pub.dev"
source: hosted
version: "3.1.0"
term_glyph: term_glyph:
dependency: transitive dependency: transitive
description: description:
......
...@@ -3,7 +3,7 @@ description: Display scrobbles data and charts ...@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
publish_to: 'none' publish_to: 'none'
version: 0.0.21+21 version: 0.0.22+22
environment: environment:
sdk: '^3.0.0' sdk: '^3.0.0'
...@@ -13,8 +13,13 @@ dependencies: ...@@ -13,8 +13,13 @@ dependencies:
sdk: flutter sdk: flutter
easy_localization: ^3.0.1 easy_localization: ^3.0.1
http: ^1.1.0 equatable: ^2.0.5
fl_chart: ^0.64.0 fl_chart: ^0.64.0
flutter_bloc: ^8.1.1
http: ^1.1.0
path_provider: ^2.0.11
hydrated_bloc: ^9.0.0
ionicons: ^0.2.2
unicons: ^2.1.1 unicons: ^2.1.1
flutter: flutter:
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please to comment