forked from aissat/easy_localization_loader
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathsmart_network_asset_loader.dart
More file actions
153 lines (122 loc) · 4.34 KB
/
smart_network_asset_loader.dart
File metadata and controls
153 lines (122 loc) · 4.34 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import 'dart:convert';
import 'dart:io';
import 'dart:ui';
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:easy_localization/easy_localization.dart';
import 'package:http/http.dart' as http;
import 'package:path_provider/path_provider.dart' as paths;
import 'package:flutter/services.dart';
/// ```dart
/// SmartNetworkAssetLoader(
/// assetsPath: 'assets/translations',
/// localCacheDuration: Duration(days: 1),
/// localeUrl: (String localeName) => Constants.appLangUrl,
/// timeout: Duration(seconds: 30),
/// )
/// ```
class SmartNetworkAssetLoader extends AssetLoader {
final Function localeUrl;
final Duration timeout;
final String assetsPath;
final Duration localCacheDuration;
SmartNetworkAssetLoader(
{required this.localeUrl,
this.timeout = const Duration(seconds: 30),
required this.assetsPath,
this.localCacheDuration = const Duration(days: 1)});
@override
Future<Map<String, dynamic>> load(String localePath, Locale locale) async {
var string = '';
// try loading local previously-saved localization file
if (await localTranslationExists(locale.toString())) {
string = await loadFromLocalFile(locale.toString());
}
// no local or failed, check if internet and download the file
if (string == '' && await isInternetConnectionAvailable()) {
string = await loadFromNetwork(locale.toString());
}
// local cache duration was reached or no internet access but prefer local file to assets
if (string == '' &&
await localTranslationExists(locale.toString(),
ignoreCacheDuration: true)) {
string = await loadFromLocalFile(locale.toString());
}
// still nothing? Load from assets
if (string == '') {
string = await rootBundle.loadString('$assetsPath/$locale.json');
}
// then returns the json file
return json.decode(string);
}
Future<bool> localeExists(String localePath) => Future.value(true);
Future<bool> isInternetConnectionAvailable() async {
final connectivityResult = await Connectivity().checkConnectivity();
if (connectivityResult.contains(ConnectivityResult.none)) {
return false;
} else {
try {
final result = await InternetAddress.lookup('google.com');
if (result.isNotEmpty && result[0].rawAddress.isNotEmpty) {
return true;
}
} on SocketException catch (_) {
return false;
}
}
return false;
}
Future<String> loadFromNetwork(String localeName) async {
String url = localeUrl(localeName);
url = '$url$localeName.json';
try {
final response =
await Future.any([http.get(Uri.parse(url)), Future.delayed(timeout)]);
if (response != null && response.statusCode == 200) {
var content = utf8.decode(response.bodyBytes);
// check valid json before saving it
if (json.decode(content) != null) {
await saveTranslation(localeName, content);
return content;
}
}
} catch (e) {
print(e.toString());
}
return '';
}
Future<bool> localTranslationExists(String localeName,
{bool ignoreCacheDuration = false}) async {
var translationFile = await getFileForLocale(localeName);
if (!await translationFile.exists()) {
return false;
}
// don't check file's age
if (!ignoreCacheDuration) {
var difference =
DateTime.now().difference(await translationFile.lastModified());
if (difference > (localCacheDuration)) {
return false;
}
}
return true;
}
Future<String> loadFromLocalFile(String localeName) async {
return await (await getFileForLocale(localeName)).readAsString();
}
Future<void> saveTranslation(String localeName, String content) async {
var file = File(await getFilenameForLocale(localeName));
await file.create(recursive: true);
await file.writeAsString(content);
return print('saved');
}
Future<String> get _localPath async {
final directory = await paths.getTemporaryDirectory();
return directory.path;
}
Future<String> getFilenameForLocale(String localeName) async {
return '${await _localPath}/translations/$localeName.json';
}
Future<File> getFileForLocale(String localeName) async {
return File(await getFilenameForLocale(localeName));
}
}