Skip to content

full support for flutter-web #385

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
fischerscode opened this issue May 27, 2020 · 59 comments
Closed

full support for flutter-web #385

fischerscode opened this issue May 27, 2020 · 59 comments

Comments

@fischerscode
Copy link
Contributor

fischerscode commented May 27, 2020

I recently tried run my app in the browser.
Last time I tried this, it worked. This time it didn't.
The difference between success and failure is the login I added recently.

Unsupported operation: Platform._operatingSystem is printed in the log.

It seems like dart:io is causing the issue. firebase/flutterfire#1257

For live query we have two separated files. One for mobile/desktop and one for web.
We could do similar for all the files using dart:io.

Any ideas/suggestions? Or should we not support flutter-web?

Edit:
CoreStoreSembastImp would need an update, too. I think sembast has an extra package for web.

@phillwiggins
Copy link
Member

Hey

I definitley think we should support flutter-web. I've been majorly tied up over the last few months so not had a chance to look into it. I was under the impression that Sembast would support flutter-web but I could be wrong. It would be great if we supported all platforms that Dart is able to run on?

@fischerscode
Copy link
Contributor Author

It seems like universal_io should solve this problem.
Has anyone used universal_io yet?

@nstrelow
Copy link
Contributor

Can we not just include universal_io? Seems it should do the trick.

@nstrelow
Copy link
Contributor

I think this is just due to Platform.isAndroid etc. not being supported. At least that's were it breaks for me first.
I believe we can just use kIsWeb from foundations to check for web first.

I'll create a PR later, as we need this now, if we still want web to keep on working for us.

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

So my bad #392 did not fix web, but circumvented the first issue that arose.
Next one is:

Overflow on channel: uk.spiralarm.flutter/devicelocale.  Messages on this channel are being discarded in FIFO fashion.  The engine may not be running or you need to adjust the buffer size if of the channel.
╭-- Parse Response
Class: _User
Function: ParseApiRQ.loginAnonymous
Status Code: -1
Type: UnknownError
Exception: MissingPluginException(No implementation found for method currentLocale on channel uk.spiralarm.flutter/devicelocale)
╰-- 

Seems to be that devicelocale.currentLocale does not work on web.

Edit: Devicelocale does not support web: magnatronus/flutter-devicelocale#9

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

To get the current locale without the package devicelocale we can use: https://api.flutter.dev/flutter/dart-ui/Window/locale.html

Would look like this in parse_installation.dart:

//Locale
    if (!kIsWeb) {
      final String locale = await Devicelocale.currentLocale;
      if (locale != null && locale.isNotEmpty) {
        set<String>(keyLocaleIdentifier, locale);
      }
    } else {
      final String locale = ui.window.locale.languageCode;
      if (locale != null && locale.isNotEmpty) {
        set<String>(keyLocaleIdentifier, locale);
      }
    }

Next unsupported package is package_info: flutter/flutter#46609

This could also be just skipped by checking for kIsWeb:

//App info
    if (!kIsWeb) {
      final PackageInfo packageInfo = await PackageInfo.fromPlatform();
      set<String>(keyAppName, packageInfo.appName);
      set<String>(keyAppVersion, packageInfo.version);
      set<String>(keyAppIdentifier, packageInfo.packageName);
    }
    set<String>(keyParseVersion, keySdkVersion);

But now when creating a new user, I get this error:

╭-- Parse Response
Class: _User
Function: ParseApiRQ.signUp
Status Code: -1
Type: UnknownError
Exception: XMLHttpRequest error.
╰-- 



----
ParseException (Type: UnknownError) :
Code: -1
Message: XMLHttpRequest error.----

Not sure where to go from here, maybe @phillwiggins has an idea what is going wrong?

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

I think I traced the last one to the incompatibility of the http package.

http added support for web with this note:

In order to use or reference the IoClient directly, you will need to import the new package:http/io_client.dart import. This is typically only necessary if you are passing a custom HttpClient instance to the constructor, in which case you are already giving up support for web.

IOClient uses the dart:io package, which is not available on web. Will see if there is an alternative.

This line in ParseHttpClient uses IOClient if a security context is given:

        _client = securityContext != null
            ? IOClient(HttpClient(context: securityContext))
            : Client();

I'll try to find a way of not using IOClient, but not sure if possible.

EDIT: It seems to use BrowserClient instead of IOClient and still fail. So probably still a different issue.

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

Alright scratch the http package. In the end is a CORS error. I think that should be fixable.

Access to XMLHttpRequest at 'https://herokuapp.com/parse/users' from origin 'http://localhost:60240' has been blocked by CORS policy: Request header field x-parse-installation-id is not allowed by Access-Control-Allow-Headers in preflight response.

@fischerscode
Copy link
Contributor Author

fischerscode commented Jun 11, 2020

There is an option provided by the server to add custom headers.

Using env variables:
PARSE_SERVER_ALLOW_HEADERS=...

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

PARSE_SERVER_ALLOW_HEADERS is not working for my heroku setup sadly. Not sure what I am doing wrong: PARSE_SERVER_ALLOW_HEADERS=X-Parse-Installation-Id. Maybe because I am using express with parse-server

Is this normally required to set when using a the mobile SDKs?

Looking at parse-server there are default headers, which do not include the installation-id:

export const DEFAULT_ALLOWED_HEADERS =
  'X-Parse-Master-Key, X-Parse-REST-API-Key, X-Parse-Javascript-Key, X-Parse-Application-Id, X-Parse-Client-Version, X-Parse-Session-Token, X-Requested-With, X-Parse-Revocable-Session, Content-Type, Pragma, Cache-Control';

I guess mobile does not care about CORS and preflight. But for supporting web, we should either:

  • Omit the installation-id when on web (change in flutter sdk)
  • Make installation-id a default header (change in parse-server)
  • Add to README, that setting custom headers via env in server is required for web to work. (change for the user)

EDIT: Was able to set allowHeaders in ParseServerOptions. The parsing of the heroku env vars does not work for some reason.

@fischerscode
Copy link
Contributor Author

I think the best solution is to add a note to the REAMDE for bow. And once web is tested a bit more and seems to work with the additional header we should create a pr to parse-server.

I am using the env methode in a kubernetes enviroment. Maybe it is only supported when using the docker image.

@nstrelow
Copy link
Contributor

nstrelow commented Jun 11, 2020

I agree with first adding something to Readme and then looking further.

Could be that the env variables are not passed through to the ParseServer npm package.

PR incoming

@fischerscode
Copy link
Contributor Author

@nstrelow
I had to add x-parse-installation-id (in lowercase).
Without doing so, I have not been able to login.
I will investigate this later.

@gorillatapstudio
Copy link

Exception when run for web: Unsupported operation: Platform._operatingSystem
caused by ParseUser.loginWith('facebook', facebookAuth);
which calls parse_installation.dart/_updateInstallation() and it calls Platform.isAndroid which is not supported by web yet.
Hack we can add kIsWeb before calling the Platform to avoid the crash.

@fischerscode
Copy link
Contributor Author

@nstrelow has done this in #395.

@phillwiggins
Copy link
Member

No activity on this in a white. Can this be closed?

@fischerscode
Copy link
Contributor Author

I had no time recently to work on this, but I want to get back to this.
But we can close this for now and reopen or open a new issue as soon as more work on this topic is done.

@fischerscode
Copy link
Contributor Author

I am currently experimenting with web support for ParseFile.
As the whole file procedure is completely different on web I thought it might be reasonable to great a ParseWebFile class similar to the ParseFile class for mobile. This should solve the problem on the SDK level and the SDK user would get either a ParseFile or a ParseWebFile depending on the current platform.
This should not break existing apps and would make the SDK user think about how to use the file in the app. (On web referring an image by the url might be the best solution and on mobile downloading might be better.)
Due to the implementation of the "registeredSubClass" feature in 1.0.27 the provisioning of the two different file classes should be rather simple.

Any other ideas/suggestions?

@fischerscode
Copy link
Contributor Author

I have started implementing this idea in this branch currently it seems to work just fine, but I have only tested reading, yet.

@fischerscode
Copy link
Contributor Author

fischerscode commented Aug 9, 2020

I have created a pr that should enable full file support (#409).
As far as I know, the sembast CoreStore is the only thing, that's missing web support.
Does anyone know about an other issue?

@SuperKMan
Copy link

Last week I tried to run my app in the browser, it worked. but today It cannot log in to my app got the error below:

Class: _User Function: ParseApiRQ.login Status Code: -1 Type: UnknownError Exception: XMLHttpRequest error.

@nstrelow
Copy link
Contributor

Sadly I have not encountered this issue and it could mean anything.

Good luck on trying to fix it 💪

@SuperKMan
Copy link

I'm lucky. It works today with nothing to fix.

@fischerscode
Copy link
Contributor Author

Maybe it was something with the server or the connection to the server was not fully working.

@SuperKMan
Copy link

Thank you. I got an error about "CoreStoreSharedPrefsImp" when I use Dart package instead of Flutter package. Do you have any suggestion?

@fischerscode
Copy link
Contributor Author

CoreStoreSharedPrefsImp is not supported by the dart package as the shared preferences package is only available on flutter.

Why are you using the dart package instead of the flutter one?

@SuperKMan
Copy link

Just try #454 because I don't know how to fix the XMLHttpRequest error.

@fischerscode
Copy link
Contributor Author

Is there any hint in your browsers log?
For example at chrome:

  • right click -> inspect -> console -> reload your application
  • right click -> inspect -> network -> reload your application

@SuperKMan
Copy link

I got this error in the console.
Access to XMLHttpRequest at 'https://parseapi.back4app.com/login?username=mongkolpoj%40gmail.com&password=xxxxxx' from origin 'http://vcm.back4app.io' has been blocked by CORS policy: Request header field x-parse-installation-id is not allowed by Access-Control-Allow-Headers in preflight response.

@nstrelow
Copy link
Contributor

So "X-Parse-Installation-Id"
is not added to the Access-Control-Allow-Headers

Check lower-case / upper-case writing.

@SuperKMan
Copy link

Thank you. I already add this JSON to Parse Server Options:
{
"allowOrigin": "*",
"allowHeaders": [
"X-Parse-Master-Key",
"X-Parse-REST-API-Key",
"X-Parse-Javascript-Key",
"X-Parse-Client-Key",
"X-Parse-Application-Id",
"X-Parse-Client-Version",
"X-Parse-Session-Token",
"X-Requested-With",
"X-Parse-Revocable-Session",
"Content-Type",
"X-Parse-Installation-Id"
]
}

@SuperKMan
Copy link

It works now when I changed the domain 'https://parseapi.back4app.com' to 'https://vcm.back4app.io' and deploy to Back4App. But still got an XMLHTTPRequest error when I ran from AndroidStudio.

@SuperKMan
Copy link

I got an error about debug property below. Any idea?

Launching lib\main.dart on Chrome in debug mode...
Syncing files to device Chrome...
Debug service listening on ws://127.0.0.1:60556/MJMZKJiV2n0=
Debug service listening on ws://127.0.0.1:60556/MJMZKJiV2n0=
TypeError: Cannot read property 'debug' of null
at Object.isDebugEnabled (http://localhost:60525/packages/parse_server_sdk/src/utils/parse_live_list.dart.lib.js:7677:81)
at parse_server_sdk.ParseUser.new.parse_server_sdk.ParseObject.new (http://localhost:60525/packages/parse_server_sdk/src/utils/parse_live_list.dart.lib.js:5609:39)
at new parse_server_sdk.ParseUser.new (http://localhost:60525/packages/parse_server_sdk/src/utils/parse_live_list.dart.lib.js:7244:46)
at user_auth_provider.UserAuthProvider.new.logIn (http://localhost:60525/packages/vcm/auth/user_auth_provider.dart.lib.js:52:21)
at logIn.next ()
at runBody (http://localhost:60525/dart_sdk.js:37613:34)
at Object._async [as async] (http://localhost:60525/dart_sdk.js:37644:7)
at user_auth_provider.UserAuthProvider.new.logIn (http://localhost:60525/packages/vcm/auth/user_auth_provider.dart.lib.js:51:20)
at login_screen._LoginScreenState.new. (http://localhost:60525/packages/vcm/screens/vc_section5_screen.dart.lib.js:83316:77)
at Generator.next ()
at runBody (http://localhost:60525/dart_sdk.js:37613:34)
at Object._async [as async] (http://localhost:60525/dart_sdk.js:37644:7)
at ink_well._InkResponseStateWidget.new. (http://localhost:60525/packages/vcm/screens/vc_section5_screen.dart.lib.js:83313:1288)
at ink_well._InkResponseState.new.[_handleTap] (http://localhost:60525/packages/flutter/src/material/icon_button.dart.lib.js:47433:21)
at http://localhost:60525/packages/flutter/src/material/icon_button.dart.lib.js:47535:668
at tap.TapGestureRecognizer.new.invokeCallback (http://localhost:60525/packages/flutter/src/gestures/recognizer.dart.lib.js:189:18)
at tap.TapGestureRecognizer.new.handleTapUp (http://localhost:60525/packages/flutter/src/gestures/tap.dart.lib.js:395:40)
at tap.TapGestureRecognizer.new.[_checkUp] (http://localhost:60525/packages/flutter/src/gestures/tap.dart.lib.js:201:12)
at tap.TapGestureRecognizer.new.acceptGesture (http://localhost:60525/packages/flutter/src/gestures/tap.dart.lib.js:178:23)
at arena.GestureArenaManager.new.sweep (http://localhost:60525/packages/flutter/src/gestures/arena.dart.lib.js:208:31)
at binding$5.WidgetsFlutterBinding.new.handleEvent (http://localhost:60525/packages/flutter/src/gestures/binding.dart.lib.js:307:27)
at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:60525/packages/flutter/src/gestures/binding.dart.lib.js:286:24)
at binding$5.WidgetsFlutterBinding.new.dispatchEvent (http://localhost:60525/packages/flutter/src/rendering/layer.dart.lib.js:5949:13)
at binding$5.WidgetsFlutterBinding.new.[_handlePointerEvent] (http://localhost:60525/packages/flutter/src/gestures/binding.dart.lib.js:257:14)
at binding$5.WidgetsFlutterBinding.new.[_flushPointerEventQueue] (http://localhost:60525/packages/flutter/src/gestures/binding.dart.lib.js:229:35)
at binding$5.WidgetsFlutterBinding.new.[_handlePointerDataPacket] (http://localhost:60525/packages/flutter/src/gestures/binding.dart.lib.js:213:65)
at Object._invoke1 (http://localhost:60525/dart_sdk.js:175453:7)
at _engine.EngineWindow.new.invokeOnPointerDataPacket (http://localhost:60525/dart_sdk.js:171307:15)
at _engine.PointerBinding.__.[_onPointerData] (http://localhost:60525/dart_sdk.js:158211:24)
at http://localhost:60525/dart_sdk.js:158598:26
at http://localhost:60525/dart_sdk.js:158557:16
at http://localhost:60525/dart_sdk.js:158310:11

@fischerscode
Copy link
Contributor Author

Do you have a ParseLiveListWidget in your widget tree before Parse.init() finished?

@PawlikMichal25
Copy link
Contributor

@fischerscode @phillwiggins
When do you expect to release version 1.0.28 to pub?
It could be even as 1.0.28-dev or something.

We have been using version 1.0.28 on Flutter Web for 3 weeks now and everything works smoothly 👍

@fischerscode
Copy link
Contributor Author

fischerscode commented Oct 2, 2020

@BaranMichal25
I would love, to add #458 to 1.0.28, maybe I will find time today to finish the tasks.
Only @phillwiggins can create a release on pub.dev, as it is his personal account.
1.0.28-dev sounds like a good idea, too.

We have been using version 1.0.28 on Flutter Web for 3 weeks now and everything works smoothly

Glad to hear that, I am currently running this branch which uses dio, and I had no time testing both branches.

@phillwiggins
Should we use dio in 1.0.28?
For me it runs great and it would add the upload progress (#366).

@phillwiggins
Copy link
Member

phillwiggins commented Oct 2, 2020 via email

@fischerscode
Copy link
Contributor Author

@phillwiggins
Great!
I think there are not breaking changes at all. (Expect I you are overriding the ParseHTTPClient?)

@phillwiggins
Copy link
Member

phillwiggins commented Oct 2, 2020 via email

@SuperKMan
Copy link

Do you have a ParseLiveListWidget in your widget tree before Parse.init() finished?

This is my init code:
class _AppState extends State {
String text = '';

@OverRide
void initState() {
super.initState();
initData();
}

Future initCoreStore() async {
//return CoreStoreSembastImp.getInstance();
return CoreStoreSharedPrefsImp.getInstance();
}

Future initData() async {
final document = await getApplicationDocumentsDirectory();
Hive.init(document.path);
Hive.registerAdapter(ProvinceAdapter());
//Hive.openBox('province');
//await Hive.initFlutter();

//await initCoreStore();

// Initialize parse
await Parse().initialize(kApplicationId, kParseServerUrl,
    //masterKey: kParseMasterKey,
    clientKey: kParseClientKey,
    //debug: false,
    //liveQueryUrl: keyLiveQueryUrl, // Required if using LiveQuery
    autoSendSessionId: true,
    //securityContext: securityContext, // Again, required for some setups
    coreStore: await CoreStoreSharedPrefsImp
        .getInstance()); // Local data storage method. Will use SharedPreferences instead of Sembast as an internal DB

//parse serve with secure store and desktop support

//    Parse().initialize(keyParseApplicationId, keyParseServerUrl,
//        masterKey: keyParseMasterKey,
//        debug: true,
//        coreStore: CoreStoreSharedPrefsImp.getInstance());

var responseCfg = await ParseConfig().getConfigs();
// Check server is healthy and live - Debug is on in this instance so check logs for result
final ParseResponse response = await Parse().healthCheck();
if (response.success) {
  print('System ready');
} else {
  print(response.error);
}

}

@SuperKMan
Copy link

@fischerscode @phillwiggins
When do you expect to release version 1.0.28 to pub?
It could be even as 1.0.28-dev or something.

We have been using version 1.0.28 on Flutter Web for 3 weeks now and everything works smoothly 👍

I use 1.0.27

@fischerscode
Copy link
Contributor Author

I think 1.0.27 does not fully support web, but most functions should work.
@SuperKMan
Are you waiting with building you ParseLiveListWidget until the Future of your initData() function finished?
For an example, have a look at the example_livelist.

@SuperKMan
Copy link

I think 1.0.27 does not fully support web, but most functions should work.
@SuperKMan
Are you waiting with building you ParseLiveListWidget until the Future of your initData() function finished?
For an example, have a look at the example_livelist.

Thank you.

@nstrelow
Copy link
Contributor

nstrelow commented Oct 7, 2020

@fischerscode Anything holding off the release?
Currently I set my pubspec.yaml to the last commit before the spilt 🙈 .

@fischerscode
Copy link
Contributor Author

@nstrelow
No, I think everything works. I just had little time this week so far.
Tomorrow this should be different.
I aim to merge all pending PRs tomorrow. And maybe include a solution for #465.

@fischerscode fischerscode mentioned this issue Oct 8, 2020
7 tasks
fischerscode added a commit to fischerscode/Parse-SDK-Flutter that referenced this issue Oct 9, 2020
Added section for tests at migration guide.
Fix: parse-community#385 (comment)
fischerscode added a commit that referenced this issue Oct 9, 2020
Added section for tests at migration guide.
Fix: #385 (comment)
@fischerscode
Copy link
Contributor Author

With the release of 1.0.28, web should now be fully supported.
Please file an issue, if you encounter a problem.

@nstrelow
Copy link
Contributor

@fischerscode Awesome, thanks for the hard work.
Will be delighted to update my pubspec.yaml to point to pub.dev again ^^

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

No branches or pull requests

6 participants