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
226e9c15
Commit
226e9c15
authored
Feb 04, 2022
by
email
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: change main language to english
parent
321183db
Changes
32
Hide whitespace changes
Inline
Side-by-side
Showing
32 changed files
with
161 additions
and
158 deletions
+161
-158
AboutSiteDialog.tsx
web/src/components/AboutSiteDialog.tsx
+3
-3
ChangePasswordDialog.tsx
web/src/components/ChangePasswordDialog.tsx
+11
-11
ConfirmResetOpenIdDialog.tsx
web/src/components/ConfirmResetOpenIdDialog.tsx
+8
-6
CreateShortcutDialog.tsx
web/src/components/CreateShortcutDialog.tsx
+8
-8
DailyMemoDiaryDialog.tsx
web/src/components/DailyMemoDiaryDialog.tsx
+2
-2
DeletedMemo.tsx
web/src/components/DeletedMemo.tsx
+4
-4
Editor.tsx
web/src/components/Editor/Editor.tsx
+2
-2
Memo.tsx
web/src/components/Memo.tsx
+5
-5
MemoCardDialog.tsx
web/src/components/MemoCardDialog.tsx
+2
-2
MemoEditor.tsx
web/src/components/MemoEditor.tsx
+3
-3
MemoFilter.tsx
web/src/components/MemoFilter.tsx
+1
-1
MemoList.tsx
web/src/components/MemoList.tsx
+8
-2
MenuBtnsPopup.tsx
web/src/components/MenuBtnsPopup.tsx
+4
-4
MyAccountSection.tsx
web/src/components/MyAccountSection.tsx
+16
-16
PreferencesSection.tsx
web/src/components/PreferencesSection.tsx
+11
-11
PreviewImageDialog.tsx
web/src/components/PreviewImageDialog.tsx
+2
-2
SearchBar.tsx
web/src/components/SearchBar.tsx
+1
-1
ShareMemoImageDialog.tsx
web/src/components/ShareMemoImageDialog.tsx
+2
-2
ShortcutList.tsx
web/src/components/ShortcutList.tsx
+5
-5
TagList.tsx
web/src/components/TagList.tsx
+2
-2
DatePicker.tsx
web/src/components/common/DatePicker.tsx
+8
-8
Selector.tsx
web/src/components/common/Selector.tsx
+1
-1
consts.ts
web/src/helpers/consts.ts
+8
-8
filter.ts
web/src/helpers/filter.ts
+15
-15
storage.ts
web/src/helpers/storage.ts
+1
-4
validator.ts
web/src/helpers/validator.ts
+10
-10
createStore.ts
web/src/labs/createStore.ts
+2
-2
MemoTrash.tsx
web/src/pages/MemoTrash.tsx
+2
-2
Setting.tsx
web/src/pages/Setting.tsx
+1
-1
Signin.tsx
web/src/pages/Signin.tsx
+12
-12
resourceService.ts
web/src/services/resourceService.ts
+1
-1
basic.d.ts
web/src/types/basic.d.ts
+0
-2
No files found.
web/src/components/AboutSiteDialog.tsx
View file @
226e9c15
...
@@ -13,7 +13,7 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -13,7 +13,7 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
<>
<>
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🤠
</
span
>
关于
<
b
>
Memos
</
b
>
<
span
className=
"icon-text"
>
🤠
</
span
>
About
<
b
>
Memos
</
b
>
</
p
>
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
...
@@ -21,9 +21,9 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -21,9 +21,9 @@ const AboutSiteDialog: React.FC<Props> = ({ destroy }: Props) => {
</
div
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"dialog-content-container"
>
<
p
>
<
p
>
把玩
<
a
href=
"https://flomoapp.com"
>
flomo
</
a
>
后有感而作的开源项目
Memos is an open source, self-hosted alternative to
<
a
href=
"https://flomoapp.com"
>
flomo
</
a
>
.
</
p
>
</
p
>
<
p
>
特点:精美且细节的视觉样式、体验优良的交互逻辑
</
p
>
<
p
>
Built with `Golang` and `React`.
</
p
>
<
br
/>
<
br
/>
<
p
>
<
p
>
🏗 This project is working in progress,
<
br
/>
and very pleasure to welcome your
{
" "
}
🏗 This project is working in progress,
<
br
/>
and very pleasure to welcome your
{
" "
}
...
...
web/src/components/ChangePasswordDialog.tsx
View file @
226e9c15
...
@@ -44,19 +44,19 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -44,19 +44,19 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const
handleSaveBtnClick
=
async
()
=>
{
const
handleSaveBtnClick
=
async
()
=>
{
if
(
oldPassword
===
""
||
newPassword
===
""
||
newPasswordAgain
===
""
)
{
if
(
oldPassword
===
""
||
newPassword
===
""
||
newPasswordAgain
===
""
)
{
toastHelper
.
error
(
"
密码不能为空
"
);
toastHelper
.
error
(
"
Please fill in all fields.
"
);
return
;
return
;
}
}
if
(
newPassword
!==
newPasswordAgain
)
{
if
(
newPassword
!==
newPasswordAgain
)
{
toastHelper
.
error
(
"
新密码两次输入不一致
"
);
toastHelper
.
error
(
"
New passwords do not match.
"
);
setNewPasswordAgain
(
""
);
setNewPasswordAgain
(
""
);
return
;
return
;
}
}
const
passwordValidResult
=
validate
(
newPassword
,
validateConfig
);
const
passwordValidResult
=
validate
(
newPassword
,
validateConfig
);
if
(
!
passwordValidResult
.
result
)
{
if
(
!
passwordValidResult
.
result
)
{
toastHelper
.
error
(
"
密码
"
+
passwordValidResult
.
reason
);
toastHelper
.
error
(
"
Password
"
+
passwordValidResult
.
reason
);
return
;
return
;
}
}
...
@@ -64,13 +64,13 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -64,13 +64,13 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
const
isValid
=
await
userService
.
checkPasswordValid
(
oldPassword
);
const
isValid
=
await
userService
.
checkPasswordValid
(
oldPassword
);
if
(
!
isValid
)
{
if
(
!
isValid
)
{
toastHelper
.
error
(
"
旧密码不匹配
"
);
toastHelper
.
error
(
"
Old password is invalid.
"
);
setOldPassword
(
""
);
setOldPassword
(
""
);
return
;
return
;
}
}
await
userService
.
updatePassword
(
newPassword
);
await
userService
.
updatePassword
(
newPassword
);
toastHelper
.
info
(
"
密码修改成功!
"
);
toastHelper
.
info
(
"
Password changed.
"
);
handleCloseBtnClick
();
handleCloseBtnClick
();
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
);
toastHelper
.
error
(
error
);
...
@@ -80,30 +80,30 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -80,30 +80,30 @@ const ChangePasswordDialog: React.FC<Props> = ({ destroy }: Props) => {
return
(
return
(
<>
<>
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
修改密码
</
p
>
<
p
className=
"title-text"
>
Change Password
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"dialog-content-container"
>
<
label
className=
"form-label input-form-label"
>
<
label
className=
"form-label input-form-label"
>
<
span
className=
{
"normal-text "
+
(
oldPassword
===
""
?
""
:
"not-null"
)
}
>
旧密码
</
span
>
<
span
className=
{
"normal-text "
+
(
oldPassword
===
""
?
""
:
"not-null"
)
}
>
Old password
</
span
>
<
input
type=
"password"
value=
{
oldPassword
}
onChange=
{
handleOldPasswordChanged
}
/>
<
input
type=
"password"
value=
{
oldPassword
}
onChange=
{
handleOldPasswordChanged
}
/>
</
label
>
</
label
>
<
label
className=
"form-label input-form-label"
>
<
label
className=
"form-label input-form-label"
>
<
span
className=
{
"normal-text "
+
(
newPassword
===
""
?
""
:
"not-null"
)
}
>
新密码
</
span
>
<
span
className=
{
"normal-text "
+
(
newPassword
===
""
?
""
:
"not-null"
)
}
>
New passworld
</
span
>
<
input
type=
"password"
value=
{
newPassword
}
onChange=
{
handleNewPasswordChanged
}
/>
<
input
type=
"password"
value=
{
newPassword
}
onChange=
{
handleNewPasswordChanged
}
/>
</
label
>
</
label
>
<
label
className=
"form-label input-form-label"
>
<
label
className=
"form-label input-form-label"
>
<
span
className=
{
"normal-text "
+
(
newPasswordAgain
===
""
?
""
:
"not-null"
)
}
>
再次输入新密码
</
span
>
<
span
className=
{
"normal-text "
+
(
newPasswordAgain
===
""
?
""
:
"not-null"
)
}
>
New password again
</
span
>
<
input
type=
"password"
value=
{
newPasswordAgain
}
onChange=
{
handleNewPasswordAgainChanged
}
/>
<
input
type=
"password"
value=
{
newPasswordAgain
}
onChange=
{
handleNewPasswordAgainChanged
}
/>
</
label
>
</
label
>
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
span
className=
"btn cancel-btn"
onClick=
{
handleCloseBtnClick
}
>
<
span
className=
"btn cancel-btn"
onClick=
{
handleCloseBtnClick
}
>
取消
Cancel
</
span
>
</
span
>
<
span
className=
"btn confirm-btn"
onClick=
{
handleSaveBtnClick
}
>
<
span
className=
"btn confirm-btn"
onClick=
{
handleSaveBtnClick
}
>
保存
Save
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/ConfirmResetOpenIdDialog.tsx
View file @
226e9c15
...
@@ -27,29 +27,31 @@ const ConfirmResetOpenIdDialog: React.FC<Props> = ({ destroy }: Props) => {
...
@@ -27,29 +27,31 @@ const ConfirmResetOpenIdDialog: React.FC<Props> = ({ destroy }: Props) => {
try
{
try
{
await
userService
.
resetOpenId
();
await
userService
.
resetOpenId
();
}
catch
(
error
)
{
}
catch
(
error
)
{
toastHelper
.
error
(
"
请求重置 Open API 失败
"
);
toastHelper
.
error
(
"
Request reset open API failed.
"
);
return
;
return
;
}
}
toastHelper
.
success
(
"
重置成功!
"
);
toastHelper
.
success
(
"
Reset open API succeeded.
"
);
handleCloseBtnClick
();
handleCloseBtnClick
();
};
};
return
(
return
(
<>
<>
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
重置
Open API
</
p
>
<
p
className=
"title-text"
>
Reset
Open API
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
</
button
>
</
button
>
</
div
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"dialog-content-container"
>
<
p
className=
"warn-text"
>
⚠️ 现有 API 将失效,并生成新的 API,确定要重置吗?
</
p
>
<
p
className=
"warn-text"
>
⚠️ The existing API will be invalidated and a new one will be generated, are you sure you want to reset?
</
p
>
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
span
className=
"btn cancel-btn"
onClick=
{
handleCloseBtnClick
}
>
<
span
className=
"btn cancel-btn"
onClick=
{
handleCloseBtnClick
}
>
取消
Cancel
</
span
>
</
span
>
<
span
className=
{
`btn confirm-btn ${resetBtnClickLoadingState.isLoading ? "loading" : ""}`
}
onClick=
{
handleConfirmBtnClick
}
>
<
span
className=
{
`btn confirm-btn ${resetBtnClickLoadingState.isLoading ? "loading" : ""}`
}
onClick=
{
handleConfirmBtnClick
}
>
确定重置!
Reset!
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/CreateShortcutDialog.tsx
View file @
226e9c15
...
@@ -40,7 +40,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -40,7 +40,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
const
handleSaveBtnClick
=
async
()
=>
{
const
handleSaveBtnClick
=
async
()
=>
{
if
(
!
title
)
{
if
(
!
title
)
{
toastHelper
.
error
(
"
标题不能为空!
"
);
toastHelper
.
error
(
"
Title is required
"
);
return
;
return
;
}
}
...
@@ -62,7 +62,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -62,7 +62,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
if
(
filters
.
length
>
0
)
{
if
(
filters
.
length
>
0
)
{
const
lastFilter
=
filters
[
filters
.
length
-
1
];
const
lastFilter
=
filters
[
filters
.
length
-
1
];
if
(
lastFilter
.
value
.
value
===
""
)
{
if
(
lastFilter
.
value
.
value
===
""
)
{
toastHelper
.
info
(
"
先完善上一个过滤器吧
"
);
toastHelper
.
info
(
"
Please fill in previous filter value
"
);
return
;
return
;
}
}
}
}
...
@@ -90,7 +90,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -90,7 +90,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🔖
</
span
>
<
span
className=
"icon-text"
>
🔖
</
span
>
{
shortcutId
?
"
编辑检索"
:
"创建检索
"
}
{
shortcutId
?
"
Edit Shortcut"
:
"Create Shortcut
"
}
</
p
>
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
button
className=
"btn close-btn"
onClick=
{
destroy
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
...
@@ -98,11 +98,11 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -98,11 +98,11 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
</
div
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"form-item-container input-form-container"
>
<
div
className=
"form-item-container input-form-container"
>
<
span
className=
"normal-text"
>
标题
</
span
>
<
span
className=
"normal-text"
>
Title
</
span
>
<
input
className=
"title-input"
type=
"text"
value=
{
title
}
onChange=
{
handleTitleInputChange
}
/>
<
input
className=
"title-input"
type=
"text"
value=
{
title
}
onChange=
{
handleTitleInputChange
}
/>
</
div
>
</
div
>
<
div
className=
"form-item-container filter-form-container"
>
<
div
className=
"form-item-container filter-form-container"
>
<
span
className=
"normal-text"
>
过滤器
</
span
>
<
span
className=
"normal-text"
>
Filter
</
span
>
<
div
className=
"filters-wrapper"
>
<
div
className=
"filters-wrapper"
>
{
filters
.
map
((
f
,
index
)
=>
{
{
filters
.
map
((
f
,
index
)
=>
{
return
(
return
(
...
@@ -116,7 +116,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -116,7 +116,7 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
);
);
})
}
})
}
<
div
className=
"create-filter-btn"
onClick=
{
handleAddFilterBenClick
}
>
<
div
className=
"create-filter-btn"
onClick=
{
handleAddFilterBenClick
}
>
添加筛选条件
New Filter
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -125,10 +125,10 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
...
@@ -125,10 +125,10 @@ const CreateShortcutDialog: React.FC<Props> = (props: Props) => {
<
div
></
div
>
<
div
></
div
>
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
span
className=
{
`tip-text ${filters.length === 0 && "hidden"}`
}
>
<
span
className=
{
`tip-text ${filters.length === 0 && "hidden"}`
}
>
符合条件的 Memo 有
<
strong
>
{
shownMemoLength
}
</
strong
>
条
<
strong
>
{
shownMemoLength
}
</
strong
>
eligible memo
</
span
>
</
span
>
<
button
className=
{
`btn save-btn ${requestState.isLoading ? "requesting" : ""}`
}
onClick=
{
handleSaveBtnClick
}
>
<
button
className=
{
`btn save-btn ${requestState.isLoading ? "requesting" : ""}`
}
onClick=
{
handleSaveBtnClick
}
>
保存
Save
</
button
>
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/DailyMemoDiaryDialog.tsx
View file @
226e9c15
...
@@ -106,11 +106,11 @@ const DailyMemoDiaryDialog: React.FC<Props> = (props: Props) => {
...
@@ -106,11 +106,11 @@ const DailyMemoDiaryDialog: React.FC<Props> = (props: Props) => {
/>
/>
{
loadingState
.
isLoading
?
(
{
loadingState
.
isLoading
?
(
<
div
className=
"tip-container"
>
<
div
className=
"tip-container"
>
<
p
className=
"tip-text"
>
努力加载中
...
</
p
>
<
p
className=
"tip-text"
>
Loading
...
</
p
>
</
div
>
</
div
>
)
:
memos
.
length
===
0
?
(
)
:
memos
.
length
===
0
?
(
<
div
className=
"tip-container"
>
<
div
className=
"tip-container"
>
<
p
className=
"tip-text"
>
空空如也
</
p
>
<
p
className=
"tip-text"
>
Oops, there is nothing.
</
p
>
</
div
>
</
div
>
)
:
(
)
:
(
<
div
className=
"dailymemos-wrapper"
>
<
div
className=
"dailymemos-wrapper"
>
...
...
web/src/components/DeletedMemo.tsx
View file @
226e9c15
...
@@ -40,7 +40,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
...
@@ -40,7 +40,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
try
{
try
{
await
memoService
.
restoreMemoById
(
memo
.
id
);
await
memoService
.
restoreMemoById
(
memo
.
id
);
handleDeletedMemoAction
(
memo
.
id
);
handleDeletedMemoAction
(
memo
.
id
);
toastHelper
.
info
(
"
恢复成功
"
);
toastHelper
.
info
(
"
Restored successfully
"
);
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
toastHelper
.
error
(
error
.
message
);
}
}
...
@@ -55,7 +55,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
...
@@ -55,7 +55,7 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
return
(
return
(
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id}`
}
onMouseLeave=
{
handleMouseLeaveMemoWrapper
}
>
<
div
className=
{
`memo-wrapper ${"memos-" + memo.id}`
}
onMouseLeave=
{
handleMouseLeaveMemoWrapper
}
>
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"memo-top-wrapper"
>
<
span
className=
"time-text"
>
删除于
{
memo
.
deletedAtStr
}
</
span
>
<
span
className=
"time-text"
>
Deleted at
{
memo
.
deletedAtStr
}
</
span
>
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
span
className=
"btn more-action-btn"
>
<
span
className=
"btn more-action-btn"
>
<
img
className=
"icon-img"
src=
"/icons/more.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/more.svg"
/>
...
@@ -63,10 +63,10 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
...
@@ -63,10 +63,10 @@ const DeletedMemo: React.FC<Props> = (props: Props) => {
<
div
className=
"more-action-btns-wrapper"
>
<
div
className=
"more-action-btns-wrapper"
>
<
div
className=
"more-action-btns-container"
>
<
div
className=
"more-action-btns-container"
>
<
span
className=
"btn restore-btn"
onClick=
{
handleRestoreMemoClick
}
>
<
span
className=
"btn restore-btn"
onClick=
{
handleRestoreMemoClick
}
>
恢复
Restore
</
span
>
</
span
>
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDeleteMemoClick
}
>
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDeleteMemoClick
}
>
{
showConfirmDeleteBtn
?
"
确定删除!"
:
"完全删除
"
}
{
showConfirmDeleteBtn
?
"
Delete!"
:
"Delete
"
}
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/Editor/Editor.tsx
View file @
226e9c15
...
@@ -176,12 +176,12 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef<EditorRef
...
@@ -176,12 +176,12 @@ const Editor = forwardRef((props: EditorProps, ref: React.ForwardedRef<EditorRef
<
div
className=
"btns-container"
>
<
div
className=
"btns-container"
>
<
Only
when=
{
showCancelBtn
}
>
<
Only
when=
{
showCancelBtn
}
>
<
button
className=
"action-btn cancel-btn"
onClick=
{
handleCommonCancelBtnClick
}
>
<
button
className=
"action-btn cancel-btn"
onClick=
{
handleCommonCancelBtnClick
}
>
撤销修改
Cancel editting
</
button
>
</
button
>
</
Only
>
</
Only
>
<
Only
when=
{
showConfirmBtn
}
>
<
Only
when=
{
showConfirmBtn
}
>
<
button
className=
"action-btn confirm-btn"
disabled=
{
!
editorRef
.
current
?.
value
}
onClick=
{
handleCommonConfirmBtnClick
}
>
<
button
className=
"action-btn confirm-btn"
disabled=
{
!
editorRef
.
current
?.
value
}
onClick=
{
handleCommonConfirmBtnClick
}
>
记下
<
span
className=
"icon-text"
>
✍️
</
span
>
Save
<
span
className=
"icon-text"
>
✍️
</
span
>
</
button
>
</
button
>
</
Only
>
</
Only
>
</
div
>
</
div
>
...
...
web/src/components/Memo.tsx
View file @
226e9c15
...
@@ -93,19 +93,19 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -93,19 +93,19 @@ const Memo: React.FC<Props> = (props: Props) => {
<
div
className=
"more-action-btns-wrapper"
>
<
div
className=
"more-action-btns-wrapper"
>
<
div
className=
"more-action-btns-container"
>
<
div
className=
"more-action-btns-container"
>
<
span
className=
"btn"
onClick=
{
handleShowMemoStoryDialog
}
>
<
span
className=
"btn"
onClick=
{
handleShowMemoStoryDialog
}
>
查看详情
View Story
</
span
>
</
span
>
<
span
className=
"btn"
onClick=
{
handleMarkMemoClick
}
>
<
span
className=
"btn"
onClick=
{
handleMarkMemoClick
}
>
Mark
Mark
</
span
>
</
span
>
<
span
className=
"btn"
onClick=
{
handleGenMemoImageBtnClick
}
>
<
span
className=
"btn"
onClick=
{
handleGenMemoImageBtnClick
}
>
分享
Share
</
span
>
</
span
>
<
span
className=
"btn"
onClick=
{
handleEditMemoClick
}
>
<
span
className=
"btn"
onClick=
{
handleEditMemoClick
}
>
编辑
Edit
</
span
>
</
span
>
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDeleteMemoClick
}
>
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDeleteMemoClick
}
>
{
showConfirmDeleteBtn
?
"
确定删除!"
:
"删除
"
}
{
showConfirmDeleteBtn
?
"
Delete!"
:
"Delete
"
}
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -151,7 +151,7 @@ export function formatMemoContent(content: string) {
...
@@ -151,7 +151,7 @@ export function formatMemoContent(content: string) {
.
replace
(
LINK_REG
,
"<a class='link' target='_blank' rel='noreferrer' href='$1'>$1</a>"
)
.
replace
(
LINK_REG
,
"<a class='link' target='_blank' rel='noreferrer' href='$1'>$1</a>"
)
.
replace
(
MEMO_LINK_REG
,
"<span class='memo-link-text' data-value='$2'>$1</span>"
);
.
replace
(
MEMO_LINK_REG
,
"<span class='memo-link-text' data-value='$2'>$1</span>"
);
//
中英文之间加空格
//
Add space in english and chinese
if
(
shouldSplitMemoWord
)
{
if
(
shouldSplitMemoWord
)
{
content
=
content
content
=
content
.
replace
(
/
([\u
4e00-
\u
9fa5
])([
A-Za-z0-9?.,;[
\]]
+
)
/g
,
"$1 $2"
)
.
replace
(
/
([\u
4e00-
\u
9fa5
])([
A-Za-z0-9?.,;[
\]]
+
)
/g
,
"$1 $2"
)
...
...
web/src/components/MemoCardDialog.tsx
View file @
226e9c15
...
@@ -148,7 +148,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
...
@@ -148,7 +148,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
</
div
>
</
div
>
{
linkMemos
.
length
>
0
?
(
{
linkMemos
.
length
>
0
?
(
<
div
className=
"linked-memos-wrapper"
>
<
div
className=
"linked-memos-wrapper"
>
<
p
className=
"normal-text"
>
关联了
{
linkMemos
.
length
}
个
MEMO
</
p
>
<
p
className=
"normal-text"
>
{
linkMemos
.
length
}
related
MEMO
</
p
>
{
linkMemos
.
map
((
m
)
=>
{
{
linkMemos
.
map
((
m
)
=>
{
const
rawtext
=
parseHtmlToRawText
(
formatMemoContent
(
m
.
content
)).
replaceAll
(
"
\n
"
,
" "
);
const
rawtext
=
parseHtmlToRawText
(
formatMemoContent
(
m
.
content
)).
replaceAll
(
"
\n
"
,
" "
);
return
(
return
(
...
@@ -162,7 +162,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
...
@@ -162,7 +162,7 @@ const MemoCardDialog: React.FC<Props> = (props: Props) => {
)
:
null
}
)
:
null
}
{
linkedMemos
.
length
>
0
?
(
{
linkedMemos
.
length
>
0
?
(
<
div
className=
"linked-memos-wrapper"
>
<
div
className=
"linked-memos-wrapper"
>
<
p
className=
"normal-text"
>
{
linkedMemos
.
length
}
个链接至此的
MEMO
</
p
>
<
p
className=
"normal-text"
>
{
linkedMemos
.
length
}
linked
MEMO
</
p
>
{
linkedMemos
.
map
((
m
)
=>
{
{
linkedMemos
.
map
((
m
)
=>
{
const
rawtext
=
parseHtmlToRawText
(
formatMemoContent
(
m
.
content
)).
replaceAll
(
"
\n
"
,
" "
);
const
rawtext
=
parseHtmlToRawText
(
formatMemoContent
(
m
.
content
)).
replaceAll
(
"
\n
"
,
" "
);
return
(
return
(
...
...
web/src/components/MemoEditor.tsx
View file @
226e9c15
...
@@ -140,7 +140,7 @@ const MemoEditor: React.FC<Props> = () => {
...
@@ -140,7 +140,7 @@ const MemoEditor: React.FC<Props> = () => {
const
handleSaveBtnClick
=
useCallback
(
async
(
content
:
string
)
=>
{
const
handleSaveBtnClick
=
useCallback
(
async
(
content
:
string
)
=>
{
if
(
content
===
""
)
{
if
(
content
===
""
)
{
toastHelper
.
error
(
"
内容不能为空呀
"
);
toastHelper
.
error
(
"
Content can't be empty
"
);
return
;
return
;
}
}
...
@@ -270,7 +270,7 @@ const MemoEditor: React.FC<Props> = () => {
...
@@ -270,7 +270,7 @@ const MemoEditor: React.FC<Props> = () => {
()
=>
({
()
=>
({
className
:
"memo-editor"
,
className
:
"memo-editor"
,
initialContent
:
getEditorContentCache
(),
initialContent
:
getEditorContentCache
(),
placeholder
:
"
现在的想法是
..."
,
placeholder
:
"
Any thoughts
..."
,
showConfirmBtn
:
true
,
showConfirmBtn
:
true
,
showCancelBtn
:
showEditStatus
,
showCancelBtn
:
showEditStatus
,
onConfirmBtnClick
:
handleSaveBtnClick
,
onConfirmBtnClick
:
handleSaveBtnClick
,
...
@@ -282,7 +282,7 @@ const MemoEditor: React.FC<Props> = () => {
...
@@ -282,7 +282,7 @@ const MemoEditor: React.FC<Props> = () => {
return
(
return
(
<
div
className=
{
"memo-editor-wrapper "
+
(
showEditStatus
?
"edit-ing"
:
""
)
}
>
<
div
className=
{
"memo-editor-wrapper "
+
(
showEditStatus
?
"edit-ing"
:
""
)
}
>
<
p
className=
{
"tip-text "
+
(
showEditStatus
?
""
:
"hidden"
)
}
>
正在修改中
...
</
p
>
<
p
className=
{
"tip-text "
+
(
showEditStatus
?
""
:
"hidden"
)
}
>
Editting
...
</
p
>
<
Editor
<
Editor
ref=
{
editorRef
}
ref=
{
editorRef
}
{
...
editorConfig
}
{
...
editorConfig
}
...
...
web/src/components/MemoFilter.tsx
View file @
226e9c15
...
@@ -18,7 +18,7 @@ const MemoFilter: React.FC<FilterProps> = () => {
...
@@ -18,7 +18,7 @@ const MemoFilter: React.FC<FilterProps> = () => {
return
(
return
(
<
div
className=
{
`filter-query-container ${showFilter ? "" : "hidden"}`
}
>
<
div
className=
{
`filter-query-container ${showFilter ? "" : "hidden"}`
}
>
<
span
className=
"tip-text"
>
筛选:
</
span
>
<
span
className=
"tip-text"
>
Filter:
</
span
>
<
div
<
div
className=
{
"filter-item-container "
+
(
queryFilter
?
""
:
"hidden"
)
}
className=
{
"filter-item-container "
+
(
queryFilter
?
""
:
"hidden"
)
}
onClick=
{
()
=>
{
onClick=
{
()
=>
{
...
...
web/src/components/MemoList.tsx
View file @
226e9c15
...
@@ -83,7 +83,7 @@ const MemoList: React.FC<Props> = () => {
...
@@ -83,7 +83,7 @@ const MemoList: React.FC<Props> = () => {
setFetchStatus
(
false
);
setFetchStatus
(
false
);
})
})
.
catch
(()
=>
{
.
catch
(()
=>
{
toastHelper
.
error
(
"😭
请求数据失败了
"
);
toastHelper
.
error
(
"😭
Refresh failed, please try again later.
"
);
});
});
}
, []);
}
, []);
...
@@ -111,7 +111,13 @@ const MemoList: React.FC<Props> = () => {
...
@@ -111,7 +111,13 @@ const MemoList: React.FC<Props> = () => {
))
}
))
}
<
div
className=
"status-text-container"
>
<
div
className=
"status-text-container"
>
<
p
className=
"status-text"
>
<
p
className=
"status-text"
>
{
isFetching
?
"努力请求数据中..."
:
shownMemos
.
length
===
0
?
"空空如也"
:
showMemoFilter
?
""
:
"所有数据加载完啦 🎉"
}
{
isFetching
?
"Fetching data..."
:
shownMemos
.
length
===
0
?
"Oops, there is nothing"
:
showMemoFilter
?
""
:
"Fetching completed 🎉"
}
</
p
>
</
p
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/MenuBtnsPopup.tsx
View file @
226e9c15
...
@@ -49,16 +49,16 @@ const MenuBtnsPopup: React.FC<Props> = (props: Props) => {
...
@@ -49,16 +49,16 @@ const MenuBtnsPopup: React.FC<Props> = (props: Props) => {
return
(
return
(
<
div
className=
{
`menu-btns-popup ${shownStatus ? "" : "hidden"}`
}
ref=
{
popupElRef
}
>
<
div
className=
{
`menu-btns-popup ${shownStatus ? "" : "hidden"}`
}
ref=
{
popupElRef
}
>
<
button
className=
"btn action-btn"
onClick=
{
handleMyAccountBtnClick
}
>
<
button
className=
"btn action-btn"
onClick=
{
handleMyAccountBtnClick
}
>
<
span
className=
"icon"
>
👤
</
span
>
账号与设置
<
span
className=
"icon"
>
👤
</
span
>
Settings
</
button
>
</
button
>
<
button
className=
"btn action-btn"
onClick=
{
handleMemosTrashBtnClick
}
>
<
button
className=
"btn action-btn"
onClick=
{
handleMemosTrashBtnClick
}
>
<
span
className=
"icon"
>
🗑️
</
span
>
回收站
<
span
className=
"icon"
>
🗑️
</
span
>
Recycle Bin
</
button
>
</
button
>
<
button
className=
"btn action-btn"
onClick=
{
handleAboutBtnClick
}
>
<
button
className=
"btn action-btn"
onClick=
{
handleAboutBtnClick
}
>
<
span
className=
"icon"
>
🤠
</
span
>
关于
<
span
className=
"icon"
>
🤠
</
span
>
About
</
button
>
</
button
>
<
button
className=
"btn action-btn"
onClick=
{
handleSignOutBtnClick
}
>
<
button
className=
"btn action-btn"
onClick=
{
handleSignOutBtnClick
}
>
<
span
className=
"icon"
>
👋
</
span
>
退出
<
span
className=
"icon"
>
👋
</
span
>
Sign out
</
button
>
</
button
>
</
div
>
</
div
>
);
);
...
...
web/src/components/MyAccountSection.tsx
View file @
226e9c15
...
@@ -30,7 +30,7 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -30,7 +30,7 @@ const MyAccountSection: React.FC<Props> = () => {
const
handleConfirmEditUsernameBtnClick
=
async
()
=>
{
const
handleConfirmEditUsernameBtnClick
=
async
()
=>
{
if
(
user
.
name
===
"guest"
)
{
if
(
user
.
name
===
"guest"
)
{
toastHelper
.
info
(
"
🈲 不要修改我的用户名
"
);
toastHelper
.
info
(
"
Do not change my username
"
);
return
;
return
;
}
}
...
@@ -40,7 +40,7 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -40,7 +40,7 @@ const MyAccountSection: React.FC<Props> = () => {
const
usernameValidResult
=
validate
(
username
,
validateConfig
);
const
usernameValidResult
=
validate
(
username
,
validateConfig
);
if
(
!
usernameValidResult
.
result
)
{
if
(
!
usernameValidResult
.
result
)
{
toastHelper
.
error
(
"
用户名
"
+
usernameValidResult
.
reason
);
toastHelper
.
error
(
"
Username
"
+
usernameValidResult
.
reason
);
return
;
return
;
}
}
...
@@ -48,13 +48,13 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -48,13 +48,13 @@ const MyAccountSection: React.FC<Props> = () => {
const
isUsable
=
await
userService
.
checkUsernameUsable
(
username
);
const
isUsable
=
await
userService
.
checkUsernameUsable
(
username
);
if
(
!
isUsable
)
{
if
(
!
isUsable
)
{
toastHelper
.
error
(
"
用户名无法使用
"
);
toastHelper
.
error
(
"
Username is not available
"
);
return
;
return
;
}
}
await
userService
.
updateUsername
(
username
);
await
userService
.
updateUsername
(
username
);
await
userService
.
doSignIn
();
await
userService
.
doSignIn
();
toastHelper
.
info
(
"
修改成功~
"
);
toastHelper
.
info
(
"
Username changed
"
);
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
toastHelper
.
error
(
error
.
message
);
toastHelper
.
error
(
error
.
message
);
}
}
...
@@ -62,7 +62,7 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -62,7 +62,7 @@ const MyAccountSection: React.FC<Props> = () => {
const
handleChangePasswordBtnClick
=
()
=>
{
const
handleChangePasswordBtnClick
=
()
=>
{
if
(
user
.
name
===
"guest"
)
{
if
(
user
.
name
===
"guest"
)
{
toastHelper
.
info
(
"
🈲 不要修改我的密码
"
);
toastHelper
.
info
(
"
Do not change my password
"
);
return
;
return
;
}
}
...
@@ -81,21 +81,21 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -81,21 +81,21 @@ const MyAccountSection: React.FC<Props> = () => {
return
(
return
(
<>
<>
<
div
className=
"section-container account-section-container"
>
<
div
className=
"section-container account-section-container"
>
<
p
className=
"title-text"
>
基本信息
</
p
>
<
p
className=
"title-text"
>
Account Information
</
p
>
<
label
className=
"form-label input-form-label"
>
<
label
className=
"form-label input-form-label"
>
<
span
className=
"normal-text"
>
ID
:
</
span
>
<
span
className=
"normal-text"
>
ID
:
</
span
>
<
span
className=
"normal-text"
>
{
user
.
id
}
</
span
>
<
span
className=
"normal-text"
>
{
user
.
id
}
</
span
>
</
label
>
</
label
>
<
label
className=
"form-label input-form-label"
>
<
label
className=
"form-label input-form-label"
>
<
span
className=
"normal-text"
>
创建时间:
</
span
>
<
span
className=
"normal-text"
>
Created at:
</
span
>
<
span
className=
"normal-text"
>
{
utils
.
getDateString
(
user
.
createdAt
)
}
</
span
>
<
span
className=
"normal-text"
>
{
utils
.
getDateString
(
user
.
createdAt
)
}
</
span
>
</
label
>
</
label
>
<
label
className=
"form-label input-form-label username-label"
>
<
label
className=
"form-label input-form-label username-label"
>
<
span
className=
"normal-text"
>
账号:
</
span
>
<
span
className=
"normal-text"
>
Username:
</
span
>
<
input
type=
"text"
value=
{
username
}
onChange=
{
handleUsernameChanged
}
/>
<
input
type=
"text"
value=
{
username
}
onChange=
{
handleUsernameChanged
}
/>
<
div
className=
{
`btns-container ${username === user.name ? "hidden" : ""}`
}
onClick=
{
handlePreventDefault
}
>
<
div
className=
{
`btns-container ${username === user.name ? "hidden" : ""}`
}
onClick=
{
handlePreventDefault
}
>
<
span
className=
"btn confirm-btn"
onClick=
{
handleConfirmEditUsernameBtnClick
}
>
<
span
className=
"btn confirm-btn"
onClick=
{
handleConfirmEditUsernameBtnClick
}
>
保存
Save
</
span
>
</
span
>
<
span
<
span
className=
"btn cancel-btn"
className=
"btn cancel-btn"
...
@@ -103,25 +103,25 @@ const MyAccountSection: React.FC<Props> = () => {
...
@@ -103,25 +103,25 @@ const MyAccountSection: React.FC<Props> = () => {
setUsername
(
user
.
name
);
setUsername
(
user
.
name
);
}
}
}
}
>
>
撤销
Cancel
</
span
>
</
span
>
</
div
>
</
div
>
</
label
>
</
label
>
<
label
className=
"form-label password-label"
>
<
label
className=
"form-label password-label"
>
<
span
className=
"normal-text"
>
密码:
</
span
>
<
span
className=
"normal-text"
>
Password:
</
span
>
<
span
className=
"btn"
onClick=
{
handleChangePasswordBtnClick
}
>
<
span
className=
"btn"
onClick=
{
handleChangePasswordBtnClick
}
>
修改密码
Change It
</
span
>
</
span
>
</
label
>
</
label
>
</
div
>
</
div
>
<
div
className=
"section-container openapi-section-container"
>
<
div
className=
"section-container openapi-section-container"
>
<
p
className=
"title-text"
>
Open API
(实验性功能)
</
p
>
<
p
className=
"title-text"
>
Open API
(Experimental feature)
</
p
>
<
p
className=
"value-text"
>
{
openAPIRoute
}
</
p
>
<
p
className=
"value-text"
>
{
openAPIRoute
}
</
p
>
<
span
className=
"reset-btn"
onClick=
{
handleResetOpenIdBtnClick
}
>
<
span
className=
"reset-btn"
onClick=
{
handleResetOpenIdBtnClick
}
>
重置
API
Reset
API
</
span
>
</
span
>
<
div
className=
"usage-guide-container"
>
<
div
className=
"usage-guide-container"
>
<
p
className=
"title-text"
>
使用方法:
</
p
>
<
p
className=
"title-text"
>
Usage guide:
</
p
>
<
pre
>
{
`POST ${openAPIRoute}\nContent-type: application/json\n{\n "content": "Hello, #memos ${window.location.origin}"\n}`
}
</
pre
>
<
pre
>
{
`POST ${openAPIRoute}\nContent-type: application/json\n{\n "content": "Hello, #memos ${window.location.origin}"\n}`
}
</
pre
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/PreferencesSection.tsx
View file @
226e9c15
...
@@ -11,7 +11,7 @@ const PreferencesSection: React.FC<Props> = () => {
...
@@ -11,7 +11,7 @@ const PreferencesSection: React.FC<Props> = () => {
const
{
globalState
}
=
useContext
(
appContext
);
const
{
globalState
}
=
useContext
(
appContext
);
const
{
useTinyUndoHistoryCache
,
shouldHideImageUrl
,
shouldSplitMemoWord
,
shouldUseMarkdownParser
}
=
globalState
;
const
{
useTinyUndoHistoryCache
,
shouldHideImageUrl
,
shouldSplitMemoWord
,
shouldUseMarkdownParser
}
=
globalState
;
const
demoMemoContent
=
"👋
你好呀~欢迎使用memos!
\n
* ✨ **开源项目**;
\n
* 😋 精美且细节的视觉样式;
\n
* 📑 体验优良的交互逻辑;
"
;
const
demoMemoContent
=
"👋
Hiya, welcome to memos!
\n
* ✨ **Open source project**;
\n
* 😋 What do you think;
\n
* 📑 Tell me something plz;
"
;
const
handleOpenTinyUndoChanged
=
()
=>
{
const
handleOpenTinyUndoChanged
=
()
=>
{
globalStateService
.
setAppSetting
({
globalStateService
.
setAppSetting
({
...
@@ -65,29 +65,29 @@ const PreferencesSection: React.FC<Props> = () => {
...
@@ -65,29 +65,29 @@ const PreferencesSection: React.FC<Props> = () => {
return
(
return
(
<>
<>
<
div
className=
"section-container preferences-section-container"
>
<
div
className=
"section-container preferences-section-container"
>
<
p
className=
"title-text"
>
Memo
显示相关
</
p
>
<
p
className=
"title-text"
>
Memo
Display
</
p
>
<
div
<
div
className=
"demo-content-container memo-content-text"
className=
"demo-content-container memo-content-text"
dangerouslySetInnerHTML=
{
{
__html
:
formatMemoContent
(
demoMemoContent
)
}
}
dangerouslySetInnerHTML=
{
{
__html
:
formatMemoContent
(
demoMemoContent
)
}
}
></
div
>
></
div
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleSplitWordsValueChanged
}
>
<
label
className=
"form-label checkbox-form-label
hidden
"
onClick=
{
handleSplitWordsValueChanged
}
>
<
span
className=
"normal-text"
>
中英文内容自动间隔
</
span
>
<
span
className=
"normal-text"
>
Auto-space in English and Chinese
</
span
>
<
img
className=
"icon-img"
src=
{
shouldSplitMemoWord
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
<
img
className=
"icon-img"
src=
{
shouldSplitMemoWord
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
</
label
>
</
label
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleUseMarkdownParserChanged
}
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleUseMarkdownParserChanged
}
>
<
span
className=
"normal-text"
>
部分 markdown 格式解析
</
span
>
<
span
className=
"normal-text"
>
Partial markdown format parsing
</
span
>
<
img
className=
"icon-img"
src=
{
shouldUseMarkdownParser
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
<
img
className=
"icon-img"
src=
{
shouldUseMarkdownParser
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
</
label
>
</
label
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleHideImageUrlValueChanged
}
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleHideImageUrlValueChanged
}
>
<
span
className=
"normal-text"
>
隐藏图片链接地址
</
span
>
<
span
className=
"normal-text"
>
Hide image url
</
span
>
<
img
className=
"icon-img"
src=
{
shouldHideImageUrl
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
<
img
className=
"icon-img"
src=
{
shouldHideImageUrl
?
"/icons/checkbox-active.svg"
:
"/icons/checkbox.svg"
}
/>
</
label
>
</
label
>
</
div
>
</
div
>
<
div
className=
"section-container preferences-section-container"
>
<
div
className=
"section-container preferences-section-container"
>
<
p
className=
"title-text"
>
编辑器
</
p
>
<
p
className=
"title-text"
>
Editor Extensions
</
p
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleOpenTinyUndoChanged
}
>
<
label
className=
"form-label checkbox-form-label"
onClick=
{
handleOpenTinyUndoChanged
}
>
<
span
className=
"normal-text"
>
<
span
className=
"normal-text"
>
启用
{
" "
}
Use
{
" "
}
<
a
target=
"_blank"
href=
"https://github.com/boojack/tiny-undo"
onClick=
{
(
e
)
=>
e
.
stopPropagation
()
}
rel=
"noreferrer"
>
<
a
target=
"_blank"
href=
"https://github.com/boojack/tiny-undo"
onClick=
{
(
e
)
=>
e
.
stopPropagation
()
}
rel=
"noreferrer"
>
tiny-undo
tiny-undo
</
a
>
</
a
>
...
@@ -96,13 +96,13 @@ const PreferencesSection: React.FC<Props> = () => {
...
@@ -96,13 +96,13 @@ const PreferencesSection: React.FC<Props> = () => {
</
label
>
</
label
>
</
div
>
</
div
>
<
div
className=
"section-container"
>
<
div
className=
"section-container"
>
<
p
className=
"title-text"
>
其他
</
p
>
<
p
className=
"title-text"
>
Others
</
p
>
<
div
className=
"w-full flex flex-row justify-start items-center"
>
<
div
className=
"w-full flex flex-row justify-start items-center"
>
<
button
className=
"px-2 py-1 border rounded text-base hover:opacity-80"
onClick=
{
handleExportBtnClick
}
>
<
button
className=
"px-2 py-1 border rounded text-base hover:opacity-80"
onClick=
{
handleExportBtnClick
}
>
导出数据(JSON)
Export data as JSON
</
button
>
</
button
>
<
button
className=
"btn format-btn hidden"
onClick=
{
handleFormatMemosBtnClick
}
>
<
button
className=
"btn format-btn hidden"
onClick=
{
handleFormatMemosBtnClick
}
>
格式化数据
Format Data
</
button
>
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/PreviewImageDialog.tsx
View file @
226e9c15
...
@@ -43,8 +43,8 @@ const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrl }: Props) => {
...
@@ -43,8 +43,8 @@ const PreviewImageDialog: React.FC<Props> = ({ destroy, imgUrl }: Props) => {
<
div
className=
"img-container"
>
<
div
className=
"img-container"
>
<
img
className=
{
imgWidth
<=
0
?
"hidden"
:
""
}
ref=
{
imgRef
}
width=
{
imgWidth
+
"%"
}
src=
{
imgUrl
}
/>
<
img
className=
{
imgWidth
<=
0
?
"hidden"
:
""
}
ref=
{
imgRef
}
width=
{
imgWidth
+
"%"
}
src=
{
imgUrl
}
/>
<
span
className=
{
"loading-text "
+
(
imgWidth
===
-
1
?
""
:
"hidden"
)
}
>
图片加载中
...
</
span
>
<
span
className=
{
"loading-text "
+
(
imgWidth
===
-
1
?
""
:
"hidden"
)
}
>
Loading image
...
</
span
>
<
span
className=
{
"loading-text "
+
(
imgWidth
===
0
?
""
:
"hidden"
)
}
>
😟
图片加载失败,可能是无效的链接
</
span
>
<
span
className=
{
"loading-text "
+
(
imgWidth
===
0
?
""
:
"hidden"
)
}
>
😟
Failed to load image
</
span
>
</
div
>
</
div
>
<
div
className=
"action-btns-container"
>
<
div
className=
"action-btns-container"
>
...
...
web/src/components/SearchBar.tsx
View file @
226e9c15
...
@@ -36,7 +36,7 @@ const SearchBar: React.FC<Props> = () => {
...
@@ -36,7 +36,7 @@ const SearchBar: React.FC<Props> = () => {
<
div
className=
"quickly-action-container"
>
<
div
className=
"quickly-action-container"
>
<
p
className=
"title-text"
>
QUICKLY FILTER
</
p
>
<
p
className=
"title-text"
>
QUICKLY FILTER
</
p
>
<
div
className=
"section-container types-container"
>
<
div
className=
"section-container types-container"
>
<
span
className=
"section-text"
>
类型
:
</
span
>
<
span
className=
"section-text"
>
Type
:
</
span
>
<
div
className=
"values-container"
>
<
div
className=
"values-container"
>
{
memoSpecialTypes
.
map
((
t
,
idx
)
=>
{
{
memoSpecialTypes
.
map
((
t
,
idx
)
=>
{
return
(
return
(
...
...
web/src/components/ShareMemoImageDialog.tsx
View file @
226e9c15
...
@@ -65,7 +65,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
...
@@ -65,7 +65,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
<>
<>
<
div
className=
"dialog-header-container"
>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
<
p
className=
"title-text"
>
<
span
className=
"icon-text"
>
🥰
</
span
>
分享 Memo 图片
<
span
className=
"icon-text"
>
🥰
</
span
>
Share Memo
</
p
>
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
button
className=
"btn close-btn"
onClick=
{
handleCloseBtnClick
}
>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/close.svg"
/>
...
@@ -73,7 +73,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
...
@@ -73,7 +73,7 @@ const ShareMemoImageDialog: React.FC<Props> = (props: Props) => {
</
div
>
</
div
>
<
div
className=
"dialog-content-container"
>
<
div
className=
"dialog-content-container"
>
<
div
className=
{
`tip-words-container ${shortcutImgUrl ? "finish" : "loading"}`
}
>
<
div
className=
{
`tip-words-container ${shortcutImgUrl ? "finish" : "loading"}`
}
>
<
p
className=
"tip-text"
>
{
shortcutImgUrl
?
"
右键或长按即可保存图片 👇"
:
"图片生成中
..."
}
</
p
>
<
p
className=
"tip-text"
>
{
shortcutImgUrl
?
"
Right click or long press to save image 👇"
:
"Generating the screenshot
..."
}
</
p
>
</
div
>
</
div
>
<
div
className=
"memo-container"
ref=
{
memoElRef
}
>
<
div
className=
"memo-container"
ref=
{
memoElRef
}
>
<
Only
when=
{
shortcutImgUrl
!==
""
}
>
<
Only
when=
{
shortcutImgUrl
!==
""
}
>
...
...
web/src/components/ShortcutList.tsx
View file @
226e9c15
...
@@ -37,7 +37,7 @@ const ShortcutList: React.FC<Props> = () => {
...
@@ -37,7 +37,7 @@ const ShortcutList: React.FC<Props> = () => {
return
(
return
(
<
div
className=
"shortcuts-wrapper"
>
<
div
className=
"shortcuts-wrapper"
>
<
p
className=
"title-text"
>
<
p
className=
"title-text"
>
<
span
className=
"normal-text"
>
快速检索
</
span
>
<
span
className=
"normal-text"
>
Shortcuts
</
span
>
<
span
className=
"btn"
onClick=
{
()
=>
showCreateQueryDialog
()
}
>
<
span
className=
"btn"
onClick=
{
()
=>
showCreateQueryDialog
()
}
>
+
+
</
span
>
</
span
>
...
@@ -45,7 +45,7 @@ const ShortcutList: React.FC<Props> = () => {
...
@@ -45,7 +45,7 @@ const ShortcutList: React.FC<Props> = () => {
<
Only
when=
{
loadingState
.
isSucceed
&&
sortedShortcuts
.
length
===
0
}
>
<
Only
when=
{
loadingState
.
isSucceed
&&
sortedShortcuts
.
length
===
0
}
>
<
div
className=
"create-shortcut-btn-container"
>
<
div
className=
"create-shortcut-btn-container"
>
<
span
className=
"btn"
onClick=
{
()
=>
showCreateQueryDialog
()
}
>
<
span
className=
"btn"
onClick=
{
()
=>
showCreateQueryDialog
()
}
>
创建检索
New shortcut
</
span
>
</
span
>
</
div
>
</
div
>
</
Only
>
</
Only
>
...
@@ -147,17 +147,17 @@ const ShortcutContainer: React.FC<ShortcutContainerProps> = (props: ShortcutCont
...
@@ -147,17 +147,17 @@ const ShortcutContainer: React.FC<ShortcutContainerProps> = (props: ShortcutCont
<
div
className=
{
`action-btns-wrapper ${showActionBtns ? "" : "hidden"}`
}
onMouseLeave=
{
handleActionBtnContainerMouseLeave
}
>
<
div
className=
{
`action-btns-wrapper ${showActionBtns ? "" : "hidden"}`
}
onMouseLeave=
{
handleActionBtnContainerMouseLeave
}
>
<
div
className=
"action-btns-container"
>
<
div
className=
"action-btns-container"
>
<
span
className=
"btn"
onClick=
{
handlePinQueryBtnClick
}
>
<
span
className=
"btn"
onClick=
{
handlePinQueryBtnClick
}
>
{
shortcut
.
rowStatus
===
"ARCHIVED"
?
"
取消置顶"
:
"置顶
"
}
{
shortcut
.
rowStatus
===
"ARCHIVED"
?
"
Unpin"
:
"Pin
"
}
</
span
>
</
span
>
<
span
className=
"btn"
onClick=
{
handleEditQueryBtnClick
}
>
<
span
className=
"btn"
onClick=
{
handleEditQueryBtnClick
}
>
编辑
Edit
</
span
>
</
span
>
<
span
<
span
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
className=
{
`btn delete-btn ${showConfirmDeleteBtn ? "final-confirm" : ""}`
}
onClick=
{
handleDeleteMemoClick
}
onClick=
{
handleDeleteMemoClick
}
onMouseLeave=
{
handleDeleteBtnMouseLeave
}
onMouseLeave=
{
handleDeleteBtnMouseLeave
}
>
>
{
showConfirmDeleteBtn
?
"
确定删除!"
:
"删除
"
}
{
showConfirmDeleteBtn
?
"
Delete!"
:
"Delete
"
}
</
span
>
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/components/TagList.tsx
View file @
226e9c15
...
@@ -70,14 +70,14 @@ const TagList: React.FC<Props> = () => {
...
@@ -70,14 +70,14 @@ const TagList: React.FC<Props> = () => {
return
(
return
(
<
div
className=
"tags-wrapper"
>
<
div
className=
"tags-wrapper"
>
<
p
className=
"title-text"
>
常用标签
</
p
>
<
p
className=
"title-text"
>
Tags
</
p
>
<
div
className=
"tags-container"
>
<
div
className=
"tags-container"
>
{
tags
.
map
((
t
,
idx
)
=>
(
{
tags
.
map
((
t
,
idx
)
=>
(
<
TagItemContainer
key=
{
t
.
text
+
"-"
+
idx
}
tag=
{
t
}
tagQuery=
{
tagQuery
}
/>
<
TagItemContainer
key=
{
t
.
text
+
"-"
+
idx
}
tag=
{
t
}
tagQuery=
{
tagQuery
}
/>
))
}
))
}
<
Only
when=
{
tags
.
length
<
5
&&
memoService
.
initialized
}
>
<
Only
when=
{
tags
.
length
<
5
&&
memoService
.
initialized
}
>
<
p
className=
"tag-tip-container"
>
<
p
className=
"tag-tip-container"
>
输入
<
span
className=
"code-text"
>
# Tag
</
span
>
来创建标签吧~
Enter
<
span
className=
"code-text"
>
# Tag
</
span
>
to create a tag
</
p
>
</
p
>
</
Only
>
</
Only
>
</
div
>
</
div
>
...
...
web/src/components/common/DatePicker.tsx
View file @
226e9c15
...
@@ -58,7 +58,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
...
@@ -58,7 +58,7 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
<
img
className=
"icon-img"
src=
"/icons/arrow-left.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/arrow-left.svg"
/>
</
span
>
</
span
>
<
span
className=
"normal-text"
>
<
span
className=
"normal-text"
>
{
firstDate
.
getFullYear
()
}
年
{
firstDate
.
getMonth
()
+
1
}
月
{
firstDate
.
getFullYear
()
}
/
{
firstDate
.
getMonth
()
+
1
}
</
span
>
</
span
>
<
span
className=
"btn-text"
onClick=
{
()
=>
handleChangeMonthBtnClick
(
1
)
}
>
<
span
className=
"btn-text"
onClick=
{
()
=>
handleChangeMonthBtnClick
(
1
)
}
>
<
img
className=
"icon-img"
src=
"/icons/arrow-right.svg"
/>
<
img
className=
"icon-img"
src=
"/icons/arrow-right.svg"
/>
...
@@ -66,13 +66,13 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
...
@@ -66,13 +66,13 @@ const DatePicker: React.FC<DatePickerProps> = (props: DatePickerProps) => {
</
div
>
</
div
>
<
div
className=
"date-picker-day-container"
>
<
div
className=
"date-picker-day-container"
>
<
div
className=
"date-picker-day-header"
>
<
div
className=
"date-picker-day-header"
>
<
span
className=
"day-item"
>
周一
</
span
>
<
span
className=
"day-item"
>
Mon
</
span
>
<
span
className=
"day-item"
>
周二
</
span
>
<
span
className=
"day-item"
>
Tue
</
span
>
<
span
className=
"day-item"
>
周三
</
span
>
<
span
className=
"day-item"
>
Web
</
span
>
<
span
className=
"day-item"
>
周四
</
span
>
<
span
className=
"day-item"
>
Thu
</
span
>
<
span
className=
"day-item"
>
周五
</
span
>
<
span
className=
"day-item"
>
Fri
</
span
>
<
span
className=
"day-item"
>
周六
</
span
>
<
span
className=
"day-item"
>
Sat
</
span
>
<
span
className=
"day-item"
>
周日
</
span
>
<
span
className=
"day-item"
>
Sun
</
span
>
</
div
>
</
div
>
{
dayList
.
map
((
d
)
=>
{
{
dayList
.
map
((
d
)
=>
{
...
...
web/src/components/common/Selector.tsx
View file @
226e9c15
...
@@ -15,7 +15,7 @@ interface Props {
...
@@ -15,7 +15,7 @@ interface Props {
}
}
const
nullItem
=
{
const
nullItem
=
{
text
:
"
请选择
"
,
text
:
"
Select
"
,
value
:
""
,
value
:
""
,
};
};
...
...
web/src/helpers/consts.ts
View file @
226e9c15
//
移动端样式适配额外类名
//
mobile style addtion classname
export
const
SHOW_SIDERBAR_MOBILE_CLASSNAME
=
"mobile-show-sidebar"
;
export
const
SHOW_SIDERBAR_MOBILE_CLASSNAME
=
"mobile-show-sidebar"
;
//
默认动画持续时长
//
default animation duration
export
const
ANIMATION_DURATION
=
200
;
export
const
ANIMATION_DURATION
=
200
;
// toast
动画持续时长
// toast
animation duration
export
const
TOAST_ANIMATION_DURATION
=
400
;
export
const
TOAST_ANIMATION_DURATION
=
400
;
//
一天的毫秒数
//
millisecond in a day
export
const
DAILY_TIMESTAMP
=
3600
*
24
*
1000
;
export
const
DAILY_TIMESTAMP
=
3600
*
24
*
1000
;
//
标签 正则
//
tag regex
export
const
TAG_REG
=
/#
\s?(
.+
?)\s
/g
;
export
const
TAG_REG
=
/#
\s?(
.+
?)\s
/g
;
// URL
正则
// URL
regex
export
const
LINK_REG
=
/
(
https
?
:
\/\/[^\s
<
\\
*>'
]
+
)
/g
;
export
const
LINK_REG
=
/
(
https
?
:
\/\/[^\s
<
\\
*>'
]
+
)
/g
;
//
图片 正则
//
image regex
export
const
IMAGE_URL_REG
=
/
([^\s
<
\\
*>'
]
+
\.(
jpeg|jpg|gif|png|svg
))
/g
;
export
const
IMAGE_URL_REG
=
/
([^\s
<
\\
*>'
]
+
\.(
jpeg|jpg|gif|png|svg
))
/g
;
//
memo 关联正则
//
linked memo regex
export
const
MEMO_LINK_REG
=
/
\[
@
(
.+
?)\]\((
.+
?)\)
/g
;
export
const
MEMO_LINK_REG
=
/
\[
@
(
.+
?)\]\((
.+
?)\)
/g
;
web/src/helpers/filter.ts
View file @
226e9c15
import
{
IMAGE_URL_REG
,
LINK_REG
,
MEMO_LINK_REG
,
TAG_REG
}
from
"./consts"
;
import
{
IMAGE_URL_REG
,
LINK_REG
,
MEMO_LINK_REG
,
TAG_REG
}
from
"./consts"
;
export
const
relationConsts
=
[
export
const
relationConsts
=
[
{
text
:
"
且
"
,
value
:
"AND"
},
{
text
:
"
And
"
,
value
:
"AND"
},
{
text
:
"
或
"
,
value
:
"OR"
},
{
text
:
"
Or
"
,
value
:
"OR"
},
];
];
export
const
filterConsts
=
{
export
const
filterConsts
=
{
TAG
:
{
TAG
:
{
text
:
"Tag"
,
value
:
"TAG"
,
value
:
"TAG"
,
text
:
"标签"
,
operators
:
[
operators
:
[
{
{
text
:
"
包括
"
,
text
:
"
Contains
"
,
value
:
"CONTAIN"
,
value
:
"CONTAIN"
,
},
},
{
{
text
:
"
排除
"
,
text
:
"
Does not contain
"
,
value
:
"NOT_CONTAIN"
,
value
:
"NOT_CONTAIN"
,
},
},
],
],
},
},
TYPE
:
{
TYPE
:
{
text
:
"Type"
,
value
:
"TYPE"
,
value
:
"TYPE"
,
text
:
"类型"
,
operators
:
[
operators
:
[
{
{
text
:
"Is"
,
value
:
"IS"
,
value
:
"IS"
,
text
:
"是"
,
},
},
{
{
text
:
"Is not"
,
value
:
"IS_NOT"
,
value
:
"IS_NOT"
,
text
:
"不是"
,
},
},
],
],
values
:
[
values
:
[
{
{
text
:
"Connected"
,
value
:
"CONNECTED"
,
value
:
"CONNECTED"
,
text
:
"有关联"
,
},
},
{
{
text
:
"No tags"
,
value
:
"NOT_TAGGED"
,
value
:
"NOT_TAGGED"
,
text
:
"无标签"
,
},
},
{
{
text
:
"Has links"
,
value
:
"LINKED"
,
value
:
"LINKED"
,
text
:
"有超链接"
,
},
},
{
{
text
:
"Has images"
,
value
:
"IMAGED"
,
value
:
"IMAGED"
,
text
:
"有图片"
,
},
},
],
],
},
},
TEXT
:
{
TEXT
:
{
text
:
"Text"
,
value
:
"TEXT"
,
value
:
"TEXT"
,
text
:
"文本"
,
operators
:
[
operators
:
[
{
{
text
:
"Contain"
,
value
:
"CONTAIN"
,
value
:
"CONTAIN"
,
text
:
"包括"
,
},
},
{
{
text
:
"Does not contain"
,
value
:
"NOT_CONTAIN"
,
value
:
"NOT_CONTAIN"
,
text
:
"排除"
,
},
},
],
],
},
},
...
...
web/src/helpers/storage.ts
View file @
226e9c15
...
@@ -4,13 +4,10 @@ import { InputAction } from "tiny-undo";
...
@@ -4,13 +4,10 @@ import { InputAction } from "tiny-undo";
* Define storage data type
* Define storage data type
*/
*/
interface
StorageData
{
interface
StorageData
{
//
编辑器输入缓存内容
//
Editor content cache
editorContentCache
:
string
;
editorContentCache
:
string
;
// 分词开关
shouldSplitMemoWord
:
boolean
;
shouldSplitMemoWord
:
boolean
;
// 是否隐藏图片链接地址
shouldHideImageUrl
:
boolean
;
shouldHideImageUrl
:
boolean
;
// markdown 解析开关
shouldUseMarkdownParser
:
boolean
;
shouldUseMarkdownParser
:
boolean
;
// Editor setting
// Editor setting
...
...
web/src/helpers/validator.ts
View file @
226e9c15
//
验证器
//
Validator
// *
主要用于验证表单
// *
use for validating form data
const
chineseReg
=
/
[\u
3000
\u
3400-
\u
4DBF
\u
4E00-
\u
9FFF
]
/
;
const
chineseReg
=
/
[\u
3000
\u
3400-
\u
4DBF
\u
4E00-
\u
9FFF
]
/
;
export
interface
ValidatorConfig
{
export
interface
ValidatorConfig
{
//
最小长度
//
min length
minLength
:
number
;
minLength
:
number
;
//
最大长度
//
max length
maxLength
:
number
;
maxLength
:
number
;
//
无空格
//
no space
noSpace
:
boolean
;
noSpace
:
boolean
;
//
无中文
//
no chinese
noChinese
:
boolean
;
noChinese
:
boolean
;
}
}
...
@@ -18,7 +18,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
...
@@ -18,7 +18,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if
(
text
.
length
<
config
.
minLength
)
{
if
(
text
.
length
<
config
.
minLength
)
{
return
{
return
{
result
:
false
,
result
:
false
,
reason
:
"
长度过短
"
,
reason
:
"
Too short
"
,
};
};
}
}
}
}
...
@@ -27,7 +27,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
...
@@ -27,7 +27,7 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if
(
text
.
length
>
config
.
maxLength
)
{
if
(
text
.
length
>
config
.
maxLength
)
{
return
{
return
{
result
:
false
,
result
:
false
,
reason
:
"
长度超出
"
,
reason
:
"
Too long
"
,
};
};
}
}
}
}
...
@@ -35,14 +35,14 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
...
@@ -35,14 +35,14 @@ export function validate(text: string, config: Partial<ValidatorConfig>): { resu
if
(
config
.
noSpace
&&
text
.
includes
(
" "
))
{
if
(
config
.
noSpace
&&
text
.
includes
(
" "
))
{
return
{
return
{
result
:
false
,
result
:
false
,
reason
:
"
不应含有空格
"
,
reason
:
"
Don't allow space
"
,
};
};
}
}
if
(
config
.
noChinese
&&
chineseReg
.
test
(
text
))
{
if
(
config
.
noChinese
&&
chineseReg
.
test
(
text
))
{
return
{
return
{
result
:
false
,
result
:
false
,
reason
:
"
不应含有中文字符
"
,
reason
:
"
Don't allow chinese
"
,
};
};
}
}
...
...
web/src/labs/createStore.ts
View file @
226e9c15
...
@@ -15,8 +15,8 @@ export interface Store<S extends State, A extends Action> {
...
@@ -15,8 +15,8 @@ export interface Store<S extends State, A extends Action> {
}
}
/**
/**
*
简单实现的
Redux
*
Toy-
Redux
* @param preloadedState
初始
state
* @param preloadedState
initial
state
* @param reducer reducer pure function
* @param reducer reducer pure function
* @returns store
* @returns store
*/
*/
...
...
web/src/pages/MemoTrash.tsx
View file @
226e9c15
...
@@ -114,13 +114,13 @@ const MemoTrash: React.FC<Props> = () => {
...
@@ -114,13 +114,13 @@ const MemoTrash: React.FC<Props> = () => {
<
img
className=
"icon-img"
src=
"/icons/menu.svg"
alt=
"menu"
/>
<
img
className=
"icon-img"
src=
"/icons/menu.svg"
alt=
"menu"
/>
</
button
>
</
button
>
</
Only
>
</
Only
>
<
span
className=
"normal-text"
>
回收站
</
span
>
<
span
className=
"normal-text"
>
Recycle Bin
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
<
MemoFilter
/>
<
MemoFilter
/>
{
loadingState
.
isLoading
?
(
{
loadingState
.
isLoading
?
(
<
div
className=
"tip-text-container"
>
<
div
className=
"tip-text-container"
>
<
p
className=
"tip-text"
>
努力请求数据中
...
</
p
>
<
p
className=
"tip-text"
>
fetching data
...
</
p
>
</
div
>
</
div
>
)
:
deletedMemos
.
length
===
0
?
(
)
:
deletedMemos
.
length
===
0
?
(
<
div
className=
"tip-text-container"
>
<
div
className=
"tip-text-container"
>
...
...
web/src/pages/Setting.tsx
View file @
226e9c15
...
@@ -30,7 +30,7 @@ const Setting: React.FC<Props> = () => {
...
@@ -30,7 +30,7 @@ const Setting: React.FC<Props> = () => {
<
img
className=
"icon-img"
src=
"/icons/menu.svg"
alt=
"menu"
/>
<
img
className=
"icon-img"
src=
"/icons/menu.svg"
alt=
"menu"
/>
</
button
>
</
button
>
</
Only
>
</
Only
>
<
span
className=
"normal-text"
>
账号与设置
</
span
>
<
span
className=
"normal-text"
>
Settings
</
span
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/pages/Signin.tsx
View file @
226e9c15
...
@@ -55,13 +55,13 @@ const Signin: React.FC<Props> = () => {
...
@@ -55,13 +55,13 @@ const Signin: React.FC<Props> = () => {
const
usernameValidResult
=
validate
(
username
,
validateConfig
);
const
usernameValidResult
=
validate
(
username
,
validateConfig
);
if
(
!
usernameValidResult
.
result
)
{
if
(
!
usernameValidResult
.
result
)
{
toastHelper
.
error
(
"
用户名
"
+
usernameValidResult
.
reason
);
toastHelper
.
error
(
"
Username:
"
+
usernameValidResult
.
reason
);
return
;
return
;
}
}
const
passwordValidResult
=
validate
(
password
,
validateConfig
);
const
passwordValidResult
=
validate
(
password
,
validateConfig
);
if
(
!
passwordValidResult
.
result
)
{
if
(
!
passwordValidResult
.
result
)
{
toastHelper
.
error
(
"
密码
"
+
passwordValidResult
.
reason
);
toastHelper
.
error
(
"
Password:
"
+
passwordValidResult
.
reason
);
return
;
return
;
}
}
...
@@ -77,7 +77,7 @@ const Signin: React.FC<Props> = () => {
...
@@ -77,7 +77,7 @@ const Signin: React.FC<Props> = () => {
if
(
user
)
{
if
(
user
)
{
locationService
.
replaceHistory
(
"/"
);
locationService
.
replaceHistory
(
"/"
);
}
else
{
}
else
{
toastHelper
.
error
(
"😟
登录失败
"
);
toastHelper
.
error
(
"😟
Login failed
"
);
}
}
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
console
.
error
(
error
);
console
.
error
(
error
);
...
@@ -107,7 +107,7 @@ const Signin: React.FC<Props> = () => {
...
@@ -107,7 +107,7 @@ const Signin: React.FC<Props> = () => {
if
(
user
)
{
if
(
user
)
{
locationService
.
replaceHistory
(
"/"
);
locationService
.
replaceHistory
(
"/"
);
}
else
{
}
else
{
toastHelper
.
error
(
"😟
登录失败
"
);
toastHelper
.
error
(
"😟
Login failed
"
);
}
}
}
catch
(
error
:
any
)
{
}
catch
(
error
:
any
)
{
console
.
error
(
error
);
console
.
error
(
error
);
...
@@ -121,7 +121,7 @@ const Signin: React.FC<Props> = () => {
...
@@ -121,7 +121,7 @@ const Signin: React.FC<Props> = () => {
<
div
className=
"page-container"
>
<
div
className=
"page-container"
>
<
div
className=
"page-header-container"
>
<
div
className=
"page-header-container"
>
<
p
className=
"title-text"
>
<
p
className=
"title-text"
>
登录
Memos
<
span
className=
"icon-text"
>
✍️
</
span
>
Login to
Memos
<
span
className=
"icon-text"
>
✍️
</
span
>
</
p
>
</
p
>
</
div
>
</
div
>
{
showAutoSigninAsGuest
?
(
{
showAutoSigninAsGuest
?
(
...
@@ -132,13 +132,13 @@ const Signin: React.FC<Props> = () => {
...
@@ -132,13 +132,13 @@ const Signin: React.FC<Props> = () => {
className=
{
`btn guest-signin ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
className=
{
`btn guest-signin ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
onClick=
{
handleAutoSigninAsGuestBtnClick
}
onClick=
{
handleAutoSigninAsGuestBtnClick
}
>
>
👉
快速登录进行体验
👉
Login as Guest quickly
</
div
>
</
div
>
<
div
<
div
className=
{
`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
className=
{
`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
onClick=
{
handleSwitchAccountSigninBtnClick
}
onClick=
{
handleSwitchAccountSigninBtnClick
}
>
>
已有账号,我要自己登录
I have an account
</
div
>
</
div
>
</
div
>
</
div
>
</>
</>
...
@@ -146,11 +146,11 @@ const Signin: React.FC<Props> = () => {
...
@@ -146,11 +146,11 @@ const Signin: React.FC<Props> = () => {
<>
<>
<
div
className=
"page-content-container"
>
<
div
className=
"page-content-container"
>
<
div
className=
"form-item-container input-form-container"
>
<
div
className=
"form-item-container input-form-container"
>
<
span
className=
{
"normal-text "
+
(
username
===
""
?
""
:
"not-null"
)
}
>
账号
</
span
>
<
span
className=
{
"normal-text "
+
(
username
===
""
?
""
:
"not-null"
)
}
>
Usernmae
</
span
>
<
input
type=
"text"
autoComplete=
"off"
value=
{
username
}
onChange=
{
handleUsernameInputChanged
}
/>
<
input
type=
"text"
autoComplete=
"off"
value=
{
username
}
onChange=
{
handleUsernameInputChanged
}
/>
</
div
>
</
div
>
<
div
className=
"form-item-container input-form-container"
>
<
div
className=
"form-item-container input-form-container"
>
<
span
className=
{
"normal-text "
+
(
password
===
""
?
""
:
"not-null"
)
}
>
密码
</
span
>
<
span
className=
{
"normal-text "
+
(
password
===
""
?
""
:
"not-null"
)
}
>
Password
</
span
>
<
input
type=
"password"
autoComplete=
"off"
value=
{
password
}
onChange=
{
handlePasswordInputChanged
}
/>
<
input
type=
"password"
autoComplete=
"off"
value=
{
password
}
onChange=
{
handlePasswordInputChanged
}
/>
</
div
>
</
div
>
</
div
>
</
div
>
...
@@ -161,14 +161,14 @@ const Signin: React.FC<Props> = () => {
...
@@ -161,14 +161,14 @@ const Signin: React.FC<Props> = () => {
className=
{
`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
className=
{
`btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
onClick=
{
handleAutoSigninAsGuestBtnClick
}
onClick=
{
handleAutoSigninAsGuestBtnClick
}
>
>
体验一下
Login as Guest
</
button
>
</
button
>
<
span
className=
"split-text"
>
/
</
span
>
<
span
className=
"split-text"
>
/
</
span
>
<
button
<
button
className=
{
`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
className=
{
`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
onClick=
{
()
=>
handleSigninBtnsClick
(
"signup"
)
}
onClick=
{
()
=>
handleSigninBtnsClick
(
"signup"
)
}
>
>
注册
Sign up
</
button
>
</
button
>
<
span
className=
"split-text"
>
/
</
span
>
<
span
className=
"split-text"
>
/
</
span
>
<
button
<
button
...
@@ -176,7 +176,7 @@ const Signin: React.FC<Props> = () => {
...
@@ -176,7 +176,7 @@ const Signin: React.FC<Props> = () => {
className=
{
`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
className=
{
`btn signin-btn ${signinBtnsClickLoadingState.isLoading ? "requesting" : ""}`
}
onClick=
{
()
=>
handleSigninBtnsClick
(
"signin"
)
}
onClick=
{
()
=>
handleSigninBtnsClick
(
"signin"
)
}
>
>
登录
Login
</
button
>
</
button
>
</
div
>
</
div
>
</
div
>
</
div
>
...
...
web/src/services/resourceService.ts
View file @
226e9c15
...
@@ -10,7 +10,7 @@ class ResourceService {
...
@@ -10,7 +10,7 @@ class ResourceService {
const
{
name
:
filename
,
size
}
=
file
;
const
{
name
:
filename
,
size
}
=
file
;
if
(
size
>
5
<<
20
)
{
if
(
size
>
5
<<
20
)
{
return
Promise
.
reject
(
"
超过最大文件大小
5Mb"
);
return
Promise
.
reject
(
"
overload max size:
5Mb"
);
}
}
const
formData
=
new
FormData
();
const
formData
=
new
FormData
();
...
...
web/src/types/basic.d.ts
View file @
226e9c15
type
BasicType
=
undefined
|
null
|
boolean
|
number
|
string
|
Record
<
string
,
unknown
>
|
Array
<
BasicType
>
;
type
BasicType
=
undefined
|
null
|
boolean
|
number
|
string
|
Record
<
string
,
unknown
>
|
Array
<
BasicType
>
;
// 日期戳
type
DateStamp
=
number
;
type
DateStamp
=
number
;
// 时间戳
type
TimeStamp
=
number
;
type
TimeStamp
=
number
;
type
FunctionType
=
(...
args
:
unknown
[])
=>
unknown
;
type
FunctionType
=
(...
args
:
unknown
[])
=>
unknown
;
...
...
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