From 34f4623a36380af78fdaede9fe24852862cca518 Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Fri, 24 Feb 2023 14:26:19 +0000 Subject: [PATCH] update settigns --- .../app/constants/settings/about/index.jsx | 109 ++++ .../app/constants/settings/about/index.less | 93 +++ .../constants/settings/apparence/index.jsx | 540 ++++++++++++++---- .../components/ImageUploader/index.jsx | 71 --- .../components/backgroundSelector/index.jsx | 57 ++ .../components/backgroundSelector/index.less | 65 +++ .../components/changePassword/index.jsx | 4 +- .../components/uploadButton/index.jsx | 69 +++ .../settings/components/urlInput/index.jsx | 31 + .../{ImageUploader => urlInput}/index.less | 0 .../constants/settings/extensions/index.jsx | 2 + .../settings/{app => general}/index.jsx | 4 +- packages/app/constants/settings/index.js | 11 +- .../settings/notifications/index.jsx | 2 + .../app/constants/settings/player/index.jsx | 40 ++ .../app/constants/settings/profile/index.jsx | 88 ++- .../app/constants/settings/security/index.jsx | 7 +- .../settings/subscriptions/index.jsx | 8 + .../app/constants/settings/sync/index.jsx | 2 + 19 files changed, 957 insertions(+), 246 deletions(-) create mode 100644 packages/app/constants/settings/about/index.jsx create mode 100755 packages/app/constants/settings/about/index.less delete mode 100755 packages/app/constants/settings/components/ImageUploader/index.jsx create mode 100644 packages/app/constants/settings/components/backgroundSelector/index.jsx create mode 100644 packages/app/constants/settings/components/backgroundSelector/index.less create mode 100644 packages/app/constants/settings/components/uploadButton/index.jsx create mode 100755 packages/app/constants/settings/components/urlInput/index.jsx rename packages/app/constants/settings/components/{ImageUploader => urlInput}/index.less (100%) rename packages/app/constants/settings/{app => general}/index.jsx (99%) create mode 100644 packages/app/constants/settings/player/index.jsx create mode 100644 packages/app/constants/settings/subscriptions/index.jsx diff --git a/packages/app/constants/settings/about/index.jsx b/packages/app/constants/settings/about/index.jsx new file mode 100644 index 00000000..be0c8dd1 --- /dev/null +++ b/packages/app/constants/settings/about/index.jsx @@ -0,0 +1,109 @@ +import React from "react" +import * as antd from "antd" +import moment from "moment" + +import { Icons } from "components/Icons" + +import config from "config" + +import "./index.less" + +const Footer = (props) => { + const isDevMode = window.__evite?.env?.NODE_ENV !== "production" + + return
+
+
{config.app?.siteName}
+
+ + v{window.app.version} + +
+
+ + {isDevMode ? : } + {isDevMode ? "development" : "stable"} + +
+
+
+} + +export default { + id: "about", + icon: "Info", + label: "About", + group: "bottom", + render: () => { + const isProduction = import.meta.env.PROD + + const [serverManifest, setServerManifest] = React.useState(null) + + const checkServerVersion = async () => { + const serverManifest = await app.cores.api.customRequest("main") + + setServerManifest(serverManifest.data) + } + + React.useEffect(() => { + checkServerVersion() + }, []) + + return
+
+
+
+ Logo +
+
+

{config.app.siteName}

+ {config.author} + Licensed with {config.package?.license ?? "unlicensed"} +
+
+
+ v{window.app.version ?? "experimental"} + + {isProduction ? : } + {String(import.meta.env.MODE)} + +
+
+ +
+

Server info

+ +
+ Powered by Linebridgeâ„¢ + +
+ v{serverManifest?.LINEBRIDGE_SERVER_VERSION ?? "Unknown"} +
+
+
+ + Origin address + + +
+ {app.cores.api?.namespaces.main.origin ?? "Unknown"} +
+
+
+ + Server Time + + +
+ {moment(serverManifest?.requestTime).format("YYYY-MM-DD HH:mm:ss")} +
+
+
+ +
+
+ } +} \ No newline at end of file diff --git a/packages/app/constants/settings/about/index.less b/packages/app/constants/settings/about/index.less new file mode 100755 index 00000000..3af67a79 --- /dev/null +++ b/packages/app/constants/settings/about/index.less @@ -0,0 +1,93 @@ +.about_app { + display: flex; + flex-direction: column; + + width: 100%; + + padding: 0 20px 20px 20px; + + background-color: var(--background-color-accent); + color: var(--text-color); + + border-radius: 12px; + + .header { + display: flex; + flex-direction: row; + + justify-content: space-between; + align-self: center; + + width: 100%; + + margin-bottom: 20px; + + padding: 20px 0; + border-bottom: 1px solid var(--border-color); + + .branding { + display: flex; + flex-direction: row; + + align-items: center; + + .logo { + width: 60px; + height: 100%; + + margin-right: 20px; + + img { + width: 100%; + height: 100%; + } + } + + .texts { + display: flex; + flex-direction: column; + + } + + h1, + h2, + h3 { + height: fit-content; + line-height: 24px; + } + + span { + height: fit-content; + color: var(--background-color-contrast); + font-size: 10px; + } + } + } + + .group { + display: inline-flex; + + flex-direction: column; + justify-content: center; + + margin-bottom: 10px; + + .field { + display: inline-flex; + flex-direction: column; + + margin-bottom: 10px; + + font-size: 0.9rem; + + .value { + font-size: 0.8rem; + + display: inline-flex; + flex-direction: row; + + margin-left: 10px; + } + } + } +} \ No newline at end of file diff --git a/packages/app/constants/settings/apparence/index.jsx b/packages/app/constants/settings/apparence/index.jsx index 3f957a74..1dfc4ef0 100755 --- a/packages/app/constants/settings/apparence/index.jsx +++ b/packages/app/constants/settings/apparence/index.jsx @@ -1,173 +1,477 @@ import React from "react" import loadable from "@loadable/component" +import { Modal } from "antd" +import UploadButton from "../components/uploadButton" import "./index.less" export default { + id: "apparence", icon: "Eye", label: "Apparence", + group: "app", settings: [ { - "id": "compactWidth", - "title": "Compact Width", - "description": "Sets the width of the app to a compact width to facilitate the vision of components.", - "component": "Switch", - "icon": "MdCompress", - "group": "layout", - "experimental": true, - "storaged": true + id: "sidebar.floating", + title: "Floating Sidebar", + description: "Make the sidebar float over layout content.", + component: "Switch", + icon: "MdOutlineLastPage", + group: "layout", + emitEvent: "app.softReload", + storaged: true, }, { - "id": "sidebar.floating", - "title": "Floating Sidebar", - "description": "Make the sidebar float over layout content.", - "component": "Switch", - "icon": "MdOutlineLastPage", - "group": "layout", - "emitEvent": "app.softReload", - "storaged": true + id: "style.reduceAnimations", + group: "animations", + component: "Switch", + icon: "MdOutlineSlowMotionVideo", + title: "Reduce animations", + experimental: true, + storaged: true, }, { - "id": "reduceAnimations", - "storaged": true, - "group": "animations", - "component": "Switch", - "icon": "MdOutlineSlowMotionVideo", - "title": "Reduce animation", - "experimental": true - }, - { - "id": "pageTransitionDuration", - "storaged": true, - "group": "animations", - "component": "Slider", - "icon": "MdOutlineSpeed", - "title": "Page transition duration", - "description": "Change the duration of the page transition animation.", - "props": { + id: "style.pageTransitionDuration", + group: "animations", + component: "Slider", + icon: "MdOutlineSpeed", + title: "Page transition duration", + description: "Change the duration of the page transition animation.", + props: { min: 0, max: 1000, step: 50, + marks: { + [app.cores.style.defaultVar("page-transition-duration").replace("ms", "")]: " ", + }, tooltip: { formatter: (value) => `${value / 1000}s` } }, - "emitEvent": "modifyTheme", - "emissionValueUpdate": (value) => { - return { + defaultValue: () => { + const value = app.cores.style.getValue("page-transition-duration") + + return value ? Number(value.replace("ms", "")) : 250 + }, + onUpdate: (value) => { + app.cores.style.modify({ "page-transition-duration": `${value}ms` - } + }) }, + storaged: true, }, { - "id": "auto_darkMode", - "experimental": true, - "storaged": true, - "group": "aspect", - "component": "Switch", - "icon": "Moon", - "title": "Auto dark mode", - "emitEvent": "style.autoDarkModeToogle", + id: "style.auto_darkMode", + group: "aspect", + component: "Switch", + icon: "Moon", + title: "Sync with system", + description: "Automatically switch to dark mode based on your system preference.", + emitEvent: "style.autoDarkModeToogle", + storaged: true, }, { - "experimental": true, - "dependsOn": { - "auto_darkMode": false + id: "style.darkMode", + group: "aspect", + component: "Switch", + icon: "Moon", + title: "Dark mode", + description: "Change the theme variant of the application to dark.", + dependsOn: { + "style.auto_darkMode": false }, - "id": "darkMode", - "storaged": true, - "group": "aspect", - "component": "Switch", - "icon": "Moon", - "title": "Dark mode", - "emitEvent": "theme.applyVariant", - "emissionValueUpdate": (value) => { - return value ? "dark" : "light" + defaultValue: () => { + return app.cores.style.currentVariant === "dark" }, + onUpdate: (value) => { + app.cores.style.modify({ + themeVariant: value ? "dark" : "light" + }) + + return value + }, + storaged: true }, { - "id": "primaryColor", - "storaged": true, - "group": "aspect", - "component": "SliderColorPicker", - "title": "Primary color", - "description": "Change primary color of the application.", - "emitEvent": "modifyTheme", - "reloadValueOnUpdateEvent": "resetTheme", - "emissionValueUpdate": (value) => { - return { - primaryColor: value - } - } + id: "style.compactMode", + group: "aspect", + component: "Switch", + icon: "MdOutlineViewCompact", + title: "Compact mode", + description: "Reduce the size of the application elements.", + defaultValue: () => { + return app.cores.style.getValue("compact-mode") + }, + onUpdate: (value) => { + app.cores.style.modify({ + "compact-mode": value + }) + + return value + }, + storaged: true }, { - "id": "backgroundImage", - "storaged": true, - "group": "aspect", - "title": "Background image", - "description": "Change background image of the application. You can use a local image or a remote image (URL).", - "component": loadable(() => import("../components/ImageUploader")), - "props": { - "noPreview": true, + id: "style.uiFont", + group: "aspect", + component: "Select", + icon: "MdOutlineFontDownload", + title: "UI font", + description: "Change the font of the application.", + props: { + style: { + width: "100%" + }, + options: [ + { + label: "Varela Round (Default)", + value: "'Varela Round', sans-serif" + }, + { + label: "Inter", + value: "'Inter', sans-serif" + }, + ] }, - "emitEvent": "modifyTheme", - "emissionValueUpdate": (value) => { - return { + defaultValue: () => { + return app.cores.style.getValue("fontFamily") + }, + onUpdate: (value) => { + app.cores.style.modify({ + "fontFamily": value + }) + + return value + }, + storaged: true + }, + { + id: "style.colorPrimary", + group: "aspect", + component: "SliderColorPicker", + title: "Primary color", + description: "Change primary color of the application.", + defaultValue: () => { + return app.cores.style.getValue("colorPrimary") + }, + onUpdate: (value) => { + app.cores.style.modify({ + "colorPrimary": value + }) + }, + storaged: false, + }, + { + id: "style.parallaxBackground", + group: "aspect", + component: "Switch", + icon: "MdOutline3DRotation", + title: "Parallax background", + description: "Create a parallax effect on the background.", + storaged: true, + }, + { + id: "style.backgroundImage", + group: "aspect", + icon: "MdOutlineImage", + title: "Background image", + description: "Change background image of the application. You can use a local image or a remote image (URL).", + component: loadable(() => import("../components/urlInput")), + props: { + noPreview: true, + }, + extraActions: [ + { + id: "delete", + icon: "Delete", + title: "Remove", + onClick: (ctx) => { + return ctx.dispatchUpdate("") + } + }, + UploadButton + ], + defaultValue: () => { + const value = app.cores.style.getValue("backgroundImage") + + console.log(value) + + return value ? value.replace(/url\(|\)/g, "") : "" + }, + onUpdate: (value) => { + app.cores.style.modify({ backgroundImage: `url(${value})` - } + }) }, + storaged: false, }, { - "id": "backgroundBlur", - "storaged": true, - "group": "aspect", - "component": "Slider", - "icon": "Eye", - "title": "Background blur", - "description": "Create a blur effect on the background.", - "props": { + id: "style.backgroundPattern", + group: "aspect", + icon: "MdGrid4X4", + component: loadable(() => import("../components/backgroundSelector")), + title: "Background pattern", + description: "Change background pattern of the application.", + extraActions: [ + { + id: "remove", + icon: "Delete", + title: "Remove", + onClick: () => { + app.cores.style.modify({ + backgroundSVG: "unset" + }) + } + } + ], + storaged: false, + }, + { + id: "style.backgroundBlur", + group: "aspect", + component: "Slider", + icon: "MdBlurOn", + title: "Background blur", + description: "Create a blur effect on the background.", + props: { min: 0, max: 50, - step: 5 + step: 1 }, - "emitEvent": "modifyTheme", - "emissionValueUpdate": (value) => { - return { - backgroundBlur: `${value}px`, - } + defaultValue: () => { + const value = app.cores.style.getValue("backgroundBlur") + + return value ? parseInt(value.replace("px", "")) : 0 }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundBlur: `${value}px` + }) + }, + storaged: false, }, { - "id": "backgroundColorTransparency", - "storaged": true, - "group": "aspect", - "component": "Slider", - "icon": "Eye", - "title": "Background color transparency", - "description": "Adjust the transparency of the background color.", - "props": { + id: "style.backgroundColorTransparency", + group: "aspect", + component: "Slider", + icon: "Eye", + title: "Background color transparency", + description: "Adjust the transparency of the background color.", + props: { min: 0, max: 1, step: 0.1 }, - "emitEvent": "modifyTheme", - "emissionValueUpdate": (value) => { - return { - backgroundColorTransparency: value, - } + defaultValue: () => { + const value = app.cores.style.getValue("backgroundColorTransparency") + + return value ? parseFloat(value) : 1 }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundColorTransparency: value + }) + }, + storaged: false }, { - "id": "resetTheme", - "storaged": true, - "group": "aspect", - "component": "Button", - "title": "Reset theme", - "props": { - "children": "Default Theme" + id: "style.backgroundSize", + group: "aspect", + component: "Select", + icon: "MdOutlineImageAspectRatio", + title: "Background size", + description: "Adjust the size of the background image.", + props: { + style: { + width: "100%" + }, + options: [ + { + label: "Cover", + value: "cover" + }, + { + label: "Contain", + value: "contain" + }, + { + label: "Auto", + value: "auto" + }, + { + label: "50%", + value: "50%" + }, + { + label: "100%", + value: "100%" + }, + { + label: "150%", + value: "150%" + }, + ] }, - "emitEvent": "resetTheme", - "noUpdate": true, + defaultValue: () => { + return app.cores.style.getValue("backgroundSize") + }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundSize: value + }) + + return value + }, + storaged: false + }, + { + id: "style.backgroundPosition", + group: "aspect", + component: "Select", + icon: "MdOutlineImageAspectRatio", + title: "Background position", + description: "Adjust the position of the background image.", + props: { + style: { + width: "100%" + }, + options: [ + { + label: "Left", + value: "left" + }, + { + label: "Center", + value: "center" + }, + { + label: "Right", + value: "right" + }, + { + label: "Top", + value: "top" + }, + ] + }, + defaultValue: () => { + return app.cores.style.getValue("backgroundPosition") + }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundPosition: value + }) + + return value + }, + storaged: false + }, + { + id: "style.backgroundRepeat", + group: "aspect", + component: "Select", + icon: "MdOutlineImageAspectRatio", + title: "Background repeat", + description: "Adjust the repeat of the background image.", + props: { + style: { + width: "100%" + }, + options: [ + { + label: "Repeat", + value: "repeat" + }, + { + label: "No repeat", + value: "no-repeat" + }, + { + label: "Repeat X", + value: "repeat-x" + }, + { + label: "Repeat Y", + value: "repeat-y" + }, + ] + }, + defaultValue: () => { + return app.cores.style.getValue("backgroundRepeat") + }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundRepeat: value + }) + + return value + }, + storaged: false + }, + { + id: "style.backgroundAttachment", + group: "aspect", + component: "Select", + icon: "MdOutlineImageAspectRatio", + title: "Background attachment", + description: "Adjust the attachment of the background image.", + props: { + style: { + width: "100%" + }, + options: [ + { + label: "Scroll", + value: "scroll" + }, + { + label: "Fixed", + value: "fixed" + }, + { + label: "Local", + value: "local" + }, + { + label: "Initial", + value: "initial" + }, + { + label: "Inherit", + value: "inherit" + }, + ] + }, + defaultValue: () => { + return app.cores.style.getValue("backgroundAttachment") + }, + onUpdate: (value) => { + app.cores.style.modify({ + backgroundAttachment: value + }) + + return value + }, + storaged: false + }, + { + id: "resetTheme", + group: "aspect", + component: "Button", + title: "Reset theme", + props: { + children: "Default Theme" + }, + onUpdate: (value) => { + Modal.confirm({ + title: "Are you sure you want to reset the theme to the default theme ?", + description: "This action will reset the theme to the default theme. All your modifications will be lost.", + onOk: () => { + app.cores.style.setDefault() + } + }) + }, + storaged: false } ] } \ No newline at end of file diff --git a/packages/app/constants/settings/components/ImageUploader/index.jsx b/packages/app/constants/settings/components/ImageUploader/index.jsx deleted file mode 100755 index 36133b0e..00000000 --- a/packages/app/constants/settings/components/ImageUploader/index.jsx +++ /dev/null @@ -1,71 +0,0 @@ -import React from "react" -import { Button, Input, Upload } from "antd" -import { Icons } from "components/Icons" - -import "./index.less" - -export default (props) => { - const [value, setValue] = React.useState(props.ctx.currentValue) - const [uploading, setUploading] = React.useState(false) - - const uploadImage = async (req) => { - setUploading(true) - - const formData = new FormData() - - formData.append("files", req.file) - - const request = await window.app.api.withEndpoints("main").post.upload(formData, undefined).catch((error) => { - console.error(error) - app.message.error(error) - - return false - }) - - setUploading(false) - - if (request) { - setValue(request.files[0].url) - props.ctx.dispatchUpdate(request.files[0].url) - } - } - - return
- { - !props.noPreview && value &&
- -
- } - - - setValue(e.target.value)} - onPressEnter={() => props.ctx.dispatchUpdate(value)} - /> - - - -
-} \ No newline at end of file diff --git a/packages/app/constants/settings/components/backgroundSelector/index.jsx b/packages/app/constants/settings/components/backgroundSelector/index.jsx new file mode 100644 index 00000000..ac06688c --- /dev/null +++ b/packages/app/constants/settings/components/backgroundSelector/index.jsx @@ -0,0 +1,57 @@ +import React from "react" +import SVG from "react-inlinesvg" + +import "./index.less" + +const defaultBackgrounds = [ + { + id: "topography", + label: "Topography", + src: "/assets/default_bg/topography.svg" + }, + { + id: "meteors", + label: "Meteors", + src: "/assets/default_bg/meteors.svg" + }, + { + id: "dots", + label: "Dots", + src: "/assets/default_bg/dots.svg" + }, + { + id: "hideout", + label: "Hideout", + src: "/assets/default_bg/hideout.svg" + } +] + +export default (props) => { + return
+
+ { + defaultBackgrounds.map((background) => { + return
+
+

{background.label}

+
+ +
{ + app.cores.style.modify({ + backgroundSVG: `url("${background.src}")` + }) + }} + style={{ + maskImage: `url("${background.src}")`, + WebkitMaskImage: `url("${background.src}")` + }} + /> + +
+ }) + } +
+
+} \ No newline at end of file diff --git a/packages/app/constants/settings/components/backgroundSelector/index.less b/packages/app/constants/settings/components/backgroundSelector/index.less new file mode 100644 index 00000000..a7d5bf9f --- /dev/null +++ b/packages/app/constants/settings/components/backgroundSelector/index.less @@ -0,0 +1,65 @@ +.background_selector { + display: flex; + flex-direction: column; + + .background_selector_defaults { + display: flex; + flex-direction: row; + align-items: center; + justify-content: flex-start; + + overflow-x: auto; + + .background_selector_defaults__item { + display: flex; + flex-direction: column; + align-items: flex-start; + justify-content: center; + + width: 10vw; + height: 300px; + + transition: all 150ms ease-in-out; + + margin-right: 20px; + + background-color: var(--background-color-accent); + + border-radius: 10px; + + .background_selector_defaults__item_name { + display: flex; + flex-direction: row; + + + + font-size: 1rem; + font-weight: 500; + + margin: 10px; + + } + + .background_selector_defaults__item_preview { + width: 100%; + height: 100%; + + overflow: hidden; + + border-radius: 10px; + + cursor: pointer; + + background-color: var(--text-color); + background-size: cover; + background-position: center; + background-repeat: no-repeat; + background-attachment: fixed; + } + + &:last-child { + margin-right: 0; + } + } + } +} \ No newline at end of file diff --git a/packages/app/constants/settings/components/changePassword/index.jsx b/packages/app/constants/settings/components/changePassword/index.jsx index 65f2b4e7..5134df4b 100755 --- a/packages/app/constants/settings/components/changePassword/index.jsx +++ b/packages/app/constants/settings/components/changePassword/index.jsx @@ -1,7 +1,7 @@ import React from "react" import * as antd from "antd" -import { User } from "models" +import { UserModel } from "models" import { Icons } from "components/Icons" import "./index.less" @@ -31,7 +31,7 @@ const ChangePasswordComponent = (props) => { setError(null) setLoading(true) - const result = await User.changePassword({ currentPassword, newPassword }).catch((err) => { + const result = await UserModel.changePassword({ currentPassword, newPassword }).catch((err) => { console.error(err) setError(err.response.data.message) return null diff --git a/packages/app/constants/settings/components/uploadButton/index.jsx b/packages/app/constants/settings/components/uploadButton/index.jsx new file mode 100644 index 00000000..483aaada --- /dev/null +++ b/packages/app/constants/settings/components/uploadButton/index.jsx @@ -0,0 +1,69 @@ +import React from "react" +import { Button, Upload } from "antd" + +import { Icons } from "components/Icons" + +export default (props) => { + const [uploading, setUploading] = React.useState(false) + + const handleUpload = async (req) => { + console.log(req) + + setUploading(true) + + const formData = new FormData() + + formData.append("files", req.file) + + const request = await window.app.cores.api.customRequest({ + url: "/upload", + method: "POST", + data: formData + }).catch((error) => { + console.error(error) + app.message.error(error.respose.data.message) + + return false + }) + + setUploading(false) + + if (request) { + // check failed uploads + if (request.failed.length > 0) { + request.failed.forEach((file) => { + app.notification.error({ + message: "Failed to upload file", + description: `Could not upload file ${file.fileName} cause > ${file.error}` + }) + }) + } + + props.ctx.dispatchUpdate(request.files[0].url) + } + } + + return + + +} \ No newline at end of file diff --git a/packages/app/constants/settings/components/urlInput/index.jsx b/packages/app/constants/settings/components/urlInput/index.jsx new file mode 100755 index 00000000..6106ae4b --- /dev/null +++ b/packages/app/constants/settings/components/urlInput/index.jsx @@ -0,0 +1,31 @@ +import React from "react" +import { Button, Input } from "antd" +import { Icons } from "components/Icons" + +import "./index.less" + +export default (props) => { + const [value, setValue] = React.useState(props.ctx.currentValue) + + return
+ { + !props.noPreview && value &&
+ +
+ } + + + setValue(e.target.value)} + onPressEnter={() => props.ctx.dispatchUpdate(value)} + /> + +
+} \ No newline at end of file diff --git a/packages/app/constants/settings/components/ImageUploader/index.less b/packages/app/constants/settings/components/urlInput/index.less similarity index 100% rename from packages/app/constants/settings/components/ImageUploader/index.less rename to packages/app/constants/settings/components/urlInput/index.less diff --git a/packages/app/constants/settings/extensions/index.jsx b/packages/app/constants/settings/extensions/index.jsx index 02bbdc2c..6b8b5fbb 100755 --- a/packages/app/constants/settings/extensions/index.jsx +++ b/packages/app/constants/settings/extensions/index.jsx @@ -2,8 +2,10 @@ import React from "react" import loadable from "@loadable/component" export default { + id: "extensions", icon: "MdOutlineCode", label: "Extensions", + group: "advanced", settings: [ ] diff --git a/packages/app/constants/settings/app/index.jsx b/packages/app/constants/settings/general/index.jsx similarity index 99% rename from packages/app/constants/settings/app/index.jsx rename to packages/app/constants/settings/general/index.jsx index 857ca0f1..4ac6224f 100755 --- a/packages/app/constants/settings/app/index.jsx +++ b/packages/app/constants/settings/general/index.jsx @@ -3,8 +3,10 @@ import config from "config" import { Select } from "antd" export default { + id: "general", icon: "Command", - label: "App", + label: "General", + group: "app", settings: [ { "id": "language", diff --git a/packages/app/constants/settings/index.js b/packages/app/constants/settings/index.js index 4acbed87..303f3df0 100755 --- a/packages/app/constants/settings/index.js +++ b/packages/app/constants/settings/index.js @@ -1,17 +1,24 @@ -import AppSettings from "./app" +import GeneralSettings from "./general" import ProfileSettings from "./profile" import SecuritySettings from "./security" +import SubcriptionsSettings from "./subscriptions" import NotificationsSettings from "./notifications" import ApparenceSettings from "./apparence" import ExtensionsSettings from "./extensions" import SyncSettings from "./sync" +import PlayerSettings from "./player" + +import AboutPage from "./about" export default { - app: AppSettings, + general: GeneralSettings, profile: ProfileSettings, apparence: ApparenceSettings, + player: PlayerSettings, security: SecuritySettings, notifications: NotificationsSettings, extensions: ExtensionsSettings, sync: SyncSettings, + subscriptions: SubcriptionsSettings, + about: AboutPage, } \ No newline at end of file diff --git a/packages/app/constants/settings/notifications/index.jsx b/packages/app/constants/settings/notifications/index.jsx index 76ac3ea9..a9a7b2c3 100755 --- a/packages/app/constants/settings/notifications/index.jsx +++ b/packages/app/constants/settings/notifications/index.jsx @@ -1,8 +1,10 @@ import React from "react" export default { + id: "notifications", icon: "Bell", label: "Notifications", + group: "basic", settings: [ ] diff --git a/packages/app/constants/settings/player/index.jsx b/packages/app/constants/settings/player/index.jsx new file mode 100644 index 00000000..7fda84f9 --- /dev/null +++ b/packages/app/constants/settings/player/index.jsx @@ -0,0 +1,40 @@ +export default { + id: "player", + icon: "PlayCircleOutlined", + label: "Player", + group: "app", + settings: [ + { + id: "player.allowVolumeOver100", + label: "Allow volume over 100%", + description: "Allow volume amplification over 100% (may cause distortion)", + component: "Switch", + storaged: true, + }, + { + id: "player.crossfade", + label: "Crossfade", + description: "Enable crossfade between tracks", + component: "Slider", + props: { + min: 0, + max: 10, + step: 0.1, + marks: { + 0: "Off", + 1: "1s", + 2: "2s", + 3: "3s", + 4: "4s", + 5: "5s", + 6: "6s", + 7: "7s", + 8: "8s", + 9: "9s", + 10: "10s", + }, + }, + storaged: true, + } + ] +} \ No newline at end of file diff --git a/packages/app/constants/settings/profile/index.jsx b/packages/app/constants/settings/profile/index.jsx index aff942c8..4c4a0f8d 100755 --- a/packages/app/constants/settings/profile/index.jsx +++ b/packages/app/constants/settings/profile/index.jsx @@ -1,12 +1,15 @@ import React from "react" -import { User } from "models" +import { UserModel } from "models" import loadable from "@loadable/component" +import UploadButton from "../components/uploadButton" export default { + id: "profile", icon: "User", label: "Profile", + group: "basic", ctxData: async () => { - const userData = await User.data() + const userData = await UserModel.data() return { userData @@ -26,47 +29,43 @@ export default { }, }, { - "id": "fullName", - "group": "account.basicInfo", - "component": "Input", - "icon": "Edit3", - "title": "Name", - "description": "Change your public name", - "props": { + id: "fullName", + group: "account.basicInfo", + component: "Input", + icon: "Edit3", + title: "Name", + description: "Change your public name", + props: { // set max length "maxLength": 120, "showCount": true, "allowClear": true, "placeholder": "Enter your name. e.g. John Doe", }, - "defaultValue": (ctx) => { + defaultValue: (ctx) => { return ctx.userData.fullName }, - "onUpdate": async (value) => { - const selfId = await User.selfUserId() - - const result = window.app.api.withEndpoints("main").post.updateUser({ - _id: selfId, - update: { - fullName: value - } + onUpdate: async (value) => { + const result = await UserModel.updateData({ + fullName: value }) if (result) { return result } }, - "extraActions": [ + extraActions: [ { "id": "unset", "icon": "Delete", "title": "Unset", "onClick": async () => { - window.app.api.withEndpoints("main").post.unsetPublicName() + await UserModel.unsetFullName() } } ], - "debounced": true, + debounced: true, + storaged: false, }, { "id": "email", @@ -85,13 +84,8 @@ export default { return ctx.userData.email }, "onUpdate": async (value) => { - const selfId = await User.selfUserId() - - const result = window.app.api.withEndpoints("main").post.updateUser({ - _id: selfId, - update: { - email: value - } + const result = await UserModel.updateData({ + email: value }) if (result) { @@ -106,18 +100,16 @@ export default { "icon": "Image", "title": "Avatar", "description": "Change your avatar (Upload an image or use an URL)", - "component": loadable(() => import("../components/ImageUploader")), + "component": loadable(() => import("../components/urlInput")), + extraActions: [ + UploadButton + ], "defaultValue": (ctx) => { return ctx.userData.avatar }, "onUpdate": async (value) => { - const selfId = await User.selfUserId() - - const result = window.app.api.withEndpoints("main").post.updateUser({ - _id: selfId, - update: { - avatar: value - } + const result = await UserModel.updateData({ + avatar: value }) if (result) { @@ -133,18 +125,16 @@ export default { "icon": "Image", "title": "Cover", "description": "Change your profile cover (Upload an image or use an URL)", - "component": loadable(() => import("../components/ImageUploader")), + "component": loadable(() => import("../components/urlInput")), + extraActions: [ + UploadButton + ], "defaultValue": (ctx) => { return ctx.userData.cover }, "onUpdate": async (value) => { - const selfId = await User.selfUserId() - - const result = window.app.api.withEndpoints("main").post.updateUser({ - _id: selfId, - update: { - cover: value - } + const result = await UserModel.updateData({ + cover: value }) if (result) { @@ -171,13 +161,8 @@ export default { return ctx.userData.description }, "onUpdate": async (value) => { - const selfId = await User.selfUserId() - - const result = window.app.api.withEndpoints("main").post.updateUser({ - _id: selfId, - update: { - description: value - } + const result = await UserModel.updateData({ + description: value }) if (result) { @@ -185,6 +170,7 @@ export default { } }, "debounced": true, + storaged: false, }, ] } \ No newline at end of file diff --git a/packages/app/constants/settings/security/index.jsx b/packages/app/constants/settings/security/index.jsx index 8bdf2d06..9be27e26 100755 --- a/packages/app/constants/settings/security/index.jsx +++ b/packages/app/constants/settings/security/index.jsx @@ -1,11 +1,14 @@ import React from "react" import loadable from "@loadable/component" +import AuthModel from "models/auth" // TODO: Make logout button require a valid session to be not disabled export default { + id: "security", icon: "Shield", label: "Security", + group: "basic", settings: [ { "id": "change-password", @@ -39,7 +42,9 @@ export default { "icon": "LogOut", "title": "Logout", "description": "Logout from your account", - "emitEvent": "session.logout", + onUpdate: async () => { + await AuthModel.logout() + } } ] } \ No newline at end of file diff --git a/packages/app/constants/settings/subscriptions/index.jsx b/packages/app/constants/settings/subscriptions/index.jsx new file mode 100644 index 00000000..bd3054c5 --- /dev/null +++ b/packages/app/constants/settings/subscriptions/index.jsx @@ -0,0 +1,8 @@ +export default { + id: "subscriptions", + label: "Subscriptions", + icon: "MdLoyalty", + group: "other", + settings: [ + ] +} \ No newline at end of file diff --git a/packages/app/constants/settings/sync/index.jsx b/packages/app/constants/settings/sync/index.jsx index a71cb0bf..9597bdab 100755 --- a/packages/app/constants/settings/sync/index.jsx +++ b/packages/app/constants/settings/sync/index.jsx @@ -5,8 +5,10 @@ import SyncModel from "models/sync" // TODO: Make logout button require a valid session to be not disabled export default { + id: "sync", icon: "MdSync", label: "Sync", + group: "advanced", ctxData: async () => { const spotifyAccount = await SyncModel.spotifyCore.getData().catch((err) => { return null