Skip to content

Fixed ignored forceUpdate and dirty ParseObject when deserialized from json #253

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 12 commits into from
Closed
87 changes: 30 additions & 57 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
![enter image description here](https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png)
![enter image description here](https://i2.wp.com/blog.openshift.com/wp-content/uploads/parse-server-logo-1.png?fit=200%2C200&ssl=1&resize=350%2C200)

[![Build Status](https://travis-ci.org/phillwiggins/flutter_parse_sdk.svg?branch=master)](https://travis-ci.org/phillwiggins/flutter_parse_sdk)
![Parse Logo](https://upload.wikimedia.org/wikipedia/commons/1/17/Google-flutter-logo.png)![Flutter Logo](https://i2.wp.com/blog.openshift.com/wp-content/uploads/parse-server-logo-1.png?fit=200%2C200&ssl=1&resize=350%2C200)

## Parse For Flutter!
Hi, this is a Flutter plugin that allows communication with a Parse Server, (https://parseplatform.org) either hosted on your own server or another, like (http://Back4App.com).
Expand All @@ -23,31 +21,32 @@ or clone this repository and add to your project. As this is an early developmen
Once you have the library added to your project, upon first call to your app (Similar to what your application class would be) add the following...

```dart
await Parse().initialize(
ApplicationConstants.keyApplicationId,
ApplicationConstants.keyParseServerUrl);
await Parse().initialize(
keyApplicationId,
keyParseServerUrl);
```
if you want to use secure storage also that's allow using sdk on desktop application

If you want to use secure storage or use the Flutter web/desktop SDK, please change to the below instance of CoreStorage as it has no dependencies on Flutter.
```dart

await Parse().initialize(keyParseApplicationId, keyParseServerUrl,
masterKey: keyParseMasterKey,
debug: true,
coreStore: await CoreStoreSembastImp.getInstance());
await Parse().initialize(
keyParseApplicationId,
keyParseServerUrl,
coreStore: await CoreStoreSembastImp.getInstance());
```
It's possible to add other params, such as ...
It's possible to add other parameters to work with your instance of Parse Server:-

```dart
await Parse().initialize(
ApplicationConstants.keyApplicationId,
ApplicationConstants.keyParseServerUrl,
masterKey: ApplicationConstants.keyParseMasterKey,
clientKey: ApplicationConstants.keyParseClientKey,
debug: true,
liveQueryUrl: ApplicationConstants.keyLiveQueryUrl,
autoSendSessionId: true,
securityContext: securityContext,
coreStore: await CoreStoreSharedPrefsImp.getInstance());
keyApplicationId,
keyParseServerUrl,
masterKey: keyParseMasterKey, // Required for Back4App and others
clientKey: keyParseClientKey, // Required for some setups
debug: true, // When enabled, prints logs to console
liveQueryUrl: keyLiveQueryUrl, // Required if using LiveQuery
autoSendSessionId: true, // Some confurations require this to be true
securityContext: securityContext, // Again, required for some setups
coreStore: await CoreStoreSharedPrefsImp.getInstance()); // Will use SharedPreferences instead of Sembast as an internal DB
```

## Objects
Expand All @@ -56,13 +55,13 @@ You can create custom objects by calling:
var dietPlan = ParseObject('DietPlan')
..set('Name', 'Ketogenic')
..set('Fat', 65);
await dietPlan.save()
await dietPlan.save();
```
Verify that the object has been successfully saved using
```dart
var response = await dietPlan.save();
if (response.success) {
dietPlan = response.result;
dietPlan = response.results.first;
}
```
Types supported:
Expand Down Expand Up @@ -134,14 +133,6 @@ and to retrieve it
var dietPlan = DietPlan().fromPin('OBJECT ID OF OBJECT');
```

## Storage
We now have 2 types of storage, secure and unsecure. We currently rely on 2 third party options:

* SharedPreferences
* Sembast

Sembast offers secured storage, whilst SharePreferences wraps NSUserDefaults (on iOS) and SharedPreferences (on Android).

## Increment Counter values in objects
Retrieve it, call

Expand Down Expand Up @@ -172,9 +163,9 @@ var response = await dietPlan.remove("listKeywords", ["a"]);
or using with save function

```dart
dietPlan.setAddAll('listKeywords', ['a','a','d']);
dietPlan.setAddAllUnique('listKeywords', ['a','a','d']);
dietPlan.setRemoveAll('listKeywords', ['a']);
dietPlan.setAdd('listKeywords', ['a','a','d']);
dietPlan.setAddUnique('listKeywords', ['a','a','d']);
dietPlan.setRemove('listKeywords', ['a']);
var response = dietPlan.save()
```

Expand Down Expand Up @@ -214,7 +205,7 @@ var queryBuilder = QueryBuilder<DietPlan>(DietPlan())
var response = await queryBuilder.query();

if (response.success) {
print(ApplicationConstants.keyAppName + ": " + ((response.result as List<dynamic>).first as DietPlan).toString());
print(ApplicationConstants.keyAppName + ": " + ((response.results as List<dynamic>).first as DietPlan).toString());
} else {
print(ApplicationConstants.keyAppName + ": " + response.exception.message);
}
Expand Down Expand Up @@ -304,11 +295,11 @@ The Parse Server configuration guide on the server is found here https://docs.pa
Initialize the Parse Live Query by entering the parameter liveQueryUrl in Parse().initialize:
```dart
Parse().initialize(
ApplicationConstants.keyApplicationId,
ApplicationConstants.keyParseServerUrl,
clientKey: ApplicationConstants.keyParseClientKey,
keyApplicationId,
keyParseServerUrl,
clientKey: keyParseClientKey,
debug: true,
liveQueryUrl: ApplicationConstants.keyLiveQueryUrl,
liveQueryUrl: keyLiveQueryUrl,
autoSendSessionId: true);
```

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

## Relation
The SDK supports Relation.

To Retrive a relation instance for user, call:
```dart
final relation = user.getRelation('dietPlans');
```

and then you can add a relation to the passed in object.

```dart
relation.add(dietPlan);
final result = await user.save();
```

## Other Features of this library
Main:
* Installation (View the example application)
Expand All @@ -584,6 +560,3 @@ Objects:

## Author:-
This project was authored by Phill Wiggins. You can contact me at [email protected]
<!--stackedit_data:
eyJoaXN0b3J5IjpbLTU4MDA4MDUwNCw3MTg2NTA0MjBdfQ==
-->
8 changes: 4 additions & 4 deletions example/lib/domain/constants/application_constants.dart
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
const String keyApplicationName = 'BodyCal';
const String keyParseApplicationId = 'bodycaldb';
const String keyParseMasterKey = '343gf35g4t6hev445f4t5f45g45d';
const String keyParseServerUrl = 'http://45.76.129.16:1338/parse/';
const String keyApplicationName = '';
const String keyParseApplicationId = '';
const String keyParseMasterKey = '';
const String keyParseServerUrl = '';
34 changes: 14 additions & 20 deletions lib/src/objects/parse_base.dart
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ abstract class ParseBase {
if (value is ParseObject && value._areChildrenDirty(seenObjects)) {
return true;
}
return false;
});
return false;
}
Expand Down Expand Up @@ -120,23 +121,23 @@ abstract class ParseBase {
if (key == parseClassName || key == '__type') {
// NO OP
} else if (key == keyVarObjectId) {
objectId = value;
_getObjectData()[keyVarObjectId] = value;
} else if (key == keyVarCreatedAt) {
if (keyVarCreatedAt is String) {
set<DateTime>(keyVarCreatedAt, _parseDateFormat.parse(value));
_getObjectData()[keyVarCreatedAt] = _parseDateFormat.parse(value);
} else {
set<DateTime>(keyVarCreatedAt, value);
_getObjectData()[keyVarCreatedAt] = value;
}
} else if (key == keyVarUpdatedAt) {
if (keyVarUpdatedAt is String) {
set<DateTime>(keyVarUpdatedAt, _parseDateFormat.parse(value));
_getObjectData()[keyVarUpdatedAt] = _parseDateFormat.parse(value);
} else {
set<DateTime>(keyVarUpdatedAt, value);
_getObjectData()[keyVarUpdatedAt] = _parseDateFormat.parse(value);
}
} else if (key == keyVarAcl) {
this[keyVarAcl] = ParseACL().fromJson(value);
_getObjectData()[keyVarAcl] = ParseACL().fromJson(value);
} else {
this[key] = parseDecode(value);
_getObjectData()[key] = parseDecode(value);
}
});

Expand Down Expand Up @@ -175,27 +176,22 @@ abstract class ParseBase {
/// Saves in storage
Future<void> saveInStorage(String key) async {
final String objectJson = json.encode(toJson(full: true));
ParseCoreData().getStore()
..setString(key, objectJson);
await ParseCoreData().getStore().setString(key, objectJson);
}

/// Sets type [T] from objectData
///
/// To set an int, call setType<int> and an int will be saved
/// [bool] forceUpdate is always true, if unsure as to whether an item is
/// needed or not, set to false
void set<T>(String key, T value, {bool forceUpdate = true}) {
void set<T>(String key, T value, {bool forceUpdate = false}) {
if (value != null) {
if (_getObjectData().containsKey(key)) {
if (_getObjectData()[key] == value) {
if (_getObjectData()[key] == value && !forceUpdate) {
return;
}
if (forceUpdate) {
_getObjectData()[key] = value;
}
} else {
_getObjectData()[key] = value;
}
_getObjectData()[key] = value;
_unsavedChanges[key] = value;
}
}
Expand Down Expand Up @@ -240,8 +236,7 @@ abstract class ParseBase {
await unpin();
final Map<String, dynamic> objectMap = parseEncode(this, full: true);
final String json = jsonEncode(objectMap);
ParseCoreData().getStore()
..setString(objectId, json);
await ParseCoreData().getStore().setString(objectId, json);
return true;
} else {
return false;
Expand All @@ -253,8 +248,7 @@ abstract class ParseBase {
/// Replicates Android SDK pin process and saves object to storage
Future<bool> unpin({String key}) async {
if (objectId != null) {
ParseCoreData().getStore()
..remove(key ?? objectId);
await ParseCoreData().getStore().remove(key ?? objectId);
return true;
}

Expand Down
10 changes: 5 additions & 5 deletions lib/src/objects/parse_installation.dart
Original file line number Diff line number Diff line change
Expand Up @@ -127,7 +127,7 @@ class ParseInstallation extends ParseObject {

/// Gets the locally stored installation
static Future<ParseInstallation> _getFromLocalStore() async {
final CoreStore coreStore = await ParseCoreData().getStore();
final CoreStore coreStore = ParseCoreData().getStore();

final String installationJson =
await coreStore.getString(keyParseStoreInstallation);
Expand Down Expand Up @@ -204,17 +204,17 @@ class ParseInstallation extends ParseObject {
}

///Subscribes the device to a channel of push notifications.
void subscribeToChannel(String value) {
Future<void> subscribeToChannel(String value) async {
final List<dynamic> channel = <String>[value];
setAddAllUnique('channels', channel);
save();
await save();
}

///Unsubscribes the device to a channel of push notifications.
void unsubscribeFromChannel(String value) {
Future<void> unsubscribeFromChannel(String value) async {
final List<dynamic> channel = <String>[value];
setRemove('channels', channel);
save();
await save();
}

///Returns an <List<String>> containing all the channel names this device is subscribed to.
Expand Down
1 change: 1 addition & 0 deletions lib/src/objects/parse_object.dart
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ class ParseObject extends ParseBase implements ParseCloneable {
else {
_revertSavingChanges();
}
return response;
}
}
return childrenResponse;
Expand Down
Loading