Skip to content

Release/1.0.4 #26

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

Merged
merged 6 commits into from
Jan 10, 2019
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
567 changes: 341 additions & 226 deletions .idea/workspace.xml

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,10 @@
## 1.0.4

Bug fix for get all items
Can now pin/unpin/fromPin for all ParseObjects
Now supports generics
Cody tidy around extending

## 1.0.3

Added persistent storage. When a logged in user closes the app, then reopens, the data
Expand Down
53 changes: 23 additions & 30 deletions example/lib/diet_plan.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import 'dart:convert';
import 'dart:core';

import 'package:parse_server_sdk/parse.dart';

class DietPlan extends ParseObject {
class DietPlan extends ParseObject implements ParseCloneable {

DietPlan() : super(DIET_PLAN);
DietPlan.clone(): this();

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

static const String DIET_PLAN = 'Diet_Plans';
static const String NAME = 'Name';
Expand All @@ -20,33 +20,26 @@ class DietPlan extends ParseObject {
static const String FAT = 'Fat';
static const String STATUS = 'Status';

@override
dynamic fromJson(Map objectData) {
this.name = objectData[NAME];
this.description = objectData[DESCRIPTION];
this.protein = objectData[PROTEIN];
this.carbs = objectData[CARBS];
this.fat = objectData[FAT];
this.status = objectData[STATUS];
return this;
}
String get name => get<String>(NAME);
set name(String name) => set<String>(NAME, name);

String get description => get<String>(DESCRIPTION);
set description(String description) => set<String>(DESCRIPTION, name);

int get protein => get<int>(PROTEIN);
set protein(int protein) => super.set<int>(PROTEIN, protein);

Map<String, dynamic> toJson() => {
NAME: name,
DESCRIPTION: description,
PROTEIN: protein,
CARBS: carbs,
FAT: fat,
STATUS: status,
};
int get carbs => get<int>(CARBS);
set carbs(int carbs) => set<int>(CARBS, carbs);

int get fat => get<int>(FAT);
set fat(int fat) => set<int>(FAT, fat);

int get status => get<int>(STATUS);
set status(int status) => set<int>(STATUS, status);

@override
String toString() {
return toJson().toString();
}

@override
dynamic copy() {
return DietPlan();
}
}
20 changes: 18 additions & 2 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,22 @@ class _MyAppState extends State<MyApp> {
var response = await DietPlan().getObject('R5EonpUDWy');

if (response.success) {
print(ApplicationConstants.APP_NAME + ": " + (response.result as DietPlan).toString());
var dietPlan = (response.result as DietPlan);

// Shows example of storing values in their proper type and retrieving them
dietPlan.set<int>('RandomInt', 8);
var randomInt = dietPlan.get<int>('RandomInt');

if (randomInt is int) print('Saving generic value worked!');

// Shows example of pinning an item
dietPlan.pin();

// shows example of retrieving a pin
var newDietPlanFromPin = DietPlan().fromPin('R5EonpUDWy');

if (newDietPlanFromPin != null) print('Retreiving from pin worked!');

} else {
print(ApplicationConstants.APP_NAME + ": " + response.error.message);
}
Expand Down Expand Up @@ -113,7 +128,8 @@ class _MyAppState extends State<MyApp> {
user = await user.verificationEmailRequest();

user = await user.save();
await user.destroy();
var destroyResponse = await user.destroy();
if (destroyResponse.success) print('object has been destroyed!');

// Returns type ParseResponse as its a query, not a single result
var response = await ParseUser.all();
Expand Down
1 change: 1 addition & 0 deletions lib/parse.dart
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ part 'src/objects/parse_geo_point.dart';
part 'src/objects/parse_object.dart';
part 'src/objects/parse_response.dart';
part 'src/objects/parse_user.dart';
part 'src/objects/parse_clonable.dart';
part 'src/utils/parse_utils_date.dart';
part 'src/utils/parse_utils_objects.dart';
part 'src/utils/parse_utils.dart';
Expand Down
2 changes: 1 addition & 1 deletion lib/src/network/parse_http_client.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ part of flutter_parse_sdk;
/// Creates a custom version of HTTP Client that has Parse Data Preset
class ParseHTTPClient extends BaseClient {
final Client _client = Client();
final String _userAgent = "Flutter Parse SDK 1.0.3";
final String _userAgent = "Flutter Parse SDK 1.0.4";
ParseCoreData data = ParseCoreData();

ParseHTTPClient();
Expand Down
84 changes: 51 additions & 33 deletions lib/src/objects/parse_base.dart
Original file line number Diff line number Diff line change
@@ -1,54 +1,62 @@
part of flutter_parse_sdk;

abstract class ParseBase {

String className;

setClassName(String className) => this.className = className;
String getClassName() => className;

/// Stores all the values of a class
Map _objectData = Map<String, dynamic>();

/// Returns [String] objectId
String get objectId => _objectData['objectId'];
set objectId(String objectId) => _objectData[objectId];
String get objectId => get<String>(OBJECT_ID);
set objectId(String objectId) => set<String>(OBJECT_ID, objectId);

/// Returns [DateTime] createdAt
DateTime get createdAt => stringToDateTime(_objectData['createdAt']);
set createdAt(DateTime createdAt) =>
_objectData['createdAt'] = dateTimeToString(createdAt);
DateTime get createdAt => stringToDateTime(get<String>(CREATED_AT));
set createdAt(DateTime createdAt) => set<String>(CREATED_AT, dateTimeToString(createdAt));

/// Returns [DateTime] updatedAt
DateTime get updatedAt => stringToDateTime(_objectData['updatedAt']);
set updatedAt(DateTime updatedAt) =>
_objectData['updatedAt'] = dateTimeToString(updatedAt);
DateTime get updatedAt => stringToDateTime(get<String>(UPDATED_AT));
set updatedAt(DateTime updatedAt) => set<String>(UPDATED_AT, dateTimeToString(updatedAt));

/// Converts object to [String] in JSON format
@protected
toJson() => JsonEncoder().convert(getObjectData());
@protected String toJson() {
return JsonEncoder().convert(getObjectData());
}

/// Creates a copy of this class
@protected
copy() => JsonDecoder().convert(fromJson(getObjectData()));
@protected copy() => fromJson(JsonDecoder().convert(toJson()));

/// Sets all the objects variables
@protected
setObjectData(Map objectData) => _objectData = objectData;
@protected setObjectData(Map objectData) {
_objectData = objectData;
}

/// Returns the objects variables
@protected
getObjectData() => _objectData;
@protected getObjectData() {
return _objectData;
}

/// Saves in storage
@protected
saveInStorage(String key) async {
@protected saveInStorage(String key) async {
await ParseCoreData().getStore().setString(key, toJson());
}

@protected
fromJson(Map objectData) {
if (_objectData == null) _objectData = Map();
_objectData.addAll(objectData);
@protected fromJson(Map objectData) {
if (getObjectData() == null) setObjectData(Map());
getObjectData().addAll(objectData);
return this;
}

/// Create a new variable for this object, [bool] forceUpdate is always true,
/// if unsure as to whether an item is needed or not, set to false
set(String key, dynamic value, {bool forceUpdate: true}) {
/// 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
set<T>(String key, T value, {bool forceUpdate: true}) {
if (value != null) {
if (getObjectData().containsKey(key)) {
if (forceUpdate) getObjectData()[key] = value;
Expand All @@ -58,10 +66,18 @@ abstract class ParseBase {
}
}

/// Returns a variable from the objectData
get(String key, {dynamic defaultValue, bool fromServer}) {
/// Gets type [T] from objectData
///
/// Returns null or [defaultValue] if provided. To get an int, call
/// getType<int> and an int will be returned, null, or a defaultValue if
/// provided
get<T>(String key, {T defaultValue}) {
if (getObjectData().containsKey(key)) {
return getObjectData()[key];
if (T != null && getObjectData()[key] is T) {
return getObjectData()[key] as T;
} else {
return getObjectData()[key];
}
} else {
return defaultValue;
}
Expand All @@ -72,7 +88,8 @@ abstract class ParseBase {
/// Replicates Android SDK pin process and saves object to storage
pin() async {
if (objectId != null) {
await ParseCoreData().getStore().setString(objectId, toJson());
var itemToSave = toJson();
await ParseCoreData().getStore().setString(objectId, itemToSave);
return true;
} else {
return false;
Expand All @@ -84,8 +101,9 @@ abstract class ParseBase {
/// Replicates Android SDK pin process and saves object to storage
unpin() async {
if (objectId != null) {
var itemToSave = await ParseCoreData().getStore().setString(objectId, null);
return true;
var itemToSave = await ParseCoreData().getStore().setString(
objectId, null);
if (itemToSave) return true;
} else {
return false;
}
Expand All @@ -94,9 +112,9 @@ abstract class ParseBase {
/// Saves item to simple key pair value storage
///
/// Replicates Android SDK pin process and saves object to storage
fromPin() async {
fromPin(String objectId) {
if (objectId != null) {
var itemFromStore = await ParseCoreData().getStore().getString(objectId);
var itemFromStore = ParseCoreData().getStore().getString(objectId);

if (itemFromStore != null) {
Map<String, dynamic> itemFromStoreMap = JsonDecoder().convert(
Expand Down
6 changes: 6 additions & 0 deletions lib/src/objects/parse_clonable.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
part of flutter_parse_sdk;

/// Creates method which can be used to deep clone objects
abstract class ParseCloneable {
clone(Map map);
}
14 changes: 10 additions & 4 deletions lib/src/objects/parse_object.dart
Original file line number Diff line number Diff line change
@@ -1,7 +1,12 @@
part of flutter_parse_sdk;

class ParseObject extends ParseBase {
final String className;
class ParseObject extends ParseBase implements ParseCloneable {

ParseObject.clone(String className): this('className');

@override
clone(Map map) => ParseObject.clone(className)..fromJson(map);

String _path;
bool _debug;
ParseHTTPClient _client;
Expand All @@ -11,7 +16,8 @@ class ParseObject extends ParseBase {
/// [String] className refers to the Table Name in your Parse Server,
/// [bool] debug will overwrite the current default debug settings and
/// [ParseHttpClient] can be overwritten to create your own HTTP Client
ParseObject(this.className, {bool debug: false}): super() {
ParseObject(String className, {bool debug: false}): super() {
setClassName(className);
_path = "/classes/$className";
setClient(ParseHTTPClient());
setDebug(isDebugEnabled(_client, objectLevelDebug: debug));
Expand Down Expand Up @@ -110,7 +116,7 @@ class ParseObject extends ParseBase {
/// Handles an API response and logs data if [bool] debug is enabled
@protected
ParseResponse handleException(Exception exception, ParseApiRQ type) {
ParseResponse parseResponse = ParseResponse.handleException(this, exception);
ParseResponse parseResponse = ParseResponse.handleException(exception);

if (_debug) {
logger(ParseCoreData().appName, className, type.toString(), parseResponse);
Expand Down
16 changes: 9 additions & 7 deletions lib/src/objects/parse_response.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ class ParseResponse {
/// Handles all the ParseObject responses
///
/// There are 3 probable outcomes from a Parse API call,
/// 1. Fail - [ParseResponse] will be returned with further details
/// 2. Success but no results. [ParseResponse] is returned.
/// 3. Success with results. Again [ParseResponse] is returned
/// 1. Fail - [ParseResponse()] will be returned with further details
/// 2. Success but no results. [ParseResponse()] is returned.
/// 3. Success with results. Again [ParseResponse()] is returned
static handleResponse(ParseBase object, Response apiResponse) {
var parseResponse = ParseResponse();

Expand All @@ -32,7 +32,7 @@ class ParseResponse {
}

/// Handles exception instead of throwing an exception
static handleException(ParseBase object, Exception exception) {
static handleException(Exception exception) {
var response = ParseResponse();
response.error = ParseError(message: exception.toString(), isTypeOfException: true);
return response;
Expand All @@ -42,6 +42,7 @@ class ParseResponse {
static ParseResponse _handleError(ParseResponse response, Response apiResponse) {
Map<String, dynamic> responseData = JsonDecoder().convert(apiResponse.body);
response.error = ParseError(code: responseData['code'], message: responseData['error']);
response.statusCode = responseData['code'];
return response;
}

Expand Down Expand Up @@ -72,15 +73,16 @@ class ParseResponse {
var resultsList = List();

for (var value in map) {
resultsList.add(_handleSingleResult(object, value));
var newObject = _handleSingleResult(object, value);
resultsList.add(newObject);
}

return resultsList;
}

/// Handles a response with a single result object
static _handleSingleResult(ParseBase object, map) {
populateObjectBaseData(object, map);
return object.fromJson(map);
if (object is ParseCloneable) return (object as ParseCloneable).clone(map);
return null;
}
}
Loading