Repository navigation
Instagram music, collaborators and trial reels - #406
Open
paulocastellano wants to merge 90 commits into
Open
paulocastellano wants to merge 90 commits into
paulocastellano wants to merge 90 commits into
Conversation
added 30 commits
October 13, 2026 09:49
Reels and feed posts on Instagram get the three options Instagram's publishing API exposes, with the same composer flow as Buffer: - Music: search Instagram audio (music and original sounds, with covers and hover previews) and attach a track with its music and video volume. Only accounts connected through Facebook can publish it; an Instagram Login account gets "Save & link", which saves the post as a draft and reconnects the same card through Facebook, keeping its posts. - Collaborators: up to three Instagram usernames on feed posts, carousels and reels. - Trial reels: Auto (SS_PERFORMANCE) or Manual graduation, confirmed each time and not combined with collaborators. Reconnecting across the two Instagram platforms now matches the Instagram professional account id, since Instagram Login reports an app-scoped id. Radio dots are painted on the ring itself so they stay centred at fractional pixel offsets.
- A rejected play of an earlier preview no longer stops the track playing now; the preview video ignores the AbortError of its own pause. - Save & link keeps an edited scheduled or pending post on its schedule and only saves a draft as a draft; the connect step opens from the save's own success callback instead of the first router visit that finishes. - instagramAccountId() asks Instagram at most once per account instance. - A new connection no longer seats an Instagram account already connected under the other Instagram platform when the two report different ids. - An invalid collaborator in any position shows its error. - Creator pictures are looked up for the first ten original sounds only, and a failed lookup is remembered for ten minutes.
…xpired Meta's cover and preview links are temporary. Publishing only sends the audio id, so a reel scheduled weeks ahead keeps its music; reopening it in the composer now shows the music icon instead of a broken image and hides the play button when the preview can no longer load.
…nd MCP parity Music and trial reels only exist on reels and the publisher never sends them elsewhere, so a feed post or story carrying them is no longer refused; the rules take the post's content type on every web, API, MCP and repurpose path. The full parity suite now publishes a carousel with a collaborator, a trial reel, and a reel through Facebook with music and volumes from web, API and MCP alike.
- GET /api/social-accounts/{account}/instagram-audio (q, type) and
/instagram-audio/{audioId}, plus search-instagram-audio-tool and
get-instagram-audio-tool, run the same SearchInstagramAudio and
GetInstagramAudio actions as the composer. Every track carries its type.
- Searches are kept for ten minutes per account, catalogue and query, and
an audio asset for an hour. A workspace may make 30 uncached calls to the
Audio API a minute across web, API and MCP; past that the lookup answers
429 without calling Meta.
- An Instagram account connected without Facebook gets the same "connect
through Facebook" answer on every surface.
- The composer refreshes a picked track's expired cover and preview from its
details before falling back to the music icon.
"Texto alternativo" and "Marcar pessoas" ran over each other in the three-column tab bar of the media editor, as did the alt text, tag people and thumbnail labels in Russian, Ukrainian, Greek, French, German, Turkish and Arabic. Every label now fits in ten characters, and the single-line copy test guards the four tab keys.
The tag list shows @username as a link to the profile, opening in a new tab, with the same helper the collaborators chips use.
The list shows a count out of 20, one row per person with a numbered badge, the profile link and quiet Move and remove actions. Move highlights that tag's marker, asks for a new position on the image and places it there on the next click; Cancel or starting to tag drops it.
…ser edges - Closing the composer on an edited post with unsaved changes asks first (Cancel, Discard), and so do an Inertia visit away and a tab reload. A new post keeps closing at once: its autosave offers it back. The guard is the reusable useUnsavedChanges composable and UnsavedChangesDialog. - A sent post with a network link offers "Share link in a post", opening the composer with the link and every workspace channel selected, and "Copy link", in the card menu, the calendar popover and the post details. - The composer is placed on whole pixels instead of translate(-50%, -50%), so its header and footer borders stay 1px at odd window sizes. - The Instagram feed preview no longer shows dark lines above and below an empty media area.
The notes button joins the card's action row (icon, "Notes", count) instead of a popover beside the card on desktop and over the thumbnails on mobile. It expands the card with the notes and the note composer, using the shadcn Collapsible and its collapsible-down/up animations, and closes it again on the next click. PostNotesPopover is removed.
The notes toggle is an icon button again: an empty bubble without notes, and a filled bubble with the count inside (1 to 99, then 99+) once there are notes, which reads better than the faint count pill and saves room in the card's action row.
… badge The hand-drawn bubble is gone: the toggle shows IconMessageCircle without notes and IconMessageCircleFilled with them, and the count (1 to 99, then 99+) sits in a primary badge on the button's corner.
The notes toggle reads "Notes" again next to the Tabler message icon, and its count (1 to 99, then 99+) sits in a primary pill instead of the faint grey one.
- The note composer is a rounded field like the MCP welcome prompt: the text sits inside the pill and the round send button turns primary once there is something to send. - Notes read as a thread: larger avatars, the author in bold beside the time, the text below, and a soft hover. - The notes toggle has a tooltip that says "Show notes" or "Hide notes" depending on whether the notes are open, in every locale.
- The note composer is the system's InputGroup with a one-line input and the primary send button inside it on the right; Enter sends. - Notes are full-width rows separated by dividers, with the author, time and text aligned, instead of rounded hover boxes.
… account, throttle audio routes
…w and cover refresh, save and link never publishes
…scord from rewriting meta on load
… queue button component, note count from the thread
added 6 commits
October 13, 2026 19:07
… a save, generic channel search copy in the composer, ig_user_id on empty meta, tighter guard and Discord cache tests
…rom the cached channel list
…whose music needs Facebook, restore page state on the held history copy, one discard dialog, and close the round 4 coverage gaps
…ty matching reads, and cover Discord names on recurrence and repurpose, draft music without a track id, the music category and reel-only gating
… and unmount restore, and cover validation failure, undo after back, a post published meanwhile and a reload behind the composer
This was referenced Oct 13, 2026
…param helper for Instagram, and document stored post meta, Instagram reel rules, model HTTP, the unsaved-changes guard and browser test traps
added 20 commits
October 13, 2026 21:20
…line, and rotate the examples every 3 seconds
…lti-line notes with Shift+Enter, and prefer the Button loading prop
…ogle Business connects
…w, the next action
… the review checklist and sources
…tia so the unsaved-changes dialog asks first
… preview video still starts both
…pen, and cover card actions on a Discord name and reel meta in webhooks
…ge, time zone offset, language, channel and board pickers
This branch has not been deployed
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.
What
PostMeta::forChannel; small changes to the welcome MCP step and the connect Finish button.Deploy
php artisan social:check-connectionsonce after deploying./meon graph.instagram.com returnsuser_idfor Instagram Login tokens.meta.channel_nameno longer being accepted.Closes #213
Manual test checklist
Ordered by risk. "Automated" marks what tests already cover with faked network calls, so the manual pass is about the real APIs.
High risk: real Meta APIs and identities
php artisan social:check-connections, with Horizon running). If Instagram refused theuser_idfield, every Instagram Login account would be marked disconnected.meta.ig_user_idgets it back from the check (tested on 2026-10-14 by removing the key first).updated_atmoves because the check stampslast_verified_aton every account, as onmain; writingig_user_iditself does not move it (automated).meta.ig_user_idis stored;social:check-connections, then repeat the second check.instagram-audio, MCPsearch-instagram-audio-tool/get-instagram-audio-tool):Medium risk: shared flows every network goes through
PostMeta::forChannel):collaborators,trial_graduationandaudio(audio.idas a string of digits);audio.idare each refused;alt, withmeta.alt_text(it wins) and withuser_tags;channel_idshows the name in the app when the channels were listed in the last 5 minutes;Low risk: visual and moved code
Decisions