From ac3a160721122768df298d2cb81547a28ca6ef9e Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 00:19:49 +0200 Subject: [PATCH 1/8] update streamingApi remote --- packages/app/config/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/packages/app/config/index.js b/packages/app/config/index.js index bc7ac92d..32b42378 100644 --- a/packages/app/config/index.js +++ b/packages/app/config/index.js @@ -14,8 +14,8 @@ export default { }, remotes: { mainApi: process.env.NODE_ENV !== "production" ? `http://${window.location.hostname}:3000` : defaultRemotesOrigins.main_api, - streamingApi: defaultRemotesOrigins.streaming_api, - websocketApi: process.env.NODE_ENV !== "production" ? `ws://${window.location.hostname}:3000` : defaultRemotesOrigins.websocket_api, + streamingApi: process.env.NODE_ENV !== "production" ? `https://${window.location.hostname}:3002` : defaultRemotesOrigins.streaming_api, + websocketApi: process.env.NODE_ENV !== "production" ? `ws://${window.location.hostname}:3001` : defaultRemotesOrigins.websocket_api, }, app: { title: packagejson.name, From 095c82a79aa8fcb189fca8078a3e434d47e354eb Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 00:32:04 +0200 Subject: [PATCH 2/8] support custom components --- packages/app/constants/settings/account.jsx | 16 +-- packages/app/constants/settings/app.jsx | 20 +-- packages/app/constants/settings/apparence.jsx | 8 +- .../app/src/components/Settings/index.jsx | 114 ++++++++++-------- 4 files changed, 85 insertions(+), 73 deletions(-) diff --git a/packages/app/constants/settings/account.jsx b/packages/app/constants/settings/account.jsx index 760eec89..4dfbeb0d 100644 --- a/packages/app/constants/settings/account.jsx +++ b/packages/app/constants/settings/account.jsx @@ -5,7 +5,7 @@ export default [ { "id": "username", "group": "account.basicInfo", - "type": "Button", + "component": "Button", "icon": "AtSign", "title": "Username", "description": "Your username is the name you use to log in to your account.", @@ -17,7 +17,7 @@ export default [ { "id": "fullName", "group": "account.basicInfo", - "type": "Input", + "component": "Input", "icon": "Edit3", "title": "Name", "description": "Change your public name", @@ -57,7 +57,7 @@ export default [ { "id": "email", "group": "account.basicInfo", - "type": "Input", + "component": "Input", "icon": "Mail", "title": "Email", "description": "Change your email address", @@ -87,7 +87,7 @@ export default [ { "id": "avatar", "group": "account.profile", - "type": "ImageUpload", + "component": "ImageUpload", "icon": "Image", "title": "Avatar", "description": "Change your avatar", @@ -95,7 +95,7 @@ export default [ { "id": "cover", "group": "account.profile", - "type": "ImageUpload", + "component": "ImageUpload", "icon": "Image", "title": "Cover", "description": "Change your cover", @@ -103,7 +103,7 @@ export default [ { "id": "primaryBadge", "group": "account.profile", - "type": "Select", + "component": "Select", "icon": "Tag", "title": "Primary badge", "description": "Change your primary badge", @@ -111,7 +111,7 @@ export default [ { "id": "description", "group": "account.profile", - "type": "TextArea", + "component": "TextArea", "icon": "Edit3", "title": "Description", "description": "Change your description for your profile", @@ -141,7 +141,7 @@ export default [ { "id": "logout", "footer": true, - "type": "Button", + "component": "Button", "icon": "LogOut", "title": "Logout", "emitEvent": "session.logout", diff --git a/packages/app/constants/settings/app.jsx b/packages/app/constants/settings/app.jsx index d3af1c8f..32178b39 100644 --- a/packages/app/constants/settings/app.jsx +++ b/packages/app/constants/settings/app.jsx @@ -7,7 +7,7 @@ export default [ "id": "language", "storaged": true, "group": "general", - "type": "Select", + "component": "Select", "icon": "MdTranslate", "title": "Language", "description": "Choose a language for the application", @@ -22,7 +22,7 @@ export default [ "id": "forceMobileMode", "storaged": true, "group": "general", - "type": "Switch", + "component": "Switch", "icon": "MdSmartphone", "title": "Force Mobile Mode", "description": "Force the application to run in mobile mode.", @@ -32,7 +32,7 @@ export default [ "id": "haptic_feedback", "storaged": true, "group": "general", - "type": "Switch", + "component": "Switch", "icon": "MdVibration", "title": "Haptic Feedback", "description": "Enable haptic feedback on touch events.", @@ -41,7 +41,7 @@ export default [ "id": "selection_longPress_timeout", "storaged": true, "group": "general", - "type": "Slider", + "component": "Slider", "icon": "MdTimer", "title": "Selection press delay", "description": "Set the delay before the selection trigger is activated.", @@ -62,7 +62,7 @@ export default [ "id": "notifications_sound", "storaged": true, "group": "notifications", - "type": "Switch", + "component": "Switch", "icon": "MdVolumeUp", "title": "Notifications Sound", "description": "Play a sound when a notification is received.", @@ -71,7 +71,7 @@ export default [ "id": "notifications_vibrate", "storaged": true, "group": "notifications", - "type": "Switch", + "component": "Switch", "icon": "MdVibration", "title": "Vibration", "description": "Vibrate the device when a notification is received.", @@ -81,7 +81,7 @@ export default [ "id": "notifications_sound_volume", "storaged": true, "group": "notifications", - "type": "Slider", + "component": "Slider", "icon": "MdVolumeUp", "title": "Sound Volume", "description": "Set the volume of the sound when a notification is received.", @@ -96,7 +96,7 @@ export default [ "id": "edit_sidebar", "storaged": true, "group": "sidebar", - "type": "Button", + "component": "Button", "icon": "Edit", "title": "Edit Sidebar", "emitEvent": "edit_sidebar", @@ -106,7 +106,7 @@ export default [ "id": "collapseOnLooseFocus", "storaged": true, "group": "sidebar", - "type": "Switch", + "component": "Switch", "icon": "Columns", "title": "Auto Collapse", "description": "Collapse the sidebar when loose focus", @@ -116,7 +116,7 @@ export default [ "id": "autoCollapseDelay", "storaged": true, "group": "sidebar", - "type": "Slider", + "component": "Slider", "icon": "Wh", "dependsOn": { "collapseOnLooseFocus": true diff --git a/packages/app/constants/settings/apparence.jsx b/packages/app/constants/settings/apparence.jsx index 310ba6f3..e3952f64 100644 --- a/packages/app/constants/settings/apparence.jsx +++ b/packages/app/constants/settings/apparence.jsx @@ -5,7 +5,7 @@ export default [ "id": "reduceAnimations", "storaged": true, "group": "aspect", - "type": "Switch", + "component": "Switch", "icon": "MdOutlineAnimation", "title": "Reduce animation", "experimental": true @@ -15,7 +15,7 @@ export default [ "id": "darkMode", "storaged": true, "group": "aspect", - "type": "Switch", + "component": "Switch", "icon": "Moon", "title": "Dark mode", "emitEvent": "theme.applyVariant", @@ -27,7 +27,7 @@ export default [ "id": "primaryColor", "storaged": true, "group": "aspect", - "type": "SliderColorPicker", + "component": "SliderColorPicker", "title": "Primary color", "description": "Change primary color of the application.", "emitEvent": "modifyTheme", @@ -42,7 +42,7 @@ export default [ "id": "resetTheme", "storaged": true, "group": "aspect", - "type": "Button", + "component": "Button", "title": "Reset theme", "props": { "children": "Default Theme" diff --git a/packages/app/src/components/Settings/index.jsx b/packages/app/src/components/Settings/index.jsx index 0887d213..72797c26 100644 --- a/packages/app/src/components/Settings/index.jsx +++ b/packages/app/src/components/Settings/index.jsx @@ -28,16 +28,15 @@ const ItemTypes = { const SettingItem = (props) => { let { item } = props + const [loading, setLoading] = React.useState(true) const [value, setValue] = React.useState(item.defaultValue ?? false) const [delayedValue, setDelayedValue] = React.useState(null) - if (!item.type) { - console.error(`Item [${item.id}] has no an type!`) - return null - } - if (typeof ItemTypes[item.type] === "undefined") { - console.error(`Item [${item.id}] has an invalid type: ${item.type}`) + let SettingComponent = item.component + + if (!SettingComponent) { + console.error(`Item [${item.id}] has no an component!`) return null } @@ -142,54 +141,67 @@ const SettingItem = (props) => { settingInitialization() }, []) - switch (item.type.toLowerCase()) { - case "slidercolorpicker": { - item.props.onChange = (color) => { - item.props.color = color.hex - } - item.props.onChangeComplete = (color) => { - onUpdateItem(color.hex) - } - item.props.color = value + if (typeof SettingComponent === "string") { + if (typeof ItemTypes[SettingComponent] === "undefined") { + console.error(`Item [${item.id}] has an invalid component: ${item.component}`) + return null + } - break - } - case "textarea": { - item.props.defaultValue = value - item.props.onPressEnter = (event) => dispatchUpdate(event.target.value) - item.props.onChange = (event) => onUpdateItem(event.target.value) - break - } - case "input": { - item.props.defaultValue = value - item.props.onPressEnter = (event) => dispatchUpdate(event.target.value) - item.props.onChange = (event) => onUpdateItem(event.target.value) - break - } - case "switch": { - item.props.checked = value - item.props.onClick = (event) => onUpdateItem(event) - break - } - case "select": { - item.props.onChange = (value) => onUpdateItem(value) - item.props.defaultValue = value - break - } - case "slider": { - item.props.defaultValue = value - item.props.onAfterChange = (value) => onUpdateItem(value) - break - } - default: { - if (!item.props.children) { - item.props.children = item.title ?? item.id + // fix props + + switch (SettingComponent.toLowerCase()) { + case "slidercolorpicker": { + item.props.onChange = (color) => { + item.props.color = color.hex + } + item.props.onChangeComplete = (color) => { + onUpdateItem(color.hex) + } + + item.props.color = value + + break + } + case "textarea": { + item.props.defaultValue = value + item.props.onPressEnter = (event) => dispatchUpdate(event.target.value) + item.props.onChange = (event) => onUpdateItem(event.target.value) + break + } + case "input": { + item.props.defaultValue = value + item.props.onPressEnter = (event) => dispatchUpdate(event.target.value) + item.props.onChange = (event) => onUpdateItem(event.target.value) + break + } + case "switch": { + item.props.checked = value + item.props.onClick = (event) => onUpdateItem(event) + break + } + case "select": { + item.props.onChange = (value) => onUpdateItem(value) + item.props.defaultValue = value + break + } + case "slider": { + item.props.defaultValue = value + item.props.onAfterChange = (value) => onUpdateItem(value) + break + } + default: { + if (!item.props.children) { + item.props.children = item.title ?? item.id + } + item.props.value = item.defaultValue + item.props.onClick = (event) => onUpdateItem(event) + break } - item.props.value = item.defaultValue - item.props.onClick = (event) => onUpdateItem(event) - break } + + // override with default item component + SettingComponent = ItemTypes[SettingComponent] } return
@@ -230,7 +242,7 @@ const SettingItem = (props) => {
- {loading ?
Loading...
: React.createElement(ItemTypes[item.type], item.props)} + {loading ?
Loading...
: React.createElement(SettingComponent, item.props)}
{delayedValue &&
From 97c0770b1e71f83a771dcf400d8aa7cba4e0cbec Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 00:45:47 +0200 Subject: [PATCH 3/8] dependsOn now should check every update --- .../app/src/components/Settings/index.jsx | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/packages/app/src/components/Settings/index.jsx b/packages/app/src/components/Settings/index.jsx index 72797c26..80e19cdc 100644 --- a/packages/app/src/components/Settings/index.jsx +++ b/packages/app/src/components/Settings/index.jsx @@ -32,6 +32,7 @@ const SettingItem = (props) => { const [loading, setLoading] = React.useState(true) const [value, setValue] = React.useState(item.defaultValue ?? false) const [delayedValue, setDelayedValue] = React.useState(null) + const [disabled, setDisabled] = React.useState(false) let SettingComponent = item.component @@ -99,6 +100,20 @@ const SettingItem = (props) => { } } + const checkDependsValidation = () => { + return !Boolean(Object.keys(item.dependsOn).every((key) => { + const storagedValue = window.app.settings.get(key) + + console.debug(`Checking validation for [${key}] with now value [${storagedValue}]`) + + if (typeof item.dependsOn[key] === "function") { + return item.dependsOn[key](storagedValue) + } + + return storagedValue === item.dependsOn[key] + })) + } + const settingInitialization = async () => { if (item.storaged) { const storagedValue = window.app.settings.get(item.id) @@ -110,17 +125,15 @@ const SettingItem = (props) => { } if (typeof item.dependsOn === "object") { - const dependsOptionsKeys = Object.keys(item.dependsOn) + // create a event handler to watch changes + Object.keys(item.dependsOn).forEach((key) => { + window.app.eventBus.on(`setting.update.${key}`, () => { + setDisabled(checkDependsValidation()) + }) + }) - item.props.disabled = !Boolean(dependsOptionsKeys.every((key) => { - const storagedValue = window.app.settings.get(key) - - if (typeof item.dependsOn[key] === "function") { - return item.dependsOn[key](storagedValue) - } - - return storagedValue === item.dependsOn[key] - })) + // by default check depends validation + item.props.disabled = checkDependsValidation() } if (typeof item.listenUpdateValue === "string") { @@ -141,7 +154,6 @@ const SettingItem = (props) => { settingInitialization() }, []) - if (typeof SettingComponent === "string") { if (typeof ItemTypes[SettingComponent] === "undefined") { console.error(`Item [${item.id}] has an invalid component: ${item.component}`) @@ -194,8 +206,10 @@ const SettingItem = (props) => { if (!item.props.children) { item.props.children = item.title ?? item.id } + item.props.value = item.defaultValue item.props.onClick = (event) => onUpdateItem(event) + break } } @@ -204,6 +218,8 @@ const SettingItem = (props) => { SettingComponent = ItemTypes[SettingComponent] } + item.props["disabled"] = disabled + return
From 05fbdd8a1cb0166415ee64e6f51e4b51ac5cd91b Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 00:46:02 +0200 Subject: [PATCH 4/8] added `auto_darkMode` --- packages/app/constants/settings/apparence.jsx | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/packages/app/constants/settings/apparence.jsx b/packages/app/constants/settings/apparence.jsx index e3952f64..5dd1864f 100644 --- a/packages/app/constants/settings/apparence.jsx +++ b/packages/app/constants/settings/apparence.jsx @@ -11,7 +11,23 @@ export default [ "experimental": true }, { + "id": "auto_darkMode", + "dependsOn": { + "darkMode": false + }, "experimental": true, + "storaged": true, + "group": "aspect", + "component": "Switch", + "icon": "Moon", + "title": "Auto dark mode", + "emitEvent": "app.autoDarkModeToogle", + }, + { + "experimental": true, + "dependsOn": { + "auto_darkMode": false + }, "id": "darkMode", "storaged": true, "group": "aspect", From 0c04019cb4163bd9b443ac2536e6ce9782b0b5b9 Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 00:51:04 +0200 Subject: [PATCH 5/8] fix depends validation & unsubscribe update events for unmounted items --- packages/app/src/components/Settings/index.jsx | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/packages/app/src/components/Settings/index.jsx b/packages/app/src/components/Settings/index.jsx index 80e19cdc..9edb6142 100644 --- a/packages/app/src/components/Settings/index.jsx +++ b/packages/app/src/components/Settings/index.jsx @@ -100,6 +100,15 @@ const SettingItem = (props) => { } } + const onUnmount = () => { + // unsubscribe eventBus events + if (typeof item.dependsOn === "object") { + for (let key in item.dependsOn) { + window.app.eventBus.off(`setting.update.${key}`, onUpdateItem) + } + } + } + const checkDependsValidation = () => { return !Boolean(Object.keys(item.dependsOn).every((key) => { const storagedValue = window.app.settings.get(key) @@ -133,7 +142,7 @@ const SettingItem = (props) => { }) // by default check depends validation - item.props.disabled = checkDependsValidation() + setDisabled(checkDependsValidation()) } if (typeof item.listenUpdateValue === "string") { @@ -152,6 +161,8 @@ const SettingItem = (props) => { React.useEffect(() => { settingInitialization() + + return onUnmount }, []) if (typeof SettingComponent === "string") { From ba58f8772a6ccbaa04cca5566cb857f20b8e82b2 Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 01:04:01 +0200 Subject: [PATCH 6/8] fix render core --- packages/app/src/cores/render/index.jsx | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/app/src/cores/render/index.jsx b/packages/app/src/cores/render/index.jsx index ff6e49dc..b767dd03 100644 --- a/packages/app/src/cores/render/index.jsx +++ b/packages/app/src/cores/render/index.jsx @@ -8,7 +8,7 @@ import NotFoundRender from "./staticsRenders/404" import CrashRender from "./staticsRenders/crash" export const ConnectWithApp = (component) => { - return window.app.bindContexts(component) + return RenderCore.bindContexts(component) } export function GetRoutesComponentMap() { @@ -107,10 +107,6 @@ export class RouteRender extends EvitePureComponent { export class RenderCore extends Core { progressBar = progressBar.configure({ parent: "html", showSpinner: false }) - publicMethods = { - setLocation: this.ctx.history.setLocation, - } - initialize = () => { const defaultTransitionDelay = 150 @@ -138,6 +134,8 @@ export class RenderCore extends Core { this.ctx.history.lastLocation = this.history.location }, delay ?? defaultTransitionDelay) } + + this.ctx.registerPublicMethod("setLocation", this.ctx.history.setLocation) } validateLocationSlash = (location) => { @@ -150,7 +148,7 @@ export class RenderCore extends Core { return key } - bindContexts = (component) => { + static bindContexts = (component) => { let contexts = { main: {}, app: {}, From 42399d3645dd92f06c4ce07954dbd304c71cbc78 Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 01:09:24 +0200 Subject: [PATCH 7/8] handle auto prefered color scheme --- packages/app/src/cores/style/index.jsx | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/app/src/cores/style/index.jsx b/packages/app/src/cores/style/index.jsx index 42b9daa9..68dd22cd 100644 --- a/packages/app/src/cores/style/index.jsx +++ b/packages/app/src/cores/style/index.jsx @@ -12,6 +12,11 @@ export default class StyleCore extends Core { currentVariant = null events = { + "app.autoDarkMode": (value) => { + if (value === true) { + this.handleAutoColorScheme() + } + }, "theme.applyVariant": (value) => { this.applyVariant(value) this.setVariant(value) @@ -28,11 +33,21 @@ export default class StyleCore extends Core { publicMethods = { style: this } - + static get currentVariant() { return document.documentElement.style.getPropertyValue("--themeVariant") } + handleAutoColorScheme() { + const prefered = window.matchMedia("(prefers-color-scheme: light)") + + if (window.app.settings.get("app.auto_darkMode") && !prefered.matches) { + this.applyVariant("dark") + }else { + this.applyVariant("false") + } + } + initialize = async () => { let theme = this.getStoragedTheme() @@ -61,6 +76,11 @@ export default class StyleCore extends Core { // apply variation this.applyVariant(variantKey) + + // handle auto prefered color scheme + if (window.app.settings.get("app.auto_darkMode")) { + window.matchMedia("(prefers-color-scheme: light)").addListener(this.handleAutoColorScheme) + } } getRootVariables = () => { From 81ef46fc5173bfdf54e40e87119b2647c4bd408f Mon Sep 17 00:00:00 2001 From: srgooglo Date: Tue, 31 May 2022 01:09:36 +0200 Subject: [PATCH 8/8] fix cores initialization --- packages/app/src/App.jsx | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/packages/app/src/App.jsx b/packages/app/src/App.jsx index f48bf090..90c4e727 100644 --- a/packages/app/src/App.jsx +++ b/packages/app/src/App.jsx @@ -298,7 +298,7 @@ class App extends React.Component { const initializationTasks = [ async () => { try { - await app.ApiController.attachAPIConnection() + await this.props.cores.ApiCore.attachAPIConnection() app.eventBus.emit("app.initialization.api_success") } catch (error) { @@ -357,8 +357,8 @@ class App extends React.Component { await Promise.tasked(initializationTasks).catch((reason) => { console.error(`[App] Initialization failed: ${reason.cause}`) app.eventBus.emit("runtime.crash", { - message: `App initialization failed`, - details: reason.cause, + message: `App initialization failed (${reason.cause})`, + details: reason.details, }) }) } @@ -384,7 +384,7 @@ class App extends React.Component { return false } - await app.ApiController.attachWSConnection() + await this.props.cores.ApiCore.attachWSConnection() } __UserInit = async () => {