feat: support Edge browser

This commit is contained in:
n4ze3m 2025-02-08 23:06:09 +05:30
parent 87c2024771
commit ef51cf85ff
10 changed files with 114 additions and 192 deletions

View File

@ -7,8 +7,10 @@
"scripts": { "scripts": {
"dev": "cross-env TARGET=chrome wxt", "dev": "cross-env TARGET=chrome wxt",
"dev:firefox": "cross-env TARGET=firefox wxt -b firefox", "dev:firefox": "cross-env TARGET=firefox wxt -b firefox",
"dev:edge": "cross-env TARGET=chrome wxt -b edge",
"build": "cross-env TARGET=chrome wxt build", "build": "cross-env TARGET=chrome wxt build",
"build:firefox": "cross-env TARGET=firefox wxt build -b firefox", "build:firefox": "cross-env TARGET=firefox wxt build -b firefox",
"build:edge": "cross-env TARGET=chrome wxt build -b edge",
"zip": "cross-env TARGET=chrome wxt zip", "zip": "cross-env TARGET=chrome wxt zip",
"zip:firefox": "cross-env TARGET=firefox wxt zip -b firefox", "zip:firefox": "cross-env TARGET=firefox wxt zip -b firefox",
"compile": "tsc --noEmit", "compile": "tsc --noEmit",

View File

@ -35,15 +35,9 @@ export default defineBackground({
} }
}) })
if (import.meta.env.BROWSER === "chrome") {
chrome.action.onClicked.addListener((tab) => { chrome.action.onClicked.addListener((tab) => {
chrome.tabs.create({ url: chrome.runtime.getURL("/options.html") }) chrome.tabs.create({ url: chrome.runtime.getURL("/options.html") })
}) })
} else {
browser.browserAction.onClicked.addListener((tab) => {
browser.tabs.create({ url: browser.runtime.getURL("/options.html") })
})
}
const contextMenuTitle = { const contextMenuTitle = {
webUi: browser.i18n.getMessage("openOptionToChat"), webUi: browser.i18n.getMessage("openOptionToChat"),
@ -91,7 +85,6 @@ export default defineBackground({
contexts: ["selection"] contexts: ["selection"]
}) })
if (import.meta.env.BROWSER === "chrome") {
browser.contextMenus.onClicked.addListener(async (info, tab) => { browser.contextMenus.onClicked.addListener(async (info, tab) => {
if (info.menuItemId === "open-side-panel-pa") { if (info.menuItemId === "open-side-panel-pa") {
chrome.sidePanel.open({ chrome.sidePanel.open({
@ -183,84 +176,7 @@ export default defineBackground({
break break
} }
}) })
}
if (import.meta.env.BROWSER === "firefox") {
browser.contextMenus.onClicked.addListener((info, tab) => {
if (info.menuItemId === "open-side-panel-pa") {
browser.sidebarAction.toggle()
} else if (info.menuItemId === "open-web-ui-pa") {
browser.tabs.create({
url: browser.runtime.getURL("/options.html")
})
} else if (info.menuItemId === "summarize-pa") {
if (!isCopilotRunning) {
browser.sidebarAction.toggle()
}
setTimeout(async () => {
await browser.runtime.sendMessage({
from: "background",
type: "summary",
text: info.selectionText
})
}, isCopilotRunning ? 0 : 5000)
} else if (info.menuItemId === "rephrase-pa") {
if (!isCopilotRunning) {
browser.sidebarAction.toggle()
}
setTimeout(async () => {
await browser.runtime.sendMessage({
type: "rephrase",
from: "background",
text: info.selectionText
})
}, isCopilotRunning ? 0 : 5000)
} else if (info.menuItemId === "translate-pg") {
if (!isCopilotRunning) {
browser.sidebarAction.toggle()
}
setTimeout(async () => {
await browser.runtime.sendMessage({
type: "translate",
from: "background",
text: info.selectionText
})
}, isCopilotRunning ? 0 : 5000)
} else if (info.menuItemId === "explain-pa") {
if (!isCopilotRunning) {
browser.sidebarAction.toggle()
}
setTimeout(async () => {
await browser.runtime.sendMessage({
type: "explain",
from: "background",
text: info.selectionText
})
}, isCopilotRunning ? 0 : 5000)
} else if (info.menuItemId === "custom-pg") {
if (!isCopilotRunning) {
browser.sidebarAction.toggle()
}
setTimeout(async () => {
await browser.runtime.sendMessage({
type: "custom",
from: "background",
text: info.selectionText
})
}, isCopilotRunning ? 0 : 5000)
}
})
browser.commands.onCommand.addListener((command) => {
switch (command) {
case "execute_side_panel":
browser.sidebarAction.toggle()
break
default:
break
}
})
}
}, },
persistent: true persistent: true
}) })

View File

@ -32,7 +32,10 @@ export const useTTS = () => {
if (isSSML) { if (isSSML) {
utterance = markdownToSSML(utterance) utterance = markdownToSSML(utterance)
} }
if (import.meta.env.BROWSER === "chrome") { if (
import.meta.env.BROWSER === "chrome" ||
import.meta.env.BROWSER === "edge"
) {
chrome.tts.speak(utterance, { chrome.tts.speak(utterance, {
voiceName: voice, voiceName: voice,
onEvent(event) { onEvent(event) {
@ -112,7 +115,7 @@ export const useTTS = () => {
return return
} }
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.tts.stop() chrome.tts.stop()
} else { } else {
window.speechSynthesis.cancel() window.speechSynthesis.cancel()

View File

@ -24,7 +24,7 @@ const _getHtml = () => {
export const getDataFromCurrentTab = async () => { export const getDataFromCurrentTab = async () => {
const result = new Promise((resolve) => { const result = new Promise((resolve) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => {
const tab = tabs[0] const tab = tabs[0]

View File

@ -1,6 +1,6 @@
const captureVisibleTab = () => { const captureVisibleTab = () => {
const result = new Promise<string>((resolve) => { const result = new Promise<string>((resolve) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => {
const tab = tabs[0] const tab = tabs[0]
chrome.tabs.captureVisibleTab(null, { format: "png" }, (dataUrl) => { chrome.tabs.captureVisibleTab(null, { format: "png" }, (dataUrl) => {

View File

@ -6,7 +6,7 @@ export const urlRewriteRuntime = async function (
) { ) {
if (browser.runtime && browser.runtime.id) { if (browser.runtime && browser.runtime.id) {
const { isEnableRewriteUrl, rewriteUrl } = await getAdvancedOllamaSettings() const { isEnableRewriteUrl, rewriteUrl } = await getAdvancedOllamaSettings()
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
const url = new URL(domain) const url = new URL(domain)
const domains = [url.hostname] const domains = [url.hostname]
let origin = `${url.protocol}//${url.hostname}` let origin = `${url.protocol}//${url.hostname}`

View File

@ -95,7 +95,7 @@ const getGoogleDocs = () => {
export const parseGoogleDocs = async () => { export const parseGoogleDocs = async () => {
const result = new Promise((resolve) => { const result = new Promise((resolve) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => { chrome.tabs.query({ active: true, currentWindow: true }, async (tabs) => {
const tab = tabs[0] const tab = tabs[0]

View File

@ -21,7 +21,7 @@ export const setTTSProvider = async (ttsProvider: string) => {
} }
export const getBrowserTTSVoices = async () => { export const getBrowserTTSVoices = async () => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
const tts = await chrome.tts.getVoices() const tts = await chrome.tts.getVoices()
return tts return tts
} else { } else {

View File

@ -1,7 +1,7 @@
import { browser } from "wxt/browser" import { browser } from "wxt/browser"
export const setTitle = ({ title }: { title: string }) => { export const setTitle = ({ title }: { title: string }) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.action.setTitle({ title }) chrome.action.setTitle({ title })
} else { } else {
browser.browserAction.setTitle({ title }) browser.browserAction.setTitle({ title })
@ -9,7 +9,7 @@ export const setTitle = ({ title }: { title: string }) => {
} }
export const setBadgeBackgroundColor = ({ color }: { color: string }) => { export const setBadgeBackgroundColor = ({ color }: { color: string }) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.action.setBadgeBackgroundColor({ color }) chrome.action.setBadgeBackgroundColor({ color })
} else { } else {
browser.browserAction.setBadgeBackgroundColor({ color }) browser.browserAction.setBadgeBackgroundColor({ color })
@ -17,7 +17,7 @@ export const setBadgeBackgroundColor = ({ color }: { color: string }) => {
} }
export const setBadgeText = ({ text }: { text: string }) => { export const setBadgeText = ({ text }: { text: string }) => {
if (import.meta.env.BROWSER === "chrome") { if (import.meta.env.BROWSER === "chrome" || import.meta.env.BROWSER === "edge") {
chrome.action.setBadgeText({ text }) chrome.action.setBadgeText({ text })
} else { } else {
browser.browserAction.setBadgeText({ text }) browser.browserAction.setBadgeText({ text })

View File

@ -1,17 +1,18 @@
import { createWorker } from 'tesseract.js'; import { createWorker } from "tesseract.js"
export async function processImageForOCR(imageData: string): Promise<string> { export async function processImageForOCR(imageData: string): Promise<string> {
const worker = await createWorker('eng-fast', undefined, { const isOCROffline = import.meta.env.BROWSER === "edge"
const worker = await createWorker(!isOCROffline ? "eng-fast" : "eng", undefined, {
workerPath: "/ocr/worker.min.js", workerPath: "/ocr/worker.min.js",
workerBlobURL: false, workerBlobURL: false,
corePath: "/ocr/tesseract-core-simd.js", corePath: "/ocr/tesseract-core-simd.js",
errorHandler: e => console.error(e), errorHandler: (e) => console.error(e),
langPath: "/ocr/lang" langPath: !isOCROffline ? "/ocr/lang" : undefined
}); })
const result = await worker.recognize(imageData); const result = await worker.recognize(imageData)
await worker.terminate(); await worker.terminate()
return result.data.text; return result.data.text
} }