Skip to content

Commit ca8e30d

Browse files
authored
Merge pull request #26 from phillwiggins/release/1.0.4
Release/1.0.4
2 parents 3a431bc + e50ce8e commit ca8e30d

13 files changed

+508
-353
lines changed

.idea/workspace.xml

+341-226
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

CHANGELOG.md

+7
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,10 @@
1+
## 1.0.4
2+
3+
Bug fix for get all items
4+
Can now pin/unpin/fromPin for all ParseObjects
5+
Now supports generics
6+
Cody tidy around extending
7+
18
## 1.0.3
29

310
Added persistent storage. When a logged in user closes the app, then reopens, the data

example/lib/diet_plan.dart

+23-30
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,16 @@
1+
import 'dart:convert';
12
import 'dart:core';
23

34
import 'package:parse_server_sdk/parse.dart';
45

5-
class DietPlan extends ParseObject {
6+
class DietPlan extends ParseObject implements ParseCloneable {
7+
68
DietPlan() : super(DIET_PLAN);
9+
DietPlan.clone(): this();
710

8-
String name;
9-
String description;
10-
num protein;
11-
num carbs;
12-
num fat;
13-
num status;
11+
/// Looks strangely hacky but due to Flutter not using reflection, we have to
12+
/// mimic a clone
13+
@override clone(Map map) => DietPlan.clone()..fromJson(map);
1414

1515
static const String DIET_PLAN = 'Diet_Plans';
1616
static const String NAME = 'Name';
@@ -20,33 +20,26 @@ class DietPlan extends ParseObject {
2020
static const String FAT = 'Fat';
2121
static const String STATUS = 'Status';
2222

23-
@override
24-
dynamic fromJson(Map objectData) {
25-
this.name = objectData[NAME];
26-
this.description = objectData[DESCRIPTION];
27-
this.protein = objectData[PROTEIN];
28-
this.carbs = objectData[CARBS];
29-
this.fat = objectData[FAT];
30-
this.status = objectData[STATUS];
31-
return this;
32-
}
23+
String get name => get<String>(NAME);
24+
set name(String name) => set<String>(NAME, name);
25+
26+
String get description => get<String>(DESCRIPTION);
27+
set description(String description) => set<String>(DESCRIPTION, name);
28+
29+
int get protein => get<int>(PROTEIN);
30+
set protein(int protein) => super.set<int>(PROTEIN, protein);
3331

34-
Map<String, dynamic> toJson() => {
35-
NAME: name,
36-
DESCRIPTION: description,
37-
PROTEIN: protein,
38-
CARBS: carbs,
39-
FAT: fat,
40-
STATUS: status,
41-
};
32+
int get carbs => get<int>(CARBS);
33+
set carbs(int carbs) => set<int>(CARBS, carbs);
34+
35+
int get fat => get<int>(FAT);
36+
set fat(int fat) => set<int>(FAT, fat);
37+
38+
int get status => get<int>(STATUS);
39+
set status(int status) => set<int>(STATUS, status);
4240

4341
@override
4442
String toString() {
4543
return toJson().toString();
4644
}
47-
48-
@override
49-
dynamic copy() {
50-
return DietPlan();
51-
}
5245
}

example/lib/main.dart

+18-2
Original file line numberDiff line numberDiff line change
@@ -78,7 +78,22 @@ class _MyAppState extends State<MyApp> {
7878
var response = await DietPlan().getObject('R5EonpUDWy');
7979

8080
if (response.success) {
81-
print(ApplicationConstants.APP_NAME + ": " + (response.result as DietPlan).toString());
81+
var dietPlan = (response.result as DietPlan);
82+
83+
// Shows example of storing values in their proper type and retrieving them
84+
dietPlan.set<int>('RandomInt', 8);
85+
var randomInt = dietPlan.get<int>('RandomInt');
86+
87+
if (randomInt is int) print('Saving generic value worked!');
88+
89+
// Shows example of pinning an item
90+
dietPlan.pin();
91+
92+
// shows example of retrieving a pin
93+
var newDietPlanFromPin = DietPlan().fromPin('R5EonpUDWy');
94+
95+
if (newDietPlanFromPin != null) print('Retreiving from pin worked!');
96+
8297
} else {
8398
print(ApplicationConstants.APP_NAME + ": " + response.error.message);
8499
}
@@ -113,7 +128,8 @@ class _MyAppState extends State<MyApp> {
113128
user = await user.verificationEmailRequest();
114129

115130
user = await user.save();
116-
await user.destroy();
131+
var destroyResponse = await user.destroy();
132+
if (destroyResponse.success) print('object has been destroyed!');
117133

118134
// Returns type ParseResponse as its a query, not a single result
119135
var response = await ParseUser.all();

lib/parse.dart

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ part 'src/objects/parse_geo_point.dart';
2222
part 'src/objects/parse_object.dart';
2323
part 'src/objects/parse_response.dart';
2424
part 'src/objects/parse_user.dart';
25+
part 'src/objects/parse_clonable.dart';
2526
part 'src/utils/parse_utils_date.dart';
2627
part 'src/utils/parse_utils_objects.dart';
2728
part 'src/utils/parse_utils.dart';

lib/src/network/parse_http_client.dart

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ part of flutter_parse_sdk;
33
/// Creates a custom version of HTTP Client that has Parse Data Preset
44
class ParseHTTPClient extends BaseClient {
55
final Client _client = Client();
6-
final String _userAgent = "Flutter Parse SDK 1.0.3";
6+
final String _userAgent = "Flutter Parse SDK 1.0.4";
77
ParseCoreData data = ParseCoreData();
88

99
ParseHTTPClient();

lib/src/objects/parse_base.dart

+51-33
Original file line numberDiff line numberDiff line change
@@ -1,54 +1,62 @@
11
part of flutter_parse_sdk;
22

33
abstract class ParseBase {
4+
5+
String className;
6+
7+
setClassName(String className) => this.className = className;
8+
String getClassName() => className;
9+
410
/// Stores all the values of a class
511
Map _objectData = Map<String, dynamic>();
612

713
/// Returns [String] objectId
8-
String get objectId => _objectData['objectId'];
9-
set objectId(String objectId) => _objectData[objectId];
14+
String get objectId => get<String>(OBJECT_ID);
15+
set objectId(String objectId) => set<String>(OBJECT_ID, objectId);
1016

1117
/// Returns [DateTime] createdAt
12-
DateTime get createdAt => stringToDateTime(_objectData['createdAt']);
13-
set createdAt(DateTime createdAt) =>
14-
_objectData['createdAt'] = dateTimeToString(createdAt);
18+
DateTime get createdAt => stringToDateTime(get<String>(CREATED_AT));
19+
set createdAt(DateTime createdAt) => set<String>(CREATED_AT, dateTimeToString(createdAt));
1520

1621
/// Returns [DateTime] updatedAt
17-
DateTime get updatedAt => stringToDateTime(_objectData['updatedAt']);
18-
set updatedAt(DateTime updatedAt) =>
19-
_objectData['updatedAt'] = dateTimeToString(updatedAt);
22+
DateTime get updatedAt => stringToDateTime(get<String>(UPDATED_AT));
23+
set updatedAt(DateTime updatedAt) => set<String>(UPDATED_AT, dateTimeToString(updatedAt));
2024

2125
/// Converts object to [String] in JSON format
22-
@protected
23-
toJson() => JsonEncoder().convert(getObjectData());
26+
@protected String toJson() {
27+
return JsonEncoder().convert(getObjectData());
28+
}
2429

2530
/// Creates a copy of this class
26-
@protected
27-
copy() => JsonDecoder().convert(fromJson(getObjectData()));
31+
@protected copy() => fromJson(JsonDecoder().convert(toJson()));
2832

2933
/// Sets all the objects variables
30-
@protected
31-
setObjectData(Map objectData) => _objectData = objectData;
34+
@protected setObjectData(Map objectData) {
35+
_objectData = objectData;
36+
}
3237

3338
/// Returns the objects variables
34-
@protected
35-
getObjectData() => _objectData;
39+
@protected getObjectData() {
40+
return _objectData;
41+
}
3642

3743
/// Saves in storage
38-
@protected
39-
saveInStorage(String key) async {
44+
@protected saveInStorage(String key) async {
4045
await ParseCoreData().getStore().setString(key, toJson());
4146
}
4247

43-
@protected
44-
fromJson(Map objectData) {
45-
if (_objectData == null) _objectData = Map();
46-
_objectData.addAll(objectData);
48+
@protected fromJson(Map objectData) {
49+
if (getObjectData() == null) setObjectData(Map());
50+
getObjectData().addAll(objectData);
51+
return this;
4752
}
4853

49-
/// Create a new variable for this object, [bool] forceUpdate is always true,
50-
/// if unsure as to whether an item is needed or not, set to false
51-
set(String key, dynamic value, {bool forceUpdate: true}) {
54+
/// Sets type [T] from objectData
55+
///
56+
/// To set an int, call setType<int> and an int will be saved
57+
/// [bool] forceUpdate is always true, if unsure as to whether an item is
58+
/// needed or not, set to false
59+
set<T>(String key, T value, {bool forceUpdate: true}) {
5260
if (value != null) {
5361
if (getObjectData().containsKey(key)) {
5462
if (forceUpdate) getObjectData()[key] = value;
@@ -58,10 +66,18 @@ abstract class ParseBase {
5866
}
5967
}
6068

61-
/// Returns a variable from the objectData
62-
get(String key, {dynamic defaultValue, bool fromServer}) {
69+
/// Gets type [T] from objectData
70+
///
71+
/// Returns null or [defaultValue] if provided. To get an int, call
72+
/// getType<int> and an int will be returned, null, or a defaultValue if
73+
/// provided
74+
get<T>(String key, {T defaultValue}) {
6375
if (getObjectData().containsKey(key)) {
64-
return getObjectData()[key];
76+
if (T != null && getObjectData()[key] is T) {
77+
return getObjectData()[key] as T;
78+
} else {
79+
return getObjectData()[key];
80+
}
6581
} else {
6682
return defaultValue;
6783
}
@@ -72,7 +88,8 @@ abstract class ParseBase {
7288
/// Replicates Android SDK pin process and saves object to storage
7389
pin() async {
7490
if (objectId != null) {
75-
await ParseCoreData().getStore().setString(objectId, toJson());
91+
var itemToSave = toJson();
92+
await ParseCoreData().getStore().setString(objectId, itemToSave);
7693
return true;
7794
} else {
7895
return false;
@@ -84,8 +101,9 @@ abstract class ParseBase {
84101
/// Replicates Android SDK pin process and saves object to storage
85102
unpin() async {
86103
if (objectId != null) {
87-
var itemToSave = await ParseCoreData().getStore().setString(objectId, null);
88-
return true;
104+
var itemToSave = await ParseCoreData().getStore().setString(
105+
objectId, null);
106+
if (itemToSave) return true;
89107
} else {
90108
return false;
91109
}
@@ -94,9 +112,9 @@ abstract class ParseBase {
94112
/// Saves item to simple key pair value storage
95113
///
96114
/// Replicates Android SDK pin process and saves object to storage
97-
fromPin() async {
115+
fromPin(String objectId) {
98116
if (objectId != null) {
99-
var itemFromStore = await ParseCoreData().getStore().getString(objectId);
117+
var itemFromStore = ParseCoreData().getStore().getString(objectId);
100118

101119
if (itemFromStore != null) {
102120
Map<String, dynamic> itemFromStoreMap = JsonDecoder().convert(

lib/src/objects/parse_clonable.dart

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
part of flutter_parse_sdk;
2+
3+
/// Creates method which can be used to deep clone objects
4+
abstract class ParseCloneable {
5+
clone(Map map);
6+
}

lib/src/objects/parse_object.dart

+10-4
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
part of flutter_parse_sdk;
22

3-
class ParseObject extends ParseBase {
4-
final String className;
3+
class ParseObject extends ParseBase implements ParseCloneable {
4+
5+
ParseObject.clone(String className): this('className');
6+
7+
@override
8+
clone(Map map) => ParseObject.clone(className)..fromJson(map);
9+
510
String _path;
611
bool _debug;
712
ParseHTTPClient _client;
@@ -11,7 +16,8 @@ class ParseObject extends ParseBase {
1116
/// [String] className refers to the Table Name in your Parse Server,
1217
/// [bool] debug will overwrite the current default debug settings and
1318
/// [ParseHttpClient] can be overwritten to create your own HTTP Client
14-
ParseObject(this.className, {bool debug: false}): super() {
19+
ParseObject(String className, {bool debug: false}): super() {
20+
setClassName(className);
1521
_path = "/classes/$className";
1622
setClient(ParseHTTPClient());
1723
setDebug(isDebugEnabled(_client, objectLevelDebug: debug));
@@ -110,7 +116,7 @@ class ParseObject extends ParseBase {
110116
/// Handles an API response and logs data if [bool] debug is enabled
111117
@protected
112118
ParseResponse handleException(Exception exception, ParseApiRQ type) {
113-
ParseResponse parseResponse = ParseResponse.handleException(this, exception);
119+
ParseResponse parseResponse = ParseResponse.handleException(exception);
114120

115121
if (_debug) {
116122
logger(ParseCoreData().appName, className, type.toString(), parseResponse);

lib/src/objects/parse_response.dart

+9-7
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,9 @@ class ParseResponse {
99
/// Handles all the ParseObject responses
1010
///
1111
/// There are 3 probable outcomes from a Parse API call,
12-
/// 1. Fail - [ParseResponse] will be returned with further details
13-
/// 2. Success but no results. [ParseResponse] is returned.
14-
/// 3. Success with results. Again [ParseResponse] is returned
12+
/// 1. Fail - [ParseResponse()] will be returned with further details
13+
/// 2. Success but no results. [ParseResponse()] is returned.
14+
/// 3. Success with results. Again [ParseResponse()] is returned
1515
static handleResponse(ParseBase object, Response apiResponse) {
1616
var parseResponse = ParseResponse();
1717

@@ -32,7 +32,7 @@ class ParseResponse {
3232
}
3333

3434
/// Handles exception instead of throwing an exception
35-
static handleException(ParseBase object, Exception exception) {
35+
static handleException(Exception exception) {
3636
var response = ParseResponse();
3737
response.error = ParseError(message: exception.toString(), isTypeOfException: true);
3838
return response;
@@ -42,6 +42,7 @@ class ParseResponse {
4242
static ParseResponse _handleError(ParseResponse response, Response apiResponse) {
4343
Map<String, dynamic> responseData = JsonDecoder().convert(apiResponse.body);
4444
response.error = ParseError(code: responseData['code'], message: responseData['error']);
45+
response.statusCode = responseData['code'];
4546
return response;
4647
}
4748

@@ -72,15 +73,16 @@ class ParseResponse {
7273
var resultsList = List();
7374

7475
for (var value in map) {
75-
resultsList.add(_handleSingleResult(object, value));
76+
var newObject = _handleSingleResult(object, value);
77+
resultsList.add(newObject);
7678
}
7779

7880
return resultsList;
7981
}
8082

8183
/// Handles a response with a single result object
8284
static _handleSingleResult(ParseBase object, map) {
83-
populateObjectBaseData(object, map);
84-
return object.fromJson(map);
85+
if (object is ParseCloneable) return (object as ParseCloneable).clone(map);
86+
return null;
8587
}
8688
}

0 commit comments

Comments
 (0)