Compare commits
2 Commits
extension-
...
extension-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4b7f308528 | ||
|
|
95ee3fa61d |
@@ -42,5 +42,17 @@
|
||||
},
|
||||
"description": "Toggle InsightReply Sidebar"
|
||||
}
|
||||
}
|
||||
},
|
||||
"web_accessible_resources": [
|
||||
{
|
||||
"resources": [
|
||||
"src/assets/*",
|
||||
"assets/*"
|
||||
],
|
||||
"matches": [
|
||||
"https://twitter.com/*",
|
||||
"https://x.com/*"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -107,28 +107,28 @@ const copyToClipboard = async (reply: any) => {
|
||||
|
||||
<template>
|
||||
<transition
|
||||
enter-active-class="transition duration-500 ease-out transform"
|
||||
enter-from-class="translate-x-full opacity-0 scale-95"
|
||||
enter-to-class="translate-x-0 opacity-100 scale-100"
|
||||
leave-active-class="transition duration-400 ease-in transform"
|
||||
leave-from-class="translate-x-0 opacity-100 scale-100"
|
||||
leave-to-class="translate-x-full opacity-0 scale-95"
|
||||
enter-active-class="transition-transform duration-500 ease-[cubic-bezier(0.2,0.8,0.2,1)]"
|
||||
enter-from-class="translate-x-full"
|
||||
enter-to-class="translate-x-0"
|
||||
leave-active-class="transition-transform duration-400 ease-[cubic-bezier(0.2,0.8,0.2,1)]"
|
||||
leave-from-class="translate-x-0"
|
||||
leave-to-class="translate-x-full"
|
||||
>
|
||||
<div v-if="isVisible" class="fixed right-6 top-1/2 -translate-y-1/2 w-[380px] max-h-[90vh] flex flex-col glass-card rounded-[24px] shadow-[0_32px_64px_rgba(0,0,0,0.5)] text-[#f8fafc] font-sans z-[2147483647] overflow-hidden border border-white/5 selection:bg-rose-500/30">
|
||||
<div v-if="isVisible" class="fixed right-0 top-0 bottom-0 w-[400px] flex flex-col bg-zinc-950/90 backdrop-blur-[40px] border-l border-white/10 shadow-[-10px_0_40px_rgba(0,0,0,0.5)] text-[#f8fafc] font-sans z-[2147483647] overflow-hidden selection:bg-rose-500/30">
|
||||
|
||||
<!-- Premium Header -->
|
||||
<div class="px-6 py-5 flex justify-between items-center bg-white/[0.02] border-b border-white/5">
|
||||
<div class="px-6 py-5 flex justify-between items-center bg-white/[0.02] border-b border-white/5 shrink-0">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="p-2 rounded-lg bg-rose-500/10 border border-rose-500/20">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="text-rose-500"><path d="m12 14 4-4"/><path d="M3.34 19a10 10 0 1 1 17.32 0"/></svg>
|
||||
<div class="p-2 rounded-xl bg-gradient-to-br from-rose-500 to-rose-600 shadow-lg shadow-rose-900/20">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="text-white"><path d="m12 14 4-4"/><path d="M3.34 19a10 10 0 1 1 17.32 0"/></svg>
|
||||
</div>
|
||||
<div>
|
||||
<span class="text-sm font-bold tracking-tight block">InsightReply</span>
|
||||
<span class="text-[9px] text-zinc-500 uppercase tracking-[0.2em] font-bold">Spatial Copilot</span>
|
||||
<span class="text-[15px] font-black tracking-tight block text-white drop-shadow-sm">InsightReply</span>
|
||||
<span class="text-[9px] text-zinc-400 uppercase tracking-[0.2em] font-bold">Spatial Copilot</span>
|
||||
</div>
|
||||
</div>
|
||||
<button @click="isVisible = false" class="p-2 rounded-full hover:bg-white/10 transition-apple group">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" class="text-zinc-500 group-hover:text-white transition-apple"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
||||
<button @click="isVisible = false" class="p-2.5 rounded-full bg-white/5 hover:bg-rose-500/20 hover:text-rose-400 border border-white/5 transition-apple group">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2.5" class="text-zinc-400 group-hover:text-rose-400 transition-apple"><path d="M18 6L6 18M6 6l12 12"/></svg>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
|
||||
@@ -8,13 +8,16 @@ const currentTweetData = ref<any>(null)
|
||||
const sidebarVisible = ref(false)
|
||||
|
||||
let isMounted = false
|
||||
let isMounting = false
|
||||
|
||||
function initSidebar() {
|
||||
if (isMounted) return
|
||||
async function initSidebar() {
|
||||
if (isMounted || isMounting) return
|
||||
|
||||
let host = document.getElementById(MOUNT_ID)
|
||||
if (host) return
|
||||
|
||||
isMounting = true
|
||||
|
||||
// 1. Create Host Element
|
||||
host = document.createElement('div')
|
||||
host.id = MOUNT_ID
|
||||
@@ -45,17 +48,51 @@ function initSidebar() {
|
||||
`
|
||||
shadowRoot.appendChild(container)
|
||||
|
||||
// 4. Inject Styles
|
||||
const injectStyles = () => {
|
||||
const styles = document.querySelectorAll('style, link[rel="stylesheet"]')
|
||||
styles.forEach(style => {
|
||||
shadowRoot.appendChild(style.cloneNode(true))
|
||||
})
|
||||
// 4. Inject Styles (Bypassing X.com CSP via fetch)
|
||||
const injectStyles = async () => {
|
||||
try {
|
||||
// Check for Vite dev mode styles first
|
||||
const devStyles = document.querySelectorAll('style[data-vite-dev-id]')
|
||||
if (devStyles.length > 0) {
|
||||
devStyles.forEach(style => shadowRoot.appendChild(style.cloneNode(true)))
|
||||
console.log('[InsightReply] Injected dev styles into shadow DOM')
|
||||
return
|
||||
}
|
||||
|
||||
// Production mode: fetch the CSS file directly to bypass rigid CSP
|
||||
// CRXJS usually puts built CSS in assets/index-[hash].css
|
||||
const cssUrl = chrome.runtime.getURL('assets/index.css')
|
||||
// In Vite dev mode the raw file might be available
|
||||
const devUrl = chrome.runtime.getURL('src/assets/tailwind.css')
|
||||
|
||||
const urlToFetch = chrome.runtime.id.includes('extension') ? cssUrl : devUrl
|
||||
|
||||
const response = await fetch(urlToFetch)
|
||||
if (response.ok) {
|
||||
const cssText = await response.text()
|
||||
const styleEl = document.createElement('style')
|
||||
styleEl.textContent = cssText
|
||||
shadowRoot.appendChild(styleEl)
|
||||
console.log('[InsightReply] Successfully injected fetched CSS into shadow DOM')
|
||||
} else {
|
||||
console.warn('[InsightReply] Failed to fetch CSS file directly, falling back to basic link tag')
|
||||
const linkEl = document.createElement('link')
|
||||
linkEl.rel = 'stylesheet'
|
||||
linkEl.href = chrome.runtime.getURL('src/assets/tailwind.css')
|
||||
shadowRoot.appendChild(linkEl)
|
||||
}
|
||||
} catch (err) {
|
||||
console.error('[InsightReply] Error injecting styles:', err)
|
||||
}
|
||||
}
|
||||
injectStyles()
|
||||
|
||||
// Inject and wait
|
||||
await injectStyles()
|
||||
|
||||
// 5. Create Vue App with reactive provide
|
||||
const app = createApp(Sidebar)
|
||||
|
||||
isMounting = false
|
||||
app.provide('currentTweetData', currentTweetData)
|
||||
app.provide('sidebarVisible', sidebarVisible)
|
||||
app.mount(container)
|
||||
|
||||
Reference in New Issue
Block a user