sub-bridge 1.2.1 → 1.2.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/index.html +89 -0
- package/package.json +1 -1
package/index.html
CHANGED
|
@@ -10,6 +10,52 @@
|
|
|
10
10
|
<body class="min-h-screen bg-neutral-950 text-neutral-100 antialiased">
|
|
11
11
|
<main class="mx-auto flex w-full max-w-xl flex-col gap-4 px-5 py-6" x-data="app()">
|
|
12
12
|
|
|
13
|
+
<!-- Embedded Browser Warning Overlay -->
|
|
14
|
+
<template x-if="embeddedBrowser.detected && !embeddedBrowser.dismissed && oauth.active">
|
|
15
|
+
<div class="fixed inset-0 z-50 flex items-center justify-center bg-neutral-950/95 p-6">
|
|
16
|
+
<div class="max-w-md rounded-2xl border border-amber-500/30 bg-neutral-900 p-6 shadow-2xl">
|
|
17
|
+
<div class="flex flex-col items-center gap-4 text-center">
|
|
18
|
+
<div class="flex h-12 w-12 items-center justify-center rounded-full bg-amber-500/20">
|
|
19
|
+
<svg class="h-6 w-6 text-amber-400" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
|
20
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"/>
|
|
21
|
+
</svg>
|
|
22
|
+
</div>
|
|
23
|
+
<div>
|
|
24
|
+
<h2 class="text-lg font-semibold text-amber-100">Open in External Browser</h2>
|
|
25
|
+
<p class="mt-2 text-sm text-neutral-400">
|
|
26
|
+
Authentication needs to run in your system browser, not Cursor's built-in browser.
|
|
27
|
+
</p>
|
|
28
|
+
</div>
|
|
29
|
+
<div class="w-full space-y-3">
|
|
30
|
+
<div class="flex items-center gap-2 rounded-lg bg-neutral-800 p-3">
|
|
31
|
+
<input
|
|
32
|
+
type="text"
|
|
33
|
+
readonly
|
|
34
|
+
:value="window.location.href"
|
|
35
|
+
class="flex-1 bg-transparent text-xs text-neutral-300 outline-none"
|
|
36
|
+
x-ref="urlInput"
|
|
37
|
+
/>
|
|
38
|
+
<button
|
|
39
|
+
@click="copyUrlToClipboard()"
|
|
40
|
+
class="shrink-0 rounded-md bg-amber-600 px-3 py-1.5 text-xs font-medium text-white hover:bg-amber-500 transition"
|
|
41
|
+
x-text="embeddedBrowser.copied ? 'Copied!' : 'Copy URL'"
|
|
42
|
+
></button>
|
|
43
|
+
</div>
|
|
44
|
+
<p class="text-xs text-neutral-500">
|
|
45
|
+
Copy the URL above and paste it in Chrome, Safari, or Firefox.
|
|
46
|
+
</p>
|
|
47
|
+
</div>
|
|
48
|
+
<button
|
|
49
|
+
@click="embeddedBrowser.dismissed = true"
|
|
50
|
+
class="mt-2 text-xs text-neutral-500 hover:text-neutral-300 underline"
|
|
51
|
+
>
|
|
52
|
+
Continue anyway (may not work)
|
|
53
|
+
</button>
|
|
54
|
+
</div>
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
</template>
|
|
58
|
+
|
|
13
59
|
<!-- SVG Icons -->
|
|
14
60
|
<svg class="hidden" aria-hidden="true">
|
|
15
61
|
<symbol id="logo-claude" viewBox="0 0 24 24">
|
|
@@ -530,6 +576,27 @@
|
|
|
530
576
|
completing: false
|
|
531
577
|
},
|
|
532
578
|
|
|
579
|
+
// Embedded browser detection (Cursor Simple Browser, VS Code, etc.)
|
|
580
|
+
embeddedBrowser: {
|
|
581
|
+
detected: (() => {
|
|
582
|
+
const ua = navigator.userAgent.toLowerCase();
|
|
583
|
+
// Detect VS Code, Cursor, Electron-based editors' embedded browsers
|
|
584
|
+
const isElectron = ua.includes('electron');
|
|
585
|
+
const isVSCode = ua.includes('vscode') || ua.includes('code/');
|
|
586
|
+
const isCursor = ua.includes('cursor');
|
|
587
|
+
// Check for Simple Browser characteristics
|
|
588
|
+
const hasVSCodeApi = typeof window.acquireVsCodeApi === 'function';
|
|
589
|
+
// Simple Browser in Electron doesn't have full Chrome features
|
|
590
|
+
const isEmbedded = isElectron || isVSCode || isCursor || hasVSCodeApi;
|
|
591
|
+
if (isEmbedded) {
|
|
592
|
+
console.log('[Sub Bridge] Embedded browser detected:', { ua, isElectron, isVSCode, isCursor, hasVSCodeApi });
|
|
593
|
+
}
|
|
594
|
+
return isEmbedded;
|
|
595
|
+
})(),
|
|
596
|
+
dismissed: false,
|
|
597
|
+
copied: false
|
|
598
|
+
},
|
|
599
|
+
|
|
533
600
|
// Check if we have an external URL (pre-configured tunnel via --tunnel flag)
|
|
534
601
|
get hasExternalUrl() {
|
|
535
602
|
return this.publicUrl.startsWith('https://') && !this.publicUrl.includes('localhost');
|
|
@@ -710,6 +777,28 @@
|
|
|
710
777
|
}
|
|
711
778
|
},
|
|
712
779
|
|
|
780
|
+
// Copy URL to clipboard for embedded browser workaround
|
|
781
|
+
async copyUrlToClipboard() {
|
|
782
|
+
try {
|
|
783
|
+
await navigator.clipboard.writeText(window.location.href);
|
|
784
|
+
this.embeddedBrowser.copied = true;
|
|
785
|
+
setTimeout(() => {
|
|
786
|
+
this.embeddedBrowser.copied = false;
|
|
787
|
+
}, 2000);
|
|
788
|
+
} catch (e) {
|
|
789
|
+
// Fallback for older browsers or if clipboard API fails
|
|
790
|
+
const input = this.$refs.urlInput;
|
|
791
|
+
if (input) {
|
|
792
|
+
input.select();
|
|
793
|
+
document.execCommand('copy');
|
|
794
|
+
this.embeddedBrowser.copied = true;
|
|
795
|
+
setTimeout(() => {
|
|
796
|
+
this.embeddedBrowser.copied = false;
|
|
797
|
+
}, 2000);
|
|
798
|
+
}
|
|
799
|
+
}
|
|
800
|
+
},
|
|
801
|
+
|
|
713
802
|
// Claude code input handler (1s debounce)
|
|
714
803
|
claudeCodeInput() {
|
|
715
804
|
clearTimeout(this._debounce);
|