mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-10-21 06:52:18 +02:00
feat(home): localize greetings and address profile names
This commit is contained in:
1 parent
1a6dc7366e
commit
4cee16e9e8
5 files changed
+132
-3
No files matched your search
@@ -7253,6 +7253,30 @@
|
||||
"profileRemovePhoto": "Remove photo",
|
||||
"profilePhotoError": "Choose a valid image smaller than 20 MB.",
|
||||
"profileSaveError": "Could not save your profile. Please try again.",
|
||||
"homeGreetingMorning1": "Good morning",
|
||||
"homeGreetingMorning2": "Rise and shine",
|
||||
"homeGreetingMorning3": "Fresh start",
|
||||
"homeGreetingAfternoon1": "Good afternoon",
|
||||
"homeGreetingAfternoon2": "Afternoon groove",
|
||||
"homeGreetingAfternoon3": "Keep the vibe going",
|
||||
"homeGreetingEvening1": "Good evening",
|
||||
"homeGreetingEvening2": "Time to unwind",
|
||||
"homeGreetingEvening3": "Golden hour",
|
||||
"homeGreetingNight1": "Good night",
|
||||
"homeGreetingNight2": "Late-night session",
|
||||
"homeGreetingNight3": "Quiet hours",
|
||||
"homeGreetingNamed": "{greeting}, {name}",
|
||||
"@homeGreetingNamed": {
|
||||
"description": "Home greeting followed by the first name from the user's profile",
|
||||
"placeholders": {
|
||||
"greeting": {
|
||||
"type": "String"
|
||||
},
|
||||
"name": {
|
||||
"type": "String"
|
||||
}
|
||||
}
|
||||
},
|
||||
"artistUpcomingConcerts": "Upcoming Concerts",
|
||||
"artistAllUpcomingConcerts": "All Upcoming Concerts",
|
||||
"artistNoUpcomingConcerts": "No upcoming concerts.",
|
||||
|
||||
@@ -7258,6 +7258,19 @@
|
||||
"profileRemovePhoto": "Hapus foto",
|
||||
"profilePhotoError": "Pilih foto yang di bawah 20MB.",
|
||||
"profileSaveError": "Tidak dapat menyimpan profil Anda. Coba lagi.",
|
||||
"homeGreetingMorning1": "Selamat pagi",
|
||||
"homeGreetingMorning2": "Pagi yang cerah",
|
||||
"homeGreetingMorning3": "Awali harimu",
|
||||
"homeGreetingAfternoon1": "Selamat siang",
|
||||
"homeGreetingAfternoon2": "Siang yang santai",
|
||||
"homeGreetingAfternoon3": "Tetap semangat",
|
||||
"homeGreetingEvening1": "Selamat malam",
|
||||
"homeGreetingEvening2": "Waktunya rileks",
|
||||
"homeGreetingEvening3": "Senja yang syahdu",
|
||||
"homeGreetingNight1": "Selamat malam",
|
||||
"homeGreetingNight2": "Teman begadang",
|
||||
"homeGreetingNight3": "Malam yang tenang",
|
||||
"homeGreetingNamed": "{greeting}, {name}",
|
||||
"artistUpcomingConcerts": "Konser Mendatang",
|
||||
"artistAllUpcomingConcerts": "Semua Konser Mendatang",
|
||||
"artistNoUpcomingConcerts": "Tiada konser mendatang.",
|
||||
|
||||
@@ -40,6 +40,7 @@ import 'package:spotiflac_android/providers/settings_provider.dart';
|
||||
import 'package:spotiflac_android/providers/extension_provider.dart';
|
||||
import 'package:spotiflac_android/providers/recent_access_provider.dart';
|
||||
import 'package:spotiflac_android/providers/explore_provider.dart';
|
||||
import 'package:spotiflac_android/providers/user_profile_provider.dart';
|
||||
import 'package:spotiflac_android/widgets/explore_featured_section.dart';
|
||||
import 'package:spotiflac_android/providers/local_library_provider.dart';
|
||||
import 'package:spotiflac_android/screens/track_metadata_screen.dart';
|
||||
@@ -58,6 +59,7 @@ import 'package:spotiflac_android/utils/nav_bar_inset.dart';
|
||||
import 'package:spotiflac_android/utils/file_access.dart';
|
||||
import 'package:spotiflac_android/utils/string_utils.dart';
|
||||
import 'package:spotiflac_android/utils/editorial_notes.dart';
|
||||
import 'package:spotiflac_android/utils/home_greeting.dart';
|
||||
import 'package:spotiflac_android/screens/playlist_screen.dart';
|
||||
import 'package:spotiflac_android/screens/downloaded_album_screen.dart';
|
||||
import 'package:spotiflac_android/widgets/download_service_picker.dart';
|
||||
@@ -1079,13 +1081,20 @@ class _HomeTabState extends ConsumerState<HomeTab>
|
||||
final exploreSections = ref.watch(
|
||||
exploreProvider.select((s) => s.sections),
|
||||
);
|
||||
final exploreGreeting = ref.watch(
|
||||
exploreProvider.select((s) => s.greeting),
|
||||
// The feed decides whether a greeting shows; its words
|
||||
// are localized here and address the profile name.
|
||||
final showGreeting =
|
||||
ref.watch(exploreProvider.select((s) => s.greeting)) !=
|
||||
null;
|
||||
final profileName = ref.watch(
|
||||
userProfileProvider.select((p) => p.value?.name ?? ''),
|
||||
);
|
||||
return SliverMainAxisGroup(
|
||||
slivers: _buildExploreSections(
|
||||
exploreSections,
|
||||
exploreGreeting,
|
||||
showGreeting
|
||||
? homeGreeting(context.l10n, name: profileName)
|
||||
: null,
|
||||
colorScheme,
|
||||
),
|
||||
);
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
import 'dart:math';
|
||||
|
||||
import 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
|
||||
/// Picked once per launch: the greeting holds still while browsing and
|
||||
/// changes the next time the app opens.
|
||||
final int _sessionVariant = Random().nextInt(1 << 16);
|
||||
|
||||
/// A time-of-day Home greeting, addressed by the profile's first name when
|
||||
/// one is set.
|
||||
String homeGreeting(
|
||||
AppLocalizations l10n, {
|
||||
String name = '',
|
||||
DateTime? now,
|
||||
int? variant,
|
||||
}) {
|
||||
final hour = (now ?? DateTime.now()).hour;
|
||||
final options = switch (hour) {
|
||||
>= 5 && < 12 => [
|
||||
l10n.homeGreetingMorning1,
|
||||
l10n.homeGreetingMorning2,
|
||||
l10n.homeGreetingMorning3,
|
||||
],
|
||||
>= 12 && < 17 => [
|
||||
l10n.homeGreetingAfternoon1,
|
||||
l10n.homeGreetingAfternoon2,
|
||||
l10n.homeGreetingAfternoon3,
|
||||
],
|
||||
>= 17 && < 21 => [
|
||||
l10n.homeGreetingEvening1,
|
||||
l10n.homeGreetingEvening2,
|
||||
l10n.homeGreetingEvening3,
|
||||
],
|
||||
_ => [
|
||||
l10n.homeGreetingNight1,
|
||||
l10n.homeGreetingNight2,
|
||||
l10n.homeGreetingNight3,
|
||||
],
|
||||
};
|
||||
final phrase = options[(variant ?? _sessionVariant) % options.length];
|
||||
final trimmed = name.trim();
|
||||
if (trimmed.isEmpty) return phrase;
|
||||
// A full name reads stiff in a headline.
|
||||
return l10n.homeGreetingNamed(phrase, trimmed.split(RegExp(r'\s+')).first);
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_test/flutter_test.dart';
|
||||
import 'package:spotiflac_android/l10n/app_localizations.dart';
|
||||
import 'package:spotiflac_android/utils/home_greeting.dart';
|
||||
|
||||
void main() {
|
||||
late AppLocalizations l10n;
|
||||
|
||||
setUpAll(() async {
|
||||
l10n = await AppLocalizations.delegate.load(const Locale('en'));
|
||||
});
|
||||
|
||||
String at(int hour, {String name = '', int variant = 0}) => homeGreeting(
|
||||
l10n,
|
||||
name: name,
|
||||
now: DateTime(2026, 10, 18, hour),
|
||||
variant: variant,
|
||||
);
|
||||
|
||||
test('follows the time of day', () {
|
||||
expect(at(8), 'Good morning');
|
||||
expect(at(13), 'Good afternoon');
|
||||
expect(at(18), 'Good evening');
|
||||
expect(at(23), 'Good night');
|
||||
expect(at(3), 'Good night');
|
||||
});
|
||||
|
||||
test('variants rotate within the same part of the day', () {
|
||||
final phrases = {for (var i = 0; i < 3; i++) at(8, variant: i)};
|
||||
expect(phrases, {'Good morning', 'Rise and shine', 'Fresh start'});
|
||||
expect(at(8, variant: 3), at(8));
|
||||
});
|
||||
|
||||
test('addresses the profile by first name only', () {
|
||||
expect(at(23, name: ' Alex Rivera '), 'Good night, Alex');
|
||||
expect(at(23, name: ' '), 'Good night');
|
||||
});
|
||||
}
|
||||
Reference in new issue
Block a user