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
96798e10
Unverified
Commit
96798e10
authored
Jan 06, 2023
by
boojack
Committed by
GitHub
Jan 06, 2023
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
feat: support embed memo with iframe (#912)
parent
0f8ce3dd
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
164 additions
and
13 deletions
+164
-13
EmbedMemoDialog.tsx
web/src/components/EmbedMemoDialog.tsx
+60
-0
Memo.tsx
web/src/components/Memo.tsx
+8
-0
ShareMemoDialog.tsx
web/src/components/ShareMemoDialog.tsx
+1
-1
global.css
web/src/css/global.css
+5
-1
auth.less
web/src/less/auth.less
+1
-1
explore.less
web/src/less/explore.less
+2
-2
home.less
web/src/less/home.less
+2
-2
memo-detail.less
web/src/less/memo-detail.less
+2
-2
memo.less
web/src/less/memo.less
+1
-1
siderbar.less
web/src/less/siderbar.less
+2
-2
EmbedMemo.tsx
web/src/pages/EmbedMemo.tsx
+65
-0
Loading.tsx
web/src/pages/Loading.tsx
+1
-1
index.tsx
web/src/router/index.tsx
+14
-0
No files found.
web/src/components/EmbedMemoDialog.tsx
0 → 100644
View file @
96798e10
import
React
from
"react"
;
import
Icon
from
"./Icon"
;
import
{
generateDialog
}
from
"./Dialog"
;
import
copy
from
"copy-to-clipboard"
;
import
toastHelper
from
"./Toast"
;
interface
Props
extends
DialogProps
{
memoId
:
MemoId
;
}
const
EmbedMemoDialog
:
React
.
FC
<
Props
>
=
(
props
:
Props
)
=>
{
const
{
memoId
,
destroy
}
=
props
;
const
memoEmbeddedCode
=
()
=>
{
return
`<iframe style="width:100%;height:auto;min-width:256px;" src="
${
window
.
location
.
origin
}
/m/
${
memoId
}
/embed" frameBorder="0"></iframe>`
;
};
const
handleCopyCode
=
()
=>
{
copy
(
memoEmbeddedCode
());
toastHelper
.
success
(
"Succeed to copy code to clipboard."
);
};
return
(
<>
<
div
className=
"dialog-header-container"
>
<
p
className=
"title-text"
>
Embed Memo
</
p
>
<
button
className=
"btn close-btn"
onClick=
{
()
=>
destroy
()
}
>
<
Icon
.
X
/>
</
button
>
</
div
>
<
div
className=
"dialog-content-container !w-80"
>
<
p
className=
"text-base leading-6 mb-2"
>
Copy and paste the below codes into your blog or website.
</
p
>
<
pre
className=
"w-full font-mono text-sm p-3 border rounded-lg"
>
<
code
className=
"w-full break-all whitespace-pre-wrap"
>
{
memoEmbeddedCode
()
}
</
code
>
</
pre
>
<
p
className=
"w-full text-sm leading-6 flex flex-row justify-between items-center mt-2"
>
* Only the public memo supports.
<
span
className=
"btn-primary"
onClick=
{
handleCopyCode
}
>
Copy
</
span
>
</
p
>
</
div
>
</>
);
};
function
showEmbedMemoDialog
(
memoId
:
MemoId
)
{
generateDialog
(
{
className
:
"embed-memo-dialog"
,
dialogName
:
"embed-memo-dialog"
,
},
EmbedMemoDialog
,
{
memoId
,
}
);
}
export
default
showEmbedMemoDialog
;
web/src/components/Memo.tsx
View file @
96798e10
...
@@ -10,6 +10,7 @@ import MemoContent from "./MemoContent";
...
@@ -10,6 +10,7 @@ import MemoContent from "./MemoContent";
import
MemoResources
from
"./MemoResources"
;
import
MemoResources
from
"./MemoResources"
;
import
showShareMemo
from
"./ShareMemoDialog"
;
import
showShareMemo
from
"./ShareMemoDialog"
;
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
showPreviewImageDialog
from
"./PreviewImageDialog"
;
import
showEmbedMemoDialog
from
"./EmbedMemoDialog"
;
import
showChangeMemoCreatedTsDialog
from
"./ChangeMemoCreatedTsDialog"
;
import
showChangeMemoCreatedTsDialog
from
"./ChangeMemoCreatedTsDialog"
;
import
"../less/memo.less"
;
import
"../less/memo.less"
;
...
@@ -54,6 +55,10 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -54,6 +55,10 @@ const Memo: React.FC<Props> = (props: Props) => {
navigate
(
`/m/
${
memo
.
id
}
`
);
navigate
(
`/m/
${
memo
.
id
}
`
);
};
};
const
handleShowEmbedMemoDialog
=
()
=>
{
showEmbedMemoDialog
(
memo
.
id
);
};
const
handleCopyContent
=
()
=>
{
const
handleCopyContent
=
()
=>
{
copy
(
memo
.
content
);
copy
(
memo
.
content
);
toastHelper
.
success
(
t
(
"message.succeed-copy-content"
));
toastHelper
.
success
(
t
(
"message.succeed-copy-content"
));
...
@@ -214,6 +219,9 @@ const Memo: React.FC<Props> = (props: Props) => {
...
@@ -214,6 +219,9 @@ const Memo: React.FC<Props> = (props: Props) => {
<
span
className=
"btn"
onClick=
{
handleViewMemoDetailPage
}
>
<
span
className=
"btn"
onClick=
{
handleViewMemoDetailPage
}
>
{
t
(
"memo.view-detail"
)
}
{
t
(
"memo.view-detail"
)
}
</
span
>
</
span
>
<
span
className=
"btn"
onClick=
{
handleShowEmbedMemoDialog
}
>
Embed memo
</
span
>
<
span
className=
"btn archive-btn"
onClick=
{
handleArchiveMemoClick
}
>
<
span
className=
"btn archive-btn"
onClick=
{
handleArchiveMemoClick
}
>
{
t
(
"common.archive"
)
}
{
t
(
"common.archive"
)
}
</
span
>
</
span
>
...
...
web/src/components/ShareMemoDialog.tsx
View file @
96798e10
...
@@ -99,7 +99,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
...
@@ -99,7 +99,7 @@ const ShareMemoDialog: React.FC<Props> = (props: Props) => {
const
handleCopyLinkBtnClick
=
()
=>
{
const
handleCopyLinkBtnClick
=
()
=>
{
copy
(
`
${
window
.
location
.
origin
}
/m/
${
memo
.
id
}
`
);
copy
(
`
${
window
.
location
.
origin
}
/m/
${
memo
.
id
}
`
);
toastHelper
.
success
(
t
(
"message.succeed-copy-content"
)
);
toastHelper
.
success
(
"Succeed to copy memo link to clipboard."
);
};
};
const
memoVisibilityOptionSelectorItems
=
VISIBILITY_SELECTOR_ITEMS
.
map
((
item
)
=>
{
const
memoVisibilityOptionSelectorItems
=
VISIBILITY_SELECTOR_ITEMS
.
map
((
item
)
=>
{
...
...
web/src/css/global.css
View file @
96798e10
html
,
html
,
body
{
body
{
@apply
text-base
dark
:
bg-zinc-800
;
@apply
text-base
w-full
h-full
dark
:
bg-zinc-800
;
font-family
:
-apple-system
,
BlinkMacSystemFont
,
"PingFang SC"
,
"Noto Sans"
,
"Noto Sans CJK SC"
,
"Microsoft YaHei UI"
,
"Microsoft YaHei"
,
font-family
:
-apple-system
,
BlinkMacSystemFont
,
"PingFang SC"
,
"Noto Sans"
,
"Noto Sans CJK SC"
,
"Microsoft YaHei UI"
,
"Microsoft YaHei"
,
"WenQuanYi Micro Hei"
,
sans-serif
,
"Segoe UI"
,
Roboto
,
"Helvetica Neue"
,
Arial
,
"Apple Color Emoji"
,
"Segoe UI Emoji"
,
"Segoe UI Symbol"
,
"WenQuanYi Micro Hei"
,
sans-serif
,
"Segoe UI"
,
Roboto
,
"Helvetica Neue"
,
Arial
,
"Apple Color Emoji"
,
"Segoe UI Emoji"
,
"Segoe UI Symbol"
,
"Noto Color Emoji"
;
"Noto Color Emoji"
;
}
}
#root
{
@apply
w-full
h-full;
}
web/src/less/auth.less
View file @
96798e10
.page-wrapper.auth {
.page-wrapper.auth {
@apply flex flex-row justify-center items-center w-full h-
screen
bg-zinc-100 dark:bg-zinc-800;
@apply flex flex-row justify-center items-center w-full h-
full
bg-zinc-100 dark:bg-zinc-800;
> .page-container {
> .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 ml-calc;
...
...
web/src/less/explore.less
View file @
96798e10
.page-wrapper.explore {
.page-wrapper.explore {
@apply relative top-0 w-full h-
screen
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
@apply relative top-0 w-full h-
full
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
> .page-container {
> .page-container {
@apply relative w-full min-h-
screen
mx-auto flex flex-col justify-start items-center pb-8;
@apply relative w-full min-h-
full
mx-auto flex flex-col justify-start items-center pb-8;
> .page-header {
> .page-header {
@apply sticky top-0 z-10 max-w-2xl w-full min-h-full flex flex-row justify-between backdrop-blur-sm items-center px-4 sm:pr-6 pt-6 mb-2 ml-calc;
@apply sticky top-0 z-10 max-w-2xl w-full min-h-full flex flex-row justify-between backdrop-blur-sm items-center px-4 sm:pr-6 pt-6 mb-2 ml-calc;
...
...
web/src/less/home.less
View file @
96798e10
.page-wrapper.home {
.page-wrapper.home {
@apply relative top-0 w-full h-
screen
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
@apply relative top-0 w-full h-
full
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
> .banner-wrapper {
> .banner-wrapper {
@apply w-full flex flex-col justify-start items-center;
@apply w-full flex flex-col justify-start items-center;
}
}
> .page-container {
> .page-container {
@apply relative w-full min-h-
screen
mx-auto flex flex-row justify-start sm:justify-center items-start;
@apply relative w-full min-h-
full
mx-auto flex flex-row justify-start sm:justify-center items-start;
> .sidebar-wrapper {
> .sidebar-wrapper {
@apply flex-shrink-0 ml-calc;
@apply flex-shrink-0 ml-calc;
...
...
web/src/less/memo-detail.less
View file @
96798e10
.page-wrapper.memo-detail {
.page-wrapper.memo-detail {
@apply relative top-0 w-full h-
screen
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
@apply relative top-0 w-full h-
full
overflow-y-auto overflow-x-hidden bg-zinc-100 dark:bg-zinc-800;
> .page-container {
> .page-container {
@apply relative w-full min-h-
screen
mx-auto flex flex-col justify-start items-center pb-8;
@apply relative w-full min-h-
full
mx-auto flex flex-col justify-start items-center pb-8;
> .page-header {
> .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 ml-calc;
...
...
web/src/less/memo.less
View file @
96798e10
...
@@ -54,7 +54,7 @@
...
@@ -54,7 +54,7 @@
@apply hidden flex-col justify-start items-center absolute top-2 -right-4 flex-nowrap hover:flex p-3;
@apply hidden flex-col justify-start items-center absolute top-2 -right-4 flex-nowrap hover:flex p-3;
> .more-action-btns-container {
> .more-action-btns-container {
@apply w-
28
h-auto p-1 z-1 whitespace-nowrap rounded-lg bg-white dark:bg-zinc-700;
@apply w-
auto
h-auto p-1 z-1 whitespace-nowrap rounded-lg bg-white dark:bg-zinc-700;
box-shadow: 0 0 8px 0 rgb(0 0 0 / 20%);
box-shadow: 0 0 8px 0 rgb(0 0 0 / 20%);
> .btns-container {
> .btns-container {
...
...
web/src/less/siderbar.less
View file @
96798e10
.sidebar-wrapper {
.sidebar-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-
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;
@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-
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 {
&.show {
@apply translate-x-0 shadow-2xl sm:shadow-none;
@apply translate-x-0 shadow-2xl sm:shadow-none;
...
@@ -19,7 +19,7 @@
...
@@ -19,7 +19,7 @@
}
}
.mask {
.mask {
@apply fixed top-0 left-0 w-
screen h-screen
bg-black opacity-0 transition-opacity duration-300 pointer-events-none z-20 sm:hidden;
@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 {
&.show {
@apply opacity-60 pointer-events-auto;
@apply opacity-60 pointer-events-auto;
...
...
web/src/pages/EmbedMemo.tsx
0 → 100644
View file @
96798e10
import
dayjs
from
"dayjs"
;
import
{
useEffect
,
useState
}
from
"react"
;
import
{
useTranslation
}
from
"react-i18next"
;
import
{
useParams
}
from
"react-router-dom"
;
import
{
UNKNOWN_ID
}
from
"../helpers/consts"
;
import
{
useMemoStore
}
from
"../store/module"
;
import
useLoading
from
"../hooks/useLoading"
;
import
toastHelper
from
"../components/Toast"
;
import
MemoContent
from
"../components/MemoContent"
;
import
MemoResources
from
"../components/MemoResources"
;
interface
State
{
memo
:
Memo
;
}
const
EmbedMemo
=
()
=>
{
const
{
i18n
}
=
useTranslation
();
const
params
=
useParams
();
const
memoStore
=
useMemoStore
();
const
[
state
,
setState
]
=
useState
<
State
>
({
memo
:
{
id
:
UNKNOWN_ID
,
}
as
Memo
,
});
const
loadingState
=
useLoading
();
useEffect
(()
=>
{
const
memoId
=
Number
(
params
.
memoId
);
if
(
memoId
&&
!
isNaN
(
memoId
))
{
memoStore
.
fetchMemoById
(
memoId
)
.
then
((
memo
)
=>
{
setState
({
memo
,
});
loadingState
.
setFinish
();
})
.
catch
((
error
)
=>
{
console
.
error
(
error
);
toastHelper
.
error
(
error
.
response
.
data
.
message
);
});
}
},
[]);
return
(
<
section
className=
"w-full h-full flex flex-row justify-start items-start p-2"
>
{
!
loadingState
.
isLoading
&&
(
<
main
className=
"w-full max-w-lg mx-auto my-auto shadow px-4 py-4 rounded-lg"
>
<
div
className=
"w-full flex flex-col justify-start items-start"
>
<
div
className=
"w-full mb-2 flex flex-row justify-start items-center text-sm text-gray-400 dark:text-gray-300"
>
<
span
>
{
dayjs
(
state
.
memo
.
displayTs
).
locale
(
i18n
.
language
).
format
(
"YYYY/MM/DD HH:mm:ss"
)
}
</
span
>
<
a
className=
"ml-2 hover:underline hover:text-green-600"
href=
{
`/u/${state.memo.creator.id}`
}
>
@
{
state
.
memo
.
creator
.
nickname
||
state
.
memo
.
creator
.
username
}
</
a
>
</
div
>
<
MemoContent
className=
"memo-content"
content=
{
state
.
memo
.
content
}
onMemoContentClick=
{
()
=>
undefined
}
/>
<
MemoResources
resourceList=
{
state
.
memo
.
resourceList
}
/>
</
div
>
</
main
>
)
}
</
section
>
);
};
export
default
EmbedMemo
;
web/src/pages/Loading.tsx
View file @
96798e10
...
@@ -2,7 +2,7 @@ import Icon from "../components/Icon";
...
@@ -2,7 +2,7 @@ import Icon from "../components/Icon";
function
Loading
()
{
function
Loading
()
{
return
(
return
(
<
div
className=
"flex flex-row justify-center items-center w-full h-
screen
bg-zinc-100 dark:bg-zinc-800"
>
<
div
className=
"flex flex-row justify-center items-center w-full h-
full
bg-zinc-100 dark:bg-zinc-800"
>
<
div
className=
"w-80 max-w-full h-full py-4 flex flex-col justify-center items-center"
>
<
div
className=
"w-80 max-w-full h-full py-4 flex flex-col justify-center items-center"
>
<
Icon
.
Loader
className=
"animate-spin dark:text-gray-200"
/>
<
Icon
.
Loader
className=
"animate-spin dark:text-gray-200"
/>
</
div
>
</
div
>
...
...
web/src/router/index.tsx
View file @
96798e10
...
@@ -8,6 +8,7 @@ const Auth = lazy(() => import("../pages/Auth"));
...
@@ -8,6 +8,7 @@ const Auth = lazy(() => import("../pages/Auth"));
const
Explore
=
lazy
(()
=>
import
(
"../pages/Explore"
));
const
Explore
=
lazy
(()
=>
import
(
"../pages/Explore"
));
const
Home
=
lazy
(()
=>
import
(
"../pages/Home"
));
const
Home
=
lazy
(()
=>
import
(
"../pages/Home"
));
const
MemoDetail
=
lazy
(()
=>
import
(
"../pages/MemoDetail"
));
const
MemoDetail
=
lazy
(()
=>
import
(
"../pages/MemoDetail"
));
const
EmbedMemo
=
lazy
(()
=>
import
(
"../pages/EmbedMemo"
));
const
router
=
createBrowserRouter
([
const
router
=
createBrowserRouter
([
{
{
...
@@ -96,6 +97,19 @@ const router = createBrowserRouter([
...
@@ -96,6 +97,19 @@ const router = createBrowserRouter([
return
null
;
return
null
;
},
},
},
},
{
path
:
"/m/:memoId/embed"
,
element
:
<
EmbedMemo
/>,
loader
:
async
()
=>
{
try
{
await
initialGlobalState
();
await
initialUserState
();
}
catch
(
error
)
{
// do nth
}
return
null
;
},
},
]);
]);
export
default
router
;
export
default
router
;
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