Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
C
canifa_note
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Vũ Hoàng Anh
canifa_note
Commits
0ad75b8f
Commit
0ad75b8f
authored
Dec 26, 2025
by
Johnny
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
refactor: replace useResponsiveWidth with useMediaQuery across components
parent
d21610cc
Changes
12
Hide whitespace changes
Inline
Side-by-side
Showing
12 changed files
with
111 additions
and
112 deletions
+111
-112
package.json
web/package.json
+0
-1
MobileHeader.tsx
web/src/components/MobileHeader.tsx
+8
-5
PagedMemoList.tsx
web/src/components/PagedMemoList/PagedMemoList.tsx
+2
-27
index.ts
web/src/hooks/index.ts
+1
-1
useMediaQuery.ts
web/src/hooks/useMediaQuery.ts
+35
-0
useResponsiveWidth.ts
web/src/hooks/useResponsiveWidth.ts
+0
-18
MainLayout.tsx
web/src/layouts/MainLayout.tsx
+3
-2
RootLayout.tsx
web/src/layouts/RootLayout.tsx
+2
-2
Attachments.tsx
web/src/pages/Attachments.tsx
+2
-2
Inboxes.tsx
web/src/pages/Inboxes.tsx
+2
-2
MemoDetail.tsx
web/src/pages/MemoDetail.tsx
+3
-3
Setting.tsx
web/src/pages/Setting.tsx
+53
-49
No files found.
web/package.json
View file @
0ad75b8f
...
@@ -55,7 +55,6 @@
...
@@ -55,7 +55,6 @@
"react-leaflet"
:
"^4.2.1"
,
"react-leaflet"
:
"^4.2.1"
,
"react-markdown"
:
"^10.1.0"
,
"react-markdown"
:
"^10.1.0"
,
"react-router-dom"
:
"^7.9.6"
,
"react-router-dom"
:
"^7.9.6"
,
"react-simple-pull-to-refresh"
:
"^1.3.3"
,
"react-use"
:
"^17.6.0"
,
"react-use"
:
"^17.6.0"
,
"rehype-katex"
:
"^7.0.1"
,
"rehype-katex"
:
"^7.0.1"
,
"rehype-raw"
:
"^7.0.0"
,
"rehype-raw"
:
"^7.0.0"
,
...
...
web/src/components/MobileHeader.tsx
View file @
0ad75b8f
import
useWindowScroll
from
"react-use/lib/useWindowScroll"
;
import
useWindowScroll
from
"react-use/lib/useWindowScroll"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
cn
}
from
"@/lib/utils"
;
import
NavigationDrawer
from
"./NavigationDrawer"
;
import
NavigationDrawer
from
"./NavigationDrawer"
;
...
@@ -10,19 +10,22 @@ interface Props {
...
@@ -10,19 +10,22 @@ interface Props {
const
MobileHeader
=
(
props
:
Props
)
=>
{
const
MobileHeader
=
(
props
:
Props
)
=>
{
const
{
className
,
children
}
=
props
;
const
{
className
,
children
}
=
props
;
const
{
sm
}
=
useResponsiveWidth
();
const
{
y
:
offsetTop
}
=
useWindowScroll
();
const
{
y
:
offsetTop
}
=
useWindowScroll
();
const
md
=
useMediaQuery
(
"md"
);
const
sm
=
useMediaQuery
(
"sm"
);
if
(
md
)
return
null
;
return
(
return
(
<
div
<
div
className=
{
cn
(
className=
{
cn
(
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-background bg-opacity-80 backdrop-blur-lg flex
md:hidden
flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1"
,
"sticky top-0 pt-3 pb-2 sm:pt-2 px-4 sm:px-6 sm:mb-1 bg-background bg-opacity-80 backdrop-blur-lg flex flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-1"
,
offsetTop
>
0
&&
"shadow-md"
,
offsetTop
>
0
&&
"shadow-md"
,
className
,
className
,
)
}
)
}
>
>
<
div
className=
"flex flex-row justify-start items-center mr-2 shrink-0 overflow-hidden"
>
{
!
sm
&&
<
NavigationDrawer
/>
}
</
div
>
{
!
sm
&&
<
NavigationDrawer
/>
}
<
div
className=
"flex flex-row justify-end items-center"
>
{
children
}
</
div
>
<
div
className=
"
w-full
flex flex-row justify-end items-center"
>
{
children
}
</
div
>
</
div
>
</
div
>
);
);
};
};
...
...
web/src/components/PagedMemoList/PagedMemoList.tsx
View file @
0ad75b8f
import
{
ArrowUpIcon
,
LoaderIcon
}
from
"lucide-react"
;
import
{
ArrowUpIcon
,
LoaderIcon
}
from
"lucide-react"
;
import
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
{
useCallback
,
useEffect
,
useMemo
,
useRef
,
useState
}
from
"react"
;
import
{
matchPath
}
from
"react-router-dom"
;
import
{
matchPath
}
from
"react-router-dom"
;
import
PullToRefresh
from
"react-simple-pull-to-refresh"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
userServiceClient
}
from
"@/connect"
;
import
{
userServiceClient
}
from
"@/connect"
;
import
{
useView
}
from
"@/contexts/ViewContext"
;
import
{
useView
}
from
"@/contexts/ViewContext"
;
import
{
DEFAULT_LIST_MEMOS_PAGE_SIZE
}
from
"@/helpers/consts"
;
import
{
DEFAULT_LIST_MEMOS_PAGE_SIZE
}
from
"@/helpers/consts"
;
import
{
useInfiniteMemos
}
from
"@/hooks/useMemoQueries"
;
import
{
useInfiniteMemos
}
from
"@/hooks/useMemoQueries"
;
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
import
{
State
}
from
"@/types/proto/api/v1/common_pb"
;
import
{
State
}
from
"@/types/proto/api/v1/common_pb"
;
import
type
{
Memo
}
from
"@/types/proto/api/v1/memo_service_pb"
;
import
type
{
Memo
}
from
"@/types/proto/api/v1/memo_service_pb"
;
...
@@ -82,14 +80,13 @@ function useAutoFetchWhenNotScrollable({
...
@@ -82,14 +80,13 @@ function useAutoFetchWhenNotScrollable({
const
PagedMemoList
=
(
props
:
Props
)
=>
{
const
PagedMemoList
=
(
props
:
Props
)
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
();
const
{
layout
}
=
useView
();
const
{
layout
}
=
useView
();
// Show memo editor only on the root route
// Show memo editor only on the root route
const
showMemoEditor
=
Boolean
(
matchPath
(
Routes
.
ROOT
,
window
.
location
.
pathname
));
const
showMemoEditor
=
Boolean
(
matchPath
(
Routes
.
ROOT
,
window
.
location
.
pathname
));
// Use React Query's infinite query for pagination
// Use React Query's infinite query for pagination
const
{
data
,
fetchNextPage
,
hasNextPage
,
isFetchingNextPage
,
isLoading
,
refetch
}
=
useInfiniteMemos
({
const
{
data
,
fetchNextPage
,
hasNextPage
,
isFetchingNextPage
,
isLoading
}
=
useInfiniteMemos
({
state
:
props
.
state
||
State
.
NORMAL
,
state
:
props
.
state
||
State
.
NORMAL
,
orderBy
:
props
.
orderBy
||
"display_time desc"
,
orderBy
:
props
.
orderBy
||
"display_time desc"
,
filter
:
props
.
filter
,
filter
:
props
.
filter
,
...
@@ -192,29 +189,7 @@ const PagedMemoList = (props: Props) => {
...
@@ -192,29 +189,7 @@ const PagedMemoList = (props: Props) => {
</
div
>
</
div
>
);
);
if
(
md
)
{
return
children
;
return
children
;
}
return
(
<
PullToRefresh
onRefresh=
{
async
()
=>
{
await
refetch
();
}
}
pullingContent=
{
<
div
className=
"w-full flex flex-row justify-center items-center my-4"
>
<
LoaderIcon
className=
"opacity-60"
/>
</
div
>
}
refreshingContent=
{
<
div
className=
"w-full flex flex-row justify-center items-center my-4"
>
<
LoaderIcon
className=
"animate-spin"
/>
</
div
>
}
>
{
children
}
</
PullToRefresh
>
);
};
};
const
BackToTop
=
()
=>
{
const
BackToTop
=
()
=>
{
...
...
web/src/hooks/index.ts
View file @
0ad75b8f
...
@@ -3,9 +3,9 @@ export * from "./useCurrentUser";
...
@@ -3,9 +3,9 @@ export * from "./useCurrentUser";
export
*
from
"./useDateFilterNavigation"
;
export
*
from
"./useDateFilterNavigation"
;
export
*
from
"./useFilteredMemoStats"
;
export
*
from
"./useFilteredMemoStats"
;
export
*
from
"./useLoading"
;
export
*
from
"./useLoading"
;
export
*
from
"./useMediaQuery"
;
export
*
from
"./useMemoFilters"
;
export
*
from
"./useMemoFilters"
;
export
*
from
"./useMemoSorting"
;
export
*
from
"./useMemoSorting"
;
export
*
from
"./useNavigateTo"
;
export
*
from
"./useNavigateTo"
;
export
*
from
"./useResponsiveWidth"
;
export
*
from
"./useUserLocale"
;
export
*
from
"./useUserLocale"
;
export
*
from
"./useUserTheme"
;
export
*
from
"./useUserTheme"
;
web/src/hooks/useMediaQuery.ts
0 → 100644
View file @
0ad75b8f
import
{
useEffect
,
useState
}
from
"react"
;
type
Breakpoint
=
"sm"
|
"md"
|
"lg"
;
const
BREAKPOINTS
:
Record
<
Breakpoint
,
number
>
=
{
sm
:
640
,
md
:
768
,
lg
:
1024
,
};
const
useMediaQuery
=
(
breakpoint
:
Breakpoint
):
boolean
=>
{
const
[
matches
,
setMatches
]
=
useState
(()
=>
{
if
(
typeof
window
===
"undefined"
)
return
false
;
return
window
.
matchMedia
(
`(min-width:
${
BREAKPOINTS
[
breakpoint
]}
px)`
).
matches
;
});
useEffect
(()
=>
{
const
mediaQuery
=
window
.
matchMedia
(
`(min-width:
${
BREAKPOINTS
[
breakpoint
]}
px)`
);
const
handleChange
=
(
e
:
MediaQueryListEvent
)
=>
{
setMatches
(
e
.
matches
);
};
mediaQuery
.
addEventListener
(
"change"
,
handleChange
);
return
()
=>
{
mediaQuery
.
removeEventListener
(
"change"
,
handleChange
);
};
},
[
breakpoint
]);
return
matches
;
};
export
default
useMediaQuery
;
web/src/hooks/useResponsiveWidth.ts
deleted
100644 → 0
View file @
d21610cc
import
useWindowSize
from
"react-use/lib/useWindowSize"
;
enum
TailwindResponsiveWidth
{
sm
=
640
,
md
=
768
,
lg
=
1024
,
}
const
useResponsiveWidth
=
()
=>
{
const
{
width
}
=
useWindowSize
();
return
{
sm
:
width
>=
TailwindResponsiveWidth
.
sm
,
md
:
width
>=
TailwindResponsiveWidth
.
md
,
lg
:
width
>=
TailwindResponsiveWidth
.
lg
,
};
};
export
default
useResponsiveWidth
;
web/src/layouts/MainLayout.tsx
View file @
0ad75b8f
...
@@ -6,12 +6,13 @@ import MobileHeader from "@/components/MobileHeader";
...
@@ -6,12 +6,13 @@ import MobileHeader from "@/components/MobileHeader";
import
{
userServiceClient
}
from
"@/connect"
;
import
{
userServiceClient
}
from
"@/connect"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
{
useFilteredMemoStats
}
from
"@/hooks/useFilteredMemoStats"
;
import
{
useFilteredMemoStats
}
from
"@/hooks/useFilteredMemoStats"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
const
MainLayout
=
()
=>
{
const
MainLayout
=
()
=>
{
const
{
md
,
lg
}
=
useResponsiveWidth
();
const
md
=
useMediaQuery
(
"md"
);
const
lg
=
useMediaQuery
(
"lg"
);
const
location
=
useLocation
();
const
location
=
useLocation
();
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
[
profileUserName
,
setProfileUserName
]
=
useState
<
string
|
undefined
>
();
const
[
profileUserName
,
setProfileUserName
]
=
useState
<
string
|
undefined
>
();
...
...
web/src/layouts/RootLayout.tsx
View file @
0ad75b8f
...
@@ -5,7 +5,7 @@ import Navigation from "@/components/Navigation";
...
@@ -5,7 +5,7 @@ import Navigation from "@/components/Navigation";
import
{
useInstance
}
from
"@/contexts/InstanceContext"
;
import
{
useInstance
}
from
"@/contexts/InstanceContext"
;
import
{
useMemoFilterContext
}
from
"@/contexts/MemoFilterContext"
;
import
{
useMemoFilterContext
}
from
"@/contexts/MemoFilterContext"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
cn
}
from
"@/lib/utils"
;
import
Loading
from
"@/pages/Loading"
;
import
Loading
from
"@/pages/Loading"
;
import
{
Routes
}
from
"@/router"
;
import
{
Routes
}
from
"@/router"
;
...
@@ -13,7 +13,7 @@ import { Routes } from "@/router";
...
@@ -13,7 +13,7 @@ import { Routes } from "@/router";
const
RootLayout
=
()
=>
{
const
RootLayout
=
()
=>
{
const
location
=
useLocation
();
const
location
=
useLocation
();
const
[
searchParams
]
=
useSearchParams
();
const
[
searchParams
]
=
useSearchParams
();
const
{
sm
}
=
useResponsiveWidth
(
);
const
sm
=
useMediaQuery
(
"sm"
);
const
currentUser
=
useCurrentUser
();
const
currentUser
=
useCurrentUser
();
const
{
memoRelatedSetting
}
=
useInstance
();
const
{
memoRelatedSetting
}
=
useInstance
();
const
{
removeFilter
}
=
useMemoFilterContext
();
const
{
removeFilter
}
=
useMemoFilterContext
();
...
...
web/src/pages/Attachments.tsx
View file @
0ad75b8f
...
@@ -15,7 +15,7 @@ import { attachmentServiceClient } from "@/connect";
...
@@ -15,7 +15,7 @@ import { attachmentServiceClient } from "@/connect";
import
{
useDeleteAttachment
}
from
"@/hooks/useAttachmentQueries"
;
import
{
useDeleteAttachment
}
from
"@/hooks/useAttachmentQueries"
;
import
useDialog
from
"@/hooks/useDialog"
;
import
useDialog
from
"@/hooks/useDialog"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
useLoading
from
"@/hooks/useLoading"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
i18n
from
"@/i18n"
;
import
i18n
from
"@/i18n"
;
import
type
{
Attachment
}
from
"@/types/proto/api/v1/attachment_service_pb"
;
import
type
{
Attachment
}
from
"@/types/proto/api/v1/attachment_service_pb"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
@@ -69,7 +69,7 @@ const AttachmentItem = ({ attachment }: AttachmentItemProps) => (
...
@@ -69,7 +69,7 @@ const AttachmentItem = ({ attachment }: AttachmentItemProps) => (
const
Attachments
=
()
=>
{
const
Attachments
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
(
);
const
md
=
useMediaQuery
(
"md"
);
const
loadingState
=
useLoading
();
const
loadingState
=
useLoading
();
const
deleteUnusedAttachmentsDialog
=
useDialog
();
const
deleteUnusedAttachmentsDialog
=
useDialog
();
const
{
mutateAsync
:
deleteAttachment
}
=
useDeleteAttachment
();
const
{
mutateAsync
:
deleteAttachment
}
=
useDeleteAttachment
();
...
...
web/src/pages/Inboxes.tsx
View file @
0ad75b8f
...
@@ -5,7 +5,7 @@ import { useState } from "react";
...
@@ -5,7 +5,7 @@ import { useState } from "react";
import
Empty
from
"@/components/Empty"
;
import
Empty
from
"@/components/Empty"
;
import
MemoCommentMessage
from
"@/components/Inbox/MemoCommentMessage"
;
import
MemoCommentMessage
from
"@/components/Inbox/MemoCommentMessage"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
import
MobileHeader
from
"@/components/MobileHeader"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
{
useNotifications
}
from
"@/hooks/useUserQueries"
;
import
{
useNotifications
}
from
"@/hooks/useUserQueries"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
UserNotification
,
UserNotification_Status
,
UserNotification_Type
}
from
"@/types/proto/api/v1/user_service_pb"
;
import
{
UserNotification
,
UserNotification_Status
,
UserNotification_Type
}
from
"@/types/proto/api/v1/user_service_pb"
;
...
@@ -13,7 +13,7 @@ import { useTranslate } from "@/utils/i18n";
...
@@ -13,7 +13,7 @@ import { useTranslate } from "@/utils/i18n";
const
Inboxes
=
()
=>
{
const
Inboxes
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
(
);
const
md
=
useMediaQuery
(
"md"
);
const
[
filter
,
setFilter
]
=
useState
<
"all"
|
"unread"
|
"archived"
>
(
"all"
);
const
[
filter
,
setFilter
]
=
useState
<
"all"
|
"unread"
|
"archived"
>
(
"all"
);
// Fetch notifications with React Query
// Fetch notifications with React Query
...
...
web/src/pages/MemoDetail.tsx
View file @
0ad75b8f
...
@@ -10,15 +10,15 @@ import MobileHeader from "@/components/MobileHeader";
...
@@ -10,15 +10,15 @@ import MobileHeader from "@/components/MobileHeader";
import
{
Button
}
from
"@/components/ui/button"
;
import
{
Button
}
from
"@/components/ui/button"
;
import
{
memoNamePrefix
}
from
"@/helpers/resource-names"
;
import
{
memoNamePrefix
}
from
"@/helpers/resource-names"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useMediaQuery
from
"@/hooks/useMediaQuery"
;
import
{
useMemo
,
useMemoComments
}
from
"@/hooks/useMemoQueries"
;
import
{
useMemo
,
useMemoComments
}
from
"@/hooks/useMemoQueries"
;
import
useNavigateTo
from
"@/hooks/useNavigateTo"
;
import
useNavigateTo
from
"@/hooks/useNavigateTo"
;
import
useResponsiveWidth
from
"@/hooks/useResponsiveWidth"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
cn
}
from
"@/lib/utils"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
const
MemoDetail
=
()
=>
{
const
MemoDetail
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
(
);
const
md
=
useMediaQuery
(
"md"
);
const
params
=
useParams
();
const
params
=
useParams
();
const
navigateTo
=
useNavigateTo
();
const
navigateTo
=
useNavigateTo
();
const
{
state
:
locationState
}
=
useLocation
();
const
{
state
:
locationState
}
=
useLocation
();
...
@@ -70,7 +70,7 @@ const MemoDetail = () => {
...
@@ -70,7 +70,7 @@ const MemoDetail = () => {
</
MobileHeader
>
</
MobileHeader
>
)
}
)
}
<
div
className=
{
cn
(
"w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4"
)
}
>
<
div
className=
{
cn
(
"w-full flex flex-row justify-start items-start px-4 sm:px-6 gap-4"
)
}
>
<
div
className=
{
cn
(
md
?
"w-[calc(100%-15rem)]"
:
"w-full
"
)
}
>
<
div
className=
{
cn
(
"w-full md:w-[calc(100%-15rem)]
"
)
}
>
{
parentMemo
&&
(
{
parentMemo
&&
(
<
div
className=
"w-auto inline-block mb-2"
>
<
div
className=
"w-auto inline-block mb-2"
>
<
Link
<
Link
...
...
web/src/pages/Setting.tsx
View file @
0ad75b8f
...
@@ -13,7 +13,7 @@ import StorageSection from "@/components/Settings/StorageSection";
...
@@ -13,7 +13,7 @@ import StorageSection from "@/components/Settings/StorageSection";
import
{
Select
,
SelectContent
,
SelectItem
,
SelectTrigger
,
SelectValue
}
from
"@/components/ui/select"
;
import
{
Select
,
SelectContent
,
SelectItem
,
SelectTrigger
,
SelectValue
}
from
"@/components/ui/select"
;
import
{
useInstance
}
from
"@/contexts/InstanceContext"
;
import
{
useInstance
}
from
"@/contexts/InstanceContext"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
useCurrentUser
from
"@/hooks/useCurrentUser"
;
import
use
ResponsiveWidth
from
"@/hooks/useResponsiveWidth
"
;
import
use
MediaQuery
from
"@/hooks/useMediaQuery
"
;
import
{
InstanceSetting_Key
}
from
"@/types/proto/api/v1/instance_service_pb"
;
import
{
InstanceSetting_Key
}
from
"@/types/proto/api/v1/instance_service_pb"
;
import
{
User_Role
}
from
"@/types/proto/api/v1/user_service_pb"
;
import
{
User_Role
}
from
"@/types/proto/api/v1/user_service_pb"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
import
{
useTranslate
}
from
"@/utils/i18n"
;
...
@@ -38,7 +38,7 @@ const SECTION_ICON_MAP: Record<SettingSection, LucideIcon> = {
...
@@ -38,7 +38,7 @@ const SECTION_ICON_MAP: Record<SettingSection, LucideIcon> = {
const
Setting
=
()
=>
{
const
Setting
=
()
=>
{
const
t
=
useTranslate
();
const
t
=
useTranslate
();
const
{
md
}
=
useResponsiveWidth
(
);
const
sm
=
useMediaQuery
(
"sm"
);
const
location
=
useLocation
();
const
location
=
useLocation
();
const
user
=
useCurrentUser
();
const
user
=
useCurrentUser
();
const
{
profile
,
fetchSetting
}
=
useInstance
();
const
{
profile
,
fetchSetting
}
=
useInstance
();
...
@@ -85,57 +85,61 @@ const Setting = () => {
...
@@ -85,57 +85,61 @@ const Setting = () => {
return
(
return
(
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-start sm:pt-3 md:pt-6 pb-8"
>
<
section
className=
"@container w-full max-w-5xl min-h-full flex flex-col justify-start items-start sm:pt-3 md:pt-6 pb-8"
>
{
!
md
&&
<
MobileHeader
/>
}
{
!
sm
&&
<
MobileHeader
/>
}
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full px-4 sm:px-6"
>
<
div
className=
"w-full border border-border flex flex-row justify-start items-start px-4 py-3 rounded-xl bg-background text-muted-foreground"
>
<
div
className=
"w-full border border-border flex flex-row justify-start items-start px-4 py-3 rounded-xl bg-background text-muted-foreground"
>
<
div
className=
"hidden sm:flex flex-col justify-start items-start w-40 h-auto shrink-0 py-2"
>
{
sm
&&
(
<
span
className=
"text-sm mt-0.5 pl-3 font-mono select-none text-muted-foreground"
>
{
t
(
"common.basic"
)
}
</
span
>
<
div
className=
"flex flex-col justify-start items-start w-40 h-auto shrink-0 py-2"
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
<
span
className=
"text-sm mt-0.5 pl-3 font-mono select-none text-muted-foreground"
>
{
t
(
"common.basic"
)
}
</
span
>
{
BASIC_SECTIONS
.
map
((
item
)
=>
(
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
<
SectionMenuItem
{
BASIC_SECTIONS
.
map
((
item
)
=>
(
key=
{
item
}
<
SectionMenuItem
text=
{
t
(
`setting.${item}`
)
}
key=
{
item
}
icon=
{
SECTION_ICON_MAP
[
item
]
}
text=
{
t
(
`setting.${item}`
)
}
isSelected=
{
state
.
selectedSection
===
item
}
icon=
{
SECTION_ICON_MAP
[
item
]
}
onClick=
{
()
=>
handleSectionSelectorItemClick
(
item
)
}
isSelected=
{
state
.
selectedSection
===
item
}
/>
onClick=
{
()
=>
handleSectionSelectorItemClick
(
item
)
}
))
}
/>
))
}
</
div
>
{
isHost
?
(
<>
<
span
className=
"text-sm mt-4 pl-3 font-mono select-none text-muted-foreground"
>
{
t
(
"common.admin"
)
}
</
span
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
{
ADMIN_SECTIONS
.
map
((
item
)
=>
(
<
SectionMenuItem
key=
{
item
}
text=
{
t
(
`setting.${item}`
)
}
icon=
{
SECTION_ICON_MAP
[
item
]
}
isSelected=
{
state
.
selectedSection
===
item
}
onClick=
{
()
=>
handleSectionSelectorItemClick
(
item
)
}
/>
))
}
<
span
className=
"px-3 mt-2 opacity-70 text-sm"
>
{
t
(
"setting.version"
)
}
: v
{
profile
.
version
}
</
span
>
</
div
>
</>
)
:
null
}
</
div
>
</
div
>
{
isHost
?
(
)
}
<>
<
span
className=
"text-sm mt-4 pl-3 font-mono select-none text-muted-foreground"
>
{
t
(
"common.admin"
)
}
</
span
>
<
div
className=
"w-full flex flex-col justify-start items-start mt-1"
>
{
ADMIN_SECTIONS
.
map
((
item
)
=>
(
<
SectionMenuItem
key=
{
item
}
text=
{
t
(
`setting.${item}`
)
}
icon=
{
SECTION_ICON_MAP
[
item
]
}
isSelected=
{
state
.
selectedSection
===
item
}
onClick=
{
()
=>
handleSectionSelectorItemClick
(
item
)
}
/>
))
}
<
span
className=
"px-3 mt-2 opacity-70 text-sm"
>
{
t
(
"setting.version"
)
}
: v
{
profile
.
version
}
</
span
>
</
div
>
</>
)
:
null
}
</
div
>
<
div
className=
"w-full grow sm:pl-4 overflow-x-auto"
>
<
div
className=
"w-full grow sm:pl-4 overflow-x-auto"
>
<
div
className=
"w-auto inline-block my-2 sm:hidden"
>
{
!
sm
&&
(
<
Select
value=
{
state
.
selectedSection
}
onValueChange=
{
(
value
)
=>
handleSectionSelectorItemClick
(
value
as
SettingSection
)
}
>
<
div
className=
"w-auto inline-block my-2"
>
<
SelectTrigger
className=
"w-[180px]"
>
<
Select
value=
{
state
.
selectedSection
}
onValueChange=
{
(
value
)
=>
handleSectionSelectorItemClick
(
value
as
SettingSection
)
}
>
<
SelectValue
placeholder=
"Select section"
/>
<
SelectTrigger
className=
"w-[180px]"
>
</
SelectTrigger
>
<
SelectValue
placeholder=
"Select section"
/>
<
SelectContent
>
</
SelectTrigger
>
{
settingsSectionList
.
map
((
settingSection
)
=>
(
<
SelectContent
>
<
SelectItem
key=
{
settingSection
}
value=
{
settingSection
}
>
{
settingsSectionList
.
map
((
settingSection
)
=>
(
{
t
(
`setting.${settingSection}`
)
}
<
SelectItem
key=
{
settingSection
}
value=
{
settingSection
}
>
</
SelectItem
>
{
t
(
`setting.${settingSection}`
)
}
))
}
</
SelectItem
>
</
SelectContent
>
))
}
</
Select
>
</
SelectContent
>
</
div
>
</
Select
>
</
div
>
)
}
{
state
.
selectedSection
===
"my-account"
?
(
{
state
.
selectedSection
===
"my-account"
?
(
<
MyAccountSection
/>
<
MyAccountSection
/>
)
:
state
.
selectedSection
===
"preference"
?
(
)
:
state
.
selectedSection
===
"preference"
?
(
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment