Skip to content

Commit 3a1a9e2

Browse files
committed
Update Flutter SDK to add offline support
1 parent 14ca37d commit 3a1a9e2

21 files changed

+1158
-91
lines changed

CONTRIBUTING.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ sdk-generator/blob/master/example.php:
115115
Run the following command (make sure you have an updated docker version on your machine):
116116

117117
```bash
118-
docker run --rm -v $(pwd):/app -w /app php:7.4-cli php example.php
118+
docker run --rm -v $(pwd):/app -w /app php:8.1-cli php example.php
119119
```
120120

121121
>Note: You can just add the new language next to the other languages in the `example.php` file. You don't need to rewrite the file completely.
@@ -252,7 +252,7 @@ Also in `.travis.yml` add new env `SDK=[Language]` so that travis will run a tes
252252

253253
Finally, you can run tests using:
254254
```sh
255-
docker run --rm -v $(pwd):$(pwd):rw -w $(pwd) -v /var/run/docker.sock:/var/run/docker.sock php:7.4-cli-alpine sh -c "apk add docker-cli && vendor/bin/phpunit"
255+
docker run --rm -v $(pwd):$(pwd):rw -w $(pwd) -v /var/run/docker.sock:/var/run/docker.sock php:8.1-cli-alpine sh -c "apk add docker-cli && vendor/bin/phpunit"
256256
```
257257

258258
## SDK Generator Interface

src/SDK/Language/Flutter.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,16 @@ public function getFiles(): array
205205
'destination' => '/lib/src/interceptor.dart',
206206
'template' => 'flutter/lib/src/interceptor.dart.twig',
207207
],
208+
[
209+
'scope' => 'default',
210+
'destination' => '/lib/src/offline_db.dart',
211+
'template' => 'flutter/lib/src/offline_db.dart.twig',
212+
],
213+
[
214+
'scope' => 'default',
215+
'destination' => '/lib/src/client_offline_mixin.dart',
216+
'template' => 'flutter/lib/src/client_offline_mixin.dart.twig',
217+
],
208218
[
209219
'scope' => 'default',
210220
'destination' => '/lib/{{ language.params.packageName }}.dart',

templates/dart/lib/id.dart.twig

Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,40 @@
11
part of {{ language.params.packageName }};
22

33
class ID {
4-
ID._();
5-
6-
static String unique() {
7-
return 'unique()';
8-
}
4+
ID._();
5+
6+
// Generate a unique ID based on timestamp
7+
// Recreated from https://www.php.net/manual/en/function.uniqid.php
8+
static String _uniqid() {
9+
final now = DateTime.now();
10+
final secondsSinceEpoch = (now.millisecondsSinceEpoch / 1000).floor();
11+
final msecs = now.microsecondsSinceEpoch - secondsSinceEpoch * 1000000;
12+
return secondsSinceEpoch.toRadixString(16) +
13+
msecs.toRadixString(16).padLeft(5, '0');
14+
}
15+
16+
// Generate a unique ID with padding to have a longer ID
17+
// Recreated from https://github.com/utopia-php/database/blob/main/src/Database/ID.php#L13
18+
static String _unique({int padding = 7}) {
19+
String id = _uniqid();
20+
21+
if (padding > 0) {
22+
StringBuffer sb = StringBuffer();
23+
for (var i = 0; i < padding; i++) {
24+
sb.write(Random().nextInt(16).toRadixString(16));
25+
}
926

10-
static String custom(String id) {
11-
return id;
27+
id += sb.toString();
1228
}
13-
}
29+
30+
return id;
31+
}
32+
33+
static String unique() {
34+
return _unique();
35+
}
36+
37+
static String custom(String id) {
38+
return id;
39+
}
40+
}

templates/dart/lib/package.dart.twig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
library {{ language.params.packageName }};
22

33
import 'dart:async';
4+
import 'dart:math';
45
import 'dart:typed_data';
56

67
import 'src/enums.dart';

templates/flutter/base/requests/api.twig

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,20 @@
88
{{~ utils.map_headers(method.headers) }}
99
};
1010

11-
final res = await client.call(HttpMethod.{{ method.method | caseLower }}, path: path, params: params, headers: headers);
11+
final cacheModel = '{{method['offline']['model']}}'{% if method['offline']['model'] is not empty %}{% for parameter in method.parameters.path %}.replaceAll('{{ '{' }}{{ parameter.name | caseCamel }}{{ '}' }}', {{ parameter.name | caseCamel | overrideIdentifier }}){% endfor %}{% endif %};
12+
final cacheKey = {% if method['offline']['key'] starts with '{' and method['offline']['key'] ends with '}' %}{{method['offline']['key'] | replace({'{': '', '}': ''}) | overrideIdentifier }}{% else %}'{{method['offline']['key']}}'{% endif %};
13+
final cacheResponseIdKey = '{{method['offline']['response-key'] | escapeDollarSign}}';
14+
final cacheResponseContainerKey = '{% for property in spec.definitions[method.responseModel].properties %}{% if property.sub_schema and property.type == 'array' %}{{property.name}}{% endif %}{% endfor %}';
15+
16+
final res = await client.call(
17+
HttpMethod.{{ method.method | caseLower }},
18+
path: path,
19+
params: params,
20+
headers: headers,
21+
cacheModel: cacheModel,
22+
cacheKey: cacheKey,
23+
cacheResponseIdKey: cacheResponseIdKey,
24+
cacheResponseContainerKey: cacheResponseContainerKey,
25+
);
1226

1327
return {% if method.responseModel and method.responseModel != 'any' %}models.{{method.responseModel | caseUcfirst | overrideIdentifier}}.fromMap(res.data){% else %} res.data{% endif %};
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
11
name: {{ language.params.packageName }}_example
22
environment:
3-
sdk: '>=2.17.0 <3.0.0'
3+
sdk: ">=2.17.0 <3.0.0"
Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,27 @@
11
library {{ language.params.packageName }};
22

33
import 'dart:async';
4+
import 'dart:math';
45
import 'dart:typed_data';
56
import 'src/enums.dart';
67
import 'src/service.dart';
78
import 'src/input_file.dart';
89
import 'models.dart' as models;
910
import 'src/upload_progress.dart';
1011

11-
export 'src/response.dart';
1212
export 'src/client.dart';
1313
export 'src/exception.dart';
14+
export 'src/input_file.dart';
1415
export 'src/realtime.dart';
15-
export 'src/upload_progress.dart';
16-
export 'src/realtime_subscription.dart';
1716
export 'src/realtime_message.dart';
18-
export 'src/input_file.dart';
17+
export 'src/realtime_subscription.dart';
18+
export 'src/response.dart';
19+
export 'src/upload_progress.dart';
1920

20-
part 'query.dart';
21+
part 'id.dart';
2122
part 'permission.dart';
23+
part 'query.dart';
2224
part 'role.dart';
23-
part 'id.dart';
2425
{% for service in spec.services %}
2526
part 'services/{{service.name | caseDash}}.dart';
2627
{% endfor %}

templates/flutter/lib/src/client.dart.twig

Lines changed: 25 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
import 'enums.dart';
21
import 'client_stub.dart'
32
if (dart.library.html) 'client_browser.dart'
43
if (dart.library.io) 'client_io.dart';
4+
import 'enums.dart';
55
import 'response.dart';
66
import 'upload_progress.dart';
77

88
abstract class Client {
9-
static const int CHUNK_SIZE = 5*1024*1024;
9+
static const int CHUNK_SIZE = 5 * 1024 * 1024;
1010
late Map<String, String> config;
1111
late String _endPoint;
1212
late String? _endPointRealtime;
1313

1414
String get endPoint => _endPoint;
1515
String? get endPointRealtime => _endPointRealtime;
1616

17-
factory Client(
18-
{String endPoint = '{{ spec.endpoint }}',
19-
bool selfSigned = false}) =>
17+
factory Client({
18+
String endPoint = '{{ spec.endpoint }}',
19+
bool selfSigned = false,
20+
}) =>
2021
createClient(endPoint: endPoint, selfSigned: selfSigned);
2122

2223
Future webAuth(Uri url, {String? callbackUrlScheme});
@@ -38,17 +39,34 @@ abstract class Client {
3839

3940
{% for header in spec.global.headers %}
4041
{% if header.description %}
41-
/// {{header.description}}
42+
/// {{header.description}}
4243
{% endif %}
4344
Client set{{header.key | caseUcfirst}}(value);
4445
{% endfor %}
4546

4647
Client addHeader(String key, String value);
4748

48-
Future<Response> call(HttpMethod method, {
49+
Future<Response> call(
50+
HttpMethod method, {
4951
String path = '',
5052
Map<String, String> headers = const {},
5153
Map<String, dynamic> params = const {},
5254
ResponseType? responseType,
55+
String cacheModel = '',
56+
String cacheKey = '',
57+
String cacheResponseIdKey = '',
58+
String cacheResponseContainerKey = '',
59+
Map<String, Object?>? previous,
60+
});
61+
62+
Future<Client> setOfflinePersistency({
63+
bool status = true,
64+
void Function(Object)? onWriteQueueError,
5365
});
66+
67+
bool getOfflinePersistency();
68+
69+
Client setOfflineCacheSize(int kbytes);
70+
71+
int getOfflineCacheSize();
5472
}

templates/flutter/lib/src/client_base.dart.twig

Lines changed: 24 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1-
import 'response.dart';
21
import 'client.dart';
32
import 'enums.dart';
3+
import 'response.dart';
44

5-
abstract class ClientBase implements Client {
5+
abstract class ClientBase implements Client {
66
{% for header in spec.global.headers %}
77
{% if header.description %}
8-
/// {{header.description}}
8+
/// {{header.description}}
99
{% endif %}
1010
@override
1111
ClientBase set{{header.key | caseUcfirst}}(value);
12-
{% endfor %}
1312

13+
{% endfor %}
1414
@override
1515
ClientBase setSelfSigned({bool status = true});
1616

@@ -30,5 +30,25 @@ abstract class ClientBase implements Client {
3030
Map<String, String> headers = const {},
3131
Map<String, dynamic> params = const {},
3232
ResponseType? responseType,
33+
String cacheModel = '',
34+
String cacheKey = '',
35+
String cacheResponseIdKey = '',
36+
String cacheResponseContainerKey = '',
37+
Map<String, Object?>? previous,
38+
});
39+
40+
@override
41+
Future<ClientBase> setOfflinePersistency({
42+
bool status = true,
43+
void Function(Object)? onWriteQueueError,
3344
});
45+
46+
@override
47+
bool getOfflinePersistency();
48+
49+
@override
50+
ClientBase setOfflineCacheSize(int kbytes);
51+
52+
@override
53+
int getOfflineCacheSize();
3454
}

0 commit comments

Comments
 (0)