Repository navigation
feat(exercises): add video and guide URL support for custom exc - #246
Closed
Vaibhav159 wants to merge 1 commit into
Closed
Vaibhav159 wants to merge 1 commit into
Vaibhav159 wants to merge 1 commit into
Conversation
Vaibhav159
commented
Sep 17, 2026
- CustomExForm & ExerciseDetail: allow attaching an optional video or guide URL when creating/editing a custom exercise
- Media display:
- YouTube: thumbnail preview with tap-to-play inline iframe (youtube-nocookie)
- Direct video (.mp4, .webm, etc.): native
- External links (Instagram, TikTok, guides): compact action card (.exlink-card) with platform branding, domain pill, and external link arrow
- Plan sharing & backup export:
- buildPlanBundle exports custom exercise URLs with the plan
- parsePlan & mergePlan sanitize URLs at trust boundary, backfill URLs on existing exercises, and preserve custom: true
- Full state backup export/import in Settings carries URLs intact
- Backend schema & validation:
- Validates and sanitizes optional URL on coach custom exercise generation (https?:// only)
- Icons & tests:
- Added instagram and tiktok stroke icons matching existing icon grid
- Comprehensive unit tests across frontend (vitest) and backend (node --test)
- CustomExForm & ExerciseDetail: allow attaching an optional video or guide URL when creating/editing a custom exercise - Media display: - YouTube: thumbnail preview with tap-to-play inline iframe (youtube-nocookie) - Direct video (.mp4, .webm, etc.): native <video controls playsInline> - External links (Instagram, TikTok, guides): compact action card (.exlink-card) with platform branding, domain pill, and external link arrow - Plan sharing & backup export: - buildPlanBundle exports custom exercise URLs with the plan - parsePlan & mergePlan sanitize URLs at trust boundary, backfill URLs on existing exercises, and preserve custom: true - Full state backup export/import in Settings carries URLs intact - Backend schema & validation: - Validates and sanitizes optional URL on coach custom exercise generation (https?:// only) - Icons & tests: - Added instagram and tiktok stroke icons matching existing icon grid - Comprehensive unit tests across frontend (vitest) and backend (node --test)
DuarteSantos8
added a commit
that referenced
this pull request
Sep 28, 2026
…es — refs, sniffing, the GIF and MP4 scrub, SHA-256 and a store-only zip - media-refs: normalizeMediaRef (the gate every reader goes through), referencedHashes (the same answers as the server, pinned by api/test/fixtures/media-refs.json), cleanUrl for the link (#246's rules plus no credentials and 2048 chars), linkKind - media-sniff: the type from magic bytes only, rule for rule the server's, plus HEIC/AVIF as input; header dimensions for the pixel guard; GIF frames/length and a copy without comment, XMP and ICC blocks; MP4/MOV brand, length, display size and codec, and the in-place scrub of udta/meta/uuid and of the samples of tracks that are neither picture nor sound; WebM size, codec and length - sha256: crypto.subtle, with a pure-JS fallback for plain-http LAN instances - media-limits: the server's caps when it sends them, the same defaults when it does not - zip: store-only, written from Blob parts and read back as slices; refuses compression, encryption, climbing names, too many entries - audit: labels for the server's media.sweep and media.throttled events, which the admin log otherwise printed raw Based on PR #246 by Vaibhav159 (cleanUrl and its test cases).
DuarteSantos8
added a commit
that referenced
this pull request
Sep 28, 2026
…video or guide — in the editor, and wherever an exercise's picture shows - The editor gets a "Photo, GIF or video" row and a link field. A picked file is re-encoded on the device (photos: WebP where the browser really writes it, else JPEG, at most 1600 px, plus a 480 px poster — EXIF and GPS gone by construction; GIFs lose their comment and metadata blocks; MP4/MOV have their metadata boxes and non-picture, non-sound tracks zeroed in place), hashed, and kept in the local store before the form is saved. The name of the file is never kept. Refusals say why: type, size, length, a photo too large to decode, a file this browser cannot read; a video that may not play everywhere says so - Media.jsx sends every custom exercise to CustomMedia.jsx, so the detail sheet, the config sheet, the workout card, the picker, the library, a past workout, the routine editor and the muscle explorer all show it with no change of their own. Lists load posters only. Videos up to 15 s loop muted like the catalogue's GIFs (not in the list layout, not under reduced motion); longer ones play with sound and controls on a tap. A file that is not here shows the tile, and a tap asks again - A link is a card that opens it in a new context without opener or referrer; nothing fetches it, no thumbnail, no embed. It is cleaned on save and again on every open - "Create your own exercise" no longer says "no animation" Based on PR #295 by horusglez (the picture row of the editor: the draft's thumb, Add/Change and Remove). Based on PR #246 by Vaibhav159 (the link field, cleanUrl and the link card).
DuarteSantos8
added a commit
that referenced
this pull request
Sep 28, 2026
…et; plan sharing carries the link, never the file; the Coach writes neither - Data: "Export backup (JSON)" says it leaves photos and videos out; "Export with photos & videos (.zip)" writes the same JSON plus every file under its hash (a store-only zip, shared through the share sheet on a phone); Import takes the .json or the .zip, and a zip's files are kept only once the import is confirmed and each matches its name, type and cap. A "Photos & videos" row says how much of the server's space they use and what is still waiting, and a tap sends it - Reset everything pushes the empty state, then asks the server to drop the files it no longer refers to, and keeps on this device only what a stash still refers to - The sign-out sheet names the photos and videos that have not reached the server, offers the backup that carries them, and its "Try again" sends them - Plan sharing keeps a custom exercise's link, cleaned both ways, and never its photo or video; a link is not added to an exercise the recipient already has (Based on PR #246 by Vaibhav159) - A plan the Coach creates never brings a link or a file ref onto its exercises
DuarteSantos8
added a commit
that referenced
this pull request
Sep 28, 2026
Owner
|
Thanks @Vaibhav159. Custom exercises can now carry one link plus one photo, GIF or short video, and that work is credited "Based on PR #295 by horusglez / #246 by Vaibhav159". To answer your question on #170: it's per profile and only for custom exercises. A YouTube link makes no request until you tap it. Media on built-in exercises waits for the catalogue work (#259, v1.4.6). It ended up as a new implementation (media kept on the server and on the device, outside the synced data), so I'm closing this one. Thanks for pushing it forward. Released in v1.3.9: https://github.com/DuarteSantos8/openGym/releases/tag/v1.3.9 |
1 task
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.