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
+
+ {
+ 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
+ }
+ loading={uploading}
+ type={
+ props.type ?? "round"
+ }
+ >
+ {
+ props.children ?? "Upload"
+ }
+
+
+}
\ 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)}
+ />
+
+ }
+ onClick={() => 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