mirror of
https://github.com/027xiguapi/code-box.git
synced 2026-04-28 15:22:15 +00:00
优化自定义选择框代码
This commit is contained in:
@@ -35,6 +35,10 @@ export default function ValidateContent(props) {
|
||||
}
|
||||
}
|
||||
|
||||
function handleCancel() {
|
||||
props.handleCancel()
|
||||
}
|
||||
|
||||
function help() {
|
||||
sendToBackground({
|
||||
name: "tab",
|
||||
@@ -45,10 +49,21 @@ export default function ValidateContent(props) {
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<div
|
||||
style={{
|
||||
width: "350px",
|
||||
padding: "10px",
|
||||
position: "absolute",
|
||||
top: "50%",
|
||||
left: "50%",
|
||||
transform: "translate(-50%, -50%)",
|
||||
backgroundColor: "white",
|
||||
borderRadius: "5px",
|
||||
textAlign: "center"
|
||||
}}>
|
||||
{isValid ? (
|
||||
<p className="valid" style={{ fontSize: "16px", color: "red" }}>
|
||||
验证成功
|
||||
验证成功, 以激活
|
||||
</p>
|
||||
) : (
|
||||
<>
|
||||
@@ -60,23 +75,33 @@ export default function ValidateContent(props) {
|
||||
)
|
||||
</div>
|
||||
<div>
|
||||
<img src={qrcodeUrl} alt="微信公众号" />
|
||||
<img style={{ margin: "auto" }} src={qrcodeUrl} alt="微信公众号" />
|
||||
</div>
|
||||
<Space.Compact style={{ width: "100%" }}>
|
||||
<div style={{ marginTop: "10px" }}>
|
||||
<Input
|
||||
placeholder="输入激活码"
|
||||
ref={inputRef}
|
||||
prefix={<KeyOutlined />}
|
||||
/>
|
||||
</div>
|
||||
<div
|
||||
style={{
|
||||
marginTop: "10px",
|
||||
display: "flex",
|
||||
justifyContent: "space-between"
|
||||
}}>
|
||||
<Button
|
||||
type="primary"
|
||||
className="valid-submit"
|
||||
onClick={handleSubmit}>
|
||||
提交
|
||||
</Button>
|
||||
</Space.Compact>
|
||||
<Button type="primary" onClick={handleCancel}>
|
||||
取消
|
||||
</Button>
|
||||
</div>
|
||||
</>
|
||||
)}
|
||||
</>
|
||||
</div>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -1,11 +1,13 @@
|
||||
import { Modal } from "antd"
|
||||
import dayjs from "dayjs"
|
||||
import React, { useEffect, useRef, useState } from "react"
|
||||
import { createRoot } from "react-dom/client"
|
||||
|
||||
import { useMessage } from "@plasmohq/messaging/hook"
|
||||
import { useStorage } from "@plasmohq/storage/hook"
|
||||
|
||||
import { addCss, saveHtml, saveMarkdown, scrollToTop, setIcon } from "~tools"
|
||||
import ValidateContent from "~component/contents/validateContent"
|
||||
import { addCss, saveHtml, saveMarkdown } from "~tools"
|
||||
import { savePdf } from "~utils/downloadPdf"
|
||||
import { useContent } from "~utils/editMarkdownHook"
|
||||
import Turndown from "~utils/turndown"
|
||||
@@ -20,10 +22,10 @@ export default function CustomDomSelector() {
|
||||
const downloadType = useRef("")
|
||||
const [content, setContent] = useContent()
|
||||
const [validTime] = useStorage("app-validTime", "1730390400")
|
||||
const [isModalOpen, setIsModalOpen] = useState(false)
|
||||
|
||||
const selectorRef = useRef<HTMLElement | null>(null)
|
||||
const tooltipRef = useRef<HTMLElement | null>(null)
|
||||
const modalRef = useRef<HTMLElement | null>(null)
|
||||
|
||||
const articleTitle = document
|
||||
.querySelector<HTMLElement>("head title")
|
||||
@@ -31,31 +33,14 @@ export default function CustomDomSelector() {
|
||||
|
||||
useEffect(() => {
|
||||
addEventListeners()
|
||||
setIcon(true)
|
||||
addCss(`.codebox-current { outline: 2px solid #42b88350 !important; }`)
|
||||
return () => {
|
||||
removeEventListeners()
|
||||
// removeSelector()
|
||||
removeTooltip()
|
||||
removeHighlight()
|
||||
}
|
||||
}, [])
|
||||
|
||||
const createSelector = () => {
|
||||
const selector = document.createElement("div")
|
||||
selector.classList.add("codebox-selector")
|
||||
selector.style.position = "absolute"
|
||||
selector.style.pointerEvents = "none"
|
||||
selector.style.zIndex = "2147483640"
|
||||
selector.style.backgroundColor = "#42b88325"
|
||||
selector.style.border = "2px solid #42b88350"
|
||||
selector.style.borderRadius = "2px"
|
||||
selector.style.transition = "all 0.1s ease-in"
|
||||
selector.style.display = "none"
|
||||
document.body.appendChild(selector)
|
||||
selectorRef.current = selector
|
||||
}
|
||||
|
||||
const createTooltip = () => {
|
||||
const tooltip = document.createElement("div")
|
||||
tooltip.classList.add("codebox-tooltip")
|
||||
@@ -66,7 +51,6 @@ export default function CustomDomSelector() {
|
||||
tooltip.style.borderRadius = "5px"
|
||||
tooltip.style.padding = "8px"
|
||||
tooltip.style.boxShadow = "0 2px 8px rgba(0, 0, 0, 0.15)"
|
||||
// tooltip.style.display = "none"
|
||||
document.body.appendChild(tooltip)
|
||||
const root = createRoot(tooltip)
|
||||
root.render(
|
||||
@@ -79,12 +63,6 @@ export default function CustomDomSelector() {
|
||||
tooltipRef.current = tooltip
|
||||
}
|
||||
|
||||
const removeSelector = () => {
|
||||
if (selectorRef.current) {
|
||||
document.body.removeChild(selectorRef.current)
|
||||
}
|
||||
}
|
||||
|
||||
const removeTooltip = () => {
|
||||
if (tooltipRef.current) {
|
||||
document.body.removeChild(tooltipRef.current)
|
||||
@@ -106,7 +84,6 @@ export default function CustomDomSelector() {
|
||||
if (isReady.current && !isSelect.current) {
|
||||
const target = event.target as HTMLElement
|
||||
highlightElement(target)
|
||||
// updateSelectorPosition(target)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,7 +99,6 @@ export default function CustomDomSelector() {
|
||||
createTooltip()
|
||||
isSelect.current = true
|
||||
highlightElement(target)
|
||||
// updateSelectorPosition(target)
|
||||
updateTooltipPosition(target)
|
||||
event.stopPropagation()
|
||||
event.preventDefault()
|
||||
@@ -142,17 +118,6 @@ export default function CustomDomSelector() {
|
||||
selectorRef.current = null
|
||||
}
|
||||
|
||||
const updateSelectorPosition = (element: HTMLElement) => {
|
||||
if (selectorRef.current) {
|
||||
const rect = element.getBoundingClientRect()
|
||||
selectorRef.current.style.top = `${rect.top + window.scrollY}px`
|
||||
selectorRef.current.style.left = `${rect.left + window.scrollX}px`
|
||||
selectorRef.current.style.width = `${rect.width}px`
|
||||
selectorRef.current.style.height = `${rect.height}px`
|
||||
selectorRef.current.style.display = "block"
|
||||
}
|
||||
}
|
||||
|
||||
const updateTooltipPosition = (element: HTMLElement) => {
|
||||
const rect = element.getBoundingClientRect()
|
||||
const distanceTop = rect.top + window.scrollY
|
||||
@@ -161,7 +126,7 @@ export default function CustomDomSelector() {
|
||||
distanceTop < 50 ? distanceTop + rect.height + 5 : distanceTop - 40
|
||||
tooltipRef.current.style.top = `${top}px`
|
||||
tooltipRef.current.style.left = `${distanceLeft + 5}px`
|
||||
scrollToTop(tooltipRef.current)
|
||||
window.scrollTo({ top: top - 150, behavior: "smooth" })
|
||||
}
|
||||
|
||||
useMessage(async (req: any, res: any) => {
|
||||
@@ -188,8 +153,9 @@ export default function CustomDomSelector() {
|
||||
isSelect.current = false
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
const handleOkModal = () => {
|
||||
if (!selectorRef.current || !downloadType.current) return
|
||||
|
||||
switch (downloadType.current) {
|
||||
case "html":
|
||||
saveHtml(selectorRef.current, articleTitle)
|
||||
@@ -207,6 +173,31 @@ export default function CustomDomSelector() {
|
||||
}
|
||||
|
||||
resetState()
|
||||
setTimeout(() => {
|
||||
document.body.removeChild(modalRef.current)
|
||||
modalRef.current = null
|
||||
}, 1000)
|
||||
}
|
||||
|
||||
const handleConfirm = () => {
|
||||
const modal = document.createElement("div")
|
||||
modal.classList.add("codebox-modal")
|
||||
modal.style.position = "fixed"
|
||||
modal.style.zIndex = "2147483642"
|
||||
modal.style.backgroundColor = "rgba(0, 0, 0, 0.7)"
|
||||
modal.style.width = "100vw"
|
||||
modal.style.height = "100vh"
|
||||
modal.style.top = "0"
|
||||
modal.style.left = "0"
|
||||
document.body.appendChild(modal)
|
||||
const root = createRoot(modal)
|
||||
root.render(
|
||||
<ValidateContent
|
||||
handleOk={handleOkModal}
|
||||
handleCancel={handleCancelModal}
|
||||
/>
|
||||
)
|
||||
modalRef.current = modal
|
||||
}
|
||||
|
||||
const handleCancel = () => {
|
||||
@@ -215,7 +206,6 @@ export default function CustomDomSelector() {
|
||||
|
||||
const resetState = () => {
|
||||
removeHighlight()
|
||||
// removeSelector()
|
||||
removeTooltip()
|
||||
isReady.current = false
|
||||
isSelect.current = false
|
||||
@@ -247,26 +237,10 @@ export default function CustomDomSelector() {
|
||||
}
|
||||
}
|
||||
|
||||
const handleOkModal = () => {
|
||||
setIsModalOpen(false)
|
||||
}
|
||||
|
||||
const handleCancelModal = () => {
|
||||
setIsModalOpen(false)
|
||||
document.body.removeChild(modalRef.current)
|
||||
modalRef.current = null
|
||||
}
|
||||
|
||||
return (
|
||||
<>
|
||||
<Modal
|
||||
title="Basic Modal"
|
||||
className="codebox-modal"
|
||||
open={isModalOpen}
|
||||
onOk={handleOkModal}
|
||||
onCancel={handleCancelModal}>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
<p>Some contents...</p>
|
||||
</Modal>
|
||||
</>
|
||||
)
|
||||
return <div style={{ display: "none" }}></div>
|
||||
}
|
||||
|
||||
@@ -22,7 +22,8 @@ export const config: PlasmoCSConfig = {
|
||||
"https://mp.weixin.qq.com/*",
|
||||
"https://day.js.org/*",
|
||||
"https://stackoverflow.com/*",
|
||||
"https://dev.to/*"
|
||||
"https://dev.to/*",
|
||||
"https://greasyfork.org/*"
|
||||
]
|
||||
}
|
||||
|
||||
@@ -70,7 +71,12 @@ const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
|
||||
|
||||
const element = anchor.element
|
||||
const style = window.getComputedStyle(element)
|
||||
const width = style.getPropertyValue("width")
|
||||
let width = style.getPropertyValue("width")
|
||||
|
||||
if (location.host.includes("greasyfork")) {
|
||||
const codeContainer = element.closest(".code-container")
|
||||
width = window.getComputedStyle(codeContainer).getPropertyValue("width")
|
||||
}
|
||||
|
||||
const onCopy = async () => {
|
||||
try {
|
||||
@@ -80,9 +86,9 @@ const PlasmoOverlay: FC<PlasmoCSUIProps> = ({ anchor }) => {
|
||||
let textContent = ""
|
||||
|
||||
if (codeBlock) {
|
||||
textContent = codeBlock.textContent
|
||||
textContent = codeBlock.innerText
|
||||
} else {
|
||||
textContent = preBlock && preBlock.textContent
|
||||
textContent = preBlock && preBlock.innerText
|
||||
}
|
||||
|
||||
navigator.clipboard.writeText(textContent)
|
||||
|
||||
@@ -5,9 +5,17 @@ import type {
|
||||
PlasmoGetShadowHostId,
|
||||
PlasmoGetStyle
|
||||
} from "plasmo"
|
||||
import { useEffect, useRef, useState } from "react"
|
||||
|
||||
import { sendToBackground } from "@plasmohq/messaging"
|
||||
import { useMessage } from "@plasmohq/messaging/hook"
|
||||
import { useStorage } from "@plasmohq/storage/hook"
|
||||
|
||||
import CustomDomSelector from "~component/customDomSelector"
|
||||
import { ThemeProvider } from "~theme"
|
||||
import { setIcon } from "~tools"
|
||||
import { getSummary } from "~utils/coze"
|
||||
import DrawImages from "~utils/drawImages"
|
||||
|
||||
const HOST_ID = "codebox-csui"
|
||||
|
||||
@@ -20,7 +28,79 @@ export const getStyle: PlasmoGetStyle = () => {
|
||||
return style
|
||||
}
|
||||
|
||||
const articleTitle = document
|
||||
.querySelector<HTMLElement>("head title")
|
||||
?.innerText.trim()
|
||||
|
||||
export default function CustomOverlay() {
|
||||
const [summary, setSummary] = useStorage("app-summary", "")
|
||||
|
||||
useEffect(() => {
|
||||
setIcon(true)
|
||||
}, [])
|
||||
|
||||
useMessage(async (req: any, res: any) => {
|
||||
if (req.name == "app-downloadImages") {
|
||||
await downloadImages(req.body?.onProgress)
|
||||
}
|
||||
if (req.name == "app-get-summary") {
|
||||
setSummary("")
|
||||
const res = await getSummary(location.href)
|
||||
if (res.code == 0) {
|
||||
const result = JSON.parse(res.data)
|
||||
setSummary(result)
|
||||
}
|
||||
}
|
||||
if (req.name == "app-full-page-screenshot") {
|
||||
if (confirm("确认截图?")) {
|
||||
const { scrollHeight, clientHeight } = document.documentElement
|
||||
const devicePixelRatio = window.devicePixelRatio || 1
|
||||
|
||||
let capturedHeight = 0
|
||||
let capturedImages = []
|
||||
|
||||
const captureAndScroll = async () => {
|
||||
const scrollAmount = clientHeight * devicePixelRatio
|
||||
const res = await sendToBackground({ name: "screenshot" })
|
||||
const dataUrl = res.dataUrl
|
||||
|
||||
capturedHeight += scrollAmount
|
||||
if (capturedHeight < scrollHeight * devicePixelRatio) {
|
||||
capturedImages.push(dataUrl)
|
||||
window.scrollTo(0, capturedHeight)
|
||||
setTimeout(captureAndScroll, 2000) // Adjust the delay as needed
|
||||
} else {
|
||||
DrawImages(capturedImages, articleTitle)
|
||||
}
|
||||
}
|
||||
|
||||
captureAndScroll()
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
async function downloadImages(
|
||||
onProgress?: (current: number, total: number) => void
|
||||
) {
|
||||
const imageUrls = Array.from(document.images).map((img) => img.src)
|
||||
try {
|
||||
const res = await sendToBackground({
|
||||
name: "download",
|
||||
body: {
|
||||
action: "downloadAllImages",
|
||||
imageUrls: imageUrls,
|
||||
title: articleTitle,
|
||||
onProgress: onProgress
|
||||
}
|
||||
})
|
||||
if (res.code == 0) {
|
||||
alert("下载失败")
|
||||
}
|
||||
} catch (error) {
|
||||
console.error(`Failed to download images:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
return (
|
||||
<ThemeProvider>
|
||||
<StyleProvider container={document.getElementById(HOST_ID).shadowRoot}>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "code-box",
|
||||
"displayName": "__MSG_extensionName__",
|
||||
"version": "0.9.24",
|
||||
"version": "0.9.25",
|
||||
"description": "__MSG_extensionDescription__",
|
||||
"author": "027xiguapi. <458813868@qq.com>",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user