-
Notifications
You must be signed in to change notification settings - Fork 62
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
89a0440
commit 2e5dd50
Showing
11 changed files
with
1,250 additions
and
15 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
const DOM_ICON_ID = "context-note-logo-icon"; | ||
|
||
let onClickEvt: EventListener; | ||
/** | ||
* generate a logo icon image dom on top left of selected text | ||
* @param x mouse x | ||
* @param y mouse y | ||
* @param cb callback when clicked | ||
* @returns | ||
*/ | ||
export function genLogoIconAndRegisterClickCb( | ||
x: number, | ||
y: number, | ||
cb: () => void | ||
) { | ||
const iconSize = 35; | ||
|
||
const ele = document | ||
.querySelector("body") | ||
?.appendChild(document.createElement("img")) as HTMLImageElement; | ||
if (!ele) return; | ||
|
||
ele.id = DOM_ICON_ID; | ||
ele.style.position = "absolute"; | ||
ele.style.left = `${x}px`; | ||
ele.style.top = `${y - iconSize}px`; | ||
ele.style.width = `${iconSize}px`; | ||
ele.style.height = `${iconSize}px`; | ||
ele.style.cursor = "pointer"; | ||
ele.style.zIndex = '100'; | ||
|
||
// get assets of exteison by `chrome.runtime.getURL` | ||
// https://stackoverflow.com/questions/11804332/insert-an-image-in-chrome-extension | ||
ele.src = chrome.runtime.getURL("assets/icon16.png"); | ||
|
||
onClickEvt = (e) => { | ||
e.preventDefault(); | ||
e.stopPropagation(); | ||
cb?.(); | ||
clearLogoIcon(); | ||
}; | ||
ele.addEventListener("mouseup", onClickEvt); | ||
} | ||
|
||
export function clearLogoIcon() { | ||
// delete all logo icon doms | ||
const eles = document.querySelectorAll(`#${DOM_ICON_ID}`); | ||
eles.forEach((ele) => { | ||
onClickEvt && ele.removeEventListener("mouseup", onClickEvt); | ||
const parent = ele.parentElement; | ||
if (parent) { | ||
parent.removeChild(ele); | ||
} | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
import { v4 as uuid } from "uuid"; | ||
import { Rect } from "@/types/common"; | ||
import { | ||
DOMATTR_RECT_GROUP, | ||
PREFIX_RECT, | ||
PREFIX_RECT_GROUP, | ||
} from "@/utils/constant"; | ||
|
||
function setHighlightStyle(ele: HTMLElement, rect: Rect) { | ||
const PADDING = 6; | ||
ele.style.position = "absolute"; | ||
ele.style.left = rect.x - PADDING / 2 + "px"; | ||
ele.style.top = rect.y - PADDING / 2 + "px"; | ||
ele.style.width = `${rect.width + PADDING}px`; | ||
ele.style.height = `${rect.height + PADDING}px`; | ||
ele.style.background = "yellow"; | ||
ele.style.opacity = "0.3"; | ||
ele.style.content = " "; | ||
} | ||
|
||
function findRelatedIds( | ||
id: string, | ||
idMap: { [key: string]: string[] } | ||
): [string, string[]] { | ||
for (const key in idMap) { | ||
const ids = idMap[key] || []; | ||
if (ids.includes(id)) { | ||
return [key, ids]; | ||
} | ||
} | ||
return ["", []]; | ||
} | ||
|
||
function setRectStyleWithIds(ids: string[], key: string, value: string) { | ||
if (ids.length === 0) return; | ||
|
||
const rects = (document.querySelectorAll( | ||
(ids.map((id) => `#${id}`) as unknown) as string | ||
) as unknown) as HTMLElement[]; | ||
rects.forEach((rect) => { | ||
((rect.style as { [key: string]: any }) || {})[key] = value; | ||
}); | ||
} | ||
|
||
const groupRectIdsMap: { [key: string]: string[] } = {}; | ||
/** | ||
* Generate the highlight rect doms and register their click event. | ||
*/ | ||
export function genHighlightRects( | ||
noteId: string, | ||
rects: Rect[] = [], | ||
clickCb?: (groupId: string) => void | ||
) { | ||
const groupId = noteId || `${PREFIX_RECT_GROUP}-${uuid()}`; | ||
groupRectIdsMap[groupId] = []; | ||
for (const rect of rects) { | ||
const ele = document.createElement("div"); | ||
const id = `${PREFIX_RECT}-${uuid()}`; | ||
ele.setAttribute("id", id); | ||
ele.setAttribute(DOMATTR_RECT_GROUP, groupId); | ||
// highlight the rect | ||
setHighlightStyle(ele, rect); | ||
document.querySelector("body")?.appendChild(ele); | ||
groupRectIdsMap[groupId].push(ele.id); | ||
|
||
// click event | ||
document.addEventListener("mouseup", (event) => { | ||
const withinBoundaries = event.composedPath().includes(ele); | ||
|
||
if (withinBoundaries) { | ||
const groupId = boldHighlightGroupRects(ele?.id, ""); | ||
clickCb?.(groupId); | ||
} else { | ||
unboldHighlightGroupRects(ele?.id); | ||
} | ||
}); | ||
} | ||
return groupId; | ||
} | ||
|
||
/** | ||
* Delete all rects with `noteId`, if `noteId` is not provided, delete all rects. | ||
*/ | ||
export function delHighlightRects(noteId?: string | undefined) { | ||
const query = !noteId ? `[${DOMATTR_RECT_GROUP}]` : `[${DOMATTR_RECT_GROUP}=${noteId}]` | ||
const rectDoms = document.querySelectorAll(query); | ||
rectDoms.forEach(dom => { | ||
dom.parentElement?.removeChild(dom); | ||
}) | ||
} | ||
|
||
/** | ||
* Bold the group highlight rects. | ||
* @param id one id of the group rects | ||
* @param groupId the group id | ||
* @param scrollIntoView if need scrollIntoView when bolding | ||
* @returns groupId | ||
*/ | ||
export function boldHighlightGroupRects( | ||
id?: string, | ||
groupId?: string, | ||
scrollIntoView?: boolean | ||
): string { | ||
// set all related rects border to dotted | ||
let relatedIds: string[]; | ||
if (groupId) { | ||
relatedIds = groupRectIdsMap[groupId] || []; | ||
} else { | ||
[groupId, relatedIds] = findRelatedIds(id || "", groupRectIdsMap); | ||
} | ||
setTimeout(() => { | ||
setRectStyleWithIds(relatedIds, "border", "2px dotted #000"); | ||
}); | ||
if (groupId) { | ||
if (scrollIntoView) { | ||
// scroll to first rect | ||
const firstRectId = relatedIds?.[0]; | ||
const firstRect = document.querySelector(`#${firstRectId}`); | ||
firstRect && firstRect.scrollIntoView({ block: "center" }); | ||
} | ||
} | ||
return groupId; | ||
} | ||
|
||
/** | ||
* Unbold the group highlight rects. | ||
* @param id one id of the group rects. | ||
*/ | ||
export function unboldHighlightGroupRects(id: string) { | ||
// set all related rects border to none | ||
const [_, relatedIds] = findRelatedIds(id, groupRectIdsMap); | ||
setRectStyleWithIds(relatedIds, "border", "none"); | ||
} |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
<template> | ||
<div v-show="visible"> | ||
<NoteBook v-clickoutside="handleClickOutside"></NoteBook> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { defineComponent, provide, ref, reactive } from "vue"; | ||
import NoteBook from "./note-book/index.vue"; | ||
import { Note } from "@/types/note"; | ||
import { Tag } from "@/types/tag"; | ||
import { Storage } from "@/types/storage"; | ||
import { get } from "@/utils/storage"; | ||
import { StorageKeys } from "@/utils/constant"; | ||
export default defineComponent({ | ||
components: { | ||
NoteBook, | ||
}, | ||
setup() { | ||
const visible = ref(false); | ||
const handleClickOutside = () => { | ||
visible.value = false; | ||
}; | ||
// global reading `notes` and `tags` from storage and provide to sub components. | ||
const storage = reactive<Storage>({ | ||
[StorageKeys.notes]: [], | ||
[StorageKeys.tags]: [], | ||
}); | ||
get(StorageKeys.notes).then((res) => { | ||
storage.notes = (res as Note[]) || []; | ||
}); | ||
get(StorageKeys.tags).then((res) => { | ||
storage.tags = (res as Tag[]) || []; | ||
}); | ||
provide("storage", storage); | ||
return { | ||
visible, | ||
handleClickOutside, | ||
}; | ||
}, | ||
}); | ||
</script> | ||
|
||
<style scoped></style> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,64 @@ | ||
<template> | ||
<div class="note-book-wrapper"> | ||
<NoteList></NoteList> | ||
<TagBook | ||
v-show="!!curNoteId" | ||
:noteId="curNoteId" | ||
:coor="tagBookCoor" | ||
@close="handleCloseTagBook" | ||
></TagBook> | ||
</div> | ||
</template> | ||
|
||
<script lang="ts"> | ||
import { ref } from "vue"; | ||
import mitt from "@/utils/mitt"; | ||
import { Coor } from "@/types/common"; | ||
import TagBook from "../tag-book/index.vue"; | ||
import NoteList from "./note-list.vue"; | ||
export default { | ||
components: { | ||
NoteList, | ||
TagBook, | ||
}, | ||
setup(props) { | ||
const tagBookCoor = ref<Coor>({ x: 0, y: 0 }); | ||
const curNoteId = ref(""); | ||
mitt.on("open-tag-book", ({ noteId, coor }: any) => { | ||
if (coor) { | ||
// `setTimeout` to let `handleCloseTagBook` trigger first. | ||
setTimeout(() => { | ||
tagBookCoor.value = coor as Coor; | ||
curNoteId.value = noteId; | ||
}); | ||
} | ||
}); | ||
const handleCloseTagBook = () => { | ||
curNoteId.value = ""; | ||
}; | ||
return { | ||
tagBookCoor, | ||
curNoteId, | ||
handleCloseTagBook, | ||
}; | ||
}, | ||
}; | ||
</script> | ||
|
||
<style scoped> | ||
.note-book-wrapper { | ||
position: fixed; | ||
right: 0px; | ||
top: 0px; | ||
width: 500px; | ||
min-width: 500px; | ||
height: 100vh; | ||
overflow-y: scroll; | ||
background-color: #646cff80; | ||
opacity: 1; | ||
border-radius: 10px; | ||
z-index: 9999; | ||
} | ||
</style> |
Oops, something went wrong.