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
6ab58f29
Unverified
Commit
6ab58f29
authored
Mar 04, 2023
by
boojack
Committed by
GitHub
Mar 04, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: update home layout (#1242)
parent
9d4bb5b3
Changes
24
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
24 changed files
with
602 additions
and
558 deletions
+602
-558
DailyReviewDialog.tsx
web/src/components/DailyReviewDialog.tsx
+1
-1
Header.tsx
web/src/components/Header.tsx
+92
-0
HomeSidebar.tsx
web/src/components/HomeSidebar.tsx
+48
-0
Memo.tsx
web/src/components/Memo.tsx
+25
-3
MobileHeader.tsx
web/src/components/MobileHeader.tsx
+62
-0
ResourcesDialog.tsx
web/src/components/ResourcesDialog.tsx
+1
-1
ResourcesSelectorDialog.tsx
web/src/components/ResourcesSelectorDialog.tsx
+1
-1
SearchBar.tsx
web/src/components/SearchBar.tsx
+1
-1
SystemSection.tsx
web/src/components/Settings/SystemSection.tsx
+1
-1
TagList.tsx
web/src/components/TagList.tsx
+0
-1
UserBanner.tsx
web/src/components/UserBanner.tsx
+41
-88
tailwind.css
web/src/css/tailwind.css
+0
-5
auth.less
web/src/less/auth.less
+1
-1
explore.less
web/src/less/explore.less
+0
-53
header.less
web/src/less/header.less
+2
-2
home-sidebar.less
web/src/less/home-sidebar.less
+15
-0
home.less
web/src/less/home.less
+4
-16
memo-detail.less
web/src/less/memo-detail.less
+2
-2
memos-header.less
web/src/less/memos-header.less
+0
-23
search-bar.less
web/src/less/search-bar.less
+1
-1
en.json
web/src/locales/en.json
+6
-10
zh.json
web/src/locales/zh.json
+256
-260
Explore.tsx
web/src/pages/Explore.tsx
+36
-71
Home.tsx
web/src/pages/Home.tsx
+6
-17
No files found.
web/src/components/DailyReviewDialog.tsx
View file @
6ab58f29
...
...
@@ -63,7 +63,7 @@ const DailyReviewDialog: React.FC<Props> = (props: Props) => {
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
onClick=
{
()
=>
toggleShowDatePicker
()
}
>
<
span
className=
"icon-text"
>
📅
</
span
>
{
t
(
"
sidebar
.daily-review"
)
}
<
span
className=
"icon-text"
>
📅
</
span
>
{
t
(
"
common
.daily-review"
)
}
</
p
>
<
div
className=
"btns-container"
>
<
button
className=
"btn-text"
onClick=
{
()
=>
setCurrentDateStamp
(
currentDateStamp
-
DAILY_TIMESTAMP
)
}
>
...
...
web/src/components/
Sideba
r.tsx
→
web/src/components/
Heade
r.tsx
View file @
6ab58f29
...
...
@@ -3,91 +3,90 @@ import { useEffect } from "react";
import
{
Link
}
from
"react-router-dom"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useLocationStore
,
useUserStore
}
from
"../store/module"
;
import
Icon
from
"./Icon"
;
import
showDailyReviewDialog
from
"./DailyReviewDialog"
;
import
showResourcesDialog
from
"./ResourcesDialog"
;
import
showSettingDialog
from
"./SettingDialog"
;
import
UserBanner
from
"./UserBanner"
;
import
UsageHeatMap
from
"./UsageHeatMap"
;
import
ShortcutList
from
"./ShortcutList"
;
import
TagList
from
"./TagList"
;
import
"../less/siderbar.less"
;
import
"../less/header.less"
;
const
Sideba
r
=
()
=>
{
const
Heade
r
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
userStore
=
useUserStore
();
const
locationStore
=
useLocationStore
();
const
query
=
locationStore
.
state
.
query
;
useEffect
(()
=>
{
toggle
Sideba
r
(
false
);
toggle
Heade
r
(
false
);
},
[
query
]);
const
handleSettingBtnClick
=
()
=>
{
showSettingDialog
();
};
return
(
<>
<
div
className=
"mask"
onClick=
{
()
=>
toggle
Sideba
r
(
false
)
}
></
div
>
<
aside
className=
"sideba
r-wrapper"
>
<
div
className=
"mask"
onClick=
{
()
=>
toggle
Heade
r
(
false
)
}
></
div
>
<
header
className=
"heade
r-wrapper"
>
<
UserBanner
/>
<
UsageHeatMap
/>
<
div
className=
"w-full px-2 my-2 flex flex-col justify-start items-start shrink-0"
>
<
div
className=
"w-full px-2 my-2 mt-4 flex flex-col justify-start items-start shrink-0 space-y-2"
>
<
Link
to=
"/"
className=
"px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
>
<
Icon
.
Home
className=
"mr-4 w-6 h-auto opacity-80"
/>
{
t
(
"common.home"
)
}
</
Link
>
<
button
className=
"
leading-10 px-4 rounded-lg text-base
dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
className=
"
px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg
dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
()
=>
showDailyReviewDialog
()
}
>
<
span
className=
"mr-1"
>
📅
</
span
>
{
t
(
"sidebar
.daily-review"
)
}
<
Icon
.
Calendar
className=
"mr-4 w-6 h-auto opacity-80"
/>
{
t
(
"common
.daily-review"
)
}
</
button
>
<
Link
to=
"/explore"
className=
"
leading-10 px-4 rounded-lg text-base
dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
className=
"
px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg
dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
>
<
span
className=
"mr-1"
>
🏂
</
span
>
{
t
(
"common.explore"
)
}
<
Icon
.
Hash
className=
"mr-4 w-6 h-auto opacity-80"
/
>
{
t
(
"common.explore"
)
}
</
Link
>
<
button
className=
"leading-10 px-4 rounded-lg text-base dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
()
=>
showResourcesDialog
()
}
>
<
span
className=
"mr-1"
>
🗂️
</
span
>
{
t
(
"sidebar.resources"
)
}
</
button
>
{
!
userStore
.
isVisitorMode
()
&&
(
<>
<
button
className=
"leading-10 px-4 rounded-lg text-base dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
handleSettingBtnClick
}
className=
"px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
()
=>
showResourcesDialog
()
}
>
<
Icon
.
Paperclip
className=
"mr-4 w-6 h-auto opacity-80"
/>
{
t
(
"common.resources"
)
}
</
button
>
<
button
className=
"px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
()
=>
showDailyReviewDialog
()
}
>
<
Icon
.
Archive
className=
"mr-4 w-6 h-auto opacity-80"
/>
{
t
(
"common.archive"
)
}
</
button
>
<
button
className=
"px-4 pr-5 py-2 rounded-lg flex flex-row items-center text-lg dark:text-gray-200 hover:bg-white hover:shadow dark:hover:bg-zinc-700"
onClick=
{
()
=>
showSettingDialog
()
}
>
<
span
className=
"mr-1"
>
⚙️
</
span
>
{
t
(
"sidebar.setting
"
)
}
<
Icon
.
Settings
className=
"mr-4 w-6 h-auto opacity-80"
/>
{
t
(
"common.settings
"
)
}
</
button
>
</>
)
}
</
div
>
{
!
userStore
.
isVisitorMode
()
&&
(
<>
<
ShortcutList
/>
<
TagList
/>
</>
)
}
</
aside
>
</
header
>
</>
);
};
export
const
toggle
Sideba
r
=
(
show
?:
boolean
)
=>
{
const
sidebarEl
=
document
.
body
.
querySelector
(
".sideba
r-wrapper"
)
as
HTMLDivElement
;
const
maskEl
=
document
.
body
.
querySelector
(
".mask"
)
as
HTMLDivElement
;
export
const
toggle
Heade
r
=
(
show
?:
boolean
)
=>
{
const
headerEl
=
document
.
body
.
querySelector
(
".heade
r-wrapper"
)
as
HTMLDivElement
;
const
maskEl
=
headerEl
.
previousSibling
as
HTMLDivElement
;
if
(
isUndefined
(
show
))
{
show
=
!
sideba
rEl
.
classList
.
contains
(
"show"
);
show
=
!
heade
rEl
.
classList
.
contains
(
"show"
);
}
if
(
show
)
{
sideba
rEl
.
classList
.
add
(
"show"
);
heade
rEl
.
classList
.
add
(
"show"
);
maskEl
.
classList
.
add
(
"show"
);
}
else
{
sideba
rEl
.
classList
.
remove
(
"show"
);
heade
rEl
.
classList
.
remove
(
"show"
);
maskEl
.
classList
.
remove
(
"show"
);
}
};
export
default
Sideba
r
;
export
default
Heade
r
;
web/src/components/HomeSidebar.tsx
0 → 100644
View file @
6ab58f29
import
{
isUndefined
}
from
"lodash-es"
;
import
{
useEffect
}
from
"react"
;
import
{
useLocationStore
}
from
"../store/module"
;
import
ShortcutList
from
"./ShortcutList"
;
import
TagList
from
"./TagList"
;
import
SearchBar
from
"./SearchBar"
;
import
"../less/home-sidebar.less"
;
const
HomeSidebar
=
()
=>
{
const
locationStore
=
useLocationStore
();
const
query
=
locationStore
.
state
.
query
;
useEffect
(()
=>
{
toggleHomeSidebar
(
false
);
},
[
query
]);
return
(
<>
<
div
className=
"mask"
onClick=
{
()
=>
toggleHomeSidebar
(
false
)
}
></
div
>
<
aside
className=
"sidebar-wrapper"
>
<
div
className=
"pl-6 pr-2 mb-4 w-full"
>
<
SearchBar
/>
</
div
>
<
ShortcutList
/>
<
TagList
/>
</
aside
>
</>
);
};
export
const
toggleHomeSidebar
=
(
show
?:
boolean
)
=>
{
const
sidebarEl
=
document
.
body
.
querySelector
(
".sidebar-wrapper"
)
as
HTMLDivElement
;
const
maskEl
=
sidebarEl
.
previousSibling
as
HTMLDivElement
;
if
(
isUndefined
(
show
))
{
show
=
!
sidebarEl
.
classList
.
contains
(
"show"
);
}
if
(
show
)
{
sidebarEl
.
classList
.
add
(
"show"
);
maskEl
.
classList
.
add
(
"show"
);
}
else
{
sidebarEl
.
classList
.
remove
(
"show"
);
maskEl
.
classList
.
remove
(
"show"
);
}
};
export
default
HomeSidebar
;
web/src/components/Memo.tsx
View file @
6ab58f29
...
...
@@ -17,6 +17,7 @@ import "../less/memo.less";
interface
Props
{
memo
:
Memo
;
readonly
?:
boolean
;
}
export
const
getFormatedMemoTimeStr
=
(
time
:
number
,
locale
=
"en"
):
string
=>
{
...
...
@@ -28,7 +29,7 @@ export const getFormatedMemoTimeStr = (time: number, locale = "en"): string => {
};
const
Memo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memo
}
=
props
;
const
{
memo
,
readonly
}
=
props
;
const
{
t
,
i18n
}
=
useTranslation
();
const
navigate
=
useNavigate
();
const
editorStore
=
useEditorStore
();
...
...
@@ -37,7 +38,7 @@ const Memo: React.FC<Props> = (props: Props) => {
const
memoStore
=
useMemoStore
();
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getFormatedMemoTimeStr
(
memo
.
createdTs
,
i18n
.
language
));
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
isVisitorMode
=
userStore
.
isVisitorMode
();
const
isVisitorMode
=
userStore
.
isVisitorMode
()
||
readonly
;
const
updatedTimeStr
=
getFormatedMemoTimeStr
(
memo
.
updatedTs
,
i18n
.
language
);
useEffect
(()
=>
{
...
...
@@ -67,6 +68,10 @@ const Memo: React.FC<Props> = (props: Props) => {
};
const
handleTogglePinMemoBtnClick
=
async
()
=>
{
if
(
isVisitorMode
)
{
return
;
}
try
{
if
(
memo
.
pinned
)
{
await
memoStore
.
unpinMemo
(
memo
.
id
);
...
...
@@ -79,10 +84,18 @@ const Memo: React.FC<Props> = (props: Props) => {
};
const
handleEditMemoClick
=
()
=>
{
if
(
isVisitorMode
)
{
return
;
}
editorStore
.
setEditMemoWithId
(
memo
.
id
);
};
const
handleArchiveMemoClick
=
async
()
=>
{
if
(
isVisitorMode
)
{
return
;
}
try
{
await
memoStore
.
patchMemo
({
id
:
memo
.
id
,
...
...
@@ -114,7 +127,7 @@ const Memo: React.FC<Props> = (props: Props) => {
locationStore
.
setTagQuery
(
tagName
);
}
}
else
if
(
targetEl
.
classList
.
contains
(
"todo-block"
))
{
if
(
userStore
.
isVisitorMode
()
)
{
if
(
isVisitorMode
)
{
return
;
}
...
...
@@ -153,6 +166,10 @@ const Memo: React.FC<Props> = (props: Props) => {
};
const
handleMemoContentDoubleClick
=
(
e
:
React
.
MouseEvent
)
=>
{
if
(
isVisitorMode
)
{
return
;
}
const
loginUser
=
userStore
.
state
.
user
;
if
(
loginUser
&&
!
loginUser
.
localSetting
.
enableDoubleClickEditing
)
{
return
;
...
...
@@ -191,6 +208,11 @@ const Memo: React.FC<Props> = (props: Props) => {
{
createdTimeStr
}
</
span
>
</
Tooltip
>
{
isVisitorMode
&&
(
<
a
className=
"ml-2 opacity-60 text-sm"
href=
{
`/u/${memo.creatorId}`
}
>
@
{
memo
.
creatorName
}
</
a
>
)
}
{
memo
.
visibility
!==
"PRIVATE"
&&
!
isVisitorMode
&&
(
<
span
className=
{
`status-text ${memo.visibility.toLocaleLowerCase()}`
}
...
...
web/src/components/M
emos
Header.tsx
→
web/src/components/M
obile
Header.tsx
View file @
6ab58f29
import
{
useCallback
,
useEffect
,
useState
}
from
"react"
;
import
{
useLocationStore
,
useMemoStore
,
useShortcutStore
,
useUserStore
}
from
"../store/module"
;
import
{
useLocationStore
,
useMemoStore
,
useShortcutStore
}
from
"../store/module"
;
import
Icon
from
"./Icon"
;
import
SearchBar
from
"./SearchBar"
;
import
{
toggleSidebar
}
from
"./Sidebar"
;
import
"../less/memos-header.less"
;
import
{
toggleHeader
}
from
"./Header"
;
import
{
toggleHomeSidebar
}
from
"./HomeSidebar"
;
let
prevRequestTimestamp
=
Date
.
now
();
const
M
emos
Header
=
()
=>
{
const
M
obile
Header
=
()
=>
{
const
locationStore
=
useLocationStore
();
const
memoStore
=
useMemoStore
();
const
shortcutStore
=
useShortcutStore
();
const
userStore
=
useUserStore
();
const
user
=
userStore
.
state
.
user
;
const
query
=
locationStore
.
state
.
query
;
const
shortcuts
=
shortcutStore
.
state
.
shortcuts
;
const
[
titleText
,
setTitleText
]
=
useState
(
"MEMOS"
);
...
...
@@ -40,23 +37,26 @@ const MemosHeader = () => {
},
[]);
return
(
<
div
className=
"memos-header-container"
>
<
div
className=
"title-container"
>
<
div
className=
"action-btn"
onClick=
{
()
=>
toggleSidebar
(
true
)
}
>
<
Icon
.
Menu
className=
"icon-img"
/>
<
div
className=
"sticky top-0 pt-4 pb-1 mb-1 backdrop-blur-sm flex sm:hidden flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-10"
>
<
div
className=
"flex flex-row justify-start items-center mr-2 shrink-0 overflow-hidden"
>
<
div
className=
"flex sm:hidden flex-row justify-center items-center w-6 h-6 mr-1 shrink-0 bg-transparent"
onClick=
{
()
=>
toggleHeader
(
true
)
}
>
<
Icon
.
Menu
className=
"w-5 h-auto dark:text-gray-200"
/>
</
div
>
<
span
className=
"title-text"
onClick=
{
handleTitleTextClick
}
>
<
span
className=
"font-bold text-lg leading-10 mr-1 text-ellipsis shrink-0 cursor-pointer overflow-hidden text-gray-700 dark:text-gray-200"
onClick=
{
handleTitleTextClick
}
>
{
titleText
}
</
span
>
{
user
&&
(
<
a
className=
"dark:text-white"
href=
{
"/u/"
+
user
.
id
+
"/rss.xml"
}
target=
"_blank"
rel=
"noreferrer"
>
<
Icon
.
Rss
className=
"w-4 h-auto opacity-40 hover:opacity-60"
/>
</
a
>
)
}
</
div
>
<
SearchBar
/>
<
div
className=
"flex flex-row justify-end items-center pr-1"
>
<
Icon
.
Search
className=
"w-5 h-auto dark:text-gray-200"
onClick=
{
()
=>
toggleHomeSidebar
(
true
)
}
/>
</
div
>
</
div
>
);
};
export
default
M
emos
Header
;
export
default
M
obile
Header
;
web/src/components/ResourcesDialog.tsx
View file @
6ab58f29
...
...
@@ -104,7 +104,7 @@ const ResourcesDialog: React.FC<Props> = (props: Props) => {
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
{
t
(
"
sidebar
.resources"
)
}
</
p
>
<
p
className=
"title-text"
>
{
t
(
"
common
.resources"
)
}
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
Icon
.
X
className=
"icon-img"
/>
</
button
>
...
...
web/src/components/ResourcesSelectorDialog.tsx
View file @
6ab58f29
...
...
@@ -79,7 +79,7 @@ const ResourcesSelectorDialog: React.FC<Props> = (props: Props) => {
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
{
t
(
"
sidebar
.resources"
)
}
</
p
>
<
p
className=
"title-text"
>
{
t
(
"
common
.resources"
)
}
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
Icon
.
X
className=
"icon-img"
/>
</
button
>
...
...
web/src/components/SearchBar.tsx
View file @
6ab58f29
...
...
@@ -86,7 +86,7 @@ const SearchBar = () => {
onBlur=
{
handleBlur
}
/>
</
div
>
<
div
className=
"quickly-action-wrapper"
>
<
div
className=
"quickly-action-wrapper
!hidden
"
>
<
div
className=
"quickly-action-container"
>
<
p
className=
"title-text"
>
{
t
(
"search.quickly-filter"
).
toUpperCase
()
}
</
p
>
<
div
className=
"section-container types-container"
>
...
...
web/src/components/Settings/SystemSection.tsx
View file @
6ab58f29
...
...
@@ -148,7 +148,7 @@ const SystemSection = () => {
</
span
>
<
Button
onClick=
{
handleVacuumBtnClick
}
>
{
t
(
"common.vacuum"
)
}
</
Button
>
</
div
>
<
p
className=
"title-text"
>
{
t
(
"
sidebar.setting
"
)
}
</
p
>
<
p
className=
"title-text"
>
{
t
(
"
common.settings
"
)
}
</
p
>
<
div
className=
"form-label"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.system-section.allow-user-signup"
)
}
</
span
>
<
Switch
checked=
{
state
.
allowSignUp
}
onChange=
{
(
event
)
=>
handleAllowSignUpChanged
(
event
.
target
.
checked
)
}
/>
...
...
web/src/components/TagList.tsx
View file @
6ab58f29
...
...
@@ -83,7 +83,6 @@ const TagList = () => {
{
tags
.
map
((
t
,
idx
)
=>
(
<
TagItemContainer
key=
{
t
.
text
+
"-"
+
idx
}
tag=
{
t
}
tagQuery=
{
query
?.
tag
}
/>
))
}
{
tags
.
length
<=
3
&&
<
p
className=
"tip-text"
>
{
t
(
"tag-list.tip-text"
)
}
</
p
>
}
</
div
>
</
div
>
);
...
...
web/src/components/UserBanner.tsx
View file @
6ab58f29
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useMemoStore
,
useTagStore
,
useUserStore
}
from
"../store/module"
;
import
{
getMemoStats
}
from
"../helpers/api"
;
import
*
as
utils
from
"../helpers/utils"
;
import
{
useUserStore
}
from
"../store/module"
;
import
Dropdown
from
"./common/Dropdown"
;
import
showArchivedMemoDialog
from
"./ArchivedMemoDialog"
;
import
showAboutSiteDialog
from
"./AboutSiteDialog"
;
import
UserAvatar
from
"./UserAvatar"
;
import
showSettingDialog
from
"./SettingDialog"
;
...
...
@@ -12,14 +9,8 @@ import showSettingDialog from "./SettingDialog";
const
UserBanner
=
()
=>
{
const
{
t
}
=
useTranslation
();
const
userStore
=
useUserStore
();
const
memoStore
=
useMemoStore
();
const
tagStore
=
useTagStore
();
const
{
user
,
owner
}
=
userStore
.
state
;
const
{
memos
}
=
memoStore
.
state
;
const
tags
=
tagStore
.
state
.
tags
;
const
[
username
,
setUsername
]
=
useState
(
"Memos"
);
const
[
memoAmount
,
setMemoAmount
]
=
useState
(
0
);
const
[
createdDays
,
setCreatedDays
]
=
useState
(
0
);
const
isVisitorMode
=
userStore
.
isVisitorMode
();
useEffect
(()
=>
{
...
...
@@ -28,31 +19,15 @@ const UserBanner = () => {
return
;
}
setUsername
(
owner
.
nickname
||
owner
.
username
);
setCreatedDays
(
Math
.
ceil
((
Date
.
now
()
-
utils
.
getTimeStampByDate
(
owner
.
createdTs
))
/
1000
/
3600
/
24
));
}
else
if
(
user
)
{
setUsername
(
user
.
nickname
||
user
.
username
);
setCreatedDays
(
Math
.
ceil
((
Date
.
now
()
-
utils
.
getTimeStampByDate
(
user
.
createdTs
))
/
1000
/
3600
/
24
));
}
},
[
isVisitorMode
,
user
,
owner
]);
useEffect
(()
=>
{
getMemoStats
(
userStore
.
getCurrentUserId
())
.
then
(({
data
:
{
data
}
})
=>
{
setMemoAmount
(
data
.
length
);
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
});
},
[
memos
]);
const
handleMyAccountClick
=
()
=>
{
showSettingDialog
(
"my-account"
);
};
const
handleArchivedBtnClick
=
()
=>
{
showArchivedMemoDialog
();
};
const
handleAboutBtnClick
=
()
=>
{
showAboutSiteDialog
();
};
...
...
@@ -63,72 +38,50 @@ const UserBanner = () => {
};
return
(
<>
<
div
className=
"flex flex-row justify-between items-center relative w-full h-auto px-3 flex-nowrap shrink-0"
>
<
Dropdown
className=
"w-full"
trigger=
{
<
div
className=
"px-2 py-1 max-w-full flex flex-row justify-start items-center cursor-pointer rounded hover:shadow hover:bg-white dark:hover:bg-zinc-700"
>
<
UserAvatar
avatarUrl=
{
user
?.
avatarUrl
}
/>
<
span
className=
"px-1 text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate"
>
{
username
}
</
span
>
{
!
isVisitorMode
&&
user
?.
role
===
"HOST"
?
(
<
span
className=
"text-xs px-1 bg-blue-600 dark:bg-blue-800 rounded text-white dark:text-gray-200 shadow"
>
MOD
</
span
>
)
:
null
}
</
div
>
}
actionsClassName=
"min-w-[128px] max-w-full"
positionClassName=
"top-full mt-2"
actions=
{
<>
{
!
userStore
.
isVisitorMode
()
&&
(
<>
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleMyAccountClick
}
>
<
span
className=
"mr-1"
>
🤠
</
span
>
{
t
(
"setting.my-account"
)
}
</
button
>
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleArchivedBtnClick
}
>
<
span
className=
"mr-1"
>
🗃️
</
span
>
{
t
(
"sidebar.archived"
)
}
</
button
>
</>
)
}
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleAboutBtnClick
}
>
<
span
className=
"mr-1"
>
🏂
</
span
>
{
t
(
"common.about"
)
}
</
button
>
{
!
userStore
.
isVisitorMode
()
&&
(
<
div
className=
"flex flex-row justify-between items-center relative w-full h-auto px-3 flex-nowrap shrink-0"
>
<
Dropdown
className=
"w-full"
trigger=
{
<
div
className=
"px-2 py-1 max-w-full flex flex-row justify-start items-center cursor-pointer rounded hover:shadow hover:bg-white dark:hover:bg-zinc-700"
>
<
UserAvatar
avatarUrl=
{
user
?.
avatarUrl
}
/>
<
span
className=
"px-1 text-lg font-medium text-slate-800 dark:text-gray-200 shrink truncate"
>
{
username
}
</
span
>
{
!
isVisitorMode
&&
user
?.
role
===
"HOST"
?
(
<
span
className=
"text-xs px-1 bg-blue-600 dark:bg-blue-800 rounded text-white dark:text-gray-200 shadow"
>
MOD
</
span
>
)
:
null
}
</
div
>
}
actionsClassName=
"min-w-[128px] max-w-full"
positionClassName=
"top-full mt-2"
actions=
{
<>
{
!
userStore
.
isVisitorMode
()
&&
(
<>
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handle
SignOutBtn
Click
}
onClick=
{
handle
MyAccount
Click
}
>
<
span
className=
"mr-1"
>
👋
</
span
>
{
t
(
"common.sign-ou
t"
)
}
<
span
className=
"mr-1"
>
🤠
</
span
>
{
t
(
"setting.my-accoun
t"
)
}
</
button
>
)
}
</>
}
/>
</
div
>
<
div
className=
"flex flex-row justify-between items-start w-full px-6 select-none shrink-0 pb-2"
>
<
div
className=
"flex flex-col justify-start items-start"
>
<
span
className=
"font-bold text-2xl opacity-80 leading-10 text-slate-600 dark:text-gray-300"
>
{
memoAmount
}
</
spa
n
>
<
span
className=
"text-gray-400 text-xs font-mono"
>
{
t
(
"amount-text.memo"
,
{
count
:
memoAmount
})
}
</
span
>
</
div
>
<
div
className=
"flex flex-col justify-start items-start"
>
<
span
className=
"font-bold text-2xl opacity-80 leading-10 text-slate-600 dark:text-gray-300"
>
{
tags
.
length
}
</
span
>
<
span
className=
"text-gray-400 text-xs font-mono"
>
{
t
(
"amount-text.tag"
,
{
count
:
tags
.
length
})
}
</
span
>
</
div
>
<
div
className=
"flex flex-col justify-start items-start"
>
<
span
className=
"font-bold text-2xl opacity-80 leading-10 text-slate-600 dark:text-gray-300"
>
{
createdDays
}
</
span
>
<
span
className=
"text-gray-400 text-xs font-mono"
>
{
t
(
"amount-text.day"
,
{
count
:
createdDays
})
}
</
span
>
</
div
>
</
div
>
</>
</>
)
}
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleAboutBtnClick
}
>
<
span
className=
"mr-1"
>
🏂
</
span
>
{
t
(
"common.about"
)
}
</
butto
n
>
{
!
userStore
.
isVisitorMode
()
&&
(
<
button
className=
"w-full px-3 truncate text-left leading-10 cursor-pointer rounded dark:text-gray-200 hover:bg-gray-100 dark:hover:bg-zinc-800"
onClick=
{
handleSignOutBtnClick
}
>
<
span
className=
"mr-1"
>
👋
</
span
>
{
t
(
"common.sign-out"
)
}
</
button
>
)
}
<
/
>
}
/
>
</
div
>
);
};
...
...
web/src/css/tailwind.css
View file @
6ab58f29
...
...
@@ -17,11 +17,6 @@
overflow-wrap
:
anywhere
;
word-break
:
normal
;
}
@media
screen
and
(
min-width
:
1024px
)
{
.ml-calc
{
margin-left
:
calc
(
100vw
-
100%
);
}
}
}
@layer
components
{
...
...
web/src/less/auth.less
View file @
6ab58f29
...
...
@@ -2,7 +2,7 @@
@apply flex flex-row justify-center items-center w-full h-full dark:bg-zinc-800;
> .page-container {
@apply w-80 max-w-full h-full py-4 flex flex-col justify-start items-center
ml-calc
;
@apply w-80 max-w-full h-full py-4 flex flex-col justify-start items-center;
> .auth-form-wrapper {
@apply w-full py-4 grow flex flex-col justify-center items-center;
...
...
web/src/less/explore.less
deleted
100644 → 0
View file @
9d4bb5b3
.page-wrapper.explore {
@apply w-full h-full overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
> .page-container {
@apply relative w-full min-h-full mx-auto flex flex-col justify-start items-center pb-8;
> .page-header {
@apply sticky top-0 z-10 max-w-2xl w-full h-auto flex flex-row justify-between backdrop-blur-sm items-center px-4 sm:pr-6 pt-6 mb-2 ml-calc;
> .title-container {
@apply flex flex-row justify-start items-center;
> .logo-img {
@apply h-12 w-auto rounded-md mr-2;
}
> .title-text {
@apply text-xl sm:text-4xl text-gray-700 dark:text-gray-200;
}
}
}
> .memos-wrapper {
@apply relative flex-grow max-w-2xl w-full h-auto flex flex-col justify-start items-start px-4 sm:pr-6 ml-calc;
> .memo-container {
@apply relative flex flex-col justify-start items-start w-full p-4 mt-2 bg-white dark:bg-zinc-700 rounded-lg border border-white dark:border-zinc-800 hover:border-gray-200 dark:hover:border-zinc-600;
&.pinned {
@apply border-gray-200 border-2 dark:border-zinc-600;
}
> .corner-container {
@apply absolute top-0 right-0 z-1;
&::after {
@apply rounded-tr-md absolute top-0 right-0 border-transparent border-t-green-600 border-r-green-600;
content: "";
border-width: 6px;
}
}
> .memo-header {
@apply mb-2 w-full flex flex-row justify-start items-center text-sm text-gray-400;
> .name-text {
@apply ml-2 hover:text-green-600 hover:underline;
}
}
}
}
}
}
web/src/less/
siderba
r.less
→
web/src/less/
heade
r.less
View file @
6ab58f29
.
sideba
r-wrapper {
@apply fixed sm:sticky top-0 z-30 sm:z-0 -translate-x-64 sm:translate-x-0 sm:flex flex-col justify-start items-start w-
64 h-auto max-h-screen
py-4 pl-2 bg-white dark:bg-zinc-800 sm:bg-transparent overflow-x-hidden overflow-y-auto transition-transform duration-300 overscroll-contain hide-scrollbar;
.
heade
r-wrapper {
@apply fixed sm:sticky top-0 z-30 sm:z-0 -translate-x-64 sm:translate-x-0 sm:flex flex-col justify-start items-start w-
56 h-full
py-4 pl-2 bg-white dark:bg-zinc-800 sm:bg-transparent overflow-x-hidden overflow-y-auto transition-transform duration-300 overscroll-contain hide-scrollbar;
&.show {
@apply translate-x-0 shadow-2xl sm:shadow-none;
...
...
web/src/less/home-sidebar.less
0 → 100644
View file @
6ab58f29
.sidebar-wrapper {
@apply flex-shrink-0 fixed sm:sticky top-0 z-30 sm:z-0 translate-x-56 sm:translate-x-0 hidden md:flex flex-col justify-start items-start w-56 h-full py-4 bg-white dark:bg-zinc-800 sm:bg-transparent overflow-x-hidden overflow-y-auto transition-transform duration-300 overscroll-contain hide-scrollbar;
&.show {
@apply flex translate-x-0 right-0 shadow-2xl sm:shadow-none;
}
}
.mask {
@apply fixed top-0 left-0 w-full h-full bg-black opacity-0 transition-opacity duration-300 pointer-events-none z-20 sm:hidden;
&.show {
@apply opacity-60 pointer-events-auto;
}
}
web/src/less/home.less
View file @
6ab58f29
.page-wrapper.home {
@apply w-full h-full overflow-y-auto
overflow-x-hidden
bg-zinc-100 dark:bg-zinc-800;
@apply w-full h-full overflow-y-auto bg-zinc-100 dark:bg-zinc-800;
> .banner-wrapper {
@apply w-full flex flex-col justify-start items-center;
...
...
@@ -8,28 +8,16 @@
> .page-container {
@apply relative w-full h-auto mx-auto flex flex-row justify-start sm:justify-center items-start;
> .
sideba
r-wrapper {
@apply flex-shrink-0 h-full
ml-calc
;
> .
heade
r-wrapper {
@apply flex-shrink-0 h-full;
}
> .memos-wrapper {
@apply relative flex-grow max-w-2xl w-full
min-h-full flex flex-col justify-start items-start px-4 sm:pr-6
;
@apply relative flex-grow max-w-2xl w-full
h-auto flex flex-col justify-start items-start px-2 sm:pt-4
;
> .memos-editor-wrapper {
@apply w-full h-auto flex flex-col justify-start items-start bg-zinc-100 dark:bg-zinc-800 rounded-lg;
}
> .addition-btn-container {
@apply fixed bottom-12 left-1/2 -translate-x-1/2;
> .btn {
@apply bg-blue-600 dark:bg-blue-800 text-white dark:text-gray-200 px-4 py-2 rounded-3xl shadow-2xl hover:opacity-80;
> .icon {
@apply text-lg mr-1;
}
}
}
}
}
}
web/src/less/memo-detail.less
View file @
6ab58f29
...
...
@@ -5,7 +5,7 @@
@apply relative w-full min-h-full mx-auto flex flex-col justify-start items-center pb-8;
> .page-header {
@apply sticky top-0 z-10 max-w-2xl w-full min-h-full flex flex-row justify-between items-center px-4 pt-6 mb-2 bg-zinc-100 dark:bg-zinc-800
ml-calc
;
@apply sticky top-0 z-10 max-w-2xl w-full min-h-full flex flex-row justify-between items-center px-4 pt-6 mb-2 bg-zinc-100 dark:bg-zinc-800;
> .title-container {
@apply flex flex-row justify-start items-center;
...
...
@@ -35,7 +35,7 @@
}
> .memos-wrapper {
@apply relative flex-grow max-w-2xl w-full min-h-full flex flex-col justify-start items-start px-4
ml-calc
;
@apply relative flex-grow max-w-2xl w-full min-h-full flex flex-col justify-start items-start px-4;
> .memo-container {
@apply flex flex-col justify-start items-start w-full p-4 mt-2 bg-white dark:bg-zinc-700 rounded-lg border border-white dark:border-zinc-800 hover:border-gray-200 dark:hover:border-zinc-700;
...
...
web/src/less/memos-header.less
deleted
100644 → 0
View file @
9d4bb5b3
.memos-header-container {
@apply sticky top-0 pt-4 pb-1 mb-1 backdrop-blur-sm flex flex-row justify-between items-center w-full h-auto flex-nowrap shrink-0 z-10;
> .title-container {
@apply flex flex-row justify-start items-center mr-2 shrink-0 overflow-hidden;
> .action-btn {
@apply flex sm:hidden flex-row justify-center items-center w-6 h-6 mr-1 shrink-0 bg-transparent;
> .icon-img {
@apply w-5 h-auto dark:text-gray-200;
}
}
> .title-text {
@apply font-bold text-lg leading-10 mr-1 text-ellipsis shrink-0 cursor-pointer overflow-hidden text-gray-700 dark:text-gray-200;
}
}
> .btns-container {
@apply flex flex-row justify-end items-center;
}
}
web/src/less/search-bar.less
View file @
6ab58f29
.search-bar-container {
@apply relative w-
auto
;
@apply relative w-
full
;
&:hover,
&:active {
...
...
web/src/locales/en.json
View file @
6ab58f29
{
"common"
:
{
"about"
:
"About"
,
"home"
:
"Home"
,
"resources"
:
"Resources"
,
"settings"
:
"Settings"
,
"daily-review"
:
"Daily Review"
,
"email"
:
"Email"
,
"password"
:
"Password"
,
"repeat-password-short"
:
"Repeat"
,
"repeat-password"
:
"Repeat the password"
,
"new-password"
:
"New password"
,
"repeat-new-password"
:
"Repeat the new password"
,
"avatar"
:
"Avatar"
,
"username"
:
"Username"
,
"nickname"
:
"Nickname"
,
"new-password"
:
"New password"
,
"repeat-new-password"
:
"Repeat the new password"
,
"save"
:
"Save"
,
"close"
:
"Close"
,
"cancel"
:
"Cancel"
,
...
...
@@ -57,12 +59,6 @@
"host-tip"
:
"You are registering as the Site Host."
,
"not-host-tip"
:
"If you don't have an account, please contact the site host."
},
"sidebar"
:
{
"daily-review"
:
"Daily Review"
,
"resources"
:
"Resources"
,
"setting"
:
"Settings"
,
"archived"
:
"Archived"
},
"daily-review"
:
{
"oops-nothing"
:
"Oops, there is nothing."
},
...
...
web/src/locales/zh.json
View file @
6ab58f29
This diff is collapsed.
Click to expand it.
web/src/pages/Explore.tsx
View file @
6ab58f29
import
dayjs
from
"dayjs"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useNavigate
}
from
"react-router-dom"
;
import
{
useGlobalStore
,
useLocationStore
,
useMemoStore
,
useUserStore
}
from
"../store/module"
;
import
{
TAG_REG
}
from
"../labs/marked/parser"
;
import
{
DEFAULT_MEMO_LIMIT
}
from
"../helpers/consts"
;
import
useLoading
from
"../hooks/useLoading"
;
import
toastHelper
from
"../components/Toast"
;
import
MemoContent
from
"../components/MemoContent"
;
import
MemoResources
from
"../components/MemoResources"
;
import
MemoFilter
from
"../components/MemoFilter"
;
import
Icon
from
"../components/Icon"
;
import
{
TAG_REG
}
from
"../labs/marked/pars
er"
;
import
"../less/explore.less
"
;
import
MemoFilter
from
"../components/MemoFilt
er"
;
import
Memo
from
"../components/Memo
"
;
interface
State
{
memos
:
Memo
[];
}
const
Explore
=
()
=>
{
const
{
t
,
i18n
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
navigate
=
useNavigate
();
const
globalStore
=
useGlobalStore
();
const
locationStore
=
useLocationStore
();
...
...
@@ -91,20 +88,6 @@ const Explore = () => {
}
};
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
const
targetEl
=
e
.
target
as
HTMLElement
;
if
(
targetEl
.
className
===
"tag-span"
)
{
const
tagName
=
targetEl
.
innerText
.
slice
(
1
);
const
currTagQuery
=
locationStore
.
getState
().
query
?.
tag
;
if
(
currTagQuery
===
tagName
)
{
locationStore
.
setTagQuery
(
undefined
);
}
else
{
locationStore
.
setTagQuery
(
tagName
);
}
}
};
const
handleTitleClick
=
()
=>
{
if
(
user
)
{
navigate
(
"/"
);
...
...
@@ -114,58 +97,40 @@ const Explore = () => {
};
return
(
<
section
className=
"page-wrapper explore"
>
<
div
className=
"page-container"
>
<
div
className=
"page-header"
>
<
div
className=
"title-container cursor-pointer hover:opacity-80"
onClick=
{
handleTitleClick
}
>
<
img
className=
"logo-img"
src=
{
customizedProfile
.
logoUrl
}
alt=
""
/>
<
span
className=
"title-text"
>
{
customizedProfile
.
name
}
</
span
>
</
div
>
<
div
className=
"flex flex-row justify-end items-center"
>
<
a
className=
"flex flex-row justify-center items-center h-12 w-12 border rounded-full hover:opacity-80 hover:shadow dark:text-white "
href=
"/explore/rss.xml"
target=
"_blank"
rel=
"noreferrer"
>
<
Icon
.
Rss
className=
"w-7 h-auto opacity-60"
/>
</
a
>
</
div
>
<
section
className=
"w-full min-h-full flex flex-col justify-start items-center pb-8 bg-zinc-100 dark:bg-zinc-800"
>
<
div
className=
"sticky top-0 z-10 max-w-2xl w-full h-auto flex flex-row justify-between backdrop-blur-sm items-center px-4 sm:pr-6 pt-6 mb-2"
>
<
div
className=
"flex flex-row justify-start items-center cursor-pointer hover:opacity-80"
onClick=
{
handleTitleClick
}
>
<
img
className=
"h-12 w-auto rounded-md mr-2"
src=
{
customizedProfile
.
logoUrl
}
alt=
""
/>
<
span
className=
"text-xl sm:text-4xl text-gray-700 dark:text-gray-200"
>
{
customizedProfile
.
name
}
</
span
>
</
div
>
<
div
className=
"flex flex-row justify-end items-center"
>
<
a
className=
"flex flex-row justify-center items-center h-12 w-12 border rounded-full hover:opacity-80 hover:shadow dark:text-white "
href=
"/explore/rss.xml"
target=
"_blank"
rel=
"noreferrer"
>
<
Icon
.
Rss
className=
"w-7 h-auto opacity-60"
/>
</
a
>
</
div
>
{
!
loadingState
.
isLoading
&&
(
<
main
className=
"memos-wrapper"
>
<
MemoFilter
/>
{
sortedMemos
.
map
((
memo
)
=>
{
const
createdAtStr
=
dayjs
(
memo
.
createdTs
).
locale
(
i18n
.
language
).
format
(
"YYYY/MM/DD HH:mm:ss"
);
return
(
<
div
className=
{
`memo-container ${memo.pinned ? "pinned" : ""}`
}
key=
{
memo
.
id
}
>
{
memo
.
pinned
&&
<
div
className=
"corner-container"
></
div
>
}
<
div
className=
"memo-header"
>
<
span
className=
"time-text"
>
{
createdAtStr
}
</
span
>
<
a
className=
"name-text"
href=
{
`/u/${memo.creatorId}`
}
>
@
{
memo
.
creatorName
}
</
a
>
</
div
>
<
MemoContent
className=
"memo-content"
content=
{
memo
.
content
}
onMemoContentClick=
{
handleMemoContentClick
}
/>
<
MemoResources
resourceList=
{
memo
.
resourceList
}
/>
</
div
>
);
})
}
{
isComplete
?
(
state
.
memos
.
length
===
0
?
(
<
p
className=
"w-full text-center mt-12 text-gray-600"
>
{
t
(
"message.no-memos"
)
}
</
p
>
)
:
null
)
:
(
<
p
className=
"m-auto text-center mt-4 italic cursor-pointer text-gray-500 hover:text-green-600"
onClick=
{
handleFetchMoreClick
}
>
{
t
(
"memo-list.fetch-more"
)
}
</
p
>
)
}
</
main
>
)
}
</
div
>
{
!
loadingState
.
isLoading
&&
(
<
main
className=
"relative flex-grow max-w-2xl w-full h-auto flex flex-col justify-start items-start px-4 sm:pr-6"
>
<
MemoFilter
/>
{
sortedMemos
.
map
((
memo
)
=>
{
return
<
Memo
key=
{
`${memo.id}-${memo.createdTs}`
}
memo=
{
memo
}
readonly=
{
true
}
/>;
})
}
{
isComplete
?
(
state
.
memos
.
length
===
0
?
(
<
p
className=
"w-full text-center mt-12 text-gray-600"
>
{
t
(
"message.no-memos"
)
}
</
p
>
)
:
null
)
:
(
<
p
className=
"m-auto text-center mt-4 italic cursor-pointer text-gray-500 hover:text-green-600"
onClick=
{
handleFetchMoreClick
}
>
{
t
(
"memo-list.fetch-more"
)
}
</
p
>
)
}
</
main
>
)
}
</
section
>
);
};
...
...
web/src/pages/Home.tsx
View file @
6ab58f29
...
...
@@ -3,12 +3,13 @@ import { useTranslation } from "react-i18next";
import
{
useLocation
}
from
"react-router-dom"
;
import
{
useGlobalStore
,
useUserStore
}
from
"../store/module"
;
import
toastHelper
from
"../components/Toast"
;
import
Sidebar
from
"../components/Sidebar"
;
import
MemosHeader
from
"../components/MemosHeader"
;
import
Header
from
"../components/Header"
;
import
MemoEditor
from
"../components/MemoEditor"
;
import
MemoFilter
from
"../components/MemoFilter"
;
import
MemoList
from
"../components/MemoList"
;
import
UpdateVersionBanner
from
"../components/UpdateVersionBanner"
;
import
MobileHeader
from
"../components/MobileHeader"
;
import
HomeSidebar
from
"../components/HomeSidebar"
;
import
"../less/home.less"
;
function
Home
()
{
...
...
@@ -40,28 +41,16 @@ function Home() {
<
UpdateVersionBanner
/>
</
div
>
<
div
className=
"page-container"
>
<
Sideba
r
/>
<
Heade
r
/>
<
main
className=
"memos-wrapper"
>
<
M
emos
Header
/>
<
M
obile
Header
/>
<
div
className=
"memos-editor-wrapper"
>
{
!
userStore
.
isVisitorMode
()
&&
<
MemoEditor
/>
}
<
MemoFilter
/>
</
div
>
<
MemoList
/>
{
userStore
.
isVisitorMode
()
&&
(
<
div
className=
"addition-btn-container"
>
{
user
?
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/"
)
}
>
<
span
className=
"icon"
>
🏠
</
span
>
{
t
(
"common.back-to-home"
)
}
</
button
>
)
:
(
<
button
className=
"btn"
onClick=
{
()
=>
(
window
.
location
.
href
=
"/auth"
)
}
>
<
span
className=
"icon"
>
👉
</
span
>
{
t
(
"common.sign-in"
)
}
</
button
>
)
}
</
div
>
)
}
</
main
>
{
!
userStore
.
isVisitorMode
()
&&
<
HomeSidebar
/>
}
</
div
>
</
section
>
);
...
...
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