webclipper: add bookmark option

Signed-off-by: 01zulfi <85733202+01zulfi@users.noreply.github.com>
This commit is contained in:
01zulfi
2025-01-09 11:14:05 +05:00
committed by Abdullah Atta
parent 05c4051cc9
commit 47be00355d
5 changed files with 98 additions and 61 deletions

View File

@@ -73,7 +73,11 @@ export class WebExtensionServer implements Server {
async saveClip(clip: Clip) {
let clipContent = "";
if (clip.mode === "simplified" || clip.mode === "screenshot") {
if (
clip.mode === "simplified" ||
clip.mode === "screenshot" ||
clip.mode === "bookmark"
) {
clipContent += clip.data;
} else {
const clippedFile = new File(
@@ -105,11 +109,17 @@ export class WebExtensionServer implements Server {
if (isCipher(content)) return;
content += clipContent;
content += h("div", [
h("hr"),
h("p", ["Clipped from ", h("a", [clip.title], { href: clip.url })]),
h("p", [`Date clipped: ${getFormattedDate(Date.now())}`])
]).innerHTML;
content +=
clip.mode === "bookmark"
? h("div", [
h("hr"),
h("p", [`Date bookmarked: ${getFormattedDate(Date.now())}`])
]).innerHTML
: h("div", [
h("hr"),
h("p", ["Clipped from ", h("a", [clip.title], { href: clip.url })]),
h("p", [`Date clipped: ${getFormattedDate(Date.now())}`])
]).innerHTML;
const id = await db.notes.add({
id: note?.id,

View File

@@ -73,6 +73,10 @@ The `Selected nodes` mode allows you to select exactly which nodes you want to c
The clipping mode controls how the final clip should look.
### Bookmark
`Bookmark` mode saves only the URL of the page along with the title. It is best suited to save pages for later reading/reference.
### Simplified
`Simplified` mode doesn't include any styles. It is best suited for long-form content such as articles & blogs. All clips in `Simplified` mode are saved directly as is i.e. they do not appear as web clip embeds in the Notesnook editor.

View File

@@ -21,7 +21,7 @@ import { ThemeDefinition } from "@notesnook/theme";
export type ClipArea = "full-page" | "visible" | "selection" | "article";
export type ClipMode = "simplified" | "screenshot" | "complete";
export type ClipMode = "bookmark" | "simplified" | "screenshot" | "complete";
export type User = {
email?: string;

View File

@@ -57,6 +57,7 @@ export const Icons = {
visible: mdiViewDayOutline,
selection: mdiCursorDefaultClickOutline,
bookmark: mdiBookmarkOutline,
simplified: mdiTextBoxOutline,
screenshot: mdiFitToScreenOutline,
complete: mdiViewDashboardOutline,

View File

@@ -68,6 +68,11 @@ const clipAreas: { name: string; id: ClipArea; icon: string }[] = [
const clipModes: { name: string; id: ClipMode; icon: string; pro?: boolean }[] =
[
{
name: "Bookmark",
id: "bookmark",
icon: Icons.bookmark
},
{
name: "Simplified",
id: "simplified",
@@ -166,7 +171,7 @@ export function Main() {
}, [settings]);
async function startClip() {
if (!clipArea || !clipMode) return;
if (!clipArea || !clipMode || clipMode === "bookmark") return;
try {
setError(undefined);
@@ -268,7 +273,11 @@ export function Main() {
setClipperState(ClipperState.Idle);
setClipArea(item.id);
}}
disabled={isClipping || clipperState === ClipperState.Clipped}
disabled={
isClipping ||
clipperState === ClipperState.Clipped ||
clipMode === "bookmark"
}
sx={{
display: "flex",
borderRadius: "default",
@@ -342,55 +351,58 @@ export function Main() {
</Button>
))}
{clipData && clipData.data && !isClipping && (
<Flex sx={{ gap: 1, justifyContent: "space-between" }}>
<Text
variant="body"
sx={{
flex: 1,
mt: 1,
bg: "shade",
color: "accent",
p: 1,
border: "1px solid var(--accent)",
borderRadius: "default",
cursor: "pointer",
":hover": {
filter: "brightness(80%)"
}
}}
onClick={async () => {
const winUrl = URL.createObjectURL(
new Blob(["\ufeff", clipData.data], { type: "text/html" })
);
await browser.windows.create({
url: winUrl
});
}}
>
Clip done. Click here to preview.
</Text>
<Text
variant="body"
sx={{
mt: 1,
bg: "background-secondary",
p: 1,
borderRadius: "default",
cursor: "pointer",
":hover": {
filter: "brightness(80%)"
}
}}
onClick={async () => {
setClipData(undefined);
setClipperState(ClipperState.Idle);
}}
>
Discard
</Text>
</Flex>
)}
{clipMode !== "bookmark" &&
clipData &&
clipData.data &&
!isClipping && (
<Flex sx={{ gap: 1, justifyContent: "space-between" }}>
<Text
variant="body"
sx={{
flex: 1,
mt: 1,
bg: "shade",
color: "accent",
p: 1,
border: "1px solid var(--accent)",
borderRadius: "default",
cursor: "pointer",
":hover": {
filter: "brightness(80%)"
}
}}
onClick={async () => {
const winUrl = URL.createObjectURL(
new Blob(["\ufeff", clipData.data], { type: "text/html" })
);
await browser.windows.create({
url: winUrl
});
}}
>
Clip done. Click here to preview.
</Text>
<Text
variant="body"
sx={{
mt: 1,
bg: "background-secondary",
p: 1,
borderRadius: "default",
cursor: "pointer",
":hover": {
filter: "brightness(80%)"
}
}}
onClick={async () => {
setClipData(undefined);
setClipperState(ClipperState.Idle);
}}
>
Discard
</Text>
</Flex>
)}
{error && (
<Text
@@ -461,7 +473,15 @@ export function Main() {
return;
}
if (!clipData || !title || !clipArea || !clipMode || !url) return;
const isBookmark = clipMode === "bookmark";
const data = isBookmark
? {
data: `<a href="${url}">${title}</a>`
}
: clipData;
if (!data || !clipData || !title || !clipArea || !clipMode || !url)
return;
const notesnook = await connectApi(false);
if (!notesnook) {
@@ -476,7 +496,7 @@ export function Main() {
note,
refs,
pageTitle: pageTitle.current,
...clipData
...data
});
setClipData(undefined);
@@ -492,7 +512,9 @@ export function Main() {
window.close();
}}
>
{clipperButtonLabelMap[clipperState]}
{clipMode === "bookmark"
? "Save bookmark"
: clipperButtonLabelMap[clipperState]}
</Button>
<Flex