Merge branch 'master' into core-integration

This commit is contained in:
srgooglo 2022-05-31 01:12:56 +02:00 committed by GitHub
commit 0dfbd5a556
7 changed files with 163 additions and 88 deletions

View File

@ -14,8 +14,8 @@ export default {
}, },
remotes: { remotes: {
mainApi: process.env.NODE_ENV !== "production" ? `http://${window.location.hostname}:3000` : defaultRemotesOrigins.main_api, mainApi: process.env.NODE_ENV !== "production" ? `http://${window.location.hostname}:3000` : defaultRemotesOrigins.main_api,
streamingApi: defaultRemotesOrigins.streaming_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}:3000` : defaultRemotesOrigins.websocket_api, websocketApi: process.env.NODE_ENV !== "production" ? `ws://${window.location.hostname}:3001` : defaultRemotesOrigins.websocket_api,
}, },
app: { app: {
title: packagejson.name, title: packagejson.name,

View File

@ -5,7 +5,7 @@ export default [
{ {
"id": "username", "id": "username",
"group": "account.basicInfo", "group": "account.basicInfo",
"type": "Button", "component": "Button",
"icon": "AtSign", "icon": "AtSign",
"title": "Username", "title": "Username",
"description": "Your username is the name you use to log in to your account.", "description": "Your username is the name you use to log in to your account.",
@ -17,7 +17,7 @@ export default [
{ {
"id": "fullName", "id": "fullName",
"group": "account.basicInfo", "group": "account.basicInfo",
"type": "Input", "component": "Input",
"icon": "Edit3", "icon": "Edit3",
"title": "Name", "title": "Name",
"description": "Change your public name", "description": "Change your public name",
@ -57,7 +57,7 @@ export default [
{ {
"id": "email", "id": "email",
"group": "account.basicInfo", "group": "account.basicInfo",
"type": "Input", "component": "Input",
"icon": "Mail", "icon": "Mail",
"title": "Email", "title": "Email",
"description": "Change your email address", "description": "Change your email address",
@ -87,7 +87,7 @@ export default [
{ {
"id": "avatar", "id": "avatar",
"group": "account.profile", "group": "account.profile",
"type": "ImageUpload", "component": "ImageUpload",
"icon": "Image", "icon": "Image",
"title": "Avatar", "title": "Avatar",
"description": "Change your avatar", "description": "Change your avatar",
@ -95,7 +95,7 @@ export default [
{ {
"id": "cover", "id": "cover",
"group": "account.profile", "group": "account.profile",
"type": "ImageUpload", "component": "ImageUpload",
"icon": "Image", "icon": "Image",
"title": "Cover", "title": "Cover",
"description": "Change your cover", "description": "Change your cover",
@ -103,7 +103,7 @@ export default [
{ {
"id": "primaryBadge", "id": "primaryBadge",
"group": "account.profile", "group": "account.profile",
"type": "Select", "component": "Select",
"icon": "Tag", "icon": "Tag",
"title": "Primary badge", "title": "Primary badge",
"description": "Change your primary badge", "description": "Change your primary badge",
@ -111,7 +111,7 @@ export default [
{ {
"id": "description", "id": "description",
"group": "account.profile", "group": "account.profile",
"type": "TextArea", "component": "TextArea",
"icon": "Edit3", "icon": "Edit3",
"title": "Description", "title": "Description",
"description": "Change your description for your profile", "description": "Change your description for your profile",
@ -141,7 +141,7 @@ export default [
{ {
"id": "logout", "id": "logout",
"footer": true, "footer": true,
"type": "Button", "component": "Button",
"icon": "LogOut", "icon": "LogOut",
"title": "Logout", "title": "Logout",
"emitEvent": "session.logout", "emitEvent": "session.logout",

View File

@ -7,7 +7,7 @@ export default [
"id": "language", "id": "language",
"storaged": true, "storaged": true,
"group": "general", "group": "general",
"type": "Select", "component": "Select",
"icon": "MdTranslate", "icon": "MdTranslate",
"title": "Language", "title": "Language",
"description": "Choose a language for the application", "description": "Choose a language for the application",
@ -22,7 +22,7 @@ export default [
"id": "forceMobileMode", "id": "forceMobileMode",
"storaged": true, "storaged": true,
"group": "general", "group": "general",
"type": "Switch", "component": "Switch",
"icon": "MdSmartphone", "icon": "MdSmartphone",
"title": "Force Mobile Mode", "title": "Force Mobile Mode",
"description": "Force the application to run in mobile mode.", "description": "Force the application to run in mobile mode.",
@ -32,7 +32,7 @@ export default [
"id": "haptic_feedback", "id": "haptic_feedback",
"storaged": true, "storaged": true,
"group": "general", "group": "general",
"type": "Switch", "component": "Switch",
"icon": "MdVibration", "icon": "MdVibration",
"title": "Haptic Feedback", "title": "Haptic Feedback",
"description": "Enable haptic feedback on touch events.", "description": "Enable haptic feedback on touch events.",
@ -41,7 +41,7 @@ export default [
"id": "selection_longPress_timeout", "id": "selection_longPress_timeout",
"storaged": true, "storaged": true,
"group": "general", "group": "general",
"type": "Slider", "component": "Slider",
"icon": "MdTimer", "icon": "MdTimer",
"title": "Selection press delay", "title": "Selection press delay",
"description": "Set the delay before the selection trigger is activated.", "description": "Set the delay before the selection trigger is activated.",
@ -62,7 +62,7 @@ export default [
"id": "notifications_sound", "id": "notifications_sound",
"storaged": true, "storaged": true,
"group": "notifications", "group": "notifications",
"type": "Switch", "component": "Switch",
"icon": "MdVolumeUp", "icon": "MdVolumeUp",
"title": "Notifications Sound", "title": "Notifications Sound",
"description": "Play a sound when a notification is received.", "description": "Play a sound when a notification is received.",
@ -71,7 +71,7 @@ export default [
"id": "notifications_vibrate", "id": "notifications_vibrate",
"storaged": true, "storaged": true,
"group": "notifications", "group": "notifications",
"type": "Switch", "component": "Switch",
"icon": "MdVibration", "icon": "MdVibration",
"title": "Vibration", "title": "Vibration",
"description": "Vibrate the device when a notification is received.", "description": "Vibrate the device when a notification is received.",
@ -81,7 +81,7 @@ export default [
"id": "notifications_sound_volume", "id": "notifications_sound_volume",
"storaged": true, "storaged": true,
"group": "notifications", "group": "notifications",
"type": "Slider", "component": "Slider",
"icon": "MdVolumeUp", "icon": "MdVolumeUp",
"title": "Sound Volume", "title": "Sound Volume",
"description": "Set the volume of the sound when a notification is received.", "description": "Set the volume of the sound when a notification is received.",
@ -96,7 +96,7 @@ export default [
"id": "edit_sidebar", "id": "edit_sidebar",
"storaged": true, "storaged": true,
"group": "sidebar", "group": "sidebar",
"type": "Button", "component": "Button",
"icon": "Edit", "icon": "Edit",
"title": "Edit Sidebar", "title": "Edit Sidebar",
"emitEvent": "edit_sidebar", "emitEvent": "edit_sidebar",
@ -106,7 +106,7 @@ export default [
"id": "collapseOnLooseFocus", "id": "collapseOnLooseFocus",
"storaged": true, "storaged": true,
"group": "sidebar", "group": "sidebar",
"type": "Switch", "component": "Switch",
"icon": "Columns", "icon": "Columns",
"title": "Auto Collapse", "title": "Auto Collapse",
"description": "Collapse the sidebar when loose focus", "description": "Collapse the sidebar when loose focus",
@ -116,7 +116,7 @@ export default [
"id": "autoCollapseDelay", "id": "autoCollapseDelay",
"storaged": true, "storaged": true,
"group": "sidebar", "group": "sidebar",
"type": "Slider", "component": "Slider",
"icon": "Wh", "icon": "Wh",
"dependsOn": { "dependsOn": {
"collapseOnLooseFocus": true "collapseOnLooseFocus": true

View File

@ -5,17 +5,33 @@ export default [
"id": "reduceAnimations", "id": "reduceAnimations",
"storaged": true, "storaged": true,
"group": "aspect", "group": "aspect",
"type": "Switch", "component": "Switch",
"icon": "MdOutlineAnimation", "icon": "MdOutlineAnimation",
"title": "Reduce animation", "title": "Reduce animation",
"experimental": true "experimental": true
}, },
{ {
"id": "auto_darkMode",
"dependsOn": {
"darkMode": false
},
"experimental": true, "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", "id": "darkMode",
"storaged": true, "storaged": true,
"group": "aspect", "group": "aspect",
"type": "Switch", "component": "Switch",
"icon": "Moon", "icon": "Moon",
"title": "Dark mode", "title": "Dark mode",
"emitEvent": "theme.applyVariant", "emitEvent": "theme.applyVariant",
@ -27,7 +43,7 @@ export default [
"id": "primaryColor", "id": "primaryColor",
"storaged": true, "storaged": true,
"group": "aspect", "group": "aspect",
"type": "SliderColorPicker", "component": "SliderColorPicker",
"title": "Primary color", "title": "Primary color",
"description": "Change primary color of the application.", "description": "Change primary color of the application.",
"emitEvent": "modifyTheme", "emitEvent": "modifyTheme",
@ -42,7 +58,7 @@ export default [
"id": "resetTheme", "id": "resetTheme",
"storaged": true, "storaged": true,
"group": "aspect", "group": "aspect",
"type": "Button", "component": "Button",
"title": "Reset theme", "title": "Reset theme",
"props": { "props": {
"children": "Default Theme" "children": "Default Theme"

View File

@ -28,16 +28,16 @@ const ItemTypes = {
const SettingItem = (props) => { const SettingItem = (props) => {
let { item } = props let { item } = props
const [loading, setLoading] = React.useState(true) const [loading, setLoading] = React.useState(true)
const [value, setValue] = React.useState(item.defaultValue ?? false) const [value, setValue] = React.useState(item.defaultValue ?? false)
const [delayedValue, setDelayedValue] = React.useState(null) const [delayedValue, setDelayedValue] = React.useState(null)
const [disabled, setDisabled] = React.useState(false)
if (!item.type) { let SettingComponent = item.component
console.error(`Item [${item.id}] has no an type!`)
return null if (!SettingComponent) {
} console.error(`Item [${item.id}] has no an component!`)
if (typeof ItemTypes[item.type] === "undefined") {
console.error(`Item [${item.id}] has an invalid type: ${item.type}`)
return null return null
} }
@ -100,6 +100,29 @@ 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)
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 () => { const settingInitialization = async () => {
if (item.storaged) { if (item.storaged) {
const storagedValue = window.app.settings.get(item.id) const storagedValue = window.app.settings.get(item.id)
@ -111,17 +134,15 @@ const SettingItem = (props) => {
} }
if (typeof item.dependsOn === "object") { 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) => { // by default check depends validation
const storagedValue = window.app.settings.get(key) setDisabled(checkDependsValidation())
if (typeof item.dependsOn[key] === "function") {
return item.dependsOn[key](storagedValue)
}
return storagedValue === item.dependsOn[key]
}))
} }
if (typeof item.listenUpdateValue === "string") { if (typeof item.listenUpdateValue === "string") {
@ -140,58 +161,76 @@ const SettingItem = (props) => {
React.useEffect(() => { React.useEffect(() => {
settingInitialization() settingInitialization()
return onUnmount
}, []) }, [])
switch (item.type.toLowerCase()) { if (typeof SettingComponent === "string") {
case "slidercolorpicker": { if (typeof ItemTypes[SettingComponent] === "undefined") {
item.props.onChange = (color) => { console.error(`Item [${item.id}] has an invalid component: ${item.component}`)
item.props.color = color.hex return null
} }
item.props.onChangeComplete = (color) => {
onUpdateItem(color.hex)
}
item.props.color = value // fix props
break switch (SettingComponent.toLowerCase()) {
} case "slidercolorpicker": {
case "textarea": { item.props.onChange = (color) => {
item.props.defaultValue = value item.props.color = color.hex
item.props.onPressEnter = (event) => dispatchUpdate(event.target.value) }
item.props.onChange = (event) => onUpdateItem(event.target.value) item.props.onChangeComplete = (color) => {
break onUpdateItem(color.hex)
} }
case "input": {
item.props.defaultValue = value item.props.color = value
item.props.onPressEnter = (event) => dispatchUpdate(event.target.value)
item.props.onChange = (event) => onUpdateItem(event.target.value) break
break }
} case "textarea": {
case "switch": { item.props.defaultValue = value
item.props.checked = value item.props.onPressEnter = (event) => dispatchUpdate(event.target.value)
item.props.onClick = (event) => onUpdateItem(event) item.props.onChange = (event) => onUpdateItem(event.target.value)
break break
} }
case "select": { case "input": {
item.props.onChange = (value) => onUpdateItem(value) item.props.defaultValue = value
item.props.defaultValue = value item.props.onPressEnter = (event) => dispatchUpdate(event.target.value)
break item.props.onChange = (event) => onUpdateItem(event.target.value)
} break
case "slider": { }
item.props.defaultValue = value case "switch": {
item.props.onAfterChange = (value) => onUpdateItem(value) item.props.checked = value
break item.props.onClick = (event) => onUpdateItem(event)
} break
default: { }
if (!item.props.children) { case "select": {
item.props.children = item.title ?? item.id 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]
} }
item.props["disabled"] = disabled
return <div key={item.id} className="settingItem"> return <div key={item.id} className="settingItem">
<div className="header"> <div className="header">
<div className="title"> <div className="title">
@ -230,7 +269,7 @@ const SettingItem = (props) => {
</div> </div>
<div className="component"> <div className="component">
<div> <div>
{loading ? <div> Loading... </div> : React.createElement(ItemTypes[item.type], item.props)} {loading ? <div> Loading... </div> : React.createElement(SettingComponent, item.props)}
</div> </div>
{delayedValue && <div> {delayedValue && <div>

View File

@ -12,6 +12,11 @@ export default class StyleCore extends Core {
currentVariant = null currentVariant = null
events = { events = {
"app.autoDarkMode": (value) => {
if (value === true) {
this.handleAutoColorScheme()
}
},
"theme.applyVariant": (value) => { "theme.applyVariant": (value) => {
this.applyVariant(value) this.applyVariant(value)
this.setVariant(value) this.setVariant(value)
@ -33,6 +38,16 @@ export default class StyleCore extends Core {
return document.documentElement.style.getPropertyValue("--themeVariant") 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 () => { initialize = async () => {
let theme = this.getStoragedTheme() let theme = this.getStoragedTheme()
@ -61,6 +76,11 @@ export default class StyleCore extends Core {
// apply variation // apply variation
this.applyVariant(variantKey) 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 = () => { getRootVariables = () => {