mirror of
https://git.unlock-music.dev/um/um-react.git
synced 2025-05-23 16:27:41 +08:00
fix: adjust layout for settings
All checks were successful
Build and Deploy / build (push) Successful in 1m26s
All checks were successful
Build and Deploy / build (push) Successful in 1m26s
This commit is contained in:
parent
9518b813bd
commit
6cb1f9f87f
@ -1,8 +1,8 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="zh-cmn-Hans-CN">
|
<html lang="zh-cmn-Hans-CN">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8" />
|
<meta charset="UTF-8" />
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
|
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no" />
|
||||||
<title>音乐解锁 - Unlock Music</title>
|
<title>音乐解锁 - Unlock Music</title>
|
||||||
|
|
||||||
<meta name="description" content="音乐解锁 - Unlock Music" />
|
<meta name="description" content="音乐解锁 - Unlock Music" />
|
||||||
@ -10,6 +10,7 @@
|
|||||||
<link rel="apple-touch-icon" href="/pwa-512x512.png" sizes="512x512" />
|
<link rel="apple-touch-icon" href="/pwa-512x512.png" sizes="512x512" />
|
||||||
<meta name="theme-color" content="#4DBA87" />
|
<meta name="theme-color" content="#4DBA87" />
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<main id="root"></main>
|
<main id="root"></main>
|
||||||
<script type="module" src="/src/main.tsx"></script>
|
<script type="module" src="/src/main.tsx"></script>
|
||||||
|
@ -12,11 +12,12 @@ import { Footer } from '~/components/Footer';
|
|||||||
import { FaqTab } from '~/tabs/FaqTab';
|
import { FaqTab } from '~/tabs/FaqTab';
|
||||||
import { SETTINGS_TABS } from '~/features/settings/settingsTabs';
|
import { SETTINGS_TABS } from '~/features/settings/settingsTabs';
|
||||||
import { Bounce, ToastContainer } from 'react-toastify';
|
import { Bounce, ToastContainer } from 'react-toastify';
|
||||||
|
import { SettingsHome } from '~/features/settings/SettingsHome';
|
||||||
|
|
||||||
// Private to this file only.
|
// Private to this file only.
|
||||||
const store = setupStore();
|
const store = setupStore();
|
||||||
|
|
||||||
const tabClassNames = ({ isActive }: { isActive: boolean }) => `tab ${isActive ? 'tab-active' : ''}`;
|
const tabClassNames = ({ isActive }: { isActive: boolean }) => `mb-[-2px] tab ${isActive ? 'tab-active' : ''}`;
|
||||||
|
|
||||||
export function AppRoot() {
|
export function AppRoot() {
|
||||||
useEffect(() => persistSettings(store), []);
|
useEffect(() => persistSettings(store), []);
|
||||||
@ -24,7 +25,7 @@ export function AppRoot() {
|
|||||||
return (
|
return (
|
||||||
<BrowserRouter>
|
<BrowserRouter>
|
||||||
<Provider store={store}>
|
<Provider store={store}>
|
||||||
<div role="tablist" className="tabs tabs-border w-full justify-center">
|
<div role="tablist" className="tabs tabs-border w-full justify-center border-b-2 border-base-200 box-content">
|
||||||
<NavLink to="/" role="tab" className={tabClassNames}>
|
<NavLink to="/" role="tab" className={tabClassNames}>
|
||||||
<MdHome />
|
<MdHome />
|
||||||
应用
|
应用
|
||||||
@ -39,10 +40,11 @@ export function AppRoot() {
|
|||||||
</NavLink>
|
</NavLink>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<main className="flex-1 flex justify-center">
|
<main className="flex-1 flex justify-center min-h-0 overflow-auto">
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" Component={MainTab} />
|
<Route path="/" Component={MainTab} />
|
||||||
<Route path="/settings" Component={SettingsTab}>
|
<Route path="/settings" Component={SettingsTab}>
|
||||||
|
<Route index Component={SettingsHome} />
|
||||||
{Object.entries(SETTINGS_TABS).map(([key, { Tab }]) => (
|
{Object.entries(SETTINGS_TABS).map(([key, { Tab }]) => (
|
||||||
<Route key={key} path={key} Component={Tab} />
|
<Route key={key} path={key} Component={Tab} />
|
||||||
))}
|
))}
|
||||||
|
@ -9,9 +9,9 @@ export interface KeyListContainerProps {
|
|||||||
export function KeyListContainer({ keys, children, ref }: KeyListContainerProps) {
|
export function KeyListContainer({ keys, children, ref }: KeyListContainerProps) {
|
||||||
const count = keys.length;
|
const count = keys.length;
|
||||||
return (
|
return (
|
||||||
<div ref={ref} className="flex grow min-h-0 overflow-auto pr-4 pt-3">
|
<div ref={ref} className="flex grow min-h-0 pr-4 pt-3">
|
||||||
{count > 0 && (
|
{count > 0 && (
|
||||||
<ul className="list bg-base-100 rounded-box shadow-md border border-base-300 w-full min-h-0 max-h-[30rem] overflow-auto">
|
<ul className="list bg-base-100 rounded-box shadow-sm border border-base-300 w-full min-h-0 overflow-auto">
|
||||||
{children}
|
{children}
|
||||||
</ul>
|
</ul>
|
||||||
)}
|
)}
|
||||||
|
29
src/features/nav/ResponsiveNav.tsx
Normal file
29
src/features/nav/ResponsiveNav.tsx
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
export interface ResponsiveNavProps {
|
||||||
|
navigationClassName?: string;
|
||||||
|
navigation?: React.ReactNode;
|
||||||
|
|
||||||
|
className?: string;
|
||||||
|
|
||||||
|
contentClassName?: string;
|
||||||
|
children?: React.ReactNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function ResponsiveNav({
|
||||||
|
className = '',
|
||||||
|
navigationClassName = '',
|
||||||
|
contentClassName = '',
|
||||||
|
children,
|
||||||
|
navigation,
|
||||||
|
}: ResponsiveNavProps) {
|
||||||
|
return (
|
||||||
|
<div
|
||||||
|
className={`@container/nav grow grid grid-cols-1 grid-rows-[auto_1fr] md:grid-rows-1 md:grid-cols-[10rem_1fr] ${className}`}
|
||||||
|
>
|
||||||
|
{/* Sidebar */}
|
||||||
|
<aside className={`bg-gray-100 md:p-4 md:block ${navigationClassName}`}>{navigation}</aside>
|
||||||
|
|
||||||
|
{/* Main content */}
|
||||||
|
<div className={`p-4 grow ${contentClassName}`}>{children}</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -5,6 +5,8 @@ import { NavLink, Outlet } from 'react-router';
|
|||||||
import { SETTINGS_TABS } from '~/features/settings/settingsTabs.tsx';
|
import { SETTINGS_TABS } from '~/features/settings/settingsTabs.tsx';
|
||||||
import { MdOutlineSettingsBackupRestore } from 'react-icons/md';
|
import { MdOutlineSettingsBackupRestore } from 'react-icons/md';
|
||||||
import { toast } from 'react-toastify';
|
import { toast } from 'react-toastify';
|
||||||
|
import { ResponsiveNav } from '../nav/ResponsiveNav';
|
||||||
|
import classNames from 'classnames';
|
||||||
|
|
||||||
export function Settings() {
|
export function Settings() {
|
||||||
const dispatch = useAppDispatch();
|
const dispatch = useAppDispatch();
|
||||||
@ -25,23 +27,37 @@ export function Settings() {
|
|||||||
};
|
};
|
||||||
const isSettingsNotSaved = useAppSelector(selectIsSettingsNotSaved);
|
const isSettingsNotSaved = useAppSelector(selectIsSettingsNotSaved);
|
||||||
|
|
||||||
|
const tabClassNames = ({ isActive }: { isActive: boolean }) =>
|
||||||
|
classNames(
|
||||||
|
'link inline-flex text-nowrap mb-[-2px] no-underline w-full',
|
||||||
|
'border-b-2 md:border-b-0 md:border-r-2',
|
||||||
|
'tab md:grow',
|
||||||
|
{
|
||||||
|
'tab-active bg-accent/10 border-accent': isActive,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="flex flex-col flex-1 container w-full">
|
<div className="flex flex-col flex-1 container w-full">
|
||||||
<div role="tablist" className="tabs tabs-border w-full justify-center gap-2">
|
<ResponsiveNav
|
||||||
{Object.entries(SETTINGS_TABS).map(([id, { name }]) => (
|
className="grow h-full overflow-auto"
|
||||||
<NavLink className="link link-neutral" key={id} to={`/settings/${id}`} role="tab">
|
contentClassName="flex flex-col overflow-auto"
|
||||||
{name}
|
navigationClassName="overflow-x-auto pb-[2px] md:pb-0 h-full md:items-center [&]:md:flex"
|
||||||
</NavLink>
|
navigation={
|
||||||
))}
|
<div role="tablist" className="tabs gap-1 flex-nowrap md:flex-col grow items-center">
|
||||||
</div>
|
{Object.entries(SETTINGS_TABS).map(([id, { name }]) => (
|
||||||
|
<NavLink className={tabClassNames} key={id} to={`/settings/${id}`} role="tab">
|
||||||
{/* TODO: ensure this flex div does not overflow */}
|
{name}
|
||||||
<div className="flex flex-1 flex-col h-full overflow-auto">
|
</NavLink>
|
||||||
|
))}
|
||||||
|
</div>
|
||||||
|
}
|
||||||
|
>
|
||||||
<Outlet />
|
<Outlet />
|
||||||
</div>
|
</ResponsiveNav>
|
||||||
|
|
||||||
<footer className="flex flex-row gap-2 w-full py-3">
|
<footer className="flex flex-row gap-2 w-full p-2 border-t border-base-200 bg-base-100">
|
||||||
<div className="grow">
|
<div className="grow inline-flex items-center">
|
||||||
{isSettingsNotSaved ? (
|
{isSettingsNotSaved ? (
|
||||||
<span>
|
<span>
|
||||||
有未储存的更改,<span className="text-red-600">设定将在保存后生效</span>
|
有未储存的更改,<span className="text-red-600">设定将在保存后生效</span>
|
||||||
@ -64,39 +80,6 @@ export function Settings() {
|
|||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</footer>
|
</footer>
|
||||||
|
|
||||||
{/* <VStack mt="4" alignItems="flex-start" w="full">*/}
|
|
||||||
{/* <Flex flexDir="row" gap="2" w="full">*/}
|
|
||||||
{/* <Center>*/}
|
|
||||||
{/* {isSettingsNotSaved ? (*/}
|
|
||||||
{/* <Box color="gray">*/}
|
|
||||||
{/* 有未储存的更改{' '}*/}
|
|
||||||
{/* <chakra.span color="red" wordBreak="keep-all">*/}
|
|
||||||
{/* 设定将在保存后生效*/}
|
|
||||||
{/* </chakra.span>*/}
|
|
||||||
{/* </Box>*/}
|
|
||||||
{/* ) : (*/}
|
|
||||||
{/* <Box color="gray">设定将在保存后生效</Box>*/}
|
|
||||||
{/* )}*/}
|
|
||||||
{/* </Center>*/}
|
|
||||||
{/* <Spacer />*/}
|
|
||||||
{/* <HStack gap="2" justifyContent="flex-end">*/}
|
|
||||||
{/* <IconButton*/}
|
|
||||||
{/* icon={<Icon as={MdOutlineSettingsBackupRestore} />}*/}
|
|
||||||
{/* onClick={handleResetSettings}*/}
|
|
||||||
{/* colorScheme="red"*/}
|
|
||||||
{/* variant="ghost"*/}
|
|
||||||
{/* title="放弃未储存的更改,将设定还原未储存前的状态。"*/}
|
|
||||||
{/* aria-label="放弃未储存的更改"*/}
|
|
||||||
{/* />*/}
|
|
||||||
{/* <Button onClick={handleApplySettings}>保存</Button>*/}
|
|
||||||
{/* </HStack>*/}
|
|
||||||
{/* </Flex>*/}
|
|
||||||
{/* </VStack>*/}
|
|
||||||
{/* </Flex>*/}
|
|
||||||
{/* ))}*/}
|
|
||||||
{/* </TabPanels>*/}
|
|
||||||
{/*</Tabs>*/}
|
|
||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
8
src/features/settings/SettingsHome.tsx
Normal file
8
src/features/settings/SettingsHome.tsx
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
export function SettingsHome() {
|
||||||
|
return (
|
||||||
|
<div className="flex flex-col gap-4">
|
||||||
|
<h1 className="text-2xl font-bold">设置</h1>
|
||||||
|
<p>在这里你可以设置应用的基本配置。</p>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
|
}
|
@ -75,7 +75,7 @@ export function PanelQingTing() {
|
|||||||
value={secretKey}
|
value={secretKey}
|
||||||
onChange={handleDataInput}
|
onChange={handleDataInput}
|
||||||
/>
|
/>
|
||||||
<p className="label">
|
<p className="label flex-wrap">
|
||||||
粘贴含有设备密钥的信息的内容时将自动提取密钥(如通过
|
粘贴含有设备密钥的信息的内容时将自动提取密钥(如通过
|
||||||
<ExtLink href={QTFM_DEVICE_ID_URL}>
|
<ExtLink href={QTFM_DEVICE_ID_URL}>
|
||||||
<code>qtfm-device-id</code>
|
<code>qtfm-device-id</code>
|
||||||
@ -91,8 +91,15 @@ export function PanelQingTing() {
|
|||||||
<p>
|
<p>
|
||||||
下载的文件位于
|
下载的文件位于
|
||||||
<VQuote>
|
<VQuote>
|
||||||
<code>
|
<code className="break-words">
|
||||||
<HiWord>[内部储存]</HiWord>/Android/data/fm.qingting.qtradio/files/Music/
|
<HiWord>[内部储存]</HiWord>/<wbr />
|
||||||
|
Android/
|
||||||
|
<wbr />
|
||||||
|
data/
|
||||||
|
<wbr />
|
||||||
|
fm.qingting.qtradio/
|
||||||
|
<wbr />
|
||||||
|
files/Music/
|
||||||
</code>
|
</code>
|
||||||
</VQuote>
|
</VQuote>
|
||||||
</p>
|
</p>
|
||||||
|
Loading…
x
Reference in New Issue
Block a user