@omg-dev/pwa 0.4.26 → 0.4.28
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/dist/remix-cta.mjs +23 -4
- package/package.json +1 -1
- package/src/remix-cta.tsx +39 -5
package/dist/remix-cta.mjs
CHANGED
|
@@ -3,7 +3,8 @@ import { jsx, jsxs } from "react/jsx-runtime";
|
|
|
3
3
|
import { createRoot } from "react-dom/client";
|
|
4
4
|
//#region src/remix-cta.tsx
|
|
5
5
|
const DISMISS_KEY = "vibes-remix:dismissed";
|
|
6
|
-
const REMIX_ORIGIN = typeof import.meta !== "undefined" && import.meta.env?.VITE_REMIX_ORIGIN || "https://omg.dev";
|
|
6
|
+
const REMIX_ORIGIN = typeof import.meta !== "undefined" && import.meta.env?.VITE_REMIX_ORIGIN || "https://app.omg.dev";
|
|
7
|
+
const CONTROLPLANE_URL = (typeof import.meta !== "undefined" && import.meta.env?.VITE_CONTROLPLANE_URL || "https://backend.omg.dev").replace(/\/$/, "");
|
|
7
8
|
function appSlug() {
|
|
8
9
|
if (typeof import.meta === "undefined") return null;
|
|
9
10
|
const slug = import.meta.env?.VITE_APP_SLUG?.trim();
|
|
@@ -22,6 +23,21 @@ function setDismissed() {
|
|
|
22
23
|
localStorage.setItem(DISMISS_KEY, "1");
|
|
23
24
|
} catch {}
|
|
24
25
|
}
|
|
26
|
+
/** Live check against the public catalog. Fail closed on network/error. */
|
|
27
|
+
async function isRemixable(slug) {
|
|
28
|
+
try {
|
|
29
|
+
const res = await fetch(`${CONTROLPLANE_URL}/api/projects/isRemixable`, {
|
|
30
|
+
method: "POST",
|
|
31
|
+
headers: { "content-type": "application/json" },
|
|
32
|
+
body: JSON.stringify({ slug }),
|
|
33
|
+
cache: "no-store"
|
|
34
|
+
});
|
|
35
|
+
if (!res.ok) return false;
|
|
36
|
+
return (await res.json())?.remixable === true;
|
|
37
|
+
} catch {
|
|
38
|
+
return false;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
25
41
|
const STYLE_ID = "vibes-remix-cta-styles";
|
|
26
42
|
function ensureStyles() {
|
|
27
43
|
if (typeof document === "undefined") return;
|
|
@@ -106,17 +122,20 @@ function shouldShow() {
|
|
|
106
122
|
if (isDismissed()) return false;
|
|
107
123
|
return appSlug() !== null;
|
|
108
124
|
}
|
|
109
|
-
function mount() {
|
|
125
|
+
async function mount() {
|
|
110
126
|
if (!shouldShow()) return;
|
|
111
127
|
const slug = appSlug();
|
|
112
128
|
if (!slug) return;
|
|
129
|
+
if (!await isRemixable(slug)) return;
|
|
130
|
+
if (isDismissed()) return;
|
|
131
|
+
if (document.getElementById("vibes-remix-cta")) return;
|
|
113
132
|
ensureStyles();
|
|
114
133
|
const host = document.createElement("div");
|
|
115
134
|
host.id = "vibes-remix-cta";
|
|
116
135
|
document.body.appendChild(host);
|
|
117
136
|
createRoot(host).render(/* @__PURE__ */ jsx(RemixCta, { slug }));
|
|
118
137
|
}
|
|
119
|
-
if (typeof window !== "undefined") if (document.readyState === "complete") setTimeout(mount, 1800);
|
|
120
|
-
else window.addEventListener("load", () => setTimeout(mount, 1800), { once: true });
|
|
138
|
+
if (typeof window !== "undefined") if (document.readyState === "complete") setTimeout(() => void mount(), 1800);
|
|
139
|
+
else window.addEventListener("load", () => setTimeout(() => void mount(), 1800), { once: true });
|
|
121
140
|
//#endregion
|
|
122
141
|
export {};
|
package/package.json
CHANGED
package/src/remix-cta.tsx
CHANGED
|
@@ -11,6 +11,8 @@
|
|
|
11
11
|
// Policy (deliberately quiet):
|
|
12
12
|
// - never in an iframe (the dashboard preview pane is not the app URL)
|
|
13
13
|
// - only when import.meta.env.VITE_APP_SLUG is baked in (prod builds only)
|
|
14
|
+
// - only when the app is currently listed public (isPublic) — private apps
|
|
15
|
+
// keep no CTA; remixBySlug rejects them
|
|
14
16
|
// - dismissable forever (per-origin localStorage)
|
|
15
17
|
|
|
16
18
|
import { createRoot } from "react-dom/client"
|
|
@@ -18,11 +20,21 @@ import { isInIframe } from "./core"
|
|
|
18
20
|
|
|
19
21
|
const DISMISS_KEY = "vibes-remix:dismissed"
|
|
20
22
|
// The dashboard origin the remix deep-link points at. Overridable for
|
|
21
|
-
// self-host via VITE_REMIX_ORIGIN
|
|
23
|
+
// self-host via VITE_REMIX_ORIGIN.
|
|
24
|
+
//
|
|
25
|
+
// app.omg.dev, NOT omg.dev: /remix/<slug> is a dashboard SPA route, and the
|
|
26
|
+
// dashboard moved off omg.dev when that host became the marketing landing.
|
|
27
|
+
// The landing has no /remix route, so the old default sent every recipient of
|
|
28
|
+
// a shared app to a "Not Found" page — the whole recipient->creator loop.
|
|
22
29
|
const REMIX_ORIGIN =
|
|
23
30
|
(typeof import.meta !== "undefined" &&
|
|
24
31
|
(import.meta as { env?: Record<string, string | undefined> }).env?.VITE_REMIX_ORIGIN) ||
|
|
25
|
-
"https://omg.dev"
|
|
32
|
+
"https://app.omg.dev"
|
|
33
|
+
const CONTROLPLANE_URL = (
|
|
34
|
+
(typeof import.meta !== "undefined" &&
|
|
35
|
+
(import.meta as { env?: Record<string, string | undefined> }).env?.VITE_CONTROLPLANE_URL) ||
|
|
36
|
+
"https://backend.omg.dev"
|
|
37
|
+
).replace(/\/$/, "")
|
|
26
38
|
|
|
27
39
|
function appSlug(): string | null {
|
|
28
40
|
if (typeof import.meta === "undefined") return null
|
|
@@ -48,6 +60,23 @@ function setDismissed() {
|
|
|
48
60
|
}
|
|
49
61
|
}
|
|
50
62
|
|
|
63
|
+
/** Live check against the public catalog. Fail closed on network/error. */
|
|
64
|
+
async function isRemixable(slug: string): Promise<boolean> {
|
|
65
|
+
try {
|
|
66
|
+
const res = await fetch(`${CONTROLPLANE_URL}/api/projects/isRemixable`, {
|
|
67
|
+
method: "POST",
|
|
68
|
+
headers: { "content-type": "application/json" },
|
|
69
|
+
body: JSON.stringify({ slug }),
|
|
70
|
+
cache: "no-store",
|
|
71
|
+
})
|
|
72
|
+
if (!res.ok) return false
|
|
73
|
+
const data = (await res.json()) as { remixable?: unknown }
|
|
74
|
+
return data?.remixable === true
|
|
75
|
+
} catch {
|
|
76
|
+
return false
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
|
|
51
80
|
const STYLE_ID = "vibes-remix-cta-styles"
|
|
52
81
|
function ensureStyles() {
|
|
53
82
|
if (typeof document === "undefined") return
|
|
@@ -139,10 +168,15 @@ function shouldShow(): boolean {
|
|
|
139
168
|
return appSlug() !== null
|
|
140
169
|
}
|
|
141
170
|
|
|
142
|
-
function mount() {
|
|
171
|
+
async function mount() {
|
|
143
172
|
if (!shouldShow()) return
|
|
144
173
|
const slug = appSlug()
|
|
145
174
|
if (!slug) return
|
|
175
|
+
// Only mount for Explore-listed public apps. Private published apps get no
|
|
176
|
+
// CTA (branding lives on the omg badge when that path is enabled).
|
|
177
|
+
if (!(await isRemixable(slug))) return
|
|
178
|
+
if (isDismissed()) return
|
|
179
|
+
if (document.getElementById("vibes-remix-cta")) return
|
|
146
180
|
ensureStyles()
|
|
147
181
|
const host = document.createElement("div")
|
|
148
182
|
host.id = "vibes-remix-cta"
|
|
@@ -153,8 +187,8 @@ function mount() {
|
|
|
153
187
|
if (typeof window !== "undefined") {
|
|
154
188
|
// Let the app paint first — the CTA is an afterthought, not a gate.
|
|
155
189
|
if (document.readyState === "complete") {
|
|
156
|
-
setTimeout(mount, 1800)
|
|
190
|
+
setTimeout(() => void mount(), 1800)
|
|
157
191
|
} else {
|
|
158
|
-
window.addEventListener("load", () => setTimeout(mount, 1800), { once: true })
|
|
192
|
+
window.addEventListener("load", () => setTimeout(() => void mount(), 1800), { once: true })
|
|
159
193
|
}
|
|
160
194
|
}
|