Skip to content

Commit 130121e

Browse files
authored
Release/1.0.22 (parse-community#193)
* Added repo example * create CoreStore interface to allow different implements for local storage (parse-community#166) (parse-community#167) implement default local store using sembast and with encryption using XXTEA algorithm add desktop support in example project * Lint/Code clean * Some dart linter fixes (parse-community#171) * Support Relation (parse-community#179) * create CoreStore interface to allow different implements for local storage (parse-community#166) implement default local store using sembast and with encryption using XXTEA algorithm add desktop support in example project * make parse shared preferences default store (parse-community#168) * add decion page to detect parse server availability throw execption if server url is empty navigate to correct page base on current user state * working on example throw exception if sever url is empty add decision page to check availability of parse server navigate to screen base on current user state * create example flow for login and signup display list of diet plan items and allow to remove and update it's status * add shared preferences corestore fix bug when create custom corestore implementation * use shared shared preferences in example * make parse shared preferences default store * Update application_constants.dart * README.md updated from https://stackedit.io/ * Support Relation. * delete vscode config * Update .gitignore * Fix Commit: 6ed26e1 (parse-community#181) * Delete `toJson` and fix exception. (parse-community#187) * Fix Commit: 6ed26e1 * Update parse_encoder.dart Fix parse encoder bug. * Fix exception when sendSessionId is null. * delete toJson calling. * Save recursively (parse-community#190) * Fix Commit: 6ed26e1 * Update parse_encoder.dart Fix parse encoder bug. * Fix exception when sendSessionId is null. * 1. Support save objects recursively. 2. Fix encoding for Add and Remove operations. 3. Fix some exceptions. 4. Support batch request and handle response. * Implemented whereRelatedTo query (parse-community#192) * Implemented querying for related objects defined based on a field of type Relation * Implemented unit test for relatedTo query * Release v1.0.22 - Fix CoreStore bug
1 parent 97eb06d commit 130121e

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

41 files changed

+709
-352
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,5 @@ build/
1010
.idea
1111
example/ios/Frameworks/
1212
example/lib/ui/
13+
14+
.vscode/

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
## 1.0.22
2+
13
## 1.0.21
24
LiveQuery fix
35
Logout fix

README.md

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ Want to get involved? Join our Slack channel and help out! (http://flutter-parse
1515
To install, either add to your pubspec.yaml
1616
```yml
1717
dependencies:
18-
parse_server_sdk: ^1.0.21
18+
parse_server_sdk: ^1.0.22
1919
```
2020
or clone this repository and add to your project. As this is an early development with multiple contributors, it is probably best to download/clone and keep updating as an when a new feature is added.
2121
@@ -163,9 +163,9 @@ var response = await dietPlan.remove("listKeywords", ["a"]);
163163
or using with save function
164164

165165
```dart
166-
dietPlan.setAdd('listKeywords', ['a','a','d']);
167-
dietPlan.setAddUnique('listKeywords', ['a','a','d']);
168-
dietPlan.setRemove('listKeywords', ['a']);
166+
dietPlan.setAddAll('listKeywords', ['a','a','d']);
167+
dietPlan.setAddAllUnique('listKeywords', ['a','a','d']);
168+
dietPlan.setRemoveAll('listKeywords', ['a']);
169169
var response = dietPlan.save()
170170
```
171171

@@ -539,6 +539,21 @@ final Map<String, String> params = <String, String>{'plan': 'paid'};
539539
function.execute(parameters: params);
540540
```
541541

542+
## Relation
543+
The SDK supports Relation.
544+
545+
To Retrive a relation instance for user, call:
546+
```dart
547+
final relation = user.getRelation('dietPlans');
548+
```
549+
550+
and then you can add a relation to the passed in object.
551+
552+
```dart
553+
relation.add(dietPlan);
554+
final result = await user.save();
555+
```
556+
542557
## Other Features of this library
543558
Main:
544559
* Installation (View the example application)

example/lib/data/repositories/user/provider_db_user.dart

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ class UserProviderDB implements UserProviderContract {
7979

8080
Map<String, dynamic> convertItemToStorageMap(User item) {
8181
final Map<String, dynamic> values = Map<String, dynamic>();
82+
// ignore: invalid_use_of_protected_member
8283
values['value'] = json.jsonEncode(item.toJson(full: true));
8384
values[keyVarObjectId] = item.objectId;
8485
item.updatedAt != null
@@ -90,8 +91,7 @@ class UserProviderDB implements UserProviderContract {
9091
User convertRecordToItem({Record record, Map<String, dynamic> values}) {
9192
try {
9293
values ??= record.value;
93-
final User item =
94-
User.clone().fromJson(json.jsonDecode(values['value']));
94+
final User item = User.clone().fromJson(json.jsonDecode(values['value']));
9595
return item;
9696
} catch (e) {
9797
return null;

example/lib/main.dart

Lines changed: 54 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ import 'package:flutter_plugin_example/data/repositories/diet_plan/repository_di
1010
import 'package:flutter_plugin_example/data/repositories/user/repository_user.dart';
1111
import 'package:flutter_plugin_example/domain/constants/application_constants.dart';
1212
import 'package:flutter_plugin_example/domain/utils/db_utils.dart';
13-
import 'package:flutter_plugin_example/pages/decision_page.dart';
1413
import 'package:flutter_stetho/flutter_stetho.dart';
1514
import 'package:parse_server_sdk/parse_server_sdk.dart';
1615

@@ -41,69 +40,82 @@ class MyApp extends StatefulWidget {
4140
class _MyAppState extends State<MyApp> {
4241
DietPlanRepository dietPlanRepo;
4342
UserRepository userRepo;
43+
44+
String text = '';
45+
4446
@override
4547
void initState() {
4648
super.initState();
47-
// initData();
49+
initData();
4850
}
4951

5052
@override
5153
Widget build(BuildContext context) {
5254
return MaterialApp(
53-
debugShowCheckedModeBanner: false,
54-
theme: ThemeData(
55-
primarySwatch: Colors.blue,
55+
home: Scaffold(
56+
appBar: AppBar(
57+
title: const Text('Plugin example app'),
58+
),
59+
body: Center(
60+
child: Text(text),
5661
),
57-
title: 'Parse Server Example',
58-
home: DecisionPage());
62+
),
63+
);
5964
}
6065

6166
Future<void> initData() async {
6267
// Initialize repository
63-
// await initRepository();
68+
await initRepository();
6469

6570
// Initialize parse
6671
Parse().initialize(keyParseApplicationId, keyParseServerUrl,
6772
masterKey: keyParseMasterKey, debug: true);
6873

6974
//parse serve with secure store and desktop support
7075

71-
// Parse().initialize(keyParseApplicationId, keyParseServerUrl,
72-
// masterKey: keyParseMasterKey,
73-
// debug: true,
74-
// coreStore: CoreStoreImp.getInstance());
76+
// Parse().initialize(keyParseApplicationId, keyParseServerUrl,
77+
// masterKey: keyParseMasterKey,
78+
// debug: true,
79+
// coreStore: CoreStoreImp.getInstance());
7580

7681
// Check server is healthy and live - Debug is on in this instance so check logs for result
7782
final ParseResponse response = await Parse().healthCheck();
7883

7984
if (response.success) {
8085
await runTestQueries();
81-
print('runTestQueries');
86+
text += 'runTestQueries\n';
87+
print(text);
8288
} else {
83-
print('Server health check failed');
89+
text += 'Server health check failed';
90+
print(text);
8491
}
8592
}
8693

8794
Future<void> runTestQueries() async {
8895
// Basic repository example
89-
//await repositoryAddUser();
90-
//await repositoryAddItems();
91-
//await repositoryGetAllItems();
96+
await repositoryAddUser();
97+
await repositoryAddItems();
98+
await repositoryGetAllItems();
9299

93100
//Basic usage
94-
// createItem();
95-
// getAllItems();
96-
// getAllItemsByName();
97-
// getSingleItem();
98-
// getConfigs();
99-
// query();
100-
// initUser();
101-
// var instalattion = await ParseInstallation.currentInstallation();
102-
// var rees = instalattion.create();
103-
// print(rees);
104-
//function();
105-
//functionWithParameters();
106-
// test();
101+
await createItem();
102+
await getAllItems();
103+
await getAllItemsByName();
104+
await getSingleItem();
105+
await getConfigs();
106+
await query();
107+
await initUser();
108+
await initInstallation();
109+
await function();
110+
await functionWithParameters();
111+
await test();
112+
}
113+
114+
Future<void> initInstallation() async {
115+
final ParseInstallation installation =
116+
await ParseInstallation.currentInstallation();
117+
final ParseResponse response = await installation.create();
118+
print(response);
107119
}
108120

109121
Future<void> test() async {
@@ -240,13 +252,13 @@ class _MyAppState extends State<MyApp> {
240252
/// Update current user from server - Best done to verify user is still a valid user
241253
response = await ParseUser.getCurrentUserFromServer(
242254
token: user?.get<String>(keyHeaderSessionToken));
243-
if (response.success) {
255+
if (response?.success ?? false) {
244256
user = response.result;
245257
}
246258

247259
/// log user out
248-
response = await user.logout();
249-
if (response.success) {
260+
response = await user?.logout();
261+
if (response?.success ?? false) {
250262
user = response.result;
251263
}
252264

@@ -359,13 +371,13 @@ class _MyAppState extends State<MyApp> {
359371
dietPlanRepo ??= DietPlanRepository.init(await getDB());
360372
userRepo ??= UserRepository.init(await getDB());
361373
}
362-
363-
String dietPlansToAdd =
364-
'[{"className":"Diet_Plans","Name":"Textbook","Description":"For an active lifestyle and a straight forward macro plan, we suggest this plan.","Fat":25,"Carbs":50,"Protein":25,"Status":0},'
365-
'{"className":"Diet_Plans","Name":"Body Builder","Description":"Default Body Builders Diet","Fat":20,"Carbs":40,"Protein":40,"Status":0},'
366-
'{"className":"Diet_Plans","Name":"Zone Diet","Description":"Popular with CrossFit users. Zone Diet targets similar macros.","Fat":30,"Carbs":40,"Protein":30,"Status":0},'
367-
'{"className":"Diet_Plans","Name":"Low Fat","Description":"Low fat diet.","Fat":15,"Carbs":60,"Protein":25,"Status":0},'
368-
'{"className":"Diet_Plans","Name":"Low Carb","Description":"Low Carb diet, main focus on quality fats and protein.","Fat":35,"Carbs":25,"Protein":40,"Status":0},'
369-
'{"className":"Diet_Plans","Name":"Paleo","Description":"Paleo diet.","Fat":60,"Carbs":25,"Protein":10,"Status":0},'
370-
'{"className":"Diet_Plans","Name":"Ketogenic","Description":"High quality fats, low carbs.","Fat":65,"Carbs":5,"Protein":30,"Status":0}]';
371374
}
375+
376+
const String dietPlansToAdd =
377+
'[{"className":"Diet_Plans","Name":"Textbook","Description":"For an active lifestyle and a straight forward macro plan, we suggest this plan.","Fat":25,"Carbs":50,"Protein":25,"Status":0},'
378+
'{"className":"Diet_Plans","Name":"Body Builder","Description":"Default Body Builders Diet","Fat":20,"Carbs":40,"Protein":40,"Status":0},'
379+
'{"className":"Diet_Plans","Name":"Zone Diet","Description":"Popular with CrossFit users. Zone Diet targets similar macros.","Fat":30,"Carbs":40,"Protein":30,"Status":0},'
380+
'{"className":"Diet_Plans","Name":"Low Fat","Description":"Low fat diet.","Fat":15,"Carbs":60,"Protein":25,"Status":0},'
381+
'{"className":"Diet_Plans","Name":"Low Carb","Description":"Low Carb diet, main focus on quality fats and protein.","Fat":35,"Carbs":25,"Protein":40,"Status":0},'
382+
'{"className":"Diet_Plans","Name":"Paleo","Description":"Paleo diet.","Fat":60,"Carbs":25,"Protein":10,"Status":0},'
383+
'{"className":"Diet_Plans","Name":"Ketogenic","Description":"High quality fats, low carbs.","Fat":65,"Carbs":5,"Protein":30,"Status":0}]';

example/lib/pages/decision_page.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class _DecisionPageState extends State<DecisionPage> {
8888
final MaterialPageRoute<bool> newRoute =
8989
MaterialPageRoute<bool>(builder: (BuildContext context) => page);
9090

91-
bool nav = await Navigator.of(context)
91+
final bool nav = await Navigator.of(context)
9292
.pushAndRemoveUntil<bool>(newRoute, ModalRoute.withName('/'));
9393
if (nav == true) {
9494
_initParse();

example/lib/pages/home_page.dart

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ import 'package:flutter_plugin_example/data/repositories/diet_plan/contract_prov
88
import 'package:parse_server_sdk/parse_server_sdk.dart';
99

1010
class HomePage extends StatefulWidget {
11-
HomePage(this._dietPlanProvider);
11+
const HomePage(this._dietPlanProvider);
12+
1213
final DietPlanProviderContract _dietPlanProvider;
1314

1415
@override
1516
_HomePageState createState() => _HomePageState();
1617
}
1718

1819
class _HomePageState extends State<HomePage> {
19-
List<DietPlan> randomDietPlans = [];
20+
List<DietPlan> randomDietPlans = <DietPlan>[];
2021

2122
@override
2223
void initState() {
@@ -50,9 +51,9 @@ class _HomePageState extends State<HomePage> {
5051
body: _showDietList(),
5152
floatingActionButton: FloatingActionButton(
5253
onPressed: () async {
53-
DietPlan dietPlan =
54+
final DietPlan dietPlan =
5455
randomDietPlans[Random().nextInt(randomDietPlans.length - 1)];
55-
ParseUser user = await ParseUser.currentUser();
56+
final ParseUser user = await ParseUser.currentUser();
5657
dietPlan.set('user', user);
5758
await widget._dietPlanProvider.add(dietPlan);
5859
setState(() {});
@@ -80,15 +81,15 @@ class _HomePageState extends State<HomePage> {
8081
shrinkWrap: true,
8182
itemCount: snapshot.data.results.length,
8283
itemBuilder: (BuildContext context, int index) {
83-
DietPlan dietPlan = snapshot.data.results[index];
84-
String id = dietPlan.objectId;
85-
String name = dietPlan.name;
86-
String description = dietPlan.description;
87-
bool status = dietPlan.status;
84+
final DietPlan dietPlan = snapshot.data.results[index];
85+
final String id = dietPlan.objectId;
86+
final String name = dietPlan.name;
87+
final String description = dietPlan.description;
88+
final bool status = dietPlan.status;
8889
return Dismissible(
8990
key: Key(id),
9091
background: Container(color: Colors.red),
91-
onDismissed: (direction) async {
92+
onDismissed: (DismissDirection direction) async {
9293
widget._dietPlanProvider.remove(dietPlan);
9394
},
9495
child: ListTile(

example/lib/pages/login_page.dart

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ class LoginPage extends StatefulWidget {
1010
}
1111

1212
class _LoginPageState extends State<LoginPage> {
13-
final _formKey = GlobalKey<FormState>();
13+
final GlobalKey<FormState> _formKey = GlobalKey<FormState>();
1414

1515
String _email;
1616
String _password;
@@ -22,7 +22,7 @@ class _LoginPageState extends State<LoginPage> {
2222

2323
// Check if form is valid before perform login or signup
2424
bool _validateAndSave() {
25-
final form = _formKey.currentState;
25+
final FormState form = _formKey.currentState;
2626
if (form.validate()) {
2727
form.save();
2828
return true;
@@ -33,11 +33,11 @@ class _LoginPageState extends State<LoginPage> {
3333
// Perform login or signup
3434
Future<void> _validateAndSubmit() async {
3535
setState(() {
36-
_errorMessage = "";
36+
_errorMessage = '';
3737
_isLoading = true;
3838
});
3939
if (_validateAndSave()) {
40-
User user = User(_email, _password, _email);
40+
final User user = User(_email, _password, _email);
4141

4242
ParseResponse response;
4343
try {
@@ -73,22 +73,22 @@ class _LoginPageState extends State<LoginPage> {
7373

7474
@override
7575
void initState() {
76-
_errorMessage = "";
76+
_errorMessage = '';
7777
_isLoading = false;
7878
super.initState();
7979
}
8080

8181
void _changeFormToSignUp() {
8282
_formKey.currentState.reset();
83-
_errorMessage = "";
83+
_errorMessage = '';
8484
setState(() {
8585
_formMode = FormMode.SIGNUP;
8686
});
8787
}
8888

8989
void _changeFormToLogin() {
9090
_formKey.currentState.reset();
91-
_errorMessage = "";
91+
_errorMessage = '';
9292
setState(() {
9393
_formMode = FormMode.LOGIN;
9494
});
@@ -185,8 +185,8 @@ class _LoginPageState extends State<LoginPage> {
185185
Icons.mail,
186186
color: Colors.grey,
187187
)),
188-
validator: (value) => value.isEmpty ? 'Email can\'t be empty' : null,
189-
onSaved: (value) => _email = value,
188+
validator: (String value) => value.isEmpty ? 'Email can\'t be empty' : null,
189+
onSaved: (String value) => _email = value,
190190
),
191191
);
192192
}
@@ -204,8 +204,8 @@ class _LoginPageState extends State<LoginPage> {
204204
Icons.lock,
205205
color: Colors.grey,
206206
)),
207-
validator: (value) => value.isEmpty ? 'Password can\'t be empty' : null,
208-
onSaved: (value) => _password = value,
207+
validator: (String value) => value.isEmpty ? 'Password can\'t be empty' : null,
208+
onSaved: (String value) => _password = value,
209209
),
210210
);
211211
}

example/windows/find_vcvars.dart

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@
1717
import 'dart:io';
1818

1919
int main() {
20-
final programDir = Platform.environment['PROGRAMFILES(X86)'];
21-
final pathPrefix = '$programDir\\Microsoft Visual Studio';
22-
const pathSuffix = 'VC\\Auxiliary\\Build\\vcvars64.bat';
23-
final years = ['2017', '2019'];
24-
final flavors = ['Community', 'Professional', 'Enterprise', 'Preview'];
25-
for (final year in years) {
26-
for (final flavor in flavors) {
27-
final testPath = '$pathPrefix\\$year\\$flavor\\$pathSuffix';
20+
final String programDir = Platform.environment['PROGRAMFILES(X86)'];
21+
final String pathPrefix = '$programDir\\Microsoft Visual Studio';
22+
const String pathSuffix = 'VC\\Auxiliary\\Build\\vcvars64.bat';
23+
final List<String> years = <String>['2017', '2019'];
24+
final List<String> flavors = <String>[
25+
'Community', 'Professional', 'Enterprise', 'Preview'];
26+
for (final String year in years) {
27+
for (final String flavor in flavors) {
28+
final String testPath = '$pathPrefix\\$year\\$flavor\\$pathSuffix';
2829
if (File(testPath).existsSync()) {
2930
print(testPath);
3031
return 0;

0 commit comments

Comments
 (0)