Skip to content
Snippets Groups Projects

Compare revisions

Changes are shown as if the source revision was being merged into the target revision. Learn more about comparing revisions.

Source

Select target project
No results found

Target

Select target project
  • android/org.benoitharrault.scrobbles
1 result
Show changes
Commits on Source (8)
Showing
with 207 additions and 106 deletions
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.benoitharrault.scrobbles">
<application
<uses-permission android:name="android.permission.INTERNET" />
<application
android:label="scrobbles"
android:icon="@mipmap/ic_launcher">
<activity
......@@ -11,20 +12,20 @@
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
</manifest>
\ No newline at end of file
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
app.versionName=0.0.2
app.versionCode=2
app.versionName=0.0.6
app.versionCode=6
......@@ -2,10 +2,9 @@
"app_name": "Scrobbles",
"global_statistics": "Global statistics",
"statistics_total_scrobbles_count": "Total scrobbles count:",
"statistics_total_scrobbles_count": "Total scrobbles count: {count}",
"statistics_last_scrobble": "Last scrobble: {datetime}",
"statistics_selected_period": "On last {daysCount} days:",
"statistics_recent_scrobbles_count": "Scrobbles:",
"statistics_discoveries": "Discoveries:",
"statistics_discoveries_artists": "artists",
"statistics_discoveries_tracks": "tracks"
"statistics_recent_scrobbles_count": "Scrobbles: {count}",
"statistics_discoveries": "Discoveries: {artistsCount} artists / {tracksCount} tracks"
}
......@@ -2,10 +2,9 @@
"app_name": "Scrobbles",
"global_statistics": "Statistiques globales d'écoutes",
"statistics_total_scrobbles_count": "Nombre total d'écoutes :",
"statistics_total_scrobbles_count": "Nombre total d'écoutes : {count}",
"statistics_last_scrobble": "Dernière écoute : {datetime}",
"statistics_selected_period": "Sur les {daysCount} derniers jours:",
"statistics_recent_scrobbles_count": "Écoutes :",
"statistics_discoveries": "Découvertes :",
"statistics_discoveries_artists": "artistes",
"statistics_discoveries_tracks": "morceaux"
"statistics_recent_scrobbles_count": "Écoutes : {count}",
"statistics_discoveries": "Découvertes : {artistsCount} artistes / {tracksCount} morceaux"
}
Fix Android permission INTERNET
Improve display error message
Display last scrobble date/time
Improve global statistic bloc
Correction sur permission Android d'accès à internet
Amélioration de l'affichage d'un message d'erreur
Affiche la date/heure de la dernière écoute enregistrée
Amélioration du bloc de statistiques globales
import 'dart:convert';
class StatisticsData {
final int totalCount;
final int recentCount;
final int firstPlayedArtistsCount;
final int firstPlayedTracksCount;
final int selectedPeriod;
final DateTime lastScrobble;
const StatisticsData({
required this.totalCount,
......@@ -11,15 +14,42 @@ class StatisticsData {
required this.firstPlayedArtistsCount,
required this.firstPlayedTracksCount,
required this.selectedPeriod,
required this.lastScrobble,
});
factory StatisticsData.fromJson(Map<String, dynamic> json) {
return StatisticsData(
totalCount: json['totalCount'] as int,
recentCount: json['recentCount'] as int,
firstPlayedArtistsCount: json['firstPlayedArtistsCount'] as int,
firstPlayedTracksCount: json['firstPlayedTracksCount'] as int,
selectedPeriod: json['selectedPeriod'] as int,
totalCount: json['totalCount'] != null ? json['totalCount'] as int : 0,
recentCount: json['recentCount'] != null ? json['recentCount'] as int : 0,
firstPlayedArtistsCount:
json['firstPlayedArtistsCount'] != null ? json['firstPlayedArtistsCount'] as int : 0,
firstPlayedTracksCount:
json['firstPlayedTracksCount'] != null ? json['firstPlayedTracksCount'] as int : 0,
selectedPeriod: json['selectedPeriod'] != null ? json['selectedPeriod'] as int : 0,
lastScrobble: (json['lastScrobble'] != null && json['lastScrobble']['date'] != null)
? DateTime.parse(
json['lastScrobble']['date'],
)
: DateTime.now(),
);
}
factory StatisticsData.createEmpty() {
return StatisticsData.fromJson({});
}
String toString() {
Map<String, dynamic> map = {
'totalCount': this.totalCount,
'recentCount': this.recentCount,
'firstPlayedArtistsCount': this.firstPlayedArtistsCount,
'firstPlayedTracksCount': this.firstPlayedTracksCount,
'selectedPeriod': this.selectedPeriod,
'lastScrobble': {
'date': this.lastScrobble.toString(),
},
};
return jsonEncode(map);
}
}
import 'package:flutter/material.dart';
import '../widgets/header.dart';
import '../widgets/main_screen/statistics.dart';
import '../widgets/main_screen/statistics_card.dart';
class MainScreen extends StatelessWidget {
const MainScreen({super.key});
......@@ -15,7 +15,7 @@ class MainScreen extends StatelessWidget {
physics: const BouncingScrollPhysics(),
children: <Widget>[
const Header(text: 'app_name'),
const Statistics(),
const StatisticsCard(),
const SizedBox(height: 36),
],
),
......
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
class ShowErrorWidget extends StatelessWidget {
const ShowErrorWidget({super.key, required this.message});
final String message;
@override
Widget build(BuildContext context) {
return Text(
'⚠️ ' + tr(message),
textAlign: TextAlign.start,
style: TextStyle(color: Colors.red),
);
}
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import '../../../models/statistics.dart';
import '../../../network/scrobbles_api.dart';
class Statistics extends StatelessWidget {
const Statistics({super.key});
@override
Widget build(BuildContext context) {
late Future<StatisticsData> futureAlbum = ScrobblesApi.fetchStatistics();
return FutureBuilder<StatisticsData>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasData) {
final TextTheme textTheme = Theme.of(context).primaryTextTheme;
return Card(
elevation: 2,
shadowColor: Theme.of(context).colorScheme.shadow,
color: Theme.of(context).colorScheme.primary,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(Radius.circular(12))),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
tr('global_statistics'),
style: textTheme.titleLarge!.apply(fontWeightDelta: 2),
),
Text(
tr('statistics_total_scrobbles_count') +
' ' +
snapshot.data!.totalCount.toString(),
style: textTheme.bodyMedium,
),
Text(
'statistics_selected_period',
style: textTheme.bodyMedium,
).tr(namedArgs: {'daysCount': snapshot.data!.selectedPeriod.toString()}),
Text(
tr('statistics_recent_scrobbles_count') +
' ' +
snapshot.data!.recentCount.toString(),
style: textTheme.bodyMedium,
),
Text(
tr('statistics_discoveries') +
' ' +
snapshot.data!.firstPlayedArtistsCount.toString() +
' ' +
tr('statistics_discoveries_artists') +
' / ' +
snapshot.data!.firstPlayedTracksCount.toString() +
' ' +
tr('statistics_discoveries_tracks'),
style: textTheme.bodyMedium,
),
],
),
),
);
} else if (snapshot.hasError) {
return Text('${snapshot.error}');
}
return const CircularProgressIndicator();
},
);
}
}
import 'dart:convert';
import 'package:flutter/material.dart';
import '../../../models/statistics.dart';
import '../../../network/scrobbles_api.dart';
import '../../../ui/widgets/error.dart';
import '../../../ui/widgets/main_screen/statistics_content.dart';
class StatisticsCard extends StatelessWidget {
const StatisticsCard({super.key});
@override
Widget build(BuildContext context) {
late Future<StatisticsData> futureAlbum = ScrobblesApi.fetchStatistics();
return FutureBuilder<StatisticsData>(
future: futureAlbum,
builder: (context, snapshot) {
if (snapshot.hasError) {
return ShowErrorWidget(message: '${snapshot.error}');
}
return Card(
elevation: 2,
shadowColor: Theme.of(context).colorScheme.shadow,
color: Theme.of(context).colorScheme.primary,
shape: const RoundedRectangleBorder(
borderRadius: BorderRadius.all(
Radius.circular(12),
),
),
child: Padding(
padding: const EdgeInsets.all(12.0),
child: StatisticsContent(
statistics: snapshot.hasData
? StatisticsData.fromJson(jsonDecode(snapshot.data.toString()))
: StatisticsData.createEmpty(),
isLoading: !snapshot.hasData,
),
),
);
},
);
}
}
import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import '../../../models/statistics.dart';
class StatisticsContent extends StatelessWidget {
final StatisticsData statistics;
final bool isLoading;
const StatisticsContent({super.key, required this.statistics, required this.isLoading});
@override
Widget build(BuildContext context) {
final TextTheme textTheme = Theme.of(context).primaryTextTheme;
final String placeholder = '⏳';
return Column(
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text(
'global_statistics',
style: textTheme.titleLarge!.apply(fontWeightDelta: 2),
).tr(),
Text(
'statistics_total_scrobbles_count',
style: textTheme.bodyMedium,
).tr(
namedArgs: {
'count': this.isLoading ? placeholder : this.statistics.totalCount.toString(),
},
),
Text(
'statistics_last_scrobble',
style: textTheme.bodyMedium,
).tr(
namedArgs: {
'datetime': this.isLoading
? placeholder
: DateFormat().format(this.statistics.lastScrobble),
},
),
Text(
'statistics_selected_period',
style: textTheme.bodyMedium,
).tr(
namedArgs: {
'daysCount':
this.isLoading ? placeholder : this.statistics.selectedPeriod.toString(),
},
),
Text(
'statistics_recent_scrobbles_count',
style: textTheme.bodyMedium,
).tr(
namedArgs: {
'count': this.isLoading ? placeholder : this.statistics.recentCount.toString(),
},
),
Text(
'statistics_discoveries',
style: textTheme.bodyMedium,
).tr(
namedArgs: {
'artistsCount': this.isLoading
? placeholder
: this.statistics.firstPlayedArtistsCount.toString(),
'tracksCount': this.isLoading
? placeholder
: this.statistics.firstPlayedTracksCount.toString(),
},
),
],
);
}
}
......@@ -3,7 +3,7 @@ description: Display scrobbles data and charts
publish_to: 'none'
version: 0.0.2+2
version: 0.0.6+6
environment:
sdk: '^3.0.0'
......