Skip to content

Commit b7d88ee

Browse files
committed
Null-safety support
1 parent aee8859 commit b7d88ee

File tree

13 files changed

+101
-88
lines changed

13 files changed

+101
-88
lines changed

CHANGELOG.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,11 @@
1+
## 0.5.0-dev.1
2+
3+
- Upgraded to Null-safety, minimum Dart SDK required 2.12.0 and minimum Flutter SDK version required 2.0.0
4+
- Upgraded all underlying dependencies to null safe version
5+
- All of Avatars service now return Future<Response></Response> instead of String like the Storage getFilePreview, getFileView and getFileDownload
6+
- Upgraded to Null-safety, minimum Dart SDK required 2.12.0
7+
- Upgraded all underlying dependencies to null safe version
8+
19
## 0.4.0
210

311
- Improved code quality

README.md

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
# Appwrite Flutter SDK
22

3-
[![pub package](https://img.shields.io/pub/v/appwrite.svg)](https://pub.dartlang.org/packages/appwrite)
4-
![License](https://img.shields.io/github/license/appwrite/sdk-for-flutter.svg?v=1)
5-
![Version](https://img.shields.io/badge/api%20version-0.7.0-blue.svg?v=1)
3+
[![pub package](https://img.shields.io/pub/v/appwrite?style=flat-square.svg)](https://pub.dartlang.org/packages/appwrite)
4+
![License](https://img.shields.io/github/license/appwrite/sdk-for-flutter.svg?style=flat-square)
5+
![Version](https://img.shields.io/badge/api%20version-0.7.0-blue.svg?style=flat-square)
6+
[![Twitter Account](https://img.shields.io/twitter/follow/appwrite_io?color=00acee&label=twitter&style=flat-square)](https://twitter.com/appwrite_io)
7+
[![Discord](https://img.shields.io/discord/564160730845151244?label=discord&style=flat-square)](https://appwrite.io/discord)
68

79
**This SDK is compatible with Appwrite server version 0.7.x. For older versions, please check [previous releases](https://github.com/appwrite/sdk-for-flutter/releases).**
810

@@ -20,7 +22,7 @@ Add this to your package's `pubspec.yaml` file:
2022

2123
```yml
2224
dependencies:
23-
appwrite: ^0.4.0
25+
appwrite: ^0.5.0-dev.1
2426
```
2527
2628
You can install packages from the command line:

example/pubspec.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
name: appwrite_example
2+
environment:
3+
sdk: '>=2.6.0 <3.0.0'

lib/appwrite.dart

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,6 @@ import 'dart:io';
44
import 'dart:convert';
55
import 'package:universal_html/html.dart' as html;
66
import 'package:dio/dio.dart';
7-
import 'package:meta/meta.dart';
87
import 'package:flutter/foundation.dart';
98
import 'package:flutter_web_auth/flutter_web_auth.dart';
109
import 'package:dio/adapter.dart';
@@ -14,7 +13,7 @@ import 'package:path_provider/path_provider.dart';
1413
import 'package:package_info_plus/package_info_plus.dart';
1514

1615

17-
export 'package:dio/dio.dart' show Response;
16+
export 'package:dio/dio.dart' show Response, MultipartFile;
1817

1918
part 'client.dart';
2019
part 'enums.dart';

lib/client.dart

Lines changed: 28 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -3,14 +3,14 @@ part of appwrite;
33
class Client {
44
String endPoint;
55
String type = 'unknown';
6-
Map<String, String> headers;
7-
Map<String, String> config;
6+
Map<String, String>? headers;
7+
late Map<String, String> config;
88
bool selfSigned;
99
bool initialized = false;
1010
Dio http;
11-
PersistCookieJar cookieJar;
11+
late PersistCookieJar cookieJar;
1212

13-
Client({this.endPoint = 'https://appwrite.io/v1', this.selfSigned = false, Dio http}) : this.http = http ?? Dio() {
13+
Client({this.endPoint = 'https://appwrite.io/v1', this.selfSigned = false, Dio? http}) : this.http = http ?? Dio() {
1414
// Platform is not supported in web so if web, set type to web automatically and skip Platform check
1515
if(kIsWeb) {
1616
type = 'web';
@@ -25,12 +25,13 @@ class Client {
2525

2626
this.headers = {
2727
'content-type': 'application/json',
28-
'x-sdk-version': 'appwrite:flutter:0.4.0',
28+
'x-sdk-version': 'appwrite:flutter:0.5.0-dev.1',
2929
};
3030

3131
this.config = {};
3232

3333
assert(endPoint.startsWith(RegExp("http://|https://")), "endPoint $endPoint must start with 'http'");
34+
init();
3435
}
3536

3637
Future<Directory> _getCookiePath() async {
@@ -66,31 +67,29 @@ class Client {
6667
}
6768

6869
Client addHeader(String key, String value) {
69-
headers[key] = value;
70+
headers![key] = value;
7071

7172
return this;
7273
}
7374

7475
Future init() async {
75-
if(!initialized) {
76-
// if web skip cookie implementation and origin header as those are automatically handled by browsers
77-
if(!kIsWeb) {
76+
// if web skip cookie implementation and origin header as those are automatically handled by browsers
77+
if(!kIsWeb) {
7878
final Directory cookieDir = await _getCookiePath();
79-
cookieJar = new PersistCookieJar(dir:cookieDir.path);
79+
cookieJar = new PersistCookieJar(storage: FileStorage(cookieDir.path));
8080
this.http.interceptors.add(CookieManager(cookieJar));
8181
PackageInfo packageInfo = await PackageInfo.fromPlatform();
82-
addHeader('Origin', 'appwrite-$type://${packageInfo.packageName ?? packageInfo.appName}');
83-
}else{
84-
// if web set httpClientAdapter as BrowserHttpClientAdapter with withCredentials true to make cookies work
82+
addHeader('Origin', 'appwrite-$type://${packageInfo.packageName}');
83+
} else {
84+
// if web set withCredentials true to make cookies work
8585
this.http.options.extra['withCredentials'] = true;
86-
}
87-
88-
this.http.options.baseUrl = this.endPoint;
89-
this.http.options.validateStatus = (status) => status < 400;
9086
}
87+
88+
this.http.options.baseUrl = this.endPoint;
89+
this.http.options.validateStatus = (status) => status! < 400;
9190
}
9291

93-
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}, ResponseType responseType}) async {
92+
Future<Response> call(HttpMethod method, {String path = '', Map<String, String> headers = const {}, Map<String, dynamic> params = const {}, ResponseType? responseType}) async {
9493
if(selfSigned && !kIsWeb) {
9594
// Allow self signed requests
9695
(http.httpClientAdapter as DefaultHttpClientAdapter).onHttpClientCreate = (HttpClient client) {
@@ -99,18 +98,21 @@ class Client {
9998
};
10099
}
101100

102-
await this.init();
101+
if(!initialized) {
102+
await this.init();
103+
}
103104

104105
// Origin is hardcoded for testing
105106
Options options = Options(
106-
headers: {...this.headers, ...headers},
107+
headers: {...this.headers!, ...headers},
107108
method: method.name(),
108-
responseType: responseType
109+
responseType: responseType,
110+
listFormat: ListFormat.multiCompatible
109111
);
110112

111113
try {
112114
if(headers['content-type'] == 'multipart/form-data') {
113-
return await http.request(path, data: FormData.fromMap(params), options: options);
115+
return await http.request(path, data: FormData.fromMap(params, ListFormat.multiCompatible), options: options);
114116
}
115117

116118
if (method == HttpMethod.get) {
@@ -127,16 +129,16 @@ class Client {
127129
throw AppwriteException(e.message);
128130
}
129131
if(responseType == ResponseType.bytes) {
130-
if(e.response.headers['content-type'].contains('application/json')) {
131-
final res = json.decode(utf8.decode(e.response.data));
132+
if(e.response!.headers['content-type']!.contains('application/json')) {
133+
final res = json.decode(utf8.decode(e.response!.data));
132134
throw AppwriteException(res['message'],res['code'], e.response);
133135
} else {
134136
throw AppwriteException(e.message);
135137
}
136138
}
137-
throw AppwriteException(e.response.data['message'],e.response.data['code'], e.response.data);
139+
throw AppwriteException(e.response!.data['message'],e.response!.data['code'], e.response!.data);
138140
} catch(e) {
139-
throw AppwriteException(e.message);
141+
throw AppwriteException(e.toString());
140142
}
141143
}
142144
}

lib/exception.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
part of appwrite;
22

33
class AppwriteException implements Exception {
4-
final String message;
5-
final int code;
4+
final String? message;
5+
final int? code;
66
final dynamic response;
77

88
AppwriteException([this.message = "", this.code, this.response]);

lib/services/account.dart

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ class Account extends Service {
3030
/// login to their new account, you need to create a new [account
3131
/// session](/docs/client/account#accountCreateSession).
3232
///
33-
Future<Response> create({@required String email, @required String password, String name = ''}) {
33+
Future<Response> create({required String email, required String password, String name = ''}) {
3434
final String path = '/account';
3535

3636
final Map<String, dynamic> params = {
@@ -74,7 +74,7 @@ class Account extends Service {
7474
/// mail is sent. For security measures, user password is required to complete
7575
/// this request.
7676
///
77-
Future<Response> updateEmail({@required String email, @required String password}) {
77+
Future<Response> updateEmail({required String email, required String password}) {
7878
final String path = '/account/email';
7979

8080
final Map<String, dynamic> params = {
@@ -111,7 +111,7 @@ class Account extends Service {
111111
///
112112
/// Update currently logged in user account name.
113113
///
114-
Future<Response> updateName({@required String name}) {
114+
Future<Response> updateName({required String name}) {
115115
final String path = '/account/name';
116116

117117
final Map<String, dynamic> params = {
@@ -130,7 +130,7 @@ class Account extends Service {
130130
/// Update currently logged in user password. For validation, user is required
131131
/// to pass the password twice.
132132
///
133-
Future<Response> updatePassword({@required String password, @required String oldPassword}) {
133+
Future<Response> updatePassword({required String password, required String oldPassword}) {
134134
final String path = '/account/password';
135135

136136
final Map<String, dynamic> params = {
@@ -167,7 +167,7 @@ class Account extends Service {
167167
/// Update currently logged in user account preferences. You can pass only the
168168
/// specific settings you wish to update.
169169
///
170-
Future<Response> updatePrefs({@required Map prefs}) {
170+
Future<Response> updatePrefs({required Map prefs}) {
171171
final String path = '/account/prefs';
172172

173173
final Map<String, dynamic> params = {
@@ -191,7 +191,7 @@ class Account extends Service {
191191
/// /account/recovery](/docs/client/account#accountUpdateRecovery) endpoint to
192192
/// complete the process.
193193
///
194-
Future<Response> createRecovery({@required String email, @required String url}) {
194+
Future<Response> createRecovery({required String email, required String url}) {
195195
final String path = '/account/recovery';
196196

197197
final Map<String, dynamic> params = {
@@ -218,7 +218,7 @@ class Account extends Service {
218218
/// the only valid redirect URLs are the ones from domains you have set when
219219
/// adding your platforms in the console interface.
220220
///
221-
Future<Response> updateRecovery({@required String userId, @required String secret, @required String password, @required String passwordAgain}) {
221+
Future<Response> updateRecovery({required String userId, required String secret, required String password, required String passwordAgain}) {
222222
final String path = '/account/recovery';
223223

224224
final Map<String, dynamic> params = {
@@ -258,7 +258,7 @@ class Account extends Service {
258258
/// Allow the user to login into their account by providing a valid email and
259259
/// password combination. This route will create a new session for the user.
260260
///
261-
Future<Response> createSession({@required String email, @required String password}) {
261+
Future<Response> createSession({required String email, required String password}) {
262262
final String path = '/account/sessions';
263263

264264
final Map<String, dynamic> params = {
@@ -298,7 +298,7 @@ class Account extends Service {
298298
/// first. Use the success and failure arguments to provide a redirect URL's
299299
/// back to your app when login is completed.
300300
///
301-
Future createOAuth2Session({@required String provider, String success = 'https://appwrite.io/auth/oauth2/success', String failure = 'https://appwrite.io/auth/oauth2/failure', List scopes = const []}) {
301+
Future createOAuth2Session({required String provider, String success = 'https://appwrite.io/auth/oauth2/success', String failure = 'https://appwrite.io/auth/oauth2/failure', List scopes = const []}) {
302302
final String path = '/account/sessions/oauth2/{provider}'.replaceAll(RegExp('{provider}'), provider);
303303

304304
final Map<String, dynamic> params = {
@@ -332,15 +332,15 @@ class Account extends Service {
332332

333333
if(kIsWeb) {
334334
html.window.location.href = url.toString();
335-
return null;
335+
return Future.value();
336336
}else{
337337

338338
return FlutterWebAuth.authenticate(
339339
url: url.toString(),
340-
callbackUrlScheme: "appwrite-callback-" + client.config['project']
340+
callbackUrlScheme: "appwrite-callback-" + client.config['project']!
341341
).then((value) async {
342342
Uri url = Uri.parse(value);
343-
Cookie cookie = new Cookie(url.queryParameters['key'], url.queryParameters['secret']);
343+
Cookie cookie = new Cookie(url.queryParameters['key']!, url.queryParameters['secret']!);
344344
cookie.domain = Uri.parse(client.endPoint).host;
345345
cookie.httpOnly = true;
346346
cookie.path = '/';
@@ -358,7 +358,7 @@ class Account extends Service {
358358
/// account sessions across all of their different devices. When using the
359359
/// option id argument, only the session unique ID provider will be deleted.
360360
///
361-
Future<Response> deleteSession({@required String sessionId}) {
361+
Future<Response> deleteSession({required String sessionId}) {
362362
final String path = '/account/sessions/{sessionId}'.replaceAll(RegExp('{sessionId}'), sessionId);
363363

364364
final Map<String, dynamic> params = {
@@ -388,7 +388,7 @@ class Account extends Service {
388388
/// adding your platforms in the console interface.
389389
///
390390
///
391-
Future<Response> createVerification({@required String url}) {
391+
Future<Response> createVerification({required String url}) {
392392
final String path = '/account/verification';
393393

394394
final Map<String, dynamic> params = {
@@ -409,7 +409,7 @@ class Account extends Service {
409409
/// to verify the user email ownership. If confirmed this route will return a
410410
/// 200 status code.
411411
///
412-
Future<Response> updateVerification({@required String userId, @required String secret}) {
412+
Future<Response> updateVerification({required String userId, required String secret}) {
413413
final String path = '/account/verification';
414414

415415
final Map<String, dynamic> params = {

lib/services/avatars.dart

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ class Avatars extends Service {
1111
/// /account/sessions endpoint. Use width, height and quality arguments to
1212
/// change the output settings.
1313
///
14-
Future<Response> getBrowser({@required String code, int width = 100, int height = 100, int quality = 100}) {
14+
Future<Response> getBrowser({required String code, int width = 100, int height = 100, int quality = 100}) {
1515
final String path = '/avatars/browsers/{code}'.replaceAll(RegExp('{code}'), code);
1616

1717
final Map<String, dynamic> params = {
@@ -34,7 +34,7 @@ class Avatars extends Service {
3434
/// provider you need. Use width, height and quality arguments to change the
3535
/// output settings.
3636
///
37-
Future<Response> getCreditCard({@required String code, int width = 100, int height = 100, int quality = 100}) {
37+
Future<Response> getCreditCard({required String code, int width = 100, int height = 100, int quality = 100}) {
3838
final String path = '/avatars/credit-cards/{code}'.replaceAll(RegExp('{code}'), code);
3939

4040
final Map<String, dynamic> params = {
@@ -57,7 +57,7 @@ class Avatars extends Service {
5757
/// website URL.
5858
///
5959
///
60-
Future<Response> getFavicon({@required String url}) {
60+
Future<Response> getFavicon({required String url}) {
6161
final String path = '/avatars/favicon';
6262

6363
final Map<String, dynamic> params = {
@@ -78,7 +78,7 @@ class Avatars extends Service {
7878
/// users. The code argument receives the 2 letter country code. Use width,
7979
/// height and quality arguments to change the output settings.
8080
///
81-
Future<Response> getFlag({@required String code, int width = 100, int height = 100, int quality = 100}) {
81+
Future<Response> getFlag({required String code, int width = 100, int height = 100, int quality = 100}) {
8282
final String path = '/avatars/flags/{code}'.replaceAll(RegExp('{code}'), code);
8383

8484
final Map<String, dynamic> params = {
@@ -102,7 +102,7 @@ class Avatars extends Service {
102102
/// remote images in your app or in case you want to make sure a 3rd party
103103
/// image is properly served using a TLS protocol.
104104
///
105-
Future<Response> getImage({@required String url, int width = 400, int height = 400}) {
105+
Future<Response> getImage({required String url, int width = 400, int height = 400}) {
106106
final String path = '/avatars/image';
107107

108108
final Map<String, dynamic> params = {
@@ -156,7 +156,7 @@ class Avatars extends Service {
156156
/// Converts a given plain text to a QR code image. You can use the query
157157
/// parameters to change the size and style of the resulting image.
158158
///
159-
Future<Response> getQR({@required String text, int size = 400, int margin = 1, bool download = false}) {
159+
Future<Response> getQR({required String text, int size = 400, int margin = 1, bool download = false}) {
160160
final String path = '/avatars/qr';
161161

162162
final Map<String, dynamic> params = {

0 commit comments

Comments
 (0)