mirror of
https://github.com/ragestudio/comty.git
synced 2025-06-09 10:34:17 +00:00
improve code & performance & desing of sidebar
This commit is contained in:
parent
0ce6d39a59
commit
105395fe76
24
packages/app/config/sidebar/BottomItems.json
Normal file
24
packages/app/config/sidebar/BottomItems.json
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
[
|
||||||
|
{
|
||||||
|
"id": "search",
|
||||||
|
"label": "Search",
|
||||||
|
"icon": "Search"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "messages",
|
||||||
|
"label": "Messages",
|
||||||
|
"icon": "MessageCircle",
|
||||||
|
"path": "/messages"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "notifications",
|
||||||
|
"label": "Notifications",
|
||||||
|
"icon": "Bell"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"id": "settings",
|
||||||
|
"label": "Settings",
|
||||||
|
"icon": "Settings",
|
||||||
|
"path": "/settings"
|
||||||
|
}
|
||||||
|
]
|
8
packages/app/config/sidebar.json → packages/app/config/sidebar/TopItems.json
Executable file → Normal file
8
packages/app/config/sidebar.json → packages/app/config/sidebar/TopItems.json
Executable file → Normal file
@ -2,25 +2,25 @@
|
|||||||
{
|
{
|
||||||
"id": "home",
|
"id": "home",
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"title": "Home",
|
"label": "Home",
|
||||||
"icon": "Home"
|
"icon": "Home"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "timeline",
|
"id": "timeline",
|
||||||
"path": "/",
|
"path": "/",
|
||||||
"title": "Timeline",
|
"label": "Timeline",
|
||||||
"icon": "MdTag"
|
"icon": "MdTag"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "tv",
|
"id": "tv",
|
||||||
"path": "/tv",
|
"path": "/tv",
|
||||||
"title": "Tv",
|
"label": "Tv",
|
||||||
"icon": "Tv"
|
"icon": "Tv"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"id": "music",
|
"id": "music",
|
||||||
"path": "/music",
|
"path": "/music",
|
||||||
"title": "Music",
|
"label": "Music",
|
||||||
"icon": "MdMusicNote"
|
"icon": "MdMusicNote"
|
||||||
}
|
}
|
||||||
]
|
]
|
@ -6,7 +6,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
z-index: 500;
|
z-index: 1200;
|
||||||
|
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-direction: row;
|
flex-direction: row;
|
||||||
@ -17,10 +17,6 @@
|
|||||||
|
|
||||||
height: 100dvh;
|
height: 100dvh;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
|
|
||||||
// &.hidden {
|
|
||||||
// display: none;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.drawers-mask {
|
.drawers-mask {
|
||||||
@ -29,7 +25,7 @@
|
|||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
|
||||||
z-index: 500;
|
z-index: 1100;
|
||||||
|
|
||||||
width: 100vw;
|
width: 100vw;
|
||||||
height: 100vh;
|
height: 100vh;
|
||||||
@ -41,7 +37,7 @@
|
|||||||
.drawer {
|
.drawer {
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
z-index: 550;
|
z-index: 1300;
|
||||||
|
|
||||||
top: 0;
|
top: 0;
|
||||||
left: 0;
|
left: 0;
|
||||||
|
@ -2,109 +2,22 @@ import React from "react"
|
|||||||
import config from "@config"
|
import config from "@config"
|
||||||
import classnames from "classnames"
|
import classnames from "classnames"
|
||||||
import { Translation } from "react-i18next"
|
import { Translation } from "react-i18next"
|
||||||
import { Motion, spring } from "react-motion"
|
import { motion, AnimatePresence } from "framer-motion"
|
||||||
import { Menu, Avatar, Dropdown, Tag, Empty } from "antd"
|
import { Menu, Avatar, Dropdown, Tag } from "antd"
|
||||||
|
|
||||||
import Drawer from "@layouts/components/drawer"
|
import Drawer from "@layouts/components/drawer"
|
||||||
|
|
||||||
import { Icons, createIconRender } from "@components/Icons"
|
import { Icons } from "@components/Icons"
|
||||||
|
|
||||||
import sidebarItems from "@config/sidebar"
|
import GenerateSidebarMenuItems from "@utils/generateSidebarMenuItems"
|
||||||
|
|
||||||
|
import TopMenuItems from "@config/sidebar/TopItems"
|
||||||
|
import BottomMenuItems from "@config/sidebar/BottomItems"
|
||||||
|
|
||||||
|
import ItemsClickHandlers from "./itemClickHandlers"
|
||||||
|
|
||||||
import "./index.less"
|
import "./index.less"
|
||||||
|
|
||||||
const onClickHandlers = {
|
|
||||||
apps: () => {
|
|
||||||
app.controls.openAppsMenu()
|
|
||||||
},
|
|
||||||
addons: () => {
|
|
||||||
window.app.location.push("/addons")
|
|
||||||
},
|
|
||||||
studio: () => {
|
|
||||||
window.app.location.push("/studio")
|
|
||||||
},
|
|
||||||
settings: () => {
|
|
||||||
window.app.navigation.goToSettings()
|
|
||||||
},
|
|
||||||
notifications: () => {
|
|
||||||
window.app.controls.openNotifications()
|
|
||||||
},
|
|
||||||
search: () => {
|
|
||||||
window.app.controls.openSearcher()
|
|
||||||
},
|
|
||||||
messages: () => {
|
|
||||||
window.app.controls.openMessages()
|
|
||||||
},
|
|
||||||
create: () => {
|
|
||||||
window.app.controls.openCreator()
|
|
||||||
},
|
|
||||||
profile: () => {
|
|
||||||
window.app.navigation.goToAccount()
|
|
||||||
},
|
|
||||||
login: () => {
|
|
||||||
window.app.navigation.goAuth()
|
|
||||||
},
|
|
||||||
logout: () => {
|
|
||||||
app.eventBus.emit("app.logout_request")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const generateTopItems = (extra = []) => {
|
|
||||||
const items = [...sidebarItems, ...extra]
|
|
||||||
|
|
||||||
return items.map((item) => {
|
|
||||||
return {
|
|
||||||
id: item.id,
|
|
||||||
key: item.id,
|
|
||||||
path: item.path,
|
|
||||||
icon: createIconRender(item.icon),
|
|
||||||
label: <Translation>
|
|
||||||
{t => t(item.title ?? item.id)}
|
|
||||||
</Translation>,
|
|
||||||
disabled: item.disabled,
|
|
||||||
children: item.children,
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
const BottomMenuDefaultItems = [
|
|
||||||
{
|
|
||||||
key: "search",
|
|
||||||
label: <Translation>
|
|
||||||
{(t) => t("Search")}
|
|
||||||
</Translation>,
|
|
||||||
icon: <Icons.Search />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "messages",
|
|
||||||
label: <Translation>
|
|
||||||
{(t) => t("Messages")}
|
|
||||||
</Translation>,
|
|
||||||
icon: <Icons.MessageCircle />,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
key: "notifications",
|
|
||||||
label: <Translation>
|
|
||||||
{(t) => t("Notifications")}
|
|
||||||
</Translation>,
|
|
||||||
icon: <Icons.Bell />,
|
|
||||||
},
|
|
||||||
// {
|
|
||||||
// key: "apps",
|
|
||||||
// label: <Translation>
|
|
||||||
// {(t) => t("Apps")}
|
|
||||||
// </Translation>,
|
|
||||||
// icon: <Icons.MdApps />,
|
|
||||||
// },
|
|
||||||
{
|
|
||||||
key: "settings",
|
|
||||||
label: <Translation>
|
|
||||||
{(t) => t("Settings")}
|
|
||||||
</Translation>,
|
|
||||||
icon: <Icons.Settings />,
|
|
||||||
}
|
|
||||||
]
|
|
||||||
|
|
||||||
const ActionMenuItems = [
|
const ActionMenuItems = [
|
||||||
{
|
{
|
||||||
key: "profile",
|
key: "profile",
|
||||||
@ -162,10 +75,10 @@ export default class Sidebar extends React.Component {
|
|||||||
visible: false,
|
visible: false,
|
||||||
expanded: false,
|
expanded: false,
|
||||||
|
|
||||||
topItems: generateTopItems(),
|
topItems: GenerateSidebarMenuItems(TopMenuItems),
|
||||||
bottomItems: [],
|
bottomItems: GenerateSidebarMenuItems(BottomMenuItems),
|
||||||
|
|
||||||
lockAutocollapse: false,
|
selectedMenuItem: null,
|
||||||
navigationRender: null,
|
navigationRender: null,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -175,9 +88,15 @@ export default class Sidebar extends React.Component {
|
|||||||
|
|
||||||
interface = window.app.layout.sidebar = {
|
interface = window.app.layout.sidebar = {
|
||||||
toggleVisibility: (to) => {
|
toggleVisibility: (to) => {
|
||||||
|
if (to === false) {
|
||||||
|
this.interface.toggleExpanded(false, {
|
||||||
|
instant: true,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
this.setState({ visible: to ?? !this.state.visible })
|
this.setState({ visible: to ?? !this.state.visible })
|
||||||
},
|
},
|
||||||
toggleCollapse: (to, force) => {
|
toggleExpanded: async (to, { instant = false, isDropdown = false } = {}) => {
|
||||||
to = to ?? !this.state.expanded
|
to = to ?? !this.state.expanded
|
||||||
|
|
||||||
if (this.collapseDebounce) {
|
if (this.collapseDebounce) {
|
||||||
@ -185,7 +104,7 @@ export default class Sidebar extends React.Component {
|
|||||||
this.collapseDebounce = null
|
this.collapseDebounce = null
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!to & this.state.dropdownOpen && !force) {
|
if (to === false & this.state.dropdownOpen === true && isDropdown === true) {
|
||||||
// FIXME: This is a walkaround for a bug in antd, causing when dropdown set to close, item click event is not fired
|
// FIXME: This is a walkaround for a bug in antd, causing when dropdown set to close, item click event is not fired
|
||||||
// The desing defines when sidebar should be collapsed, dropdown should be closed, but in this case, gonna to keep it open untils dropdown is closed
|
// The desing defines when sidebar should be collapsed, dropdown should be closed, but in this case, gonna to keep it open untils dropdown is closed
|
||||||
//this.setState({ dropdownOpen: false })
|
//this.setState({ dropdownOpen: false })
|
||||||
@ -193,18 +112,14 @@ export default class Sidebar extends React.Component {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!to) {
|
if (to === false) {
|
||||||
if (this.state.lockAutocollapse) {
|
if (instant === false) {
|
||||||
return false
|
await new Promise((resolve) => setTimeout(resolve, window.app.cores.settings.get("sidebar.collapse_delay_time") ?? 500))
|
||||||
}
|
}
|
||||||
|
|
||||||
this.collapseDebounce = setTimeout(() => {
|
|
||||||
this.setState({ expanded: to })
|
|
||||||
}, window.app.cores.settings.get("sidebar.collapse_delay_time") ?? 500)
|
|
||||||
} else {
|
|
||||||
this.setState({ expanded: to })
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
this.setState({ expanded: to })
|
||||||
|
|
||||||
app.eventBus.emit("sidebar.expanded", to)
|
app.eventBus.emit("sidebar.expanded", to)
|
||||||
},
|
},
|
||||||
isVisible: () => this.state.visible,
|
isVisible: () => this.state.visible,
|
||||||
@ -217,60 +132,23 @@ export default class Sidebar extends React.Component {
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
},
|
},
|
||||||
updateBottomItemProps: (id, newProps) => {
|
updateMenuItemProps: this.updateBottomItemProps,
|
||||||
let updatedValue = this.state.bottomItems
|
addMenuItem: this.addMenuItem,
|
||||||
|
removeMenuItem: this.removeMenuItem,
|
||||||
updatedValue = updatedValue.map((item) => {
|
|
||||||
if (item.id === id) {
|
|
||||||
item.props = {
|
|
||||||
...item.props,
|
|
||||||
...newProps,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
bottomItems: updatedValue
|
|
||||||
})
|
|
||||||
},
|
|
||||||
attachBottomItem: (id, children, options) => {
|
|
||||||
if (!id) {
|
|
||||||
throw new Error("ID is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!children) {
|
|
||||||
throw new Error("Children is required")
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this.state.bottomItems.find((item) => item.id === id)) {
|
|
||||||
throw new Error("Item already exists")
|
|
||||||
}
|
|
||||||
|
|
||||||
let updatedValue = this.state.bottomItems
|
|
||||||
|
|
||||||
updatedValue.push({
|
|
||||||
id,
|
|
||||||
children,
|
|
||||||
...options
|
|
||||||
})
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
bottomItems: updatedValue
|
|
||||||
})
|
|
||||||
},
|
|
||||||
removeBottomItem: (id) => {
|
|
||||||
let updatedValue = this.state.bottomItems
|
|
||||||
|
|
||||||
updatedValue = updatedValue.filter((item) => item.id !== id)
|
|
||||||
|
|
||||||
this.setState({
|
|
||||||
bottomItems: updatedValue
|
|
||||||
})
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
events = {
|
events = {
|
||||||
|
"router.navigate": (path) => {
|
||||||
|
// recalculate sidebar selected item
|
||||||
|
const item = [...this.state.topItems, ...this.state.bottomItems].find((item) => item.path === path)
|
||||||
|
|
||||||
|
|
||||||
|
console.log(`Recalculate sidebar selected item: path [${path}]`, item)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
selectedMenuItem: item
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
componentDidMount = async () => {
|
componentDidMount = async () => {
|
||||||
@ -282,7 +160,7 @@ export default class Sidebar extends React.Component {
|
|||||||
this.interface.toggleVisibility(true)
|
this.interface.toggleVisibility(true)
|
||||||
|
|
||||||
if (app.cores.settings.is("sidebar.collapsable", false)) {
|
if (app.cores.settings.is("sidebar.collapsable", false)) {
|
||||||
this.interface.toggleCollapse(true)
|
this.interface.toggleExpanded(true)
|
||||||
}
|
}
|
||||||
}, 10)
|
}, 10)
|
||||||
}
|
}
|
||||||
@ -292,84 +170,81 @@ export default class Sidebar extends React.Component {
|
|||||||
app.eventBus.off(event, handler)
|
app.eventBus.off(event, handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
//delete app.layout.sidebar
|
delete app.layout.sidebar
|
||||||
}
|
}
|
||||||
|
|
||||||
handleClick = (e) => {
|
addMenuItem = (group, item) => {
|
||||||
if (e.item.props.ignore_click === "true") {
|
group = this.getMenuItemGroupStateKey(group)
|
||||||
return
|
|
||||||
|
if (!group) {
|
||||||
|
throw new Error("Invalid group")
|
||||||
}
|
}
|
||||||
|
|
||||||
if (e.item.props.override_event) {
|
const newItems = [...this.state[group], item]
|
||||||
return app.eventBus.emit(e.item.props.override_event, e.item.props.override_event_props)
|
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof e.key === "undefined") {
|
this.setState({
|
||||||
app.eventBus.emit("invalidSidebarKey", e)
|
[group]: newItems
|
||||||
return false
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if (typeof onClickHandlers[e.key] === "function") {
|
return newItems
|
||||||
return onClickHandlers[e.key](e)
|
|
||||||
}
|
|
||||||
|
|
||||||
app.cores.sfx.play("sidebar.switch_tab")
|
|
||||||
|
|
||||||
const item = this.state.topItems.find((item) => item.id === e.key)
|
|
||||||
|
|
||||||
return app.location.push(`/${item.path ?? e.key}`, 150)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
onMouseEnter = (event) => {
|
removeMenuItem = (group, id) => {
|
||||||
if (!this.state.visible) return
|
group = this.getMenuItemGroupStateKey(group)
|
||||||
|
|
||||||
if (window.app.cores.settings.is("sidebar.collapsable", false)) {
|
if (!group) {
|
||||||
if (!this.state.expanded) {
|
throw new Error("Invalid group")
|
||||||
this.interface.toggleCollapse(true)
|
}
|
||||||
|
|
||||||
|
const newItems = this.state[group].filter((item) => item.id !== id)
|
||||||
|
|
||||||
|
this.setState({
|
||||||
|
[group]: newItems
|
||||||
|
})
|
||||||
|
|
||||||
|
return newItems
|
||||||
|
}
|
||||||
|
|
||||||
|
updateBottomItemProps = (group, id, newProps) => {
|
||||||
|
group = this.getMenuItemGroupStateKey(group)
|
||||||
|
|
||||||
|
if (!group) {
|
||||||
|
throw new Error("Invalid group")
|
||||||
|
}
|
||||||
|
|
||||||
|
let updatedValue = this.state[group]
|
||||||
|
|
||||||
|
updatedValue = updatedValue.map((item) => {
|
||||||
|
if (item.id === id) {
|
||||||
|
item.props = {
|
||||||
|
...item.props,
|
||||||
|
...newProps,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return
|
this.setState({
|
||||||
}
|
[group]: updatedValue
|
||||||
|
})
|
||||||
|
|
||||||
// do nothing if is mask visible
|
return updatedValue
|
||||||
if (app.layout.drawer.isMaskVisible()) {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
this.interface.toggleCollapse(true)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
handleMouseLeave = (event) => {
|
getMenuItemGroupStateKey = (group) => {
|
||||||
if (!this.state.visible) return
|
switch (group) {
|
||||||
|
case "top": {
|
||||||
if (window.app.cores.settings.is("sidebar.collapsable", false)) return
|
return "topItems"
|
||||||
|
}
|
||||||
this.interface.toggleCollapse(false)
|
case "bottom": {
|
||||||
}
|
return "bottomItems"
|
||||||
|
}
|
||||||
onDropdownOpenChange = (to) => {
|
default: {
|
||||||
// this is another walkaround for a bug in antd, causing when dropdown set to close, item click event is not fired
|
return null
|
||||||
if (!to && this.state.expanded) {
|
}
|
||||||
this.interface.toggleCollapse(false, true)
|
|
||||||
}
|
|
||||||
|
|
||||||
this.setState({ dropdownOpen: to })
|
|
||||||
}
|
|
||||||
|
|
||||||
onClickDropdownItem = (item) => {
|
|
||||||
const handler = onClickHandlers[item.key]
|
|
||||||
|
|
||||||
if (typeof handler === "function") {
|
|
||||||
handler()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
getBottomItems = () => {
|
injectUserItems(items = []) {
|
||||||
const items = [
|
|
||||||
...BottomMenuDefaultItems,
|
|
||||||
...this.state.bottomItems,
|
|
||||||
]
|
|
||||||
|
|
||||||
if (app.userData) {
|
if (app.userData) {
|
||||||
items.push({
|
items.push({
|
||||||
key: "account",
|
key: "account",
|
||||||
@ -387,9 +262,8 @@ export default class Sidebar extends React.Component {
|
|||||||
<Avatar shape="square" src={app.userData?.avatar} />
|
<Avatar shape="square" src={app.userData?.avatar} />
|
||||||
</Dropdown>,
|
</Dropdown>,
|
||||||
})
|
})
|
||||||
}
|
|
||||||
|
|
||||||
if (!app.userData) {
|
} else {
|
||||||
items.push({
|
items.push({
|
||||||
key: "login",
|
key: "login",
|
||||||
label: <Translation>
|
label: <Translation>
|
||||||
@ -402,43 +276,123 @@ export default class Sidebar extends React.Component {
|
|||||||
return items
|
return items
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleClick = (e) => {
|
||||||
|
if (e.item.props.ignore_click === "true") {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (e.item.props.override_event) {
|
||||||
|
return app.eventBus.emit(e.item.props.override_event, e.item.props.override_event_props)
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof e.key === "undefined") {
|
||||||
|
app.eventBus.emit("invalidSidebarKey", e)
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof ItemsClickHandlers[e.key] === "function") {
|
||||||
|
return ItemsClickHandlers[e.key](e)
|
||||||
|
}
|
||||||
|
|
||||||
|
app.cores.sfx.play("sidebar.switch_tab")
|
||||||
|
|
||||||
|
let item = [...this.state.topItems, ...this.state.bottomItems].find((item) => item.id === e.key)
|
||||||
|
|
||||||
|
return app.location.push(`/${item.path ?? e.key}`, 150)
|
||||||
|
}
|
||||||
|
|
||||||
|
onMouseEnter = () => {
|
||||||
|
if (!this.state.visible) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.app.cores.settings.is("sidebar.collapsable", false)) {
|
||||||
|
if (!this.state.expanded) {
|
||||||
|
this.interface.toggleExpanded(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// do nothing if is mask visible
|
||||||
|
if (app.layout.drawer.isMaskVisible()) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.interface.toggleExpanded(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
handleMouseLeave = () => {
|
||||||
|
if (!this.state.visible) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if (window.app.cores.settings.is("sidebar.collapsable", false)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
this.interface.toggleExpanded(false)
|
||||||
|
}
|
||||||
|
|
||||||
|
onDropdownOpenChange = (to) => {
|
||||||
|
// this is another walkaround for a bug in antd, causing when dropdown set to close, item click event is not fired
|
||||||
|
if (!to && this.state.expanded) {
|
||||||
|
this.interface.toggleExpanded(false, true)
|
||||||
|
}
|
||||||
|
|
||||||
|
this.setState({ dropdownOpen: to })
|
||||||
|
}
|
||||||
|
|
||||||
|
onClickDropdownItem = (item) => {
|
||||||
|
const handler = onClickHandlers[item.key]
|
||||||
|
|
||||||
|
if (typeof handler === "function") {
|
||||||
|
handler()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
const defaultSelectedKey = window.location.pathname.replace("/", "")
|
const selectedKeyId = this.state.selectedMenuItem?.id ?? "home"
|
||||||
|
|
||||||
return <Motion style={{
|
return <div
|
||||||
x: spring(!this.state.visible ? 100 : 0),
|
className="app_sidebar_wrapper"
|
||||||
}}>
|
onMouseEnter={this.onMouseEnter}
|
||||||
{({ x }) => {
|
onMouseLeave={this.handleMouseLeave}
|
||||||
return <div
|
>
|
||||||
className={classnames(
|
{
|
||||||
"app_sidebar_wrapper",
|
window.__TAURI__ && navigator.platform.includes("Mac") && <div
|
||||||
{
|
className="app_sidebar_tauri"
|
||||||
visible: this.state.visible,
|
data-tauri-drag-region
|
||||||
}
|
/>
|
||||||
)}
|
}
|
||||||
style={{
|
|
||||||
transform: `translateX(-${x}%)`,
|
|
||||||
}}
|
|
||||||
onMouseEnter={this.onMouseEnter}
|
|
||||||
onMouseLeave={this.handleMouseLeave}
|
|
||||||
>
|
|
||||||
{
|
|
||||||
window.__TAURI__ && navigator.platform.includes("Mac") && <div
|
|
||||||
className="app_sidebar_tauri"
|
|
||||||
data-tauri-drag-region
|
|
||||||
/>
|
|
||||||
}
|
|
||||||
|
|
||||||
<div
|
<AnimatePresence
|
||||||
|
mode="popLayout"
|
||||||
|
>
|
||||||
|
{
|
||||||
|
this.state.visible && <motion.div
|
||||||
className={classnames(
|
className={classnames(
|
||||||
"app_sidebar",
|
"app_sidebar",
|
||||||
{
|
{
|
||||||
["expanded"]: this.state.visible && this.state.expanded,
|
["expanded"]: this.state.expanded,
|
||||||
["hidden"]: !this.state.visible,
|
|
||||||
}
|
}
|
||||||
)
|
)}
|
||||||
}
|
|
||||||
ref={this.sidebarRef}
|
ref={this.sidebarRef}
|
||||||
|
initial={{
|
||||||
|
x: -500
|
||||||
|
}}
|
||||||
|
animate={{
|
||||||
|
x: 0,
|
||||||
|
}}
|
||||||
|
exit={{
|
||||||
|
x: -500
|
||||||
|
}}
|
||||||
|
transition={{
|
||||||
|
type: "spring",
|
||||||
|
stiffness: 100,
|
||||||
|
damping: 20
|
||||||
|
}}
|
||||||
|
layout
|
||||||
>
|
>
|
||||||
<div className="app_sidebar_header">
|
<div className="app_sidebar_header">
|
||||||
<div className="app_sidebar_header_logo">
|
<div className="app_sidebar_header_logo">
|
||||||
@ -455,9 +409,8 @@ export default class Sidebar extends React.Component {
|
|||||||
<Menu
|
<Menu
|
||||||
mode="inline"
|
mode="inline"
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
defaultSelectedKeys={[defaultSelectedKey]}
|
selectedKeys={[selectedKeyId]}
|
||||||
items={this.state.topItems}
|
items={this.state.topItems}
|
||||||
selectable
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
@ -469,17 +422,17 @@ export default class Sidebar extends React.Component {
|
|||||||
)}
|
)}
|
||||||
>
|
>
|
||||||
<Menu
|
<Menu
|
||||||
selectable={false}
|
|
||||||
mode="inline"
|
mode="inline"
|
||||||
onClick={this.handleClick}
|
onClick={this.handleClick}
|
||||||
items={this.getBottomItems()}
|
items={[...this.state.bottomItems, ...this.injectUserItems()]}
|
||||||
|
selectedKeys={[selectedKeyId]}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</motion.div>
|
||||||
|
}
|
||||||
|
</AnimatePresence>
|
||||||
|
|
||||||
<Drawer />
|
<Drawer />
|
||||||
</div>
|
</div >
|
||||||
}}
|
|
||||||
</Motion>
|
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -25,9 +25,7 @@
|
|||||||
height: 100vh;
|
height: 100vh;
|
||||||
height: 100dvh;
|
height: 100dvh;
|
||||||
|
|
||||||
&.visible {
|
padding: 10px;
|
||||||
padding: 10px;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.app_sidebar {
|
.app_sidebar {
|
||||||
@ -47,7 +45,7 @@
|
|||||||
|
|
||||||
padding: 10px 0;
|
padding: 10px 0;
|
||||||
|
|
||||||
transition: all 150ms ease-in-out;
|
transition: width 150ms ease-in-out;
|
||||||
|
|
||||||
background-color: var(--sidebar-background-color);
|
background-color: var(--sidebar-background-color);
|
||||||
|
|
||||||
@ -113,8 +111,16 @@
|
|||||||
user-select: none;
|
user-select: none;
|
||||||
--webkit-user-select: none;
|
--webkit-user-select: none;
|
||||||
|
|
||||||
width: 80%;
|
width: fit-content;
|
||||||
max-height: 40px;
|
max-height: 46px;
|
||||||
|
|
||||||
|
transition: all 150ms ease-in-out;
|
||||||
|
|
||||||
|
&:hover {
|
||||||
|
cursor: pointer;
|
||||||
|
scale: 1.1;
|
||||||
|
filter: drop-shadow(0 0 5px var(--shadow-color));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,32 @@
|
|||||||
|
export default {
|
||||||
|
apps: () => {
|
||||||
|
app.controls.openAppsMenu()
|
||||||
|
},
|
||||||
|
addons: () => {
|
||||||
|
window.app.location.push("/addons")
|
||||||
|
},
|
||||||
|
studio: () => {
|
||||||
|
window.app.location.push("/studio")
|
||||||
|
},
|
||||||
|
settings: () => {
|
||||||
|
window.app.navigation.goToSettings()
|
||||||
|
},
|
||||||
|
notifications: () => {
|
||||||
|
window.app.controls.openNotifications()
|
||||||
|
},
|
||||||
|
search: () => {
|
||||||
|
window.app.controls.openSearcher()
|
||||||
|
},
|
||||||
|
create: () => {
|
||||||
|
window.app.controls.openCreator()
|
||||||
|
},
|
||||||
|
profile: () => {
|
||||||
|
window.app.navigation.goToAccount()
|
||||||
|
},
|
||||||
|
login: () => {
|
||||||
|
window.app.navigation.goAuth()
|
||||||
|
},
|
||||||
|
logout: () => {
|
||||||
|
app.eventBus.emit("app.logout_request")
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user