Skip to content

Commit a8d286a

Browse files
committed
Improves embed and upload page handling
Addresses several issues and improves the user experience. - Ensures the active uploads warning only appears when not on the upload page by checking the pathname more reliably. - Corrects collection redirection logic by adding a code block. - Removes duplicate URI building logic in embed wrappers. - Enhances Farcaster embed functionality by including the SDK and ready script only on embed pages to avoid unnecessary overhead on other pages.
1 parent 7b0d3f5 commit a8d286a

File tree

5 files changed

+54
-72
lines changed

5 files changed

+54
-72
lines changed

ui/component/app/view.jsx

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -227,8 +227,10 @@ function App(props: Props) {
227227

228228
// Active uploads warning (show globally so users know why the browser prompts on leave)
229229
if (uploadCount > 0 && !embedPath) {
230+
const pathname = location && location.pathname;
230231
const onUploadPage =
231-
location?.pathname?.startsWith(`/$/${PAGES.UPLOAD}`) || location?.pathname?.startsWith(`/$/${PAGES.UPLOADS}`);
232+
(pathname && pathname.startsWith(`/$/${PAGES.UPLOAD}`)) ||
233+
(pathname && pathname.startsWith(`/$/${PAGES.UPLOADS}`));
232234
if (!onUploadPage) {
233235
return (
234236
<Nag

ui/page/claim/internal/claimPageComponent/view.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -161,11 +161,11 @@ const ClaimPageComponent = (props: Props) => {
161161
if (claim && isCollection && collectionFirstItemUri) {
162162
switch (collection?.type) {
163163
case COL_TYPES.COLLECTION:
164-
case COL_TYPES.PLAYLIST:
164+
case COL_TYPES.PLAYLIST: {
165165
urlParams.set(COLLECTIONS_CONSTS.COLLECTION_ID, claim.claim_id);
166166
const newUrl = formatLbryUrlForWeb(`${collectionFirstItemUri}?${urlParams.toString()}`);
167167
return <Redirect to={newUrl} />;
168-
168+
}
169169
case COL_TYPES.FEATURED_CHANNELS:
170170
return <Redirect to={`/$/${PAGES.PLAYLIST}/${claim.claim_id}`} />;
171171

ui/page/embedWrapper/index.js

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -109,10 +109,6 @@ function getUriFromMatch(match) {
109109
try {
110110
return buildURI({ claimName, claimId });
111111
} catch (error) {}
112-
try {
113-
return buildURI({ claimName, claimId });
114-
} catch (error) {}
115-
// ^-------- why twice?
116112
}
117113

118114
if (isCanonicalUriFormat) {

ui/page/embedWrapper/view.jsx

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -106,9 +106,6 @@ function getUriFromMatch(match) {
106106
try {
107107
return buildURI({ claimName, claimId });
108108
} catch (error) {}
109-
try {
110-
return buildURI({ claimName, claimId });
111-
} catch (error) {}
112109
}
113110

114111
if (isCanonicalUriFormat && claimName) {

web/src/html.js

Lines changed: 49 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -88,11 +88,46 @@ function getCategoryMeta(path) {
8888
return null;
8989
}
9090

91+
function buildFarcasterEmbedScripts() {
92+
return `<script src="https://cdn.jsdelivr.net/npm/@farcaster/miniapp-sdk/dist/index.min.js"></script>
93+
<script>
94+
(function() {
95+
function signalReady() {
96+
try {
97+
var sdk = (window.miniapp && window.miniapp.sdk) || window.sdk || (window.frame && window.frame.sdk);
98+
if (sdk && sdk.actions && typeof sdk.actions.ready === 'function') {
99+
sdk.actions.ready();
100+
}
101+
return true;
102+
} catch (e) {
103+
return false;
104+
}
105+
}
106+
107+
var attempts = 0;
108+
var maxAttempts = 50;
109+
var checkAndSignal = setInterval(function() {
110+
attempts++;
111+
if (signalReady()) {
112+
clearInterval(checkAndSignal);
113+
} else if (attempts >= maxAttempts) {
114+
clearInterval(checkAndSignal);
115+
try {
116+
if (window.parent && window.parent.postMessage) {
117+
window.parent.postMessage({ type: 'miniapp-ready-timeout' }, '*');
118+
}
119+
} catch (e) {}
120+
}
121+
}, 100);
122+
})();
123+
</script>`;
124+
}
125+
91126
//
92127
// Normal metadata with option to override certain values
93128
//
94129
function buildOgMetadata(overrideOptions = {}) {
95-
const { title, description, image, path, urlQueryString, baseUrl, fcActionUrl } = overrideOptions;
130+
const { title, description, image, path, urlQueryString, baseUrl, fcActionUrl, isEmbed } = overrideOptions;
96131
const BASE = baseUrl || URL;
97132
const cleanDescription = escapeHtmlProperty(removeMd(description || SITE_DESCRIPTION));
98133
const cleanTitle = escapeHtmlProperty(title);
@@ -164,11 +199,9 @@ function buildOgMetadata(overrideOptions = {}) {
164199
out += `\n<meta name="fc:frame:button:1:action" content="link"/>`;
165200
out += `\n<meta name="fc:frame:button:1:target" content="${fcActionUrl || url}"/>`;
166201

167-
// If Farcaster MiniApp/Frame tags are emitted, also include a minimal
168-
// "ready" signal so clients can hook in immediately.
169-
if (fcActionUrl) {
170-
const readyScript = `\n<script>(function(){function r(){try{var s=(window.miniapp&&window.miniapp.sdk)||window.sdk||(window.frame&&window.frame.sdk);if(s&&s.actions&&typeof s.actions.ready==='function'){s.actions.ready();}if(window.parent&&window.parent.postMessage){window.parent.postMessage({type:'miniapp-ready'},'*');}return true;}catch(e){return false;}}var a=0,m=50,t=setInterval(function(){a++;if(r()){clearInterval(t);}else if(a>=m){clearInterval(t);try{if(window.parent&&window.parent.postMessage){window.parent.postMessage({type:'miniapp-ready-timeout'},'*');}}catch(e){}}},100);})();</script>`;
171-
out += readyScript;
202+
// Only load SDK and ready script for actual embed pages
203+
if (isEmbed) {
204+
out += '\n' + buildFarcasterEmbedScripts();
172205
}
173206

174207
return out;
@@ -217,7 +250,7 @@ function buildBasicOgMetadata(overrideOptions = {}) {
217250
//
218251
async function buildClaimOgMetadata(uri, claim, overrideOptions = {}, referrerQuery) {
219252
// Initial setup for claim based og metadata
220-
const { userAgent, baseUrl } = overrideOptions;
253+
const { userAgent, baseUrl, isEmbed } = overrideOptions;
221254
const BASE = baseUrl || URL;
222255
const { claimName } = parseURI(uri);
223256
const { meta, value, signing_channel } = claim;
@@ -391,57 +424,11 @@ async function buildClaimOgMetadata(uri, claim, overrideOptions = {}, referrerQu
391424
head += `<meta name="fc:frame:button:2" content="Next ▶"/>`;
392425
head += `<meta name="fc:frame:button:2:action" content="post"/>`;
393426
head += `<meta name="fc:frame:post_url" content="${BASE}/$/frame"/>`;
394-
head += `<script src="https://cdn.jsdelivr.net/npm/@farcaster/miniapp-sdk/dist/index.min.js"></script>`;
395427

396-
// Ready signal script - runs after SDK loads
397-
head += `<script>
398-
(function() {
399-
function signalReady() {
400-
try {
401-
// Try multiple SDK locations
402-
const sdk = (window.miniapp && window.miniapp.sdk) || window.sdk || (window.frame && window.frame.sdk);
403-
404-
if (sdk && sdk.actions && typeof sdk.actions.ready === 'function') {
405-
sdk.actions.ready();
406-
console.log('MiniApp ready signal sent via SDK');
407-
}
408-
409-
// Also send postMessage as fallback
410-
if (window.parent && window.parent.postMessage) {
411-
window.parent.postMessage({ type: 'miniapp-ready' }, '*');
412-
console.log('MiniApp ready signal sent via postMessage');
413-
}
414-
415-
return true;
416-
} catch (e) {
417-
console.error('MiniApp ready signal failed:', e);
418-
return false;
419-
}
420-
}
421-
422-
// Wait for SDK to be available
423-
let attempts = 0;
424-
const maxAttempts = 50;
425-
426-
const checkAndSignal = setInterval(function() {
427-
attempts++;
428-
429-
if (signalReady()) {
430-
clearInterval(checkAndSignal);
431-
} else if (attempts >= maxAttempts) {
432-
console.warn('MiniApp ready timeout after', attempts * 100, 'ms');
433-
clearInterval(checkAndSignal);
434-
435-
// Send timeout signal
436-
try {
437-
if (window.parent && window.parent.postMessage) {
438-
window.parent.postMessage({ type: 'miniapp-ready-timeout' }, '*');
439-
}
440-
} catch (e) {}
428+
// Only load SDK and ready script for actual embed pages
429+
if (isEmbed) {
430+
head += buildFarcasterEmbedScripts();
441431
}
442-
}, 100);
443-
})();
444-
</script>`;
445432
} catch (e) {
446433
console.error('MiniApp embed meta failed:', e);
447434
}
@@ -565,7 +552,11 @@ async function getHtml(ctx) {
565552
if (requestPath.includes(embedPath)) {
566553
// Special-case: homepage embed (early) only when enabled
567554
if (requestPath === '/$/embed/home' || requestPath === '/$/embed/home/') {
568-
const ogMetadata = buildOgMetadata({ baseUrl: ctx.origin, fcActionUrl: `${ctx.origin}/$/embed/home` });
555+
const ogMetadata = buildOgMetadata({
556+
baseUrl: ctx.origin,
557+
fcActionUrl: `${ctx.origin}/$/embed/home`,
558+
isEmbed: true,
559+
});
569560
return insertToHead(html, ogMetadata);
570561
}
571562
// Otherwise, try to resolve an embed claim
@@ -576,15 +567,11 @@ async function getHtml(ctx) {
576567
const ogMetadata = await buildClaimOgMetadata(claimUri, claim, {
577568
userAgent: userAgent,
578569
baseUrl: ctx.origin,
570+
isEmbed: true,
579571
});
580572
const googleVideoMetadata = await buildGoogleVideoMetadata(claimUri, claim);
581573
return insertToHead(html, ogMetadata.concat('\n', googleVideoMetadata));
582574
}
583-
// Late special-case: homepage embed when not enabled (maintain old order)
584-
if (requestPath === '/$/embed/home' || requestPath === '/$/embed/home/') {
585-
const ogMetadata = buildOgMetadata({ baseUrl: ctx.origin, fcActionUrl: `${URL}/$/embed/home` });
586-
return insertToHead(html, ogMetadata);
587-
}
588575

589576
return insertToHead(html);
590577
}

0 commit comments

Comments
 (0)