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
ccdcd3d1
Unverified
Commit
ccdcd3d1
authored
Mar 09, 2023
by
boojack
Committed by
GitHub
Mar 09, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: fold memo when content overflow (#1327)
* feat: fold memo when content overflow * chore: update
parent
8c774316
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
with
24 additions
and
64 deletions
+24
-64
DailyMemo.tsx
web/src/components/DailyMemo.tsx
+2
-5
Memo.tsx
web/src/components/Memo.tsx
+5
-9
MemoContent.tsx
web/src/components/MemoContent.tsx
+15
-36
PreferencesSection.tsx
web/src/components/Settings/PreferencesSection.tsx
+0
-8
ShareMemoDialog.tsx
web/src/components/ShareMemoDialog.tsx
+1
-1
memo-content.less
web/src/less/memo-content.less
+1
-3
user.ts
web/src/store/module/user.ts
+0
-1
setting.d.ts
web/src/types/modules/setting.d.ts
+0
-1
No files found.
web/src/components/DailyMemo.tsx
View file @
ccdcd3d1
import
*
as
utils
from
"../helpers/utils"
;
import
*
as
utils
from
"../helpers/utils"
;
import
MemoContent
,
{
DisplayConfig
}
from
"./MemoContent"
;
import
MemoContent
from
"./MemoContent"
;
import
MemoResources
from
"./MemoResources"
;
import
MemoResources
from
"./MemoResources"
;
import
"../less/daily-memo.less"
;
import
"../less/daily-memo.less"
;
...
@@ -10,9 +10,6 @@ interface Props {
...
@@ -10,9 +10,6 @@ interface Props {
const
DailyMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
DailyMemo
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memo
}
=
props
;
const
{
memo
}
=
props
;
const
createdTimeStr
=
utils
.
getTimeString
(
memo
.
createdTs
);
const
createdTimeStr
=
utils
.
getTimeString
(
memo
.
createdTs
);
const
displayConfig
:
DisplayConfig
=
{
enableExpand
:
false
,
};
return
(
return
(
<
div
className=
"daily-memo-wrapper"
>
<
div
className=
"daily-memo-wrapper"
>
...
@@ -20,7 +17,7 @@ const DailyMemo: React.FC<Props> = (props: Props) => {
...
@@ -20,7 +17,7 @@ const DailyMemo: React.FC<Props> = (props: Props) => {
<
span
className=
"normal-text"
>
{
createdTimeStr
}
</
span
>
<
span
className=
"normal-text"
>
{
createdTimeStr
}
</
span
>
</
div
>
</
div
>
<
div
className=
"memo-container"
>
<
div
className=
"memo-container"
>
<
MemoContent
content=
{
memo
.
content
}
displayConfig=
{
displayConfig
}
/>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
<
MemoResources
resourceList=
{
memo
.
resourceList
}
/>
<
MemoResources
resourceList=
{
memo
.
resourceList
}
/>
</
div
>
</
div
>
<
div
className=
"split-line"
></
div
>
<
div
className=
"split-line"
></
div
>
...
...
web/src/components/Memo.tsx
View file @
ccdcd3d1
import
{
Tooltip
}
from
"@mui/joy"
;
import
copy
from
"copy-to-clipboard"
;
import
copy
from
"copy-to-clipboard"
;
import
dayjs
from
"dayjs"
;
import
dayjs
from
"dayjs"
;
import
{
memo
,
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
memo
,
useEffect
,
useRef
,
useState
}
from
"react"
;
...
@@ -39,7 +38,6 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -39,7 +38,6 @@ const Memo: React.FC<Props> = (props: Props) => {
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getFormatedMemoTimeStr
(
memo
.
createdTs
,
i18n
.
language
));
const
[
createdTimeStr
,
setCreatedTimeStr
]
=
useState
<
string
>
(
getFormatedMemoTimeStr
(
memo
.
createdTs
,
i18n
.
language
));
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
isVisitorMode
=
userStore
.
isVisitorMode
()
||
readonly
;
const
isVisitorMode
=
userStore
.
isVisitorMode
()
||
readonly
;
const
updatedTimeStr
=
getFormatedMemoTimeStr
(
memo
.
updatedTs
,
i18n
.
language
);
useEffect
(()
=>
{
useEffect
(()
=>
{
let
intervalFlag
:
any
=
-
1
;
let
intervalFlag
:
any
=
-
1
;
...
@@ -111,7 +109,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -111,7 +109,7 @@ const Memo: React.FC<Props> = (props: Props) => {
}
}
};
};
const
handleGenMemoImageBtnClick
=
()
=>
{
const
handleGen
erate
MemoImageBtnClick
=
()
=>
{
showShareMemo
(
memo
);
showShareMemo
(
memo
);
};
};
...
@@ -203,11 +201,9 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -203,11 +201,9 @@ const Memo: React.FC<Props> = (props: Props) => {
{
memo
.
pinned
&&
<
div
className=
"corner-container"
></
div
>
}
{
memo
.
pinned
&&
<
div
className=
"corner-container"
></
div
>
}
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"memo-top-wrapper"
>
<
div
className=
"status-text-container"
>
<
div
className=
"status-text-container"
>
<
Tooltip
title=
{
`Updated at ${updatedTimeStr}`
}
placement=
"top"
arrow
>
<
span
className=
"time-text"
onDoubleClick=
{
handleMemoCreatedTimeClick
}
>
<
span
className=
"time-text"
onDoubleClick=
{
handleMemoCreatedTimeClick
}
>
{
createdTimeStr
}
{
createdTimeStr
}
</
span
>
</
span
>
</
Tooltip
>
{
isVisitorMode
&&
(
{
isVisitorMode
&&
(
<
a
className=
"name-text"
href=
{
`/u/${memo.creatorId}`
}
>
<
a
className=
"name-text"
href=
{
`/u/${memo.creatorId}`
}
>
@
{
memo
.
creatorName
}
@
{
memo
.
creatorName
}
...
@@ -238,7 +234,7 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -238,7 +234,7 @@ const Memo: React.FC<Props> = (props: Props) => {
<
Icon
.
Edit3
className=
"icon-img"
/>
<
Icon
.
Edit3
className=
"icon-img"
/>
<
span
className=
"tip-text"
>
{
t
(
"common.edit"
)
}
</
span
>
<
span
className=
"tip-text"
>
{
t
(
"common.edit"
)
}
</
span
>
</
div
>
</
div
>
<
div
className=
"btn"
onClick=
{
handleGenMemoImageBtnClick
}
>
<
div
className=
"btn"
onClick=
{
handleGen
erate
MemoImageBtnClick
}
>
<
Icon
.
Share
className=
"icon-img"
/>
<
Icon
.
Share
className=
"icon-img"
/>
<
span
className=
"tip-text"
>
{
t
(
"common.share"
)
}
</
span
>
<
span
className=
"tip-text"
>
{
t
(
"common.share"
)
}
</
span
>
</
div
>
</
div
>
...
...
web/src/components/MemoContent.tsx
View file @
ccdcd3d1
import
{
useEffect
,
use
Memo
,
use
Ref
,
useState
}
from
"react"
;
import
{
useEffect
,
useRef
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useUserStore
}
from
"../store/module"
;
import
{
marked
}
from
"../labs/marked"
;
import
{
marked
}
from
"../labs/marked"
;
import
Icon
from
"./Icon"
;
import
Icon
from
"./Icon"
;
import
"../less/memo-content.less"
;
import
"../less/memo-content.less"
;
export
interface
DisplayConfig
{
const
MAX_EXPAND_HEIGHT
=
384
;
enableExpand
:
boolean
;
}
interface
Props
{
interface
Props
{
content
:
string
;
content
:
string
;
className
?:
string
;
className
?:
string
;
displayConfig
?:
Partial
<
DisplayConfig
>
;
showFull
?:
boolean
;
onMemoContentClick
?:
(
e
:
React
.
MouseEvent
)
=>
void
;
onMemoContentClick
?:
(
e
:
React
.
MouseEvent
)
=>
void
;
onMemoContentDoubleClick
?:
(
e
:
React
.
MouseEvent
)
=>
void
;
onMemoContentDoubleClick
?:
(
e
:
React
.
MouseEvent
)
=>
void
;
}
}
...
@@ -23,48 +20,29 @@ interface State {
...
@@ -23,48 +20,29 @@ interface State {
expandButtonStatus
:
ExpandButtonStatus
;
expandButtonStatus
:
ExpandButtonStatus
;
}
}
const
defaultDisplayConfig
:
DisplayConfig
=
{
enableExpand
:
true
,
};
const
MemoContent
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
MemoContent
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
className
,
content
,
onMemoContentClick
,
onMemoContentDoubleClick
}
=
props
;
const
{
className
,
content
,
showFull
,
onMemoContentClick
,
onMemoContentDoubleClick
}
=
props
;
const
{
t
}
=
useTranslation
();
const
{
t
}
=
useTranslation
();
const
userStore
=
useUserStore
();
const
user
=
userStore
.
state
.
user
;
const
foldedContent
=
useMemo
(()
=>
{
const
firstHorizontalRuleIndex
=
content
.
search
(
/^---$|^
\*\*\*
$|^___$/m
);
return
firstHorizontalRuleIndex
!==
-
1
?
content
.
slice
(
0
,
firstHorizontalRuleIndex
)
:
content
;
},
[
content
]);
const
[
state
,
setState
]
=
useState
<
State
>
({
const
[
state
,
setState
]
=
useState
<
State
>
({
expandButtonStatus
:
-
1
,
expandButtonStatus
:
-
1
,
});
});
const
memoContentContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
memoContentContainerRef
=
useRef
<
HTMLDivElement
>
(
null
);
const
displayConfig
=
{
...
defaultDisplayConfig
,
...
props
.
displayConfig
,
};
useEffect
(()
=>
{
useEffect
(()
=>
{
if
(
!
memoContentContainerRef
)
{
if
(
showFull
)
{
return
;
return
;
}
}
if
(
displayConfig
.
enableExpand
&&
user
&&
user
.
localSetting
.
enableFoldMemo
)
{
if
(
memoContentContainerRef
.
current
)
{
if
(
foldedContent
.
length
!==
content
.
length
)
{
const
height
=
memoContentContainerRef
.
current
.
clientHeight
;
if
(
height
>
MAX_EXPAND_HEIGHT
)
{
setState
({
setState
({
...
state
,
expandButtonStatus
:
0
,
expandButtonStatus
:
0
,
});
});
}
}
}
else
{
setState
({
...
state
,
expandButtonStatus
:
-
1
,
});
}
}
},
[
user
?.
localSetting
.
enableFoldMemo
,
content
]);
},
[]);
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
const
handleMemoContentClick
=
async
(
e
:
React
.
MouseEvent
)
=>
{
if
(
onMemoContentClick
)
{
if
(
onMemoContentClick
)
{
...
@@ -89,17 +67,18 @@ const MemoContent: React.FC<Props> = (props: Props) => {
...
@@ -89,17 +67,18 @@ const MemoContent: React.FC<Props> = (props: Props) => {
<
div
className=
{
`memo-content-wrapper ${className || ""}`
}
>
<
div
className=
{
`memo-content-wrapper ${className || ""}`
}
>
<
div
<
div
ref=
{
memoContentContainerRef
}
ref=
{
memoContentContainerRef
}
className=
{
`memo-content-text ${state.expandButtonStatus === 0 ? "
expanded
" : ""}`
}
className=
{
`memo-content-text ${state.expandButtonStatus === 0 ? "
max-h-64 overflow-y-hidden
" : ""}`
}
onClick=
{
handleMemoContentClick
}
onClick=
{
handleMemoContentClick
}
onDoubleClick=
{
handleMemoContentDoubleClick
}
onDoubleClick=
{
handleMemoContentDoubleClick
}
>
>
{
marked
(
state
.
expandButtonStatus
===
0
?
foldedContent
:
content
)
}
{
marked
(
content
)
}
</
div
>
</
div
>
{
state
.
expandButtonStatus
!==
-
1
&&
(
{
state
.
expandButtonStatus
!==
-
1
&&
(
<
div
className=
"expand-btn-container"
>
<
div
className=
{
`expand-btn-container ${state.expandButtonStatus === 0 && "!-mt-7"}`
}
>
<
span
className=
{
`btn ${state.expandButtonStatus === 0 ? "expand-btn" : "fold-btn"}`
}
onClick=
{
handleExpandBtnClick
}
>
<
div
className=
"absolute top-0 left-0 w-full h-full blur-lg bg-white"
></
div
>
<
span
className=
{
`btn z-10 ${state.expandButtonStatus === 0 ? "expand-btn" : "fold-btn"}`
}
onClick=
{
handleExpandBtnClick
}
>
{
state
.
expandButtonStatus
===
0
?
t
(
"common.expand"
)
:
t
(
"common.fold"
)
}
{
state
.
expandButtonStatus
===
0
?
t
(
"common.expand"
)
:
t
(
"common.fold"
)
}
<
Icon
.
ChevronRight
className=
"icon-img"
/>
<
Icon
.
ChevronRight
className=
"icon-img
opacity-80
"
/>
</
span
>
</
span
>
</
div
>
</
div
>
)
}
)
}
...
...
web/src/components/Settings/PreferencesSection.tsx
View file @
ccdcd3d1
...
@@ -40,10 +40,6 @@ const PreferencesSection = () => {
...
@@ -40,10 +40,6 @@ const PreferencesSection = () => {
await
userStore
.
upsertUserSetting
(
"resourceVisibility"
,
value
);
await
userStore
.
upsertUserSetting
(
"resourceVisibility"
,
value
);
};
};
const
handleIsFoldingEnabledChanged
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
userStore
.
upsertLocalSetting
({
...
localSetting
,
enableFoldMemo
:
event
.
target
.
checked
});
};
const
handleDoubleClickEnabledChanged
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
const
handleDoubleClickEnabledChanged
=
(
event
:
React
.
ChangeEvent
<
HTMLInputElement
>
)
=>
{
userStore
.
upsertLocalSetting
({
...
localSetting
,
enableDoubleClickEditing
:
event
.
target
.
checked
});
userStore
.
upsertLocalSetting
({
...
localSetting
,
enableDoubleClickEditing
:
event
.
target
.
checked
});
};
};
...
@@ -131,10 +127,6 @@ const PreferencesSection = () => {
...
@@ -131,10 +127,6 @@ const PreferencesSection = () => {
</
span
>
</
span
>
</
div
>
</
div
>
<
label
className=
"form-label selector"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.preference-section.enable-folding-memo"
)
}
</
span
>
<
Switch
className=
"ml-2"
checked=
{
localSetting
.
enableFoldMemo
}
onChange=
{
handleIsFoldingEnabledChanged
}
/>
</
label
>
<
label
className=
"form-label selector"
>
<
label
className=
"form-label selector"
>
<
span
className=
"normal-text"
>
{
t
(
"setting.preference-section.enable-double-click"
)
}
</
span
>
<
span
className=
"normal-text"
>
{
t
(
"setting.preference-section.enable-double-click"
)
}
</
span
>
<
Switch
className=
"ml-2"
checked=
{
localSetting
.
enableDoubleClickEditing
}
onChange=
{
handleDoubleClickEnabledChanged
}
/>
<
Switch
className=
"ml-2"
checked=
{
localSetting
.
enableDoubleClickEditing
}
onChange=
{
handleDoubleClickEnabledChanged
}
/>
...
...
web/src/components/ShareMemoDialog.tsx
View file @
ccdcd3d1
...
@@ -126,7 +126,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
...
@@ -126,7 +126,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
<
div
className=
"memo-container"
ref=
{
memoElRef
}
>
<
div
className=
"memo-container"
ref=
{
memoElRef
}
>
<
span
className=
"time-text"
>
{
memo
.
createdAtStr
}
</
span
>
<
span
className=
"time-text"
>
{
memo
.
createdAtStr
}
</
span
>
<
div
className=
"memo-content-wrapper"
>
<
div
className=
"memo-content-wrapper"
>
<
MemoContent
content=
{
memo
.
content
}
displayConfig=
{
{
enableExpand
:
false
}
}
/>
<
MemoContent
content=
{
memo
.
content
}
showFull=
{
true
}
/>
<
MemoResources
resourceList=
{
memo
.
resourceList
}
/>
<
MemoResources
resourceList=
{
memo
.
resourceList
}
/>
</
div
>
</
div
>
<
div
className=
"watermark-container"
>
<
div
className=
"watermark-container"
>
...
...
web/src/less/memo-content.less
View file @
ccdcd3d1
...
@@ -110,11 +110,9 @@
...
@@ -110,11 +110,9 @@
@apply w-full relative flex flex-row justify-start items-center;
@apply w-full relative flex flex-row justify-start items-center;
> .btn {
> .btn {
@apply flex flex-row justify-start items-center pl-2 pr-1 py-1 my-
1 text-xs rounded-lg border bg-gray-100 dark:bg-zinc-600 border-gray-200 dark:border-zinc-600 opacity-80 shadow hover:opacity-6
0 cursor-pointer;
@apply flex flex-row justify-start items-center pl-2 pr-1 py-1 my-
2 text-xs rounded-lg border bg-gray-100 dark:bg-zinc-600 border-gray-200 dark:border-zinc-600 shadow hover:opacity-9
0 cursor-pointer;
&.expand-btn {
&.expand-btn {
@apply mt-2;
> .icon-img {
> .icon-img {
@apply rotate-90;
@apply rotate-90;
}
}
...
...
web/src/store/module/user.ts
View file @
ccdcd3d1
...
@@ -14,7 +14,6 @@ const defaultSetting: Setting = {
...
@@ -14,7 +14,6 @@ const defaultSetting: Setting = {
};
};
const
defaultLocalSetting
:
LocalSetting
=
{
const
defaultLocalSetting
:
LocalSetting
=
{
enableFoldMemo
:
true
,
enableDoubleClickEditing
:
true
,
enableDoubleClickEditing
:
true
,
dailyReviewTimeOffset
:
0
,
dailyReviewTimeOffset
:
0
,
};
};
...
...
web/src/types/modules/setting.d.ts
View file @
ccdcd3d1
...
@@ -8,7 +8,6 @@ interface Setting {
...
@@ -8,7 +8,6 @@ interface Setting {
}
}
interface
LocalSetting
{
interface
LocalSetting
{
enableFoldMemo
:
boolean
;
enableDoubleClickEditing
:
boolean
;
enableDoubleClickEditing
:
boolean
;
dailyReviewTimeOffset
:
number
;
dailyReviewTimeOffset
:
number
;
}
}
...
...
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