Skip to content

Commit 3b4f6d7

Browse files
committed
Enhances embed functionality for channels/playlists
Extends the embed component to support homepage, channels, playlists, and markdown content. For channel embeds, it now displays a grid of the latest uploads. Playlist embeds showcase the cover and a playable list. Adds support for rendering markdown content within embeds, fetching the content and displaying it. Also configures the homepage embed to point Mini App action to the homepage embed. Simplify unsaved settings warning logic remove comment Removed embed menu item to maintain focus on current changes.
1 parent aa734b9 commit 3b4f6d7

File tree

36 files changed

+759
-289
lines changed

36 files changed

+759
-289
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,5 @@ package-lock.json
4141
.env.lbrytv
4242
analyzeResults*.html
4343
ecosystem.config.js
44+
45+
.claude/settings.local.json

config.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -115,6 +115,8 @@ const config = {
115115
// FROM COMMAND LINE
116116
COMMIT_ID: process.env.COMMIT_ID,
117117
NODE_ENV: process.env.NODE_ENV,
118+
// Dev/staged feature gating
119+
DYNAMIC_ROUTES_FIRST: process.env.DYNAMIC_ROUTES_FIRST === 'true',
118120
};
119121

120122
config.SDK_API_PATH = `${config.LBRY_WEB_API}/api/v1`;

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@
2727
"dev": "yarn dev:electron",
2828
"dev:electron": "cross-env NODE_ENV=development node ./electron/devServer.js",
2929
"dev:web": "yarn copyenv && cd web && yarn dev",
30-
"dev:web-server": "cross-env NODE_ENV=development yarn compile:web && concurrently \"cross-env NODE_ENV=development yarn compile:web --watch\" \"cd web && yarn dev:server\"",
30+
"dev:web-server": "cross-env NODE_ENV=development DYNAMIC_ROUTES_FIRST=true yarn compile:web && cross-env NODE_ENV=development DYNAMIC_ROUTES_FIRST=true concurrently \"yarn compile:web --watch\" \"cd web && yarn dev:server\"",
3131
"dev:internal-apis": "LBRY_API_URL='http://localhost:8080' yarn dev:electron",
3232
"dev:iatv": "LBRY_API_URL='http://localhost:15400' SDK_API_URL='http://localhost:15100' yarn dev:web",
3333
"run:web-server": "cross-env NODE_ENV=production yarn compile:web && cd web && yarn dev:server",

ui/component/app/view.jsx

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,22 @@ function App(props: Props) {
225225

226226
// Only 1 nag is possible, so show the most important:
227227

228+
// Active uploads warning (show globally so users know why the browser prompts on leave)
229+
if (uploadCount > 0 && !embedPath) {
230+
const onUploadPage =
231+
location?.pathname?.startsWith(`/$/${PAGES.UPLOAD}`) || location?.pathname?.startsWith(`/$/${PAGES.UPLOADS}`);
232+
if (!onUploadPage) {
233+
return (
234+
<Nag
235+
type="helpful"
236+
message={__('Upload in progress. Closing or reloading may interrupt your upload.')}
237+
actionText={__('View Uploads')}
238+
onClick={() => history.push(`/$/${PAGES.UPLOADS}`)}
239+
/>
240+
);
241+
}
242+
}
243+
228244
if (user === null && !embedPath) {
229245
return <NagNoUser />;
230246
}

ui/component/claimMenuList/view.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -341,6 +341,7 @@ function ClaimMenuList(props: Props) {
341341
};
342342

343343
const ToggleLastUsedCollectionMenuItems = () => {
344+
if (!lastUsedCollections || !Array.isArray(lastUsedCollections)) return null;
344345
return lastUsedCollections.map((lastUsedCollection) => {
345346
return (
346347
<MenuItem

ui/component/claimTilesDiscover/view.jsx

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,8 @@ function ClaimTilesDiscover(props: Props) {
116116
const uris = (prefixUris || []).concat(claimSearchUris);
117117
if (prefixUris && prefixUris.length) uris.splice(prefixUris.length * -1, prefixUris.length);
118118

119-
if (window.location.pathname === '/') {
119+
// Treat the embed homepage the same as the main homepage for pin injection.
120+
if (window.location.pathname === '/' || window.location.pathname === '/$/embed/home') {
120121
injectPinUrls(uris, pins, resolvedPinUris);
121122
}
122123

ui/component/embedTextArea/view.jsx

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@ export default function EmbedTextArea(props: Props) {
2323
props;
2424

2525
const [embedAutoplay, setEmbedAutoplay] = React.useState(false);
26+
const isChannel = claim && claim.value_type === 'channel';
27+
const isCollection = claim && claim.value_type === 'collection';
28+
const showAutoplayToggle = !isChannel && !isCollection && !newestType;
2629

2730
const { canonical_url: canonicalUri } = claim;
2831
const input = useRef();
@@ -66,15 +69,17 @@ export default function EmbedTextArea(props: Props) {
6669
readOnly
6770
/>
6871

69-
<div className="margin-vertical-medium">
70-
<FormField
71-
name={'embed-autoplay' + (newestType ? ' ' + newestType : '')}
72-
type="checkbox"
73-
label={__('Enable Autoplay')}
74-
checked={embedAutoplay}
75-
onChange={() => setEmbedAutoplay((prev) => !prev)}
76-
/>
77-
</div>
72+
{showAutoplayToggle && (
73+
<div className="margin-vertical-medium">
74+
<FormField
75+
name={'embed-autoplay' + (newestType ? ' ' + newestType : '')}
76+
type="checkbox"
77+
label={__('Enable Autoplay')}
78+
checked={embedAutoplay}
79+
onChange={() => setEmbedAutoplay((prev) => !prev)}
80+
/>
81+
</div>
82+
)}
7883

7984
<div className="section__actions">
8085
<Button

ui/component/fileActions/view.jsx

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -90,8 +90,13 @@ export default function FileActions(props: Props) {
9090
const channelName = signingChannel && signingChannel.name;
9191
const fileName = value && value.source && value.source.name;
9292
const claimType = isLivestreamClaim ? 'livestream' : isPostClaim ? 'post' : 'upload';
93-
94-
const webShareable = costInfo && costInfo.cost === 0 && RENDER_MODES.WEB_SHAREABLE_MODES.includes(renderMode);
93+
const isCollectionClaim = claim && claim.value_type === 'collection';
94+
const isChannel = claim && claim.value_type === 'channel';
95+
const webShareable =
96+
(costInfo && costInfo.cost === 0 && RENDER_MODES.WEB_SHAREABLE_MODES.includes(renderMode)) ||
97+
RENDER_MODES.TEXT_MODES.includes(renderMode) ||
98+
isCollectionClaim ||
99+
isChannel;
95100
const urlParams = new URLSearchParams(search);
96101
const collectionId = urlParams.get(COLLECTIONS_CONSTS.COLLECTION_ID);
97102

ui/component/header/view.jsx

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type Props = {
5555
openChangelog: ({}) => void,
5656
setSidebarOpen: (boolean) => void,
5757
signOut: () => void,
58+
hideSidebarToggle?: boolean,
5859
};
5960

6061
const Header = (props: Props) => {
@@ -116,7 +117,9 @@ const Header = (props: Props) => {
116117

117118
// Sign out if they click the "x" when they are on the password prompt
118119
const authHeaderAction = syncError && { onClick: signOut };
119-
const homeButtonNavigationProps = (isVerifyPage && {}) || (authHeader && authHeaderAction) || { navigate: '/' };
120+
const isEmbedPath = pathname.startsWith('/$/embed');
121+
const homeButtonNavigationProps = (isVerifyPage && {}) ||
122+
(authHeader && authHeaderAction) || { navigate: isEmbedPath ? '/$/embed/home' : '/' };
120123
const sidebarLabel = sidebarOpen
121124
? __('Close sidebar - hide channels you are following.')
122125
: __('Expand sidebar - view channels you are following.');
@@ -244,7 +247,7 @@ const Header = (props: Props) => {
244247
<div className="header__menu--left">
245248
<SkipNavigationButton />
246249

247-
{!authHeader && (
250+
{!authHeader && !props.hideSidebarToggle && (
248251
<span style={{ position: 'relative' }}>
249252
<Button
250253
aria-label={sidebarLabel}
@@ -262,7 +265,7 @@ const Header = (props: Props) => {
262265
aria-label={__('Home')}
263266
className="header__navigationItem--logo"
264267
onClick={() => {
265-
if (pathname === '/') {
268+
if (pathname === '/' || pathname === '/$/embed/home') {
266269
window.scrollTo({ top: 0, left: 0, behavior: 'smooth' });
267270
doClearClaimSearch();
268271
}

ui/component/page/view.jsx

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,7 @@ function Page(props: Props) {
101101
sidebarOpen={sidebarOpen}
102102
isAbsoluteSideNavHidden={isAbsoluteSideNavHidden}
103103
setSidebarOpen={openSidebar}
104+
hideSidebarToggle={noSideNavigation}
104105
/>
105106
)}
106107

0 commit comments

Comments
 (0)