Skip to content
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

Bug: Can't save language preference #314

Open
ceruleanjo opened this issue Apr 22, 2021 · 11 comments · Fixed by Kuuchuu/focalboard#5 · May be fixed by #4915
Open

Bug: Can't save language preference #314

ceruleanjo opened this issue Apr 22, 2021 · 11 comments · Fixed by Kuuchuu/focalboard#5 · May be fixed by #4915
Labels
Bug Something isn't working Hacktoberfest Help Wanted Extra attention is needed Up for grabs Looking for a contributor to fix it

Comments

@ceruleanjo
Copy link

Summary:
The app forgets my language choice every time I restart it.

Steps to reproduce the behavior:

  1. Go to Settings
  2. Set Language
  3. Choose anything
  4. Close the app
  5. Reopen the app, and see the error

Expected behavior:
The language preference should be persistent.

Screenshots:
If applicable, add screenshots to help explain your problem.

Platform:

  • Win standalone app

Additional context:
Add any other context about the problem here.

@ceruleanjo ceruleanjo added the Bug Something isn't working label Apr 22, 2021
@Johennes
Copy link
Contributor

I can confirm this on the native mac app v0.6.5 as well.

@chenilim
Copy link
Contributor

Thanks @ceruleanjo and @Johennes! The root issue is that both the Mac and Windows apps pick a random port for each session, causing any saved LocalStorage items (including the language and theme preferences) to be reset. Ideally, we need a mechanism for each native app to save user preferences outside of the hosted web app, then restore them at launch.

@chenilim chenilim added Help Wanted Extra attention is needed Up for grabs Looking for a contributor to fix it labels Apr 23, 2021
@Johennes
Copy link
Contributor

Oh, interesting. I think that would be a limitation for #310 as well then. 😔

I'm not proficient in the Windows side, unfortunately. But for the mac app, we could maybe retrieve the storage in applicationWillTerminate (which allows for around 5 seconds of processing) and store it into the native user defaults. Then on launch of the app, we could re-inject it into the web view similar to how it's done for the session token – only that of course we'd only want to run this once, not on every page load.

I had a brief look at the event APIs for storage objects as well and they seem limited. window.addEventListener('storage', ... will only trigger for changes made from other pages, but not for changes made from the current page.

@chenilim
Copy link
Contributor

Thanks @Johennes. Yes, ideally the native app would retrieve localStorage and store that in UserDefault, then push that back to the WebView on reload.

The localStorage keys we need to persist are:

  • language
  • theme
  • lastBoardId
  • lastViewId
  • emoji-mart.last
  • emoji-mart.frequently

Ideally, there would be a JS/TS function that returns the properties to persist, and a corresponding one to apply them - so the list would live in the web code, called from the native app wrapper.

P1 is calling this before terminate (though I have found the terminate event to be unreliable on macOS).
P2 is adding a callback so the JS code can trigger this (e.g. when the user changes settings).

If you would like to take a crack at any part of this, that would be great! We can follow the same pattern on the other OS clients later. Thanks!

@Johennes
Copy link
Contributor

I took a stab at the pre-terminate-export in #331. There were a lot more moving pieces to it than I had anticipated though and I had to deviate from the original idea a little to get it to work. Would appreciate thoughts and feedback in the PR.

@chenilim
Copy link
Contributor

Awesome, thanks so much @Johennes! I added some thoughts and comments in the PR.

chenilim pushed a commit that referenced this issue Apr 27, 2021
* [GH-314] Persist and reapply users settings in mac app

Relates to: #314

* Inject settings blob at document start, push base64 conversion into TS, use proper quotes

* Remove whitespace

* Rename base64 to blob for consistency
@chenilim
Copy link
Contributor

Continuing the conversation from the PR here @Willyfrog. I've merged PR #331 (thanks @Johennes!), which persists the localStorage settings as a blob on window close on macOS. There are a number of additional improvements we can make from here, including:

  • Support Windows and Linux as well
  • Cleaning up / refactoring the webapp-to-native API / interface
  • Support for app migrations (I think we only need to worry about upgrades right?)
    • For now, the settings are nice-to-have, and losing them on corner cases is not catastrophic

Keeping this issue open for further discussion and fixes. If anyone wants to work on this further, just mention it here. Thanks!

@Johennes
Copy link
Contributor

Johennes commented Apr 29, 2021

I took a look into the webview API used in the Linux app:

  • We can use Init to inject the settings blob at document start just like we did for the mac app
  • To export the settings, we need to combine Eval and Bind. Eval doesn't return a result so we have to first bind a native callback function like this:
w.Bind("storeBlob", func(blob string) bool { /* store the blob */ })
w.Eval("storeBlob(Focalboard.exportUserSettingsBlob());")

One problem I hit when fooling around with the above is that the app seems to be killed when quitting it via the window manager button. I tried catching SIGINT and SIGTERM but that didn't work. I've been trying this out on macOS so it's possible that on Linux it behaves differently. If not, we may have to think about alternatives to exporting the data on exit.

As for storing the exported settings, the most naive idea I had was to just put the base64 blob into a text file at $XDG_DATA_HOME/focalboard/settings. Would that be acceptable?

@Willyfrog
Copy link
Contributor

One problem I hit when fooling around with the above is that the app seems to be killed when quitting it via the window manager button. I tried catching SIGINT and SIGTERM but that didn't work. I've been trying this out on macOS so it's possible that on Linux it behaves differently. If not, we may have to think about alternatives to exporting the data on exit.

yep, linux has a couple of ways of killing an app, so it might be tricky to look for all. when you mention the "window manager button" you mean the X in the title bar or killing it from another app?

As for storing the exported settings, the most naive idea I had was to just put the base64 blob into a text file at $XDG_DATA_HOME/focalboard/settings. Would that be acceptable?

I'd go with $XDG_CONFIG_HOME/focalboard/settings and failing that because it might not be set, fallback to $HOME/.config/focalboard/settings

@Johennes
Copy link
Contributor

yep, linux has a couple of ways of killing an app, so it might be tricky to look for all. when you mention the "window manager button" you mean the X in the title bar or killing it from another app?

I meant the X button, yeah.

Maybe it would make sense then to first follow through along the path you started in #333 and implement dynamic settings export upon settings change. That would free us from having to deal with any application life-cycle events.

Johennes added a commit to Johennes/focalboard that referenced this issue May 3, 2021
This switches from exporting the native app user settings on window close to exporting
on settings change. This way the settings export remains independent of native application
life-cycle events.

This is a stop-gap towards enabling settings export on the native Linux app. The latter
does not have an easy way to catch window close events.

Relates to: mattermost-community#314
@Johennes
Copy link
Contributor

Johennes commented May 3, 2021

I pushed #380 to switch over to exporting the user settings dynamically on change. Apart from making the export in the mac app more reliable, this should make for a good basis to implement the export in the Linux (and possibly Windows) app as there's no more dependence on app life-cycle events anymore.

jespino added a commit that referenced this issue Aug 15, 2021
* [GH-314] Export native app user settings on change

This switches from exporting the native app user settings on window close to exporting
on settings change. This way the settings export remains independent of native application
life-cycle events.

This is a stop-gap towards enabling settings export on the native Linux app. The latter
does not have an easy way to catch window close events.

Relates to: #314

* Disable no-shadow rule to prevent false-positive

* Verify allowed localStorage keys

* Fix import order/spacing

* Treat JSON parsing errors as failed import

* Read known keys from the correct type 🤦

* Extend logging with imported keys and always include _current_ user settings

* Fixing eslint

Co-authored-by: Hossein <[email protected]>
Co-authored-by: Jesús Espino <[email protected]>
Johennes added a commit to Johennes/focalboard that referenced this issue Oct 9, 2021
This commit adds persistence for the user settings in the native Linux
app. The settings are written to $XDG_CONFIG_HOME/focalboard/settings.
If XDG_CONFIG_HOME is unset, the app falls back to $HOME/.config.

The change hooks into the existing settings export already used in the
nativve macOS app which means the settings are persisted immediately on
change.

Unfortunately, the golang webview package uses a custom native binding
technology and doesn't allow to define WebKit message handlers. As a
result, a dedicated message handler function was added to the existing
NativeApp object. In the native macOS app, said handler is
short-circuited to window.webkit.messagehandlers.[NAME].postMessage.
This has the benefit that the web app remains agnostic of the particular
native binding mechanism.

Relates to: mattermost-community#314
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug Something isn't working Hacktoberfest Help Wanted Extra attention is needed Up for grabs Looking for a contributor to fix it
Projects
None yet
4 participants