-
Notifications
You must be signed in to change notification settings - Fork 2k
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
[GH-314] Export native app user settings on change #380
Changes from 1 commit
087fc80
d843b2f
48f27c4
80f2d20
c237179
453a66c
f9ae2c9
894d03f
5006bd4
485ee55
b9a400c
77b0e27
34f7a8e
b0b6ec1
4ea405e
ddae786
5c4ac0b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,13 +2,18 @@ | |
// See LICENSE.txt for license information. | ||
import React from 'react' | ||
import ReactDOM from 'react-dom' | ||
import {store} from 'emoji-mart' | ||
|
||
import App from './app' | ||
import {initThemes} from './theme' | ||
import {importNativeAppSettings} from './nativeApp' | ||
import {UserSettings} from './userSettings' | ||
|
||
import './styles/variables.scss' | ||
import './styles/main.scss' | ||
import './styles/labels.scss' | ||
|
||
store.setHandlers({getter: UserSettings.getEmojiMartSetting, setter: UserSettings.setEmojiMartSetting}) | ||
importNativeAppSettings() | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I moved this here because the |
||
initThemes() | ||
ReactDOM.render(<App/>, document.getElementById('main-app')) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||
// See LICENSE.txt for license information. | ||
|
||
import {importUserSettingsBlob} from './userSettings' | ||
import {exportUserSettingsBlob, importUserSettingsBlob} from './userSettings' | ||
|
||
declare interface INativeApp { | ||
settingsBlob: string | null; | ||
|
@@ -19,14 +19,10 @@ export function importNativeAppSettings() { | |
NativeApp.settingsBlob = null | ||
} | ||
|
||
export function notifySettingsChanged(key: string) { | ||
postWebKitMessage({type: 'didChangeUserSettings', key, settingsBlob: exportUserSettingsBlob()}) | ||
} | ||
|
||
function postWebKitMessage(message: any) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Love this construct - for extending webapp-to-native messaging in the future. We'll add a mental todo to also adapt this for Windows / Linux in the future. |
||
const webkit = (window as any).webkit | ||
if (typeof webkit === 'undefined') { | ||
return | ||
} | ||
const handler = webkit.messageHandlers.nativeApp | ||
if (typeof handler === 'undefined') { | ||
return | ||
} | ||
handler.postMessage(message) | ||
(window as any).webkit?.messageHandlers.nativeApp?.postMessage(message) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,23 +1,94 @@ | ||
// Copyright (c) 2015-present Mattermost, Inc. All Rights Reserved. | ||
// See LICENSE.txt for license information. | ||
|
||
import {notifySettingsChanged} from './nativeApp' | ||
import {Utils} from './utils' | ||
|
||
enum UserSettingKey { | ||
Language = 'language', | ||
Theme = 'theme', | ||
LastBoardId = 'lastBoardId', | ||
LastViewId = 'lastViewId', | ||
EmojiMartSkin = 'emoji-mart.skin', | ||
EmojiMartLast = 'emoji-mart.last', | ||
EmojiMartFrequently = 'emoji-mart.frequently', | ||
RandomIcons = 'randomIcons' | ||
} | ||
|
||
export class UserSettings { | ||
static get(key: UserSettingKey): string | null { | ||
return localStorage.getItem(key) | ||
} | ||
|
||
static set(key: UserSettingKey, value: string | null) { | ||
Johennes marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (value === null) { | ||
localStorage.removeItem(key) | ||
} else { | ||
localStorage.setItem(key, value) | ||
} | ||
notifySettingsChanged(key) | ||
} | ||
|
||
static get language(): string | null { | ||
return UserSettings.get(UserSettingKey.Language) | ||
} | ||
|
||
static set language(newValue: string | null) { | ||
UserSettings.set(UserSettingKey.Language, newValue) | ||
} | ||
|
||
static get theme(): string | null { | ||
return UserSettings.get(UserSettingKey.Theme) | ||
} | ||
|
||
static set theme(newValue: string | null) { | ||
UserSettings.set(UserSettingKey.Theme, newValue) | ||
} | ||
|
||
static get lastBoardId(): string | null { | ||
return UserSettings.get(UserSettingKey.LastBoardId) | ||
} | ||
|
||
static set lastBoardId(newValue: string | null) { | ||
UserSettings.set(UserSettingKey.LastBoardId, newValue) | ||
} | ||
|
||
static get lastViewId(): string | null { | ||
return UserSettings.get(UserSettingKey.LastViewId) | ||
} | ||
|
||
static set lastViewId(newValue: string | null) { | ||
UserSettings.set(UserSettingKey.LastViewId, newValue) | ||
} | ||
|
||
static get prefillRandomIcons(): boolean { | ||
return localStorage.getItem('randomIcons') !== 'false' | ||
return UserSettings.get(UserSettingKey.RandomIcons) !== 'false' | ||
} | ||
|
||
static set prefillRandomIcons(newValue: boolean) { | ||
localStorage.setItem('randomIcons', JSON.stringify(newValue)) | ||
UserSettings.set(UserSettingKey.RandomIcons, JSON.stringify(newValue)) | ||
} | ||
} | ||
|
||
const keys = ['language', 'theme', 'lastBoardId', 'lastViewId', 'emoji-mart.last', 'emoji-mart.frequently'] | ||
static getEmojiMartSetting(key: string): any { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This method and the one below are a bit hairy. There's some documentation about the emoji-mart settings keys and values in the upstream README (see the "Storage" section). There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, thanks for parsing the Emojimart settings! We expect to refactor the emoji picker in the future, so this will likely change (not for a while though). |
||
const prefixed = `emoji-mart.${key}` | ||
Utils.assert((Object as any).values(UserSettingKey).includes(prefixed)) | ||
const json = UserSettings.get(prefixed as UserSettingKey) | ||
return json ? JSON.parse(json) : null | ||
} | ||
|
||
static setEmojiMartSetting(key: string, value: any) { | ||
const prefixed = `emoji-mart.${key}` | ||
Utils.assert((Object as any).values(UserSettingKey).includes(prefixed)) | ||
UserSettings.set(prefixed as UserSettingKey, JSON.stringify(value)) | ||
} | ||
} | ||
|
||
export function exportUserSettingsBlob(): string { | ||
return window.btoa(exportUserSettings()) | ||
} | ||
|
||
function exportUserSettings(): string { | ||
const keys = Object.values(UserSettingKey) | ||
const settings = Object.fromEntries(keys.map((key) => [key, localStorage.getItem(key)])) | ||
settings.timestamp = `${Date.now()}` | ||
return JSON.stringify(settings) | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Busy wait be gone! 🎉