From c52834c0c8418a10f59d4d45b0f4e9107d7bf990 Mon Sep 17 00:00:00 2001 From: SrGooglo Date: Mon, 26 Jun 2023 23:08:44 +0000 Subject: [PATCH] improve layout for mobile & use of top-bar --- packages/app/constants/defaultTheme.json | 1 + packages/app/constants/routes.js | 6 +- packages/app/src/components/Layout/index.js | 1 + .../src/components/Layout/topBar/index.jsx | 157 ++++++++++++++ .../src/components/Layout/topBar/index.less | 52 +++++ .../PagePanels/components/NavMenu/index.jsx | 38 ++-- .../PagePanels/components/NavMenu/index.less | 74 ++++--- .../app/src/components/PagePanels/index.jsx | 30 ++- .../app/src/components/PagePanels/index.less | 54 +++++ .../app/src/components/PostsList/index.jsx | 104 ++++++---- .../app/src/components/PostsList/index.less | 36 +++- packages/app/src/layout.jsx | 77 ++++--- packages/app/src/layouts/blank/index.jsx | 2 +- packages/app/src/layouts/default/index.jsx | 55 +++-- packages/app/src/layouts/index.js | 6 +- .../src/layouts/{none => minimal}/index.jsx | 2 +- packages/app/src/layouts/mobile/index.jsx | 21 -- packages/app/src/pages/account/index.less | 55 +++++ packages/app/src/pages/live/index.less | 25 +++ packages/app/src/pages/play/index.less | 37 +++- .../app/src/pages/settings/index.mobile.jsx | 37 ++-- .../app/src/pages/settings/index.mobile.less | 71 +++---- packages/app/src/theme/index.less | 37 +--- packages/app/src/theme/mobile.less | 191 ++++-------------- packages/app/src/theme/vars.less | 6 +- 25 files changed, 761 insertions(+), 414 deletions(-) create mode 100644 packages/app/src/components/Layout/topBar/index.jsx create mode 100644 packages/app/src/components/Layout/topBar/index.less rename packages/app/src/layouts/{none => minimal}/index.jsx (76%) delete mode 100755 packages/app/src/layouts/mobile/index.jsx diff --git a/packages/app/constants/defaultTheme.json b/packages/app/constants/defaultTheme.json index c993a4b6..f248d990 100755 --- a/packages/app/constants/defaultTheme.json +++ b/packages/app/constants/defaultTheme.json @@ -17,6 +17,7 @@ "backgroundPosition": "center", "backgroundRepeat": "no-repeat", "backgroundAttachment": "fixed", + "top-bar-height": "52px", "compact-mode": false }, "defaultVariant": "dark", diff --git a/packages/app/constants/routes.js b/packages/app/constants/routes.js index b4390386..5b840790 100755 --- a/packages/app/constants/routes.js +++ b/packages/app/constants/routes.js @@ -1,7 +1,7 @@ export default [ { path: "/login", - useLayout: "none", + useLayout: "minimal", public: true }, { @@ -46,12 +46,12 @@ export default [ }, { path: "/landing/*", - useLayout: "blank", + useLayout: "minimal", public: true }, { path: "/nfc/*", - useLayout: "blank", + useLayout: "minimal", public: true } ] \ No newline at end of file diff --git a/packages/app/src/components/Layout/index.js b/packages/app/src/components/Layout/index.js index 6d0d1a46..8b890cee 100755 --- a/packages/app/src/components/Layout/index.js +++ b/packages/app/src/components/Layout/index.js @@ -1,3 +1,4 @@ +export { default as TopBar } from "./topBar" export { default as BottomBar } from "./bottomBar" export { default as Drawer } from "./drawer" export { default as Sidebar } from "./sidebar" diff --git a/packages/app/src/components/Layout/topBar/index.jsx b/packages/app/src/components/Layout/topBar/index.jsx new file mode 100644 index 00000000..ff1d9a5a --- /dev/null +++ b/packages/app/src/components/Layout/topBar/index.jsx @@ -0,0 +1,157 @@ +import React from "react" +import classnames from "classnames" +import { Motion, spring } from "react-motion" + +import "./index.less" + +const useLayoutInterface = (namespace, ctx) => { + React.useEffect(() => { + if (app.layout["namespace"] === "object") { + throw new Error(`Layout namespace [${namespace}] already exists`) + } + + app.layout[namespace] = ctx + }, []) + + return app.layout[namespace] +} + +const useDefaultVisibility = (defaultValue) => { + const [visible, setVisible] = React.useState(defaultValue ?? false) + + React.useEffect(() => { + setTimeout(() => { + setVisible(true) + }, 10) + }, []) + + return [visible, setVisible] +} + +export const UseTopBar = (props) => { + app.layout.top_bar.render( + + {props.children} + , + props.options) + + React.useEffect(() => { + return () => { + app.layout.top_bar.renderDefault() + } + }, []) + + return null +} + +export default (props) => { + const [visible, setVisible] = useDefaultVisibility() + const [shouldUseTopBarSpacer, setShouldUseTopBarSpacer] = React.useState(true) + const [render, setRender] = React.useState(null) + + useLayoutInterface("top_bar", { + toggleVisibility: (to) => { + setVisible((prev) => { + if (typeof to === undefined) { + to = !prev + } + + return to + }) + }, + render: (component, options) => { + handleUpdateRender(component, options) + }, + renderDefault: () => { + setRender(null) + }, + shouldUseTopBarSpacer: (to) => { + app.layout.toogleTopBarSpacer(to) + setShouldUseTopBarSpacer(to) + } + }) + + const handleUpdateRender = (...args) => { + if (document.startViewTransition) { + return document.startViewTransition(() => { + updateRender(...args) + }) + } + + return updateRender(...args) + } + + const updateRender = (component, options = {}) => { + setRender({ + component, + options + }) + } + + React.useEffect(() => { + if (!shouldUseTopBarSpacer) { + app.layout.tooglePagePanelSpacer(true) + } else { + app.layout.tooglePagePanelSpacer(false) + } + }, [shouldUseTopBarSpacer]) + + React.useEffect(() => { + if (shouldUseTopBarSpacer) { + if (visible) { + app.layout.toogleTopBarSpacer(true) + } else { + app.layout.toogleTopBarSpacer(false) + } + } else { + if (visible) { + app.layout.tooglePagePanelSpacer(true) + } else { + app.layout.tooglePagePanelSpacer(false) + } + + app.layout.toogleTopBarSpacer(false) + } + }, [visible]) + + React.useEffect(() => { + if (render) { + setVisible(true) + } else { + setVisible(false) + } + }, [render]) + + const heightValue = visible ? Number(app.cores.style.defaultVar("top-bar-height").replace("px", "")) : 0 + + console.log(render) + + return + {({ y, height }) => { + return <> +
+
+ { + render?.component && React.cloneElement(render?.component, render?.options?.props ?? {}) + } +
+
+ + }} +
+} \ No newline at end of file diff --git a/packages/app/src/components/Layout/topBar/index.less b/packages/app/src/components/Layout/topBar/index.less new file mode 100644 index 00000000..9ca9ba14 --- /dev/null +++ b/packages/app/src/components/Layout/topBar/index.less @@ -0,0 +1,52 @@ +@import "theme/vars.less"; + +#top-bar_spacer { + position: relative; + + display: block; + + width: 100%; + height: calc(@top_bar_height + @top_bar_padding * 2); + min-height: calc(@top_bar_height + @top_bar_padding * 2); + + //height: 0; + //min-height: 0; +} + +.top-bar_wrapper { + position: absolute; + + top: 0; + left: 0; + + z-index: 310; + + padding: 10px; + + width: 100%; +} + +.top-bar { + position: relative; + + display: flex; + flex-direction: row; + + justify-content: center; + align-items: center; + + background-color: var(--background-color-accent); + + border-radius: 12px; + + width: 100%; + height: @top_bar_height; + + padding: 10px; + + box-shadow: @card-shadow-top; + + transition: all 150ms ease-in-out; + + color: var(--text-color); +} \ No newline at end of file diff --git a/packages/app/src/components/PagePanels/components/NavMenu/index.jsx b/packages/app/src/components/PagePanels/components/NavMenu/index.jsx index 33820990..22bfdee6 100644 --- a/packages/app/src/components/PagePanels/components/NavMenu/index.jsx +++ b/packages/app/src/components/PagePanels/components/NavMenu/index.jsx @@ -29,26 +29,24 @@ const NavMenu = (props) => { const NavMenuMobile = (props) => { return
-
- { - props.items.map((item) => { - return props.onClickItem(item.key)} - type="ghost" - disabled={item.disabled} - > -
- {item.icon} -
-
- }) - } -
+ { + props.items.map((item) => { + return props.onClickItem(item.key)} + type="ghost" + disabled={item.disabled} + > +
+ {item.icon} +
+
+ }) + }
} diff --git a/packages/app/src/components/PagePanels/components/NavMenu/index.less b/packages/app/src/components/PagePanels/components/NavMenu/index.less index 90aa882f..8e196b6c 100644 --- a/packages/app/src/components/PagePanels/components/NavMenu/index.less +++ b/packages/app/src/components/PagePanels/components/NavMenu/index.less @@ -5,60 +5,58 @@ } .__mobile__navmenu_wrapper { - box-sizing: border-box; + display: flex; + flex-direction: row; - position: relative; - - top: 0; - left: 0; + justify-content: space-evenly; width: 100%; +} - .card { - width: 100%; - height: @app_topBar_height; +.card { + width: 100%; + height: @app_topBar_height; - display: flex; - flex-direction: row; + display: flex; + flex-direction: row; - justify-content: space-evenly; + justify-content: space-evenly; - box-shadow: @card-shadow; + box-shadow: @card-shadow; - gap: 10px; - padding: 5px; - border-radius: 12px; + gap: 10px; + padding: 5px; + border-radius: 12px; - isolation: unset; - overflow: visible; + isolation: unset; + overflow: visible; +} - .item { - display: flex; - flex-direction: column; +.card_item { + display: flex; + flex-direction: column; - align-items: center; + align-items: center; - height: fit-content; + height: fit-content; - gap: 4px; + gap: 4px; - padding: 8px 10px; + padding: 8px 10px; - &.active { - color: var(--colorPrimary); - } + &.active { + color: var(--colorPrimary); + } - .icon { - margin: 0; - line-height: 1rem; - font-size: 1.5rem; - } + .icon { + margin: 0; + line-height: 1rem; + font-size: 1.5rem; + } - .label { - height: fit-content; - line-height: 1rem; - font-size: 0.8rem; - } - } + .label { + height: fit-content; + line-height: 1rem; + font-size: 0.8rem; } } \ No newline at end of file diff --git a/packages/app/src/components/PagePanels/index.jsx b/packages/app/src/components/PagePanels/index.jsx index 889d2688..397c55a9 100755 --- a/packages/app/src/components/PagePanels/index.jsx +++ b/packages/app/src/components/PagePanels/index.jsx @@ -4,6 +4,7 @@ import * as antd from "antd" import { createIconRender } from "components/Icons" +import { UseTopBar } from "components/Layout/topBar" import NavMenu from "./components/NavMenu" import "./index.less" @@ -29,6 +30,14 @@ export class PagePanelWithNavMenu extends React.Component { primaryPanelRef = React.createRef() + componentDidMount() { + app.layout.top_bar.shouldUseTopBarSpacer(false) + } + + componentWillUnmount() { + app.layout.top_bar.shouldUseTopBarSpacer(true) + } + renderActiveTab() { if (!Array.isArray(this.props.tabs)) { console.error("PagePanelWithNavMenu: tabs must be an array") @@ -158,14 +167,27 @@ export class PagePanelWithNavMenu extends React.Component { }, ] + if (app.isMobile) { + delete panels[0] + } + if (this.props.extraPanel) { panels.push(this.props.extraPanel) } - return + return <> + { + app.isMobile && app.layout.top_bar.render( this.handleTabChange(key)} + />) + } + + } } diff --git a/packages/app/src/components/PagePanels/index.less b/packages/app/src/components/PagePanels/index.less index 4c161508..e377a3ac 100755 --- a/packages/app/src/components/PagePanels/index.less +++ b/packages/app/src/components/PagePanels/index.less @@ -1,3 +1,57 @@ +@import "theme/vars.less"; + +#root { + &.mobile { + &.page-panel-spacer { + .pagePanels { + .panel { + &.center { + padding-top: calc(@top_bar_height + @top_bar_padding * 2); + } + } + } + } + + .pagePanels { + display: flex; + flex-direction: column; + + align-items: center; + justify-content: flex-start; + + overflow: unset; + overflow-x: visible; + overflow-y: overlay; + + width: 100%; + height: max-content; + + padding: 0; + + -webkit-mask-image: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 1) 5%, rgba(0, 0, 0, 1) 97%, transparent 100%); + mask-image: linear-gradient(180deg, transparent 0%, rgba(0, 0, 0, 1) 5%, rgba(0, 0, 0, 1) 97%, transparent 100%); + + .panel { + width: 100%; + + height: unset; + + &.center { + z-index: 300; + + overflow: unset; + overflow-x: unset; + overflow-y: unset; + + height: unset; + + transition: all 150ms ease-in-out; + } + } + } + } +} + .pagePanels { display: grid; diff --git a/packages/app/src/components/PostsList/index.jsx b/packages/app/src/components/PostsList/index.jsx index 165e65b1..5211c896 100755 --- a/packages/app/src/components/PostsList/index.jsx +++ b/packages/app/src/components/PostsList/index.jsx @@ -36,6 +36,46 @@ const typeToComponent = { "playlist": (args) => , } +const PostList = (props) => { + return + { + !props.realtimeUpdates && !app.isMobile &&
+ } + > + Resume + +
+ } + { + props.list.map((data) => { + return React.createElement(typeToComponent[data.type ?? "post"] ?? PostCard, { + key: data._id, + data: data, + events: { + onClickLike: props.onLikePost, + onClickSave: props.onSavePost, + onClickDelete: props.onDeletePost, + onClickEdit: props.onEditPost, + } + }) + }) + } +
+} + export class PostsListsComponent extends React.Component { state = { openPost: null, @@ -366,44 +406,34 @@ export class PostsListsComponent extends React.Component { } + const PostListProps = { + listRef: this.listRef, + list: this.state.list, + + onLikePost: this.onLikePost, + onSavePost: this.onSavePost, + onDeletePost: this.onDeletePost, + onEditPost: this.onEditPost, + + onLoadMore: this.onLoadMore, + hasMore: this.state.hasMore, + loading: this.state.loading, + + realtimeUpdates: this.state.realtimeUpdates, + resumingLoading: this.state.resumingLoading, + onResumeRealtimeUpdates: this.onResumeRealtimeUpdates, + } + + if (app.isMobile) { + return + } + return
- - { - !this.state.realtimeUpdates && !app.isMobile &&
- } - > - Resume - -
- } - { - this.state.list.map((data) => { - return React.createElement(typeToComponent[data.type ?? "post"] ?? PostCard, { - key: data._id, - data: data, - events: { - onClickLike: this.onLikePost, - onClickSave: this.onSavePost, - onClickDelete: this.onDeletePost, - onClickEdit: this.onEditPost, - } - }) - }) - } -
+
} } diff --git a/packages/app/src/components/PostsList/index.less b/packages/app/src/components/PostsList/index.less index 4c73f2cf..f93f9613 100755 --- a/packages/app/src/components/PostsList/index.less +++ b/packages/app/src/components/PostsList/index.less @@ -1,3 +1,37 @@ +@import "theme/vars.less"; + +#root { + &.mobile { + .post-list { + overflow: unset; + overflow-x: hidden; + overflow-y: overlay; + + height: 100%; + + //padding-top: 5px; + border-radius: 0; + + .playlistTimelineEntry { + width: 100%; + + .playlistTimelineEntry_content { + .playlistTimelineEntry_thumbnail { + img { + width: 20vw; + height: 20vw; + } + } + } + } + + .postCard { + width: 100%; + } + } + } +} + .post-list_wrapper { display: flex; flex-direction: column; @@ -20,7 +54,7 @@ //will-change: transform; overflow: hidden; overflow-y: overlay; - + width: 100%; height: 100%; diff --git a/packages/app/src/layout.jsx b/packages/app/src/layout.jsx index 2558d716..213974bf 100755 --- a/packages/app/src/layout.jsx +++ b/packages/app/src/layout.jsx @@ -7,7 +7,7 @@ export default class Layout extends React.PureComponent { progressBar = progressBar.configure({ parent: "html", showSpinner: false }) state = { - layoutType: app.isMobile ? "mobile" : "default", + layoutType: "default", renderError: null, } @@ -51,14 +51,18 @@ export default class Layout extends React.PureComponent { } componentDidMount() { - // if (window.app.cores.settings.get("forceMobileMode") || app.isMobile) { - // app.layout.set("mobile") - // } - // register events Object.keys(this.events).forEach((event) => { window.app.eventBus.on(event, this.events[event]) }) + + if (app.isMobile) { + this.layoutInterface.toogleMobileStyle(true) + } + + if (app.cores.settings.get("reduceAnimations")) { + this.layoutInterface.toogleRootContainerClassname("reduce-animations", true) + } } componentWillUnmount() { @@ -75,25 +79,22 @@ export default class Layout extends React.PureComponent { makePageTransition(path, options = {}) { this.progressBar.start() - if (app.cores.settings.get("reduceAnimations") || options.state?.noTransition) { + const content_layout = document.getElementById("content_layout") + + if (!content_layout) { + console.warn("content_layout not found, no animation will be played") + this.progressBar.done() return false } - const transitionLayer = document.getElementById("transitionLayer") - - if (!transitionLayer) { - console.warn("transitionLayer not found, no animation will be played") - return false - } - - transitionLayer.classList.add("fade-transverse-leave") + content_layout.classList.add("fade-transverse-leave") setTimeout(() => { this.progressBar.done() - transitionLayer.classList.remove("fade-transverse-leave") + content_layout.classList.remove("fade-transverse-leave") }, options.state?.transitionDelay ?? 250) } @@ -110,25 +111,53 @@ export default class Layout extends React.PureComponent { }) }, toogleCenteredContent: (to) => { + return this.layoutInterface.toogleRootContainerClassname("centered-content", to) + }, + toogleMobileStyle: (to) => { + return this.layoutInterface.toogleRootContainerClassname("mobile", to) + }, + toogleReducedAnimations: (to) => { + return this.layoutInterface.toogleRootContainerClassname("reduce-animations", to) + }, + toogleTopBarSpacer: (to) => { + return this.layoutInterface.toogleRootContainerClassname("top-bar-spacer", to) + }, + tooglePagePanelSpacer: (to) => { + return this.layoutInterface.toogleRootContainerClassname("page-panel-spacer", to) + }, + toogleRootContainerClassname: (classname, to) => { const root = document.getElementById("root") - if (app.isMobile) { - console.warn("Skipping centered content on mobile") - return false - } - if (!root) { console.error("root not found") return false } - to = typeof to === "boolean" ? to : !root.classList.contains("centered-content") + to = typeof to === "boolean" ? to : !root.classList.contains(classname) + + if (root.classList.contains(classname) === to) { + // ignore + return false + } if (to === true) { - root.classList.add("centered_content") + root.classList.add(classname) } else { - root.classList.remove("centered_content") + root.classList.remove(classname) } + }, + scrollTo: (to) => { + const content_layout = document.getElementById("content_layout") + + if (!content_layout) { + console.error("content_layout not found") + return false + } + + content_layout.scrollTo({ + ...to, + behavior: "smooth", + }) } } @@ -148,7 +177,7 @@ export default class Layout extends React.PureComponent { return JSON.stringify(this.state.renderError) } - const Layout = Layouts[app.isMobile ? "mobile" : layoutType] + const Layout = Layouts[layoutType] if (!Layout) { return app.eventBus.emit("runtime.crash", new Error(`Layout type [${layoutType}] not found`)) diff --git a/packages/app/src/layouts/blank/index.jsx b/packages/app/src/layouts/blank/index.jsx index 7e64f6a9..9ad02977 100644 --- a/packages/app/src/layouts/blank/index.jsx +++ b/packages/app/src/layouts/blank/index.jsx @@ -2,4 +2,4 @@ import React from "react" export default (props) => { return props.children -} +} \ No newline at end of file diff --git a/packages/app/src/layouts/default/index.jsx b/packages/app/src/layouts/default/index.jsx index 5dd1ce79..fd4195a0 100755 --- a/packages/app/src/layouts/default/index.jsx +++ b/packages/app/src/layouts/default/index.jsx @@ -2,13 +2,13 @@ import React from "react" import classnames from "classnames" import { Layout } from "antd" -import { Sidebar, Drawer, Sidedrawer, Modal } from "components/Layout" +import { Sidebar, Drawer, Sidedrawer, Modal, BottomBar, TopBar } from "components/Layout" import BackgroundDecorator from "components/BackgroundDecorator" import { createWithDom as FloatingStack } from "../components/floatingStack" -export default (props) => { +const DesktopLayout = (props) => { React.useEffect(() => { const floatingStack = FloatingStack() @@ -20,30 +20,55 @@ export default (props) => { return <> - + -
- {React.cloneElement(props.children, props)} -
+ { + React.cloneElement(props.children, props) + }
-} \ No newline at end of file +} + +const MobileLayout = (props) => { + return + + + + + + { + React.cloneElement(props.children, props) + } + + + + + + +} + +export default (props) => { + return window.app.isMobile ? : +} \ No newline at end of file diff --git a/packages/app/src/layouts/index.js b/packages/app/src/layouts/index.js index 787b189d..e7d22b51 100755 --- a/packages/app/src/layouts/index.js +++ b/packages/app/src/layouts/index.js @@ -1,11 +1,9 @@ import Default from "./default" -import Mobile from "./mobile" -import None from "./none" +import Minimal from "./minimal" import Blank from "./blank" export default { default: Default, - mobile: Mobile, - none: None, + minimal: Minimal, blank: Blank, } \ No newline at end of file diff --git a/packages/app/src/layouts/none/index.jsx b/packages/app/src/layouts/minimal/index.jsx similarity index 76% rename from packages/app/src/layouts/none/index.jsx rename to packages/app/src/layouts/minimal/index.jsx index e05c7417..4642ce4e 100755 --- a/packages/app/src/layouts/none/index.jsx +++ b/packages/app/src/layouts/minimal/index.jsx @@ -5,7 +5,7 @@ import classnames from "classnames" import { Drawer, Sidedrawer } from "components/Layout" export default (props) => { - return + return
diff --git a/packages/app/src/layouts/mobile/index.jsx b/packages/app/src/layouts/mobile/index.jsx deleted file mode 100755 index 725421a5..00000000 --- a/packages/app/src/layouts/mobile/index.jsx +++ /dev/null @@ -1,21 +0,0 @@ -import React from "react" -import classnames from "classnames" -import * as antd from "antd" - -import { BottomBar, Drawer, Sidedrawer, Modal } from "components/Layout" - -export default (props) => { - return - - - -
- {React.cloneElement(props.children, props)} -
-
- - - - -
-} diff --git a/packages/app/src/pages/account/index.less b/packages/app/src/pages/account/index.less index 948da5b7..ef83acf5 100755 --- a/packages/app/src/pages/account/index.less +++ b/packages/app/src/pages/account/index.less @@ -1,5 +1,60 @@ +@import "theme/vars.less"; + @borderRadius: 12px; +#root { + &.mobile { + .accountProfile { + display: flex; + flex-direction: column; + + .panels { + display: flex; + flex-direction: column; + + .tabMenuWrapper { + position: fixed; + + top: 0px; + left: 0px; + + z-index: 300; + + width: 100%; + + height: @top_bar_height; + + padding: @top_bar_padding; + + box-shadow: @card-shadow-top; + + display: flex; + flex-direction: row; + + align-items: center; + + opacity: 0; + + .ant-menu { + display: flex; + flex-direction: row; + + .ant-menu-item { + width: fit-content; + } + } + } + } + + &.topHidden { + .tabMenuWrapper { + opacity: 1; + } + } + } + } +} + .accountProfile { display: flex; diff --git a/packages/app/src/pages/live/index.less b/packages/app/src/pages/live/index.less index dc070724..6c211340 100755 --- a/packages/app/src/pages/live/index.less +++ b/packages/app/src/pages/live/index.less @@ -1,6 +1,31 @@ @panel-width: 500px; @chatbox-header-height: 50px; +#root { + &.mobile { + .livestream { + flex-direction: column; + height: 100%; + } + + .livestream_panel { + position: absolute; + bottom: 0; + height: 20%; + } + + .livestream_player { + height: 100%; + width: 100%; + + .plyr { + width: 100%; + height: 100%; + } + } + } +} + .plyr__controls { width: 100%; display: inline-flex; diff --git a/packages/app/src/pages/play/index.less b/packages/app/src/pages/play/index.less index c4a31764..7bd2459c 100755 --- a/packages/app/src/pages/play/index.less +++ b/packages/app/src/pages/play/index.less @@ -1,3 +1,38 @@ +#root { + &.mobile { + .playlist_view { + display: flex; + flex-direction: column; + + width: 100%; + + .play_info_wrapper { + position: relative; + + .play_info { + width: 100%; + + .play_info_cover { + width: 20vh; + height: 20vh; + + img { + width: 100%; + height: 100%; + + object-fit: contain; + } + } + } + } + + .list { + padding: 30px 10px; + } + } + } +} + .playlist_view { display: grid; @@ -60,7 +95,7 @@ width: 100%; height: 100%; - object-fit: cover; + object-fit: contain; } } diff --git a/packages/app/src/pages/settings/index.mobile.jsx b/packages/app/src/pages/settings/index.mobile.jsx index b6f99c2b..add59890 100644 --- a/packages/app/src/pages/settings/index.mobile.jsx +++ b/packages/app/src/pages/settings/index.mobile.jsx @@ -5,6 +5,7 @@ import { Translation } from "react-i18next" import useUrlQueryActiveKey from "hooks/useUrlQueryActiveKey" import { Icons, createIconRender } from "components/Icons" +import { UseTopBar } from "components/Layout/topBar" import { composedSettingsByGroups as settingsGroups, @@ -20,38 +21,31 @@ const SettingsHeader = ({ activeKey, back = () => { } } = {}) => { - if (activeKey) { - const currentTab = composedTabs[activeKey] + const currentTab = composedTabs[activeKey] - return
- + { + activeKey && } onClick={back} size="large" type="ghost" /> + } -

- { - createIconRender(currentTab?.icon) - } - - {(t) => t(currentTab?.label ?? activeKey)} - -

-
- } - - return

{ - createIconRender("Settings") + createIconRender(currentTab?.icon ?? "Settings") } - {(t) => t("Settings")} + {(t) => t(currentTab?.label ?? activeKey ?? "Settings")}

-
+ } export default (props) => { @@ -80,6 +74,11 @@ export default (props) => { const changeTab = (key) => { lastKey = key setActiveKey(key) + + // scroll to top + app.layout.scrollTo({ + top: 0, + }) } return
diff --git a/packages/app/src/pages/settings/index.mobile.less b/packages/app/src/pages/settings/index.mobile.less index 4f7a2e94..b62db44c 100644 --- a/packages/app/src/pages/settings/index.mobile.less +++ b/packages/app/src/pages/settings/index.mobile.less @@ -1,4 +1,32 @@ -@top_nav_height: 52px; +.settings_nav { + display: flex; + + flex-direction: row; + align-items: center; + justify-content: flex-start; + + width: 100%; + + gap: 20px; + + h1 { + margin: 0; + view-transition-name: main-header-text; + width: fit-content; + } + + svg { + color: var(--colorPrimary); + } + + .ant-btn { + font-size: 2rem; + + svg { + color: var(--text-color); + } + } +} .__mobile__settings { display: flex; @@ -7,47 +35,6 @@ gap: 30px; - .__mobile__settings_header { - position: sticky; - top: 0; - left: 0; - z-index: 200; - - width: 100%; - height: @top_nav_height; - - display: flex; - flex-direction: row; - align-items: center; - - gap: 20px; - - padding: 5px 20px; - - border-radius: 12px; - - border-bottom: 1px solid var(--border-color); - background-color: var(--background-color-accent); - - h1 { - margin: 0; - view-transition-name: main-header-text; - width: fit-content; - } - - svg { - color: var(--colorPrimary); - } - - .ant-btn { - font-size: 2rem; - - svg { - color: var(--text-color); - } - } - } - .settings_list { view-transition-name: settings-list; diff --git a/packages/app/src/theme/index.less b/packages/app/src/theme/index.less index c484d748..a0f7b79b 100755 --- a/packages/app/src/theme/index.less +++ b/packages/app/src/theme/index.less @@ -128,25 +128,19 @@ html { font-size: calc(16px * var(--fontScale)); &.electron { - .page_layout { - padding-top: 35px; - } - .ant-layout-sider { padding-top: 0px; } } &.centered_content { - .content_layout { - display: flex; - flex-direction: column; - justify-content: center; - align-items: center; + .app_layout { + .content_layout { + display: flex; + flex-direction: column; - .page_layout { - width: 60%; - height: calc(100vh - var(--layoutPadding) * 2); + justify-content: center; + align-items: center; } } } @@ -192,27 +186,19 @@ html { z-index: 200; transition: all 200ms ease-in-out; } - - &.mobile { - //padding-top: 20px; - - ::-webkit-scrollbar { - display: none !important; - width: 0; - height: 0; - z-index: 0; - } - } } .content_layout { position: relative; -webkit-overflow-scrolling: touch; + box-sizing: border-box; + display: flex; flex-direction: column; align-items: center; + justify-content: flex-start; height: 100%; width: 100%; @@ -232,11 +218,6 @@ html { &.floating-sidebar { margin-left: @app_sidebar_width; } - - .page_layout { - width: 100%; - height: 100%; - } } .root_background { diff --git a/packages/app/src/theme/mobile.less b/packages/app/src/theme/mobile.less index f581a538..4c4eccfd 100755 --- a/packages/app/src/theme/mobile.less +++ b/packages/app/src/theme/mobile.less @@ -1,183 +1,66 @@ @import "theme/vars.less"; -@top_bar_height: 52px; - -// #root,body,html { -// height: 100%!important; -// max-height: 100%!important; -// } - -.app_layout { +#root { &.mobile { - display: flex; - flex-direction: column; + &.centered-content { + .app_layout { + .content_layout { + display: flex; + flex-direction: column; - height: 100% !important; - max-height: 100% !important; + justify-content: flex-start; + align-items: center; - padding: 0; - - .content_wrapper { - height: 100%; - width: 100%; - max-height: 100%; - - overflow-y: scroll; + padding: 10px; + } + } } - .content_layout { + &.top-bar-spacer { + .app_layout { + .content_layout { + padding-top: calc(@top_bar_height + @top_bar_padding * 2); + } + } + } + + .app_layout { display: flex; flex-direction: column; - overflow: hidden; - align-items: center; - justify-content: center; - - width: 100%; height: 100%; - max-height: 100%; - - padding: 7px 0; - padding-bottom: 0px; - - box-sizing: border-box; - } - - .pagePanels { - display: flex; - flex-direction: column; - - align-items: center; - justify-content: flex-start; - - overflow-x: visible; - width: 100%; - height: 100%; padding: 0; - .panel { - width: 100%; - - &.left { - position: absolute; - - height: @top_bar_height; - - padding: 10px; - z-index: 310; - - top: 0; - left: 0; - - overflow: visible; - overflow-x: visible; - } - - &.center { - z-index: 300; - - overflow-y: visible; - overflow-x: hidden; - - margin-top: calc(@top_bar_height + 10px); - margin-bottom: 10px; - - border-radius: 12px; - - height: 100%; - - //-webkit-mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 10px, rgb(0, 0, 0) calc(100% - 10px), rgba(0, 0, 0, 0) 100%); - //mask-image: linear-gradient(0deg, rgba(0, 0, 0, 0) 0%, rgb(0, 0, 0) 10px, rgb(0, 0, 0) calc(100% - 10px), rgba(0, 0, 0, 0) 100%); - } + ::-webkit-scrollbar { + display: none !important; + width: 0; + height: 0; + z-index: 0; } - .card { - width: 100%; - height: 100%; + transition: all 150ms ease-in-out; + .content_layout { display: flex; - flex-direction: row; + flex-direction: column; - padding: 5px; + align-items: center; + justify-content: flex-start; - justify-content: space-evenly; + margin: 0; + padding: 0; + padding-bottom: 0px; - box-shadow: @card-shadow; + overflow: unset; + overflow-x: hidden; + overflow-y: overlay; - border-radius: 12px; - - isolation: unset; - overflow: visible; - } - } - - .playlist_view { - display: flex; - flex-direction: column; - - .play_info_wrapper { - position: relative; - - .play_info { - width: 100%; - - .play_info_cover { - width: 100%; - height: 100%; - } - } - } - - .list { - padding: 30px 10px; - } - } - - .post-list_wrapper { - .post-list { - padding-top: 10px; - border-radius: 0; - - .playlistTimelineEntry { - width: 100%; - - .playlistTimelineEntry_content { - .playlistTimelineEntry_thumbnail { - img { - width: 20vw; - height: 20vw; - } - } - } - } - - .postCard { + >div { width: 100%; } } } - - .livestream { - flex-direction: column; - height: 100%; - } - - .livestream_panel { - position: absolute; - bottom: 0; - height: 20%; - } - - .livestream_player { - height: 100%; - width: 100%; - - .plyr { - width: 100%; - height: 100%; - } - } } } \ No newline at end of file diff --git a/packages/app/src/theme/vars.less b/packages/app/src/theme/vars.less index 13cf0e3c..2b7a79e9 100755 --- a/packages/app/src/theme/vars.less +++ b/packages/app/src/theme/vars.less @@ -18,4 +18,8 @@ @transition-ease-inout: all 150ms ease-in-out; @card-shadow: 0 0 0 1px rgba(63, 63, 68, 0.05), 0 1px 3px 0 var(--shadow-color); -@card-shadow-top: 0 -4px 3px 0 rgba(63, 63, 68, 0.05), 0 0 0 2px var(--shadow-color); \ No newline at end of file +@card-shadow-top: 0 -4px 3px 0 rgba(63, 63, 68, 0.05), 0 0 0 2px var(--shadow-color); + +// Mobile +@top_bar_height: 52px; +@top_bar_padding: 10px; \ No newline at end of file