Skip to content

Commit 80c3bb3

Browse files
authored
feat(#50): Support UI update when updating locale using NStack SDK instance (#54)
* feat(#50): Introduce onLocaleChanged stream * refactor(#50): Make methods return futures * feat(#50): Subscribe to the stream in the NStackWidget * chore(#50): Update example
1 parent 03e9767 commit 80c3bb3

File tree

5 files changed

+67
-10
lines changed

5 files changed

+67
-10
lines changed

example/lib/main.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ class MainScreen extends StatelessWidget {
4141
? const Locale('de-DE')
4242
: const Locale('en-EN');
4343

44-
NStackScope.of(context).changeLanguage(locale);
44+
NStack.localization.changeLocalization(locale);
4545
},
4646
child: Text(
4747
'Selected locale: ${activeLanguage.name}',

example/lib/nstack.dart

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,8 @@
2121
* `context.localization.yourSection.yourKey`.
2222
*/
2323

24+
import 'dart:async';
25+
2426
import 'package:flutter/foundation.dart';
2527
import 'package:flutter/widgets.dart';
2628
import 'package:nstack/models/app_open_platform.dart';
@@ -181,19 +183,36 @@ class NStackState extends State<NStackWidget> {
181183

182184
late Future<bool> _nstackInitFuture;
183185

186+
late final StreamSubscription _localeChangedSubscription;
187+
184188
@override
185189
void initState() {
186190
super.initState();
187191

188192
_nstackInitFuture = _nstack.init();
193+
194+
_localeChangedSubscription =
195+
NStack.localization.onLocaleChanged.listen(_onLocaleChanged);
196+
}
197+
198+
void _onLocaleChanged(Locale locale) {
199+
setState(() {});
189200
}
190201

202+
@Deprecated('Use `NStack.localization.changeLocalization` instead')
191203
Future<void> changeLanguage(Locale locale) {
192204
return _nstack.localization
193205
.changeLocalization(locale)
194206
.whenComplete(() => setState(() {}));
195207
}
196208

209+
@override
210+
void dispose() {
211+
_localeChangedSubscription.cancel();
212+
213+
super.dispose();
214+
}
215+
197216
@override
198217
Widget build(BuildContext context) {
199218
if (!_initializedNStack) {

lib/sdk/localization/nstack_localization.dart

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import 'dart:async';
12
import 'dart:convert';
23

34
import 'package:flutter/widgets.dart';
@@ -15,6 +16,8 @@ class NStackLocalization<TLocalization> {
1516
static const _prefsKeyLastUpdated = "nstack_last_updated";
1617
static const _prefsSelectedLocale = "nstack_selected_locale";
1718

19+
final _onLocaleChanged = StreamController<Locale>.broadcast();
20+
1821
final NStackConfig config;
1922
final TLocalization translations;
2023
final NStackRepository _repository;
@@ -31,6 +34,8 @@ class NStackLocalization<TLocalization> {
3134

3235
String get checksum => LocalizationRepository().checksum;
3336

37+
Stream<Locale> get onLocaleChanged => _onLocaleChanged.stream;
38+
3439
Locale? clientLocale;
3540

3641
NStackLocalization({
@@ -53,6 +58,19 @@ class NStackLocalization<TLocalization> {
5358
);
5459
}
5560

61+
Future<void> _updateLocaleAndNotify({
62+
required Map<String, dynamic> translationData,
63+
required String languageLocale,
64+
required Locale locale,
65+
}) async {
66+
await LocalizationRepository().updateLocalization(
67+
translationData,
68+
languageLocale,
69+
);
70+
71+
_onLocaleChanged.add(locale);
72+
}
73+
5674
/// Change the localization in the internal map
5775
/// 1. Find the best match in the language list that the project was built with
5876
/// 2. Look if we have a cached localization in preferences and use that
@@ -76,9 +94,10 @@ class NStackLocalization<TLocalization> {
7694

7795
final languageResponse = LocalizationData.fromJson(cachedResponse);
7896

79-
LocalizationRepository().updateLocalization(
80-
languageResponse.data!,
81-
localLanguage.language!.locale!,
97+
await _updateLocaleAndNotify(
98+
translationData: languageResponse.data!,
99+
languageLocale: localLanguage.language!.locale!,
100+
locale: locale,
82101
);
83102

84103
_log("Switched cached localization...");
@@ -94,9 +113,10 @@ class NStackLocalization<TLocalization> {
94113
jsonDecode(localizationResponse),
95114
);
96115

97-
LocalizationRepository().updateLocalization(
98-
translationJson.data!,
99-
localLanguage.language!.locale!,
116+
await _updateLocaleAndNotify(
117+
translationData: translationJson.data!,
118+
languageLocale: localLanguage.language!.locale!,
119+
locale: locale,
100120
);
101121

102122
_log("Switched API localization...");

lib/src/nstack_builder.dart

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ class NstackBuilder implements Builder {
115115
* `context.localization.yourSection.yourKey`.
116116
*/
117117
118+
import 'dart:async';
119+
118120
import 'package:flutter/foundation.dart';
119121
import 'package:flutter/widgets.dart';
120122
import 'package:nstack/models/app_open_platform.dart';
@@ -328,17 +330,33 @@ class NStackState extends State<NStackWidget> {
328330
329331
late Future<bool> _nstackInitFuture;
330332
333+
late final StreamSubscription _localeChangedSubscription;
334+
331335
@override
332336
void initState() {
333337
super.initState();
334338
335339
_nstackInitFuture = _nstack.init();
340+
341+
_localeChangedSubscription = NStack.localization.onLocaleChanged.listen(_onLocaleChanged);
342+
}
343+
344+
void _onLocaleChanged(Locale locale) {
345+
setState(() {});
336346
}
337347
348+
@Deprecated('Use `NStack.localization.changeLocalization` instead')
338349
Future<void> changeLanguage(Locale locale) {
339350
return _nstack.localization.changeLocalization(locale).whenComplete(() => setState(() {}));
340351
}
341352
353+
@override
354+
void dispose() {
355+
_localeChangedSubscription.cancel();
356+
357+
super.dispose();
358+
}
359+
342360
@override
343361
Widget build(BuildContext context) {
344362
if (!_initializedNStack) {

lib/src/repository.dart

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ class LocalizationRepository {
5959
_setupInternalMap();
6060
}
6161

62-
void updateLocalization(
62+
Future<void> updateLocalization(
6363
Map<String, dynamic> localizationJson,
6464
String bestFitLocale,
6565
) {
@@ -68,7 +68,7 @@ class LocalizationRepository {
6868
orElse: () => this._pickedLanguage,
6969
);
7070
_sectionsMap = localizationJson;
71-
_persistInternalMap();
71+
return _persistInternalMap();
7272
}
7373

7474
overridePickedLanguage(String locale) {
@@ -95,7 +95,7 @@ class LocalizationRepository {
9595
}
9696
}
9797

98-
_persistInternalMap() async {
98+
Future<void> _persistInternalMap() async {
9999
try {
100100
WidgetsFlutterBinding.ensureInitialized();
101101
final prefs = await SharedPreferences.getInstance();

0 commit comments

Comments
 (0)