Closed mbfakourii closed 1 year ago
I will reformat the title to use the proper commit message syntax.
@parse-community/flutter-sdk-review Are there other tasks?
If we will merge this we need first to publish a new version of the Flutter SDK to inform the package user about this transition.
TODOs for the README file in the Flutter SDK:
TODOs for the README file in the Dart SDK(new):
let me know if I missed anything.
Are there other tasks?
For now, I do not think of any other tasks.
@parse-community/flutter-sdk-review Almost all tasks have been completed. please check it and not sure if CI works !
@parse-community/flutter-sdk-review I made the suggested changes, is it possible to check again and is it ready for merge?
3 checks are reporting errors. we need to fix them before!
Patch coverage: 75.00
% and project coverage change: +0.55
:tada:
Comparison is base (
94be044
) 16.36% compared to head (2340211
) 16.92%.:exclamation: Current head 2340211 differs from pull request most recent head f3aab34. Consider uploading reports for the commit f3aab34 to get more accurate results
:umbrella: View full report in Codecov by Sentry.
:loudspeaker: Do you have feedback about the report comment? Let us know in this issue.
We still need a migration guide for the developer coming from the Flutter SDK
@Nidal-Bakir Thanks ci fixed
We still need a migration guide for the developer coming from the Flutter SDK
What should we explain in this guide ? The developer should only use Dart instead of the Flutter version !
If you look at the parse_server_sdk.dart
in the Flutter package and the parse_server_sdk.dart
in the Dart package. You will see the difference, the flutter package uses default values if the developer did not provide a value
here is a list of the parameters that should be required in the Dart SDK from now on...
kindly compare the three files:
and see the issues that will pop in the face of the developers because the defaults are not there anymore
One of the downsides of this transition is that the package user should provide arguments for parameters that were optional ones previously.
I'm following this journey message by message. And the solution is fantastic. Because actually Parse Server is more Dart than Flutter. But @Nidal-Bakir last approach made me curious.
I use b4a's ParseServer on Dart and I don't need all these parameters. Because with the elimination of Flutter would I need it?
If you look at the
parse_server_sdk.dart
in the Flutter package and theparse_server_sdk.dart
in the Dart package. You will see the difference, the flutter package uses default values if the developer did not provide a valuehere is a list of the parameters that should be required in the Dart SDK from now on...
- appPackageName
- appName
- appVersion
- locale
- coreStore (CoreStoreSharedPrefsImp,CoreStoreMemoryImp,CoreStoreSembastImp)
- connectivityProvider (For liveQuery)
- fileDirectory
kindly compare the three files:
- parse_server_sdk.dart (Flutter SDK)
- parse_server_sdk.dart (Dart SDK)
- parse_core_data.dart (Dart SDK)
and see the issues that will pop in the face of the developers because the defaults are not there anymore
Do you think this description should be in a new file or in README.md?
I'm following this journey message by message. And the solution is fantastic. Because actually Parse Server is more Dart than Flutter. But @Nidal-Bakir last approach made me curious.
I use b4a's ParseServer on Dart and I don't need all these parameters. Because with the elimination of Flutter would I need it?
These parameters are optional and do not need to be sent to the server, but an explanation can be given about coreStore and connectivityProvider and fileDirectory.
I use b4a's ParseServer on Dart and I don't need all these parameters. Because with the elimination of Flutter would I need it?
If you are using the Parse Dart SDK and the default configuration work with you then you are good to go no need to pass any additional argument.
But the Flutter framework users will have to pass arguments to these parameters . Because the Parse Dart SDK will have different behavior than the Parse Flutter SDK if they didn't pass arguments to these parameters.
For example, the Parse Flutter SDK will automatically provide a connectivityProvider
to the SDK, but the Parse Dart SDK will not provide connectivityProvider
and will keep it null
.
The liveQuery
feature expect a connectivityProvider
so when the connection is cut off and then restored again later the liveQuery
will try to reconnect to the server. if the user did not pass a connectivityProvider
the liveQuery will NOT work
https://github.com/parse-community/Parse-SDK-Flutter/blob/94be0442883d22056a1e898384abc3adf1495990/packages/dart/lib/src/network/parse_live_query.dart#L42-L50
Another example, the Parse Flutter SDK will provide the CoreStoreSharedPrefsImp
as default storage but the Parse Dart SDK will not provide any storage option and will fallback to the CoreStoreMemoryImp
One of the things we need to do is we need to make it crystal clear that the liveQuery
feature will not work without a connectivityProvider
argument
Do you think this description should be in a new file or in README.md?
We need a proper migration guide, steps, and code documentation (parameters and behaviors)
Parse_Dart_SDK is NOT one-drop replacement for Parse_Flutter_SDK
Thanks for the detailed explanation @Nidal-Bakir I believe that some users of Parse_Flutter_SDK like me will not have this vision due to the facilities already presented by Parse_Flutter_SDK. I support your warnings that the README.md should contain a detailed step-by-step migration to Parse_Dart_SDK. Avoiding affecting users in the continuity of their projects. Once I have the beta version of this migration it will be a pleasure to test it on some of my projects to help them. Thanks to you and everyone else for this fantastic contribution.
@mtrezza Can I help him with adding code, documentation, and guides? It will be faster if we collaborate.
If yes, do I have a write permission to push commits to this PR?
do I have a write permission to push commits to this PR?
I don't assume that you have write permissions given your team membership, but you could just try to push a commit. If it fails, then @mbfakourii could give you access to his fork so you can push to his branch to collaborate.
We need a proper migration guide, steps, and code documentation (parameters and behaviors) Parse_Dart_SDK is NOT one-drop replacement for Parse_Flutter_SDK
In order to merge the 2 packages, the complexity to migrate should be manageable, even for a less proficient developer.
So this trickles down 1-2-3. The better the 1st and 2nd focus, the less migration guide is needed for us to write and for the developer to read.
To be honest the developer will write all the code that was previously provided by the Flutter SDK. which is:
in summary, we are asking the developers to code the Flutter SDK
And that is what we called boilerplate.
I hope we think again about this transition, even if the parse community, in general, moving toward one package/repo. sometimes it is better to have more than one package, so the SDK users do not need to do a lot of work to set up the SDK and use it.
No one loves to write a boilerplate
@Nidal-Bakir Do you have push access now?
I fully agree @Nidal-Bakir
Improvement for some would complicate for many.
Considering my level of knowledge and necessary work compared to what I already have to use, it would not be good news.
I fully agree @Nidal-Bakir
Improvement for some would complicate for many.
Considering my level of knowledge and necessary work compared to what I already have to use, it would not be good news.
I think it can be solved with an explanation
Do you have push access now?
Yes, thanks
let us wait and see what @mtrezza will say. it's up to him to decide what should we do.
@Nidal-Bakir
The coreStore (CoreStoreSharedPrefsImp,CoreStoreMemoryImp,CoreStoreSembastImp)
problem has been solved in this file. The idea of using dynamics was to see if it is a good method or not.
and how to use
coreStore: await CoreStoreSharedPrefsImp.getInstance(
sharedPreferences: (await SharedPreferences.getInstance())),
Any issue related to Flutter can be transferred outside
That's what the Flutter SDK was doing!! now the developers need to do it manually.
as @catalunha said:
Considering my level of knowledge and necessary work compared to what I already have to use, it would not be good news.
The package users already not liking this transition! because they need to write code that was hidden in the Flutter SDK.
do not forget all of this:
* init a database with a path using path_porvider package if they need to use Sembast database * create a connectivityProvider class and instantiate it if they need to use liveQuery * specifying the fileDirectory using path_provider package so the SDK can store the downloaded files * specifying appName, appVersion, appPackageName the Flutter SDK was using PackageInfo package
in summary, we are asking the developers to code the Flutter SDK
The SDK before this transition was plug-and-play no extra thing you need to do. Just set your parse API keys and you're good to go.
But now they need to install the SDK set the parse API keys, set up the database storage, file storage, appResumedStreamController, connectivityProvider for the live query, and specify the appName, appVersion, and appPackageName.
Literally, no one will like this over the old way. which was basically a plug-and-play no extra configuration was required.
Take a look at the firebase SDK they built a CLI to set up the SDK. So the developers do not need to do anything.
set up the database storage, file storage, appResumedStreamController, connectivityProvider for the live query, and specify the appName, appVersion, and appPackageName.
Can you help me understand why we could not provide this in the new single SDK? And could you give a code example for these, to get an idea of what that actually means in terms of coding effort for the developer?
Sure, here is the full story...
Can you help me understand why we could not provide this in the new single SDK?
Those packages depend on Flutter in their dependency to make platform-specific calls. but the new SDK should be os-agnostic. because it's pure Dart and if we use these packages in the new SKD now we are not a pure Dart package and we have a platform-specific code, even though the SDK itself not making these calls.
If we need to add these packages in the SDK we need to migrate the other way around. we need to remove the dart SDK and migrate to the Flutter SDK. then we can use packages that make calls to platform-specific functions. because in this case, a (Flutter package) package uses should use this package in the Flutter context (in a Flutter project) and not in a Dart project.
Another unexpected thing that will face the developers if we add these packages to the Dart SDK is that the developers expect the package to be pure dart so they can use it in a CLI for example or any context outside the Flutter framework, but here is the plot twist the SDK will download the entire Flutter framework for this simple console application because our dependency graph contains Flutter Framework itself as a dependency of a dependency that we are using.
The following code is from the path_provider package:
dependencies:
flutter:
sdk: flutter
As you can see the path_provider package depends on the Flutter framework.
In the world of Flutter and Dart packages, we have two types:
Flutter packages which in turn have tow types:
Packages can contain more than one kind of content:
Dart packages: General packages written in Dart, for example, the path package. Some of these might contain Flutter-specific functionality and thus have a dependency on the Flutter framework, restricting their use to Flutter only, for example, the fluro package.
Plugin packages: A specialized Dart package that contains an API written in Dart code combined with one or more platform-specific implementations.
Plugin packages can be written for Android (using Kotlin or Java), iOS (using Swift or Objective-C), web, macOS, Windows, or Linux, or any combination thereof.
Because the new SDK is a pure dart with no platform-specific code which means the new SDK is os-agnostic. i.e. we do not request features from any platform.
And could you give a code example for these, to get an idea of what that actually means in terms of coding effort for the developer?
Sure, here is a two code snippet the first one before the transition and the second after the transition:
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart';
var keyParseApplicationId = '';
var keyParseServerUrl = '';
var keyParseClientKey = '';
var liveQueryUrl = '';
class InitParse {
Future<void> init() async {
await Parse().initialize(
keyParseApplicationId,
keyParseServerUrl,
clientKey: keyParseClientKey,
liveQueryUrl: liveQueryUrl,
coreStore: await CoreStoreSembastImp.getInstance(),
);
}
}
import 'dart:async';
import 'dart:io';
import 'dart:ui' as ui;
import 'package:connectivity_plus/connectivity_plus.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:package_info_plus/package_info_plus.dart';
import 'package:parse_server_sdk/parse_server_sdk.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart' as path_provider;
var keyParseApplicationId = '';
var keyParseServerUrl = '';
var keyParseClientKey = '';
var liveQueryUrl = '';
class InitParse with WidgetsBindingObserver {
StreamController<void> appResumedStreamController = StreamController();
void init() async {
final PackageInfo packageInfo = await PackageInfo.fromPlatform();
final appName = packageInfo.appName;
final appVersion = packageInfo.version;
final appPackageName = packageInfo.packageName;
await Parse().initialize(
keyParseApplicationId,
keyParseServerUrl,
clientKey: keyParseClientKey,
liveQueryUrl: liveQueryUrl,
appName: appName,
appPackageName: appPackageName,
appVersion: appVersion,
coreStore: await CoreStoreSembastImp.getInstance(await databaseFile()),
fileDirectory: await getTempDirectory(),
connectivityProvider: MyConnectivityProvider(),
locale: local(),
appResumedStream: appResumedStreamController.stream,
);
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) {
super.didChangeAppLifecycleState(state);
appResumedStreamController.sink.add(null);
}
String local() {
return (kIsWeb ? ui.window.locale.toString() : Platform.localeName);
}
Future<String> databaseFile() async {
final databaseDir = await getDatabaseDirectory();
return path.join(databaseDir, 'parse', 'parse.db');
}
Future<String> getDatabaseDirectory() async {
if (kIsWeb) {
return '';
}
if (defaultTargetPlatform == TargetPlatform.iOS) {
return (await path_provider.getLibraryDirectory()).path;
}
return (await path_provider.getApplicationDocumentsDirectory()).path;
}
Future<String> getTempDirectory() async {
return (await path_provider.getTemporaryDirectory()).path;
}
}
class MyConnectivityProvider extends ParseConnectivityProvider {
@override
Future<ParseConnectivityResult> checkConnectivity() async {
switch (await Connectivity().checkConnectivity()) {
case ConnectivityResult.wifi:
return ParseConnectivityResult.wifi;
case ConnectivityResult.mobile:
return ParseConnectivityResult.mobile;
case ConnectivityResult.none:
return ParseConnectivityResult.none;
default:
return ParseConnectivityResult.wifi;
}
}
@override
Stream<ParseConnectivityResult> get connectivityStream {
return Connectivity().onConnectivityChanged.map((ConnectivityResult event) {
switch (event) {
case ConnectivityResult.wifi:
return ParseConnectivityResult.wifi;
case ConnectivityResult.mobile:
return ParseConnectivityResult.mobile;
default:
return ParseConnectivityResult.none;
}
});
}
}
We have two options:
The dart package seems more like a classic "core module" that is pretty useless for developers because they will always run it on some OS, so they always need to wrap it into platform specific code, right?
Why would we want to merge into a single dart package instead of a single flutter package? What's the practical application of a pure dart package?
In your example code, can't we build this platform specific code into the package, so that the package contains code for multiple platforms, similar to a multiarchitecture binary? If the SDK could detect the platforms type then it can do that automatically. If not, then the developer could set it manually. For example, our API mail adapter supports multiple email services providers out of the box, the developer just needs to set the correct one and the adapter will automatically encode the payload so that the specific service provider can understand it.
The dart package seems more like a classic "core module" that is pretty useless for developers because they will always run it on some OS, so they always need to wrap it into platform specific code, right?
At the end of the day yes, will run on some OS, the idea behind this "core module" (Dart SDK) is the separation of concerns. so that any OS-related call will be handled outside the core module (Dart SDK).
Why would we want to merge into a single dart package instead of a single flutter package? What's the practical application of a pure dart package?
That was a mistake, we did not realize the amount of manual work the developers will do to set up the SDK.
In your example code, can't we build this platform specific code into the package, so that the package contains code for multiple platforms, similar to a multiarchitecture binary? If the SDK could detect the platforms type then it can do that automatically. If not, then the developer could set it manually. For example, our API mail adapter supports multiple email services providers out of the box, the developer just needs to set the correct one and the adapter will automatically encode the payload so that the specific service provider can understand it.
yes, we can do that. by migrating to the Flutter SDK
Just sharing @mtrezza
What's the practical application of a pure dart package?
In two of my projects I open a pure Dart connection to do CRUDs and Querys in Parse Serve from b4a. Performing all the tests I need. Not in the TDD standard, but being able to access Parse Serve from b4a from a simple App in pure Dart. So when I go to the Flutter application I already have all the CRUDs and Querys ready and it's just developing the interface.
Sure, here is the full story...
Can you help me understand why we could not provide this in the new single SDK?
Those packages depend on Flutter in their dependency to make platform-specific calls. but the new SDK should be os-agnostic. because it's pure Dart and if we use these packages in the new SKD now we are not a pure Dart package and we have a platform-specific code, even though the SDK itself not making these calls.
If we need to add these packages in the SDK we need to migrate the other way around. we need to remove the dart SDK and migrate to the Flutter SDK. then we can use packages that make calls to platform-specific functions. because in this case, a (Flutter package) package uses should use this package in the Flutter context (in a Flutter project) and not in a Dart project.
Another unexpected thing that will face the developers if we add these packages to the Dart SDK is that the developers expect the package to be pure dart so they can use it in a CLI for example or any context outside the Flutter framework, but here is the plot twist the SDK will download the entire Flutter framework for this simple console application because our dependency graph contains Flutter Framework itself as a dependency of a dependency that we are using.
The following code is from the path_provider package:
dependencies: flutter: sdk: flutter
As you can see the path_provider package depends on the Flutter framework.
In the world of Flutter and Dart packages, we have two types:
- Dart package (pure Dart): the package contains only dart code no platform-specific calls, nor Flutter-related code. an example of these types of packages would be math, HTTP, Dio, or any other package that is contained in itself. i.e. can run without interaction with the host OS or the Flutter framework.
Flutter packages which in turn have tow types:
- Flutter Package: a package that depends on the Flutter framework to do its work. you can use any package that calls functions on the host OS like path_provider.
- Flutter Plugin: it is a type of package that will call the underlying platform by itself like the path_provider. using platform channels for example.
Packages can contain more than one kind of content: Dart packages: General packages written in Dart, for example, the path package. Some of these might contain Flutter-specific functionality and thus have a dependency on the Flutter framework, restricting their use to Flutter only, for example, the fluro package. Plugin packages: A specialized Dart package that contains an API written in Dart code combined with one or more platform-specific implementations.
Plugin packages can be written for Android (using Kotlin or Java), iOS (using Swift or Objective-C), web, macOS, Windows, or Linux, or any combination thereof.
Because the new SDK is a pure dart with no platform-specific code which means the new SDK is os-agnostic. i.e. we do not request features from any platform.
And could you give a code example for these, to get an idea of what that actually means in terms of coding effort for the developer?
Sure, here is a two code snippet the first one before the transition and the second after the transition:
Before the transition:
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart'; var keyParseApplicationId = ''; var keyParseServerUrl = ''; var keyParseClientKey = ''; var liveQueryUrl = ''; class InitParse { Future<void> init() async { await Parse().initialize( keyParseApplicationId, keyParseServerUrl, clientKey: keyParseClientKey, liveQueryUrl: liveQueryUrl, coreStore: await CoreStoreSembastImp.getInstance(), ); } }
After the transition:
import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:parse_server_sdk/parse_server_sdk.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart' as path_provider; var keyParseApplicationId = ''; var keyParseServerUrl = ''; var keyParseClientKey = ''; var liveQueryUrl = ''; class InitParse with WidgetsBindingObserver { StreamController<void> appResumedStreamController = StreamController(); void init() async { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final appName = packageInfo.appName; final appVersion = packageInfo.version; final appPackageName = packageInfo.packageName; await Parse().initialize( keyParseApplicationId, keyParseServerUrl, clientKey: keyParseClientKey, liveQueryUrl: liveQueryUrl, appName: appName, appPackageName: appPackageName, appVersion: appVersion, coreStore: await CoreStoreSembastImp.getInstance(await databaseFile()), fileDirectory: await getTempDirectory(), connectivityProvider: MyConnectivityProvider(), locale: local(), appResumedStream: appResumedStreamController.stream, ); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); appResumedStreamController.sink.add(null); } String local() { return (kIsWeb ? ui.window.locale.toString() : Platform.localeName); } Future<String> databaseFile() async { final databaseDir = await getDatabaseDirectory(); return path.join(databaseDir, 'parse', 'parse.db'); } Future<String> getDatabaseDirectory() async { if (kIsWeb) { return ''; } if (defaultTargetPlatform == TargetPlatform.iOS) { return (await path_provider.getLibraryDirectory()).path; } return (await path_provider.getApplicationDocumentsDirectory()).path; } Future<String> getTempDirectory() async { return (await path_provider.getTemporaryDirectory()).path; } } class MyConnectivityProvider extends ParseConnectivityProvider { @override Future<ParseConnectivityResult> checkConnectivity() async { switch (await Connectivity().checkConnectivity()) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; case ConnectivityResult.none: return ParseConnectivityResult.none; default: return ParseConnectivityResult.wifi; } } @override Stream<ParseConnectivityResult> get connectivityStream { return Connectivity().onConnectivityChanged.map((ConnectivityResult event) { switch (event) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; default: return ParseConnectivityResult.none; } }); } }
How to avoid this?
We have two options:
- If we still insist on one package/repo, then we need to migrate to the Flutter SDK and embed the Dart SDK in the Flutter SDK. But then the SDK can not run without the Flutter framework.
- keep everything as is. two packages.
Hi guys, as I commented before this was the exact reason the package was split into two in the first please again I’ve been using it from day one and in the beginning it was together but because of platform-specific that’s why it was divided. I hope this helps.
Sure, here is the full story...
Can you help me understand why we could not provide this in the new single SDK?
Those packages depend on Flutter in their dependency to make platform-specific calls. but the new SDK should be os-agnostic. because it's pure Dart and if we use these packages in the new SKD now we are not a pure Dart package and we have a platform-specific code, even though the SDK itself not making these calls.
If we need to add these packages in the SDK we need to migrate the other way around. we need to remove the dart SDK and migrate to the Flutter SDK. then we can use packages that make calls to platform-specific functions. because in this case, a (Flutter package) package uses should use this package in the Flutter context (in a Flutter project) and not in a Dart project.
Another unexpected thing that will face the developers if we add these packages to the Dart SDK is that the developers expect the package to be pure dart so they can use it in a CLI for example or any context outside the Flutter framework, but here is the plot twist the SDK will download the entire Flutter framework for this simple console application because our dependency graph contains Flutter Framework itself as a dependency of a dependency that we are using.
The following code is from the path_provider package:
dependencies: flutter: sdk: flutter
As you can see the path_provider package depends on the Flutter framework.
In the world of Flutter and Dart packages, we have two types:
- Dart package (pure Dart): the package contains only dart code no platform-specific calls, nor Flutter-related code. an example of these types of packages would be math, HTTP, Dio, or any other package that is contained in itself. i.e. can run without interaction with the host OS or the Flutter framework.
Flutter packages which in turn have tow types:
- Flutter Package: a package that depends on the Flutter framework to do its work. you can use any package that calls functions on the host OS like path_provider.
- Flutter Plugin: it is a type of package that will call the underlying platform by itself like the path_provider. using platform channels for example.
Packages can contain more than one kind of content: Dart packages: General packages written in Dart, for example, the path package. Some of these might contain Flutter-specific functionality and thus have a dependency on the Flutter framework, restricting their use to Flutter only, for example, the fluro package. Plugin packages: A specialized Dart package that contains an API written in Dart code combined with one or more platform-specific implementations.
Plugin packages can be written for Android (using Kotlin or Java), iOS (using Swift or Objective-C), web, macOS, Windows, or Linux, or any combination thereof.
Because the new SDK is a pure dart with no platform-specific code which means the new SDK is os-agnostic. i.e. we do not request features from any platform.
And could you give a code example for these, to get an idea of what that actually means in terms of coding effort for the developer?
Sure, here is a two code snippet the first one before the transition and the second after the transition:
Before the transition:
import 'package:parse_server_sdk_flutter/parse_server_sdk.dart'; var keyParseApplicationId = ''; var keyParseServerUrl = ''; var keyParseClientKey = ''; var liveQueryUrl = ''; class InitParse { Future<void> init() async { await Parse().initialize( keyParseApplicationId, keyParseServerUrl, clientKey: keyParseClientKey, liveQueryUrl: liveQueryUrl, coreStore: await CoreStoreSembastImp.getInstance(), ); } }
After the transition:
import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:parse_server_sdk/parse_server_sdk.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart' as path_provider; var keyParseApplicationId = ''; var keyParseServerUrl = ''; var keyParseClientKey = ''; var liveQueryUrl = ''; class InitParse with WidgetsBindingObserver { StreamController<void> appResumedStreamController = StreamController(); void init() async { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final appName = packageInfo.appName; final appVersion = packageInfo.version; final appPackageName = packageInfo.packageName; await Parse().initialize( keyParseApplicationId, keyParseServerUrl, clientKey: keyParseClientKey, liveQueryUrl: liveQueryUrl, appName: appName, appPackageName: appPackageName, appVersion: appVersion, coreStore: await CoreStoreSembastImp.getInstance(await databaseFile()), fileDirectory: await getTempDirectory(), connectivityProvider: MyConnectivityProvider(), locale: local(), appResumedStream: appResumedStreamController.stream, ); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); appResumedStreamController.sink.add(null); } String local() { return (kIsWeb ? ui.window.locale.toString() : Platform.localeName); } Future<String> databaseFile() async { final databaseDir = await getDatabaseDirectory(); return path.join(databaseDir, 'parse', 'parse.db'); } Future<String> getDatabaseDirectory() async { if (kIsWeb) { return ''; } if (defaultTargetPlatform == TargetPlatform.iOS) { return (await path_provider.getLibraryDirectory()).path; } return (await path_provider.getApplicationDocumentsDirectory()).path; } Future<String> getTempDirectory() async { return (await path_provider.getTemporaryDirectory()).path; } } class MyConnectivityProvider extends ParseConnectivityProvider { @override Future<ParseConnectivityResult> checkConnectivity() async { switch (await Connectivity().checkConnectivity()) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; case ConnectivityResult.none: return ParseConnectivityResult.none; default: return ParseConnectivityResult.wifi; } } @override Stream<ParseConnectivityResult> get connectivityStream { return Connectivity().onConnectivityChanged.map((ConnectivityResult event) { switch (event) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; default: return ParseConnectivityResult.none; } }); } }
How to avoid this?
We have two options:
- If we still insist on one package/repo, then we need to migrate to the Flutter SDK and embed the Dart SDK in the Flutter SDK. But then the SDK can not run without the Flutter framework.
- keep everything as is. two packages.
Sorry guys, I think we should keep the two packages. My reason for that is the dart version is the core and the flatter is built on top of that and anyone can build another package on top of it say a sign up package on top of the dart and people will have the choice to use it or not. Again anyone using the dart version do not need the flatter package , but if you use the flutter package, you will still need to import the data version into it. So I think we should leave the two packages and just allow people to build packages on top of the Dart package That’s my view.
@mtrezza We have wasted a lot of time on this. We need to make up our minds. There are a lot of open issues and feature requests besides improving the SDK, adding some documentation in the code, adding any missing features, and so on ...
Currently, the options are the next:
@mtrezza We have wasted a lot of time on this. We need to make up our minds. There are a lot of open issues and feature requests besides improving the SDK, adding some documentation in the code, adding any missing features, and so on ...
Currently, the options are the next:
- drop the Flutter SDK and keep the Dart SDK (this PR)
- mege the Dart SDK in Fluttter SDK
- keep everything as it is. (the best option)
- defer this to another time
Option 3 sounds good for now and let’s take time and really think about this properly.
In my opinion, we should solve the problem with some explanations, I think that the problem will be solved by explaining the data and the developers can adapt.
We spent a lot of time on this PR, I don't think it's right to skip it
We spent a lot of time on this PR, I don't think it's right to skip it
I don’t think it’s been skip is just that we need to take time and really think about it but in the meantime we should continue to update the flutter package .
Thanks everyone for their input in this discussion. The time is well spent if we come to the right conclusion.
My previous point is still unclear to me:
Why would we want to merge into a single dart package instead of a single flutter package? What's the practical application of a pure dart package?
And what's the practical downside of offering a flutter package instead of a dart package? From @catalunha's explaination it sounds like a developer would always want the flutter package, because they will always run it on some OS and may need platform specific code.
Whatever we have on other open bug fixes and features we can go ahead and merge in the meantime.
I have seen a lot of developers code the domain/business logic in the dart console application, so it's easier to test and run. no need for a device to run the code. And then take the results code and put it in a Flutter application and then implement the UI with the state management. Offering a Dart SDK enable them to do that. Because it is not dependent on the Flutter framework.
Another use case for the Dart SDK is if any developer needs to build a CLI application.
Offering a Flutter SDK only will prevent the use cases I mention above.
Got it, thanks. And can't we include the platform specific code that is mentioned in "After the transition" in the dart package to make it a "universal package"? The code contains flutter imports - could they be imported only optionally somehow?
And can't we include the platform specific code that is mentioned in https://github.com/parse-community/Parse-SDK-Flutter/pull/852#issuecomment-1473357297 in the dart package to make it a "universal package"?
Because any platform specific code requires the Flutter framework to be present. any platform specific call is done through the Flutter framework
The code contains flutter imports - could they be imported only optionally somehow?
These imports are declared outside the SDK. i.e. the developer is writing this.
the developer will write this.
After the transition:
import 'dart:async'; import 'dart:io'; import 'dart:ui' as ui; import 'package:connectivity_plus/connectivity_plus.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/widgets.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:parse_server_sdk/parse_server_sdk.dart'; import 'package:path/path.dart' as path; import 'package:path_provider/path_provider.dart' as path_provider; var keyParseApplicationId = ''; var keyParseServerUrl = ''; var keyParseClientKey = ''; var liveQueryUrl = ''; class InitParse with WidgetsBindingObserver { StreamController<void> appResumedStreamController = StreamController(); void init() async { final PackageInfo packageInfo = await PackageInfo.fromPlatform(); final appName = packageInfo.appName; final appVersion = packageInfo.version; final appPackageName = packageInfo.packageName; await Parse().initialize( keyParseApplicationId, keyParseServerUrl, clientKey: keyParseClientKey, liveQueryUrl: liveQueryUrl, appName: appName, appPackageName: appPackageName, appVersion: appVersion, coreStore: await CoreStoreSembastImp.getInstance(await databaseFile()), fileDirectory: await getTempDirectory(), connectivityProvider: MyConnectivityProvider(), locale: local(), appResumedStream: appResumedStreamController.stream, ); } @override void didChangeAppLifecycleState(AppLifecycleState state) { super.didChangeAppLifecycleState(state); appResumedStreamController.sink.add(null); } String local() { return (kIsWeb ? ui.window.locale.toString() : Platform.localeName); } Future<String> databaseFile() async { final databaseDir = await getDatabaseDirectory(); return path.join(databaseDir, 'parse', 'parse.db'); } Future<String> getDatabaseDirectory() async { if (kIsWeb) { return ''; } if (defaultTargetPlatform == TargetPlatform.iOS) { return (await path_provider.getLibraryDirectory()).path; } return (await path_provider.getApplicationDocumentsDirectory()).path; } Future<String> getTempDirectory() async { return (await path_provider.getTemporaryDirectory()).path; } } class MyConnectivityProvider extends ParseConnectivityProvider { @override Future<ParseConnectivityResult> checkConnectivity() async { switch (await Connectivity().checkConnectivity()) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; case ConnectivityResult.none: return ParseConnectivityResult.none; default: return ParseConnectivityResult.wifi; } } @override Stream<ParseConnectivityResult> get connectivityStream { return Connectivity().onConnectivityChanged.map((ConnectivityResult event) { switch (event) { case ConnectivityResult.wifi: return ParseConnectivityResult.wifi; case ConnectivityResult.mobile: return ParseConnectivityResult.mobile; default: return ParseConnectivityResult.none; } }); } }
Another convention in the Flutter/Dart packages world is that if any package on the pub.dev has the "Dart" in its name that means it does not need flutter to run.
And the same thing goes for any package that has the "Flutter" name in it. it is like a hint that the package needs flutter to run
That's why we can not convert a Dart package to Flutter one. (We can but we should not)
Well, I think we can put this PR on hold for now as further deliberation seems to be needed.
New Pull Request Checklist
Issue Description
In order to reduce conflicts, it was decided to remove the Flutter version, so the following tasks should be done
example
to test the packageexample_ui
for graphic widgetsexample
projectexample_ui
projectCloses: #850
Approach
n/a
TODOs before merging