mirror of
https://github.com/streetwriters/notesnook.git
synced 2025-12-16 19:57:52 +01:00
Merge pull request #7294 from 01zulfi/webclipper/bookmark
webclipper: add bookmark option
This commit is contained in:
@@ -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("p", [`Date bookmarked: ${getFormattedDate(Date.now())}`]),
|
||||
h("hr")
|
||||
]).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,
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -57,6 +57,7 @@ export const Icons = {
|
||||
visible: mdiViewDayOutline,
|
||||
selection: mdiCursorDefaultClickOutline,
|
||||
|
||||
bookmark: mdiBookmarkOutline,
|
||||
simplified: mdiTextBoxOutline,
|
||||
screenshot: mdiFitToScreenOutline,
|
||||
complete: mdiViewDashboardOutline,
|
||||
|
||||
@@ -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
|
||||
@@ -454,14 +466,24 @@ export function Main() {
|
||||
disabled={isClipping}
|
||||
onClick={async () => {
|
||||
if (
|
||||
clipperState === ClipperState.Idle ||
|
||||
clipperState === ClipperState.Error
|
||||
clipMode !== "bookmark" &&
|
||||
(clipperState === ClipperState.Idle ||
|
||||
clipperState === ClipperState.Error)
|
||||
) {
|
||||
await startClip();
|
||||
return;
|
||||
}
|
||||
|
||||
if (!clipData || !title || !clipArea || !clipMode || !url) return;
|
||||
if (!title || !clipArea || !clipMode || !url) return;
|
||||
|
||||
const data =
|
||||
clipMode === "bookmark"
|
||||
? {
|
||||
data: createBookmark(url, title)
|
||||
}
|
||||
: clipData;
|
||||
|
||||
if (!data) return;
|
||||
|
||||
const notesnook = await connectApi(false);
|
||||
if (!notesnook) {
|
||||
@@ -476,7 +498,7 @@ export function Main() {
|
||||
note,
|
||||
refs,
|
||||
pageTitle: pageTitle.current,
|
||||
...clipData
|
||||
...data
|
||||
});
|
||||
|
||||
setClipData(undefined);
|
||||
@@ -492,7 +514,9 @@ export function Main() {
|
||||
window.close();
|
||||
}}
|
||||
>
|
||||
{clipperButtonLabelMap[clipperState]}
|
||||
{clipMode === "bookmark"
|
||||
? "Save bookmark"
|
||||
: clipperButtonLabelMap[clipperState]}
|
||||
</Button>
|
||||
|
||||
<Flex
|
||||
@@ -567,3 +591,11 @@ export async function clip(
|
||||
settings
|
||||
});
|
||||
}
|
||||
|
||||
function createBookmark(url: string, title: string) {
|
||||
const a = document.createElement("a");
|
||||
a.setAttribute("href", url);
|
||||
a.setAttribute("title", title);
|
||||
a.innerText = title;
|
||||
return a.outerHTML;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user