Skip to content

create CoreStore interface to allow different implements for local st… #167

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 1 commit into from
May 1, 2019

Conversation

phillwiggins
Copy link
Member

…orage (#166)

implement default local store using sembast and with encryption using XXTEA algorithm

add desktop support in example project

…orage (#166)

implement default local store using sembast and with encryption using XXTEA algorithm

add desktop support in example project
@phillwiggins phillwiggins merged commit 97905a9 into release/1.0.22 May 1, 2019
@RodrigoSMarques
Copy link
Contributor

Hi @phillwiggins.

I did a test using my test project.
I just ran the project without change to see what happened.
I had errors on Android (below) and also bugs on iOS.
I did not look at the implementation, but it would be interesting to leave the shared_preference as default, not to break apps that are working and are just updating the release, or the lib giving a runtime alert that some kind of tuning should be done in the code.

Error in Android.

Launching lib/main.dart on Android SDK built for x86 in debug mode...
Note: /Users/rodrigo/Desenvolvimento/flutter/.pub-cache/hosted/pub.dartlang.org/package_info-0.4.0+3/android/src/main/java/io/flutter/plugins/packageinfo/PackageInfoPlugin.java uses or overrides a deprecated API.
Note: Recompile with -Xlint:deprecation for details.

Built build/app/outputs/apk/debug/app-debug.apk.
I/OpenGLRenderer(23188): Initialized EGL, version 1.4
D/OpenGLRenderer(23188): Swap behavior 1
D/        (23188): HostConnection::get() New Host Connection established 0x8a6676c0, tid 23224
D/EGL_emulation(23188): eglCreateContext: 0xa87e37a0: maj 3 min 0 rcv 3
D/EGL_emulation(23188): eglMakeCurrent: 0xa87e37a0: ver 3 0 (tinfo 0x8ad50080)
D/        (23188): HostConnection::get() New Host Connection established 0x8ad761c0, tid 23217
D/EGL_emulation(23188): eglCreateContext: 0xa09a25e0: maj 3 min 0 rcv 3
D/EGL_emulation(23188): eglMakeCurrent: 0xa09a25e0: ver 3 0 (tinfo 0x8ad50460)
I/Choreographer(23188): Skipped 168 frames!  The application may be doing too much work on its main thread.
D/EGL_emulation(23188): eglMakeCurrent: 0xa87e37a0: ver 3 0 (tinfo 0x8ad50080)
E/flutter (23188): [ERROR:flutter/lib/ui/ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The getter 'length' was called on null.
E/flutter (23188): Receiver: null
E/flutter (23188): Tried calling: length
E/flutter (23188): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
E/flutter (23188): #1      XXTEA._fixkey
E/flutter (23188): #2      XXTEA.encrypt
E/flutter (23188): #3      XXTEA.encryptToString
E/flutter (23188): #4      _XXTeaEncoder.convert
E/flutter (23188): #5      Codec.encode (dart:convert/codec.dart:21:32)
E/flutter (23188): #6      getCodecEncodedSignature
E/flutter (23188): #7      SembastDatabase.open.<anonymous closure>._openDone
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #8      SembastDatabase.open.<anonymous closure>
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #9      BasicLock.synchronized
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #10     SembastDatabase.open
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #11     DatabaseOpenHelper.openDatabase.<anonymous closure>
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #12     BasicLock.synchronized
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #13     DatabaseOpenHelper.openDatabase
E/flutter (23188): #14     _DatabaseFactoryFs&SembastDatabaseFactory&DatabaseFactoryMixin.openDatabaseWithOptions
E/flutter (23188): #15     DatabaseFactoryIo.openDatabaseWithOptions
E/flutter (23188): #16     _DatabaseFactoryFs&SembastDatabaseFactory&DatabaseFactoryMixin.openDatabase
E/flutter (23188): #17     CoreStoreImp.getInstance
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #18     ParseCoreData.init
E/flutter (23188): #19     Parse.initialize
E/flutter (23188): #20     main
E/flutter (23188): <asynchronous suspension>
E/flutter (23188): #21     _runMainZoned.<anonymous closure>.<anonymous closure> (dart:ui/hooks.dart:199:25)
E/flutter (23188): #22     _rootRun (dart:async/zone.dart:1124:13)
E/flutter (23188): #23     _CustomZone.run (dart:async/zone.dart:1021:19)
E/flutter (23188): #24     _runZoned (dart:async/zone.dart:1516:10)
E/flutter (23188): #25     runZoned (dart:async/zone.dart:1500:12)
E/flutter (23188): #26     _runMainZoned.<anonymous closure> (dart:ui/hooks.dart:190:5)
E/flutter (23188): #27     _startIsolate.<anonymous closure> (dart:isolate-patch/isolate_patch.dart:300:19)
E/flutter (23188): #28     _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:171:12)
E/flutter (23188):

Error in iOS.

Launching lib/main.dart on iPhone Xʀ in debug mode...
Xcode build done.                                           29,6s
[VERBOSE-2:ui_dart_state.cc(148)] Unhandled Exception: NoSuchMethodError: The getter 'length' was called on null.
Receiver: null
Tried calling: length
#0      Object.noSuchMethod (dart:core-patch/object_patch.dart:50:5)
#1      XXTEA._fixkey
#2      XXTEA.encrypt
#3      XXTEA.encryptToString
#4      _XXTeaEncoder.convert
#5      Codec.encode (dart:convert/codec.dart:21:32)
#6      getCodecEncodedSignature
#7      SembastDatabase.open.<anonymous closure>._openDone
<asynchronous suspension>
#8      SembastDatabase.open.<anonymous closure>
<asynchronous suspension>
#9      BasicLock.synchronized
<asynchronous suspension>
#10     SembastDatabase.open (p<>

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

hi @RodrigoSMarques
you can implement your custom a core store class base on SharedPreferences,
below a sample I idea here is to remove any dependencies on the os platform so it will make easy to support multiplatform android, ios, web, and desktop

import 'dart:async';

import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesCoreStore implements CoreStore {
  SharedPreferencesCoreStore(FutureOr<SharedPreferences> sharedPreference)
      : _sharedPreferencesFuture = Future.value(sharedPreference);

  Future<SharedPreferences> _sharedPreferencesFuture;

  @override
  Future<bool> clear() async {
    final SharedPreferences sharedPreferences = await _sharedPreferencesFuture;
    final bool result = await sharedPreferences.clear();
    return result;
  }

  @override
  Future get(String key) =>
      _sharedPreferencesFuture.then<dynamic>((shared) => shared.get(key));

  @override
  Future<bool> getBool(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getBool(key));

  @override
  Future<double> getDouble(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getDouble(key));

  @override
  Future<int> getInt(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getInt(key));

  @override
  Future<String> getString(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getString(key));

  @override
  Future<List<String>> getStringList(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getStringList(key));

  @override
  Future<bool> remove(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.remove(key));

  @override
  Future<bool> setBool(String key, bool value) =>
      _sharedPreferencesFuture.then((shared) => shared.setBool(key, value));

  @override
  Future<bool> setDouble(String key, double value) =>
      _sharedPreferencesFuture.then((shared) => shared.setDouble(key, value));

  @override
  Future<bool> setInt(String key, int value) =>
      _sharedPreferencesFuture.then((shared) => shared.setInt(key, value));

  @override
  Future<bool> setString(String key, String value) =>
      _sharedPreferencesFuture.then((shared) => shared.setString(key, value));

  @override
  Future<bool> setStringList(String key, List<String> values) =>
      _sharedPreferencesFuture
          .then((shared) => shared.setStringList(key, values));

  @override
  Future<bool> containsKey(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.containsKey(key));
}

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

there is a bug in
https://github.com/phillwiggins/flutter_parse_sdk/blob/master/lib/src/data/parse_core_data.dart#L29
it should be

    _instance.storage ??=
        Future.value(store) ?? CoreStoreImp.getInstance(password: appId);

instead of

   _instance.storage ??=
      store ?? CoreStoreImp.getInstance(password: masterkey);   

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

you can have a lock on my repo, also I'm working on enhancement example app
https://github.com/WahdanZ/flutter_parse_sdk/tree/example_enhancement

@RodrigoSMarques
Copy link
Contributor

hi @RodrigoSMarques
you can implement your custom a core store class base on SharedPreferences,
below a sample I idea here is to remove any dependencies on the os platform so it will make easy to support multiplatform android, ios, web, and desktop

import 'dart:async';

import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:shared_preferences/shared_preferences.dart';

class SharedPreferencesCoreStore implements CoreStore {
  SharedPreferencesCoreStore(FutureOr<SharedPreferences> sharedPreference)
      : _sharedPreferencesFuture = Future.value(sharedPreference);

  Future<SharedPreferences> _sharedPreferencesFuture;

  @override
  Future<bool> clear() async {
    final SharedPreferences sharedPreferences = await _sharedPreferencesFuture;
    final bool result = await sharedPreferences.clear();
    return result;
  }

  @override
  Future get(String key) =>
      _sharedPreferencesFuture.then<dynamic>((shared) => shared.get(key));

  @override
  Future<bool> getBool(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getBool(key));

  @override
  Future<double> getDouble(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getDouble(key));

  @override
  Future<int> getInt(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getInt(key));

  @override
  Future<String> getString(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getString(key));

  @override
  Future<List<String>> getStringList(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.getStringList(key));

  @override
  Future<bool> remove(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.remove(key));

  @override
  Future<bool> setBool(String key, bool value) =>
      _sharedPreferencesFuture.then((shared) => shared.setBool(key, value));

  @override
  Future<bool> setDouble(String key, double value) =>
      _sharedPreferencesFuture.then((shared) => shared.setDouble(key, value));

  @override
  Future<bool> setInt(String key, int value) =>
      _sharedPreferencesFuture.then((shared) => shared.setInt(key, value));

  @override
  Future<bool> setString(String key, String value) =>
      _sharedPreferencesFuture.then((shared) => shared.setString(key, value));

  @override
  Future<bool> setStringList(String key, List<String> values) =>
      _sharedPreferencesFuture
          .then((shared) => shared.setStringList(key, values));

  @override
  Future<bool> containsKey(String key) =>
      _sharedPreferencesFuture.then((shared) => shared.containsKey(key));
}

Hi @WahdanZ
I understood the implementation.

Remember to document this in README.md and if possible in the sample application.

I think of other developers who receive a notification of a new version but can not see these changes in README.md or in the sample application and app does not run anymore.

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

I agree with you I'll update README also in the release notes, and now it's added in the sample application

@RodrigoSMarques
Copy link
Contributor

RodrigoSMarques commented May 2, 2019

you can have a lock on my repo, also I'm working on enhancement example app
https://github.com/WahdanZ/flutter_parse_sdk/tree/example_enhancement

My sugestion.
Change shared_preferences_corestore.dart in parse_shared_preferences_corestore.dart

If CoreStore is not informed, it defaults to parse_shared_preferences_corestore.dart

This does not break any code and allows each developer to customize with the available options, stating that parse_shared_preferences_corestore.dart will work only on iOS and Android.

This allows a simple implementation.

What do you think about this?

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

I think I sound good, but what I'm thinking about it to make parse SDK to be pure dart parse SDK, and for flutter and web we can customize the implementation of using each platform link notification for example if we are going to support also for Installation, Parse file and etc.

@RodrigoSMarques
Copy link
Contributor

RodrigoSMarques commented May 2, 2019

I'm working on a Flutter course with Parse Server and comparing it to Firebase.

They are people often starting in the development of mobile applications.

The easier and simpler the start with the better Flutter and Parse Server.
Having to explain that they must implement a CoreData to save information that is saved on the device can create a bit of confusion.

It's just a suggestion.

I like the easy use of Parse Server. Just have the AppID, the URL and you're done.

@WahdanZ
Copy link
Contributor

WahdanZ commented May 2, 2019

That good, I love to used parse instead of using firebase, it's easy to use compared to Firebase
I think they don't need to implement I tested sembast on android, ios, and mac and it works fine.
but anyway I'll move parse_shared_preferences_corestore to the library and make it the default implementation for core store instead of sembast.

@RodrigoSMarques
Copy link
Contributor

Very good, we are on the right track.
We have to keep SharedPreference as default.
What would happen to the applications in production that have information written to the SharedPreference.
After the PR is approved, I test again.

phillwiggins pushed a commit that referenced this pull request May 31, 2019
* Added repo example

* create CoreStore interface to allow different implements for local storage (#166) (#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 (#171)

* Support Relation.

* delete vscode config

* Update .gitignore
phillwiggins added a commit that referenced this pull request Jun 11, 2019
* Added repo example

* create CoreStore interface to allow different implements for local storage (#166) (#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 (#171)

* Support Relation (#179)

* create CoreStore interface to allow different implements for local storage (#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 (#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 (#181)

* Delete `toJson` and fix exception. (#187)

* Fix Commit: 6ed26e1

* Update parse_encoder.dart

Fix parse encoder bug.

* Fix exception when sendSessionId is null.

* delete toJson calling.

* Save recursively (#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 (#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
@RodrigoSMarques RodrigoSMarques mentioned this pull request Jun 11, 2019
fischerscode pushed a commit to fischerscode/Parse-SDK-Flutter that referenced this pull request Sep 5, 2020
…orage (parse-community#166) (parse-community#167)

implement default local store using sembast and with encryption using XXTEA algorithm

add desktop support in example project
fischerscode pushed a commit to fischerscode/Parse-SDK-Flutter that referenced this pull request Sep 5, 2020
* 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.

* delete vscode config

* Update .gitignore
fischerscode pushed a commit to fischerscode/Parse-SDK-Flutter that referenced this pull request Sep 5, 2020
* 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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants