diff --git a/packages/app/src/components/Layout/bottomBar/index.jsx b/packages/app/src/components/Layout/bottomBar/index.jsx
index 1749f42b..86c96c6a 100755
--- a/packages/app/src/components/Layout/bottomBar/index.jsx
+++ b/packages/app/src/components/Layout/bottomBar/index.jsx
@@ -83,6 +83,75 @@ const AccountButton = (props) => {
}
+
+const QuickNavMenuItems = [
+ {
+ id: "music",
+ icon: "MdAlbum",
+ label: "Music",
+ location: "/music"
+ },
+ {
+ id: "tv",
+ icon: "Tv",
+ label: "Tv",
+ location: "/tv"
+ },
+ {
+ id: "groups",
+ icon: "MdGroups",
+ label: "Groups",
+ location: "/groups",
+ disabled: true,
+ },
+ {
+ id: "marketplace",
+ icon: "Box",
+ label: "Marketplace",
+ location: "/marketplace",
+ disabled: true
+ },
+]
+
+const QuickNavMenu = ({
+ visible,
+}) => {
+ return
+ {
+ QuickNavMenuItems.map((item, index) => {
+ return
+ {
+ createIconRender(item.icon)
+ }
+
+
+ {
+ item.label
+ }
+
+
+ })
+ }
+
+}
+
export default (props) => {
return
{
+ this._navTouchStart = setTimeout(() => {
+ this.setState({ quickNavVisible: true })
+
+ app.cores.haptics.vibrate(80)
+
+ // remove the timeout
+ this._navTouchStart = null
+ }, 400)
+ }
+
+ handleNavTouchEnd = (event) => {
+ if (this._lastHovered) {
+ this._lastHovered.classList.remove("hover")
+ }
+
+ if (this._navTouchStart) {
+ clearTimeout(this._navTouchStart)
+
+ this._navTouchStart = null
+
+ return false
+ }
+
+ this.setState({ quickNavVisible: false })
+
+ // get cords of the touch
+ const x = event.changedTouches[0].clientX
+ const y = event.changedTouches[0].clientY
+
+ // get the element at the touch
+ const element = document.elementFromPoint(x, y)
+
+ // get the closest element with the attribute
+ const closest = element.closest(".quick-nav_item")
+
+ if (!closest) {
+ return false
+ }
+
+ const item = QuickNavMenuItems.find((item) => {
+ return item.id === closest.getAttribute("quicknav-item")
+ })
+
+ if (!item) {
+ return false
+ }
+
+ if (item.location) {
+ app.setLocation(item.location)
+
+ app.cores.haptics.vibrate([40, 80])
+ }
+ }
+
+ handleNavTouchMove = (event) => {
+ // check if the touch is hovering a quicknav item
+ const x = event.changedTouches[0].clientX
+ const y = event.changedTouches[0].clientY
+
+ // get the element at the touch
+ const element = document.elementFromPoint(x, y)
+
+ // get the closest element with the attribute
+ const closest = element.closest("[quicknav-item]")
+
+ if (!closest) {
+ if (this._lastHovered) {
+ this._lastHovered.classList.remove("hover")
+ }
+
+ this._lastHovered = null
+
+ return false
+ }
+
+ if (this._lastHovered !== closest) {
+ if (this._lastHovered) {
+ this._lastHovered.classList.remove("hover")
+ }
+
+ this._lastHovered = closest
+
+ closest.classList.add("hover")
+
+ app.cores.haptics.vibrate(40)
+ }
+ }
+
render() {
if (this.state.render) {
return
@@ -173,63 +332,75 @@ export class BottomBar extends React.Component {
return null
}
- return
- {({ y }) =>
-
-
app.setLocation("/")}
- >
-
- {createIconRender("PlusCircle")}
-
-
+ return <>
+
- {
- this.context.currentManifest &&
+ {({ y }) =>
+
+
app.setLocation("/")}
>
-
+
+ {createIconRender("PlusCircle")}
+
- }
-
app.setLocation("/")}
- >
-
- {createIconRender("Home")}
+ {
+ this.context.currentManifest &&
+ }
+
+
app.setLocation("/")}
+ onTouchMove={this.handleNavTouchMove}
+ onTouchStart={this.handleNavTouchStart}
+ onTouchEnd={this.handleNavTouchEnd}
+ onTouchCancel={() => {
+ this.setState({ quickNavVisible: false })
+ }}
+ >
+
+ {createIconRender("Home")}
+
+
+
+
+ {createIconRender("Search")}
+
+
+
+
-
-
-
- {createIconRender("Search")}
-
-
-
-
-
-
}
-
+
}
+
+ >
}
}
\ No newline at end of file
diff --git a/packages/app/src/components/Layout/bottomBar/index.less b/packages/app/src/components/Layout/bottomBar/index.less
index 13ac626d..f5635ee3 100755
--- a/packages/app/src/components/Layout/bottomBar/index.less
+++ b/packages/app/src/components/Layout/bottomBar/index.less
@@ -1,6 +1,114 @@
@import "theme/vars.less";
@import "theme/animations.less";
+.quick-nav {
+ position: absolute;
+
+ box-sizing: border-box;
+
+ bottom: @app_bottomBar_height;
+ left: 0;
+ right: 0;
+
+ z-index: 500;
+
+ display: flex;
+
+ flex-direction: row;
+
+ align-items: center;
+ justify-content: space-evenly;
+
+ width: 100%;
+ height: 0;
+ opacity: 0;
+
+ background-color: var(--background-color-accent);
+
+ box-shadow: @card-shadow-top;
+
+ transform: translateY(10px);
+ padding-bottom: 20px;
+
+ gap: 20px;
+
+ pointer-events: none;
+
+ transition: all 150ms ease-in-out;
+
+ border-radius: 12px 12px 0 0;
+
+ &.active {
+ pointer-events: all;
+
+ height: 100px;
+
+ opacity: 1;
+ }
+
+ .quick-nav_item {
+ position: relative;
+
+ display: flex;
+ flex-direction: column;
+
+ align-items: center;
+ justify-content: center;
+
+ z-index: 500;
+
+ width: 20vw;
+ height: 100%;
+ //padding: 0 30px;
+
+ transition: all 150ms ease-in-out;
+
+ color: var(--text-color);
+
+ h1 {
+ margin: 0;
+
+ font-size: 0px;
+
+ transition: all 150ms ease-in-out;
+ }
+
+ svg {
+ margin: 0 !important;
+ transition: all 150ms ease-in-out;
+ font-size: 2rem;
+ }
+
+ &.disabled {
+ pointer-events: none;
+
+ h1 {
+ font-size: 0px;
+ }
+
+ svg {
+ font-size: 2rem;
+ color: var(--disabled-color);
+ }
+
+ color: var(--disabled-color);
+ }
+
+ &.hover {
+ h1 {
+ font-size: 1rem;
+ }
+
+ svg {
+ font-size: 2.2rem;
+ color: var(--colorPrimary);
+ }
+
+ color: var(--colorPrimary);
+ }
+ }
+}
+
.player_btn {
color: var(--color);
@@ -23,6 +131,7 @@
}
.bottomBar {
+ position: absolute;
display: flex;
flex-direction: row;
@@ -31,6 +140,8 @@
position: relative;
+ z-index: 550;
+
left: 0;
bottom: 0;
@@ -46,7 +157,7 @@
background-color: var(--background-color-accent);
border-radius: 12px 12px 0 0;
- box-shadow: @card-shadow;
+ box-shadow: @card-shadow-top;
.items {
display: inline-flex;