diff --git a/index.html b/index.html index cee6bcf..935f224 100644 --- a/index.html +++ b/index.html @@ -1149,12 +1149,13 @@ -
- - +
+ + +
+
diff --git a/play.html b/play.html index b78ab93..94f5aa5 100644 --- a/play.html +++ b/play.html @@ -16,7 +16,7 @@ - + diff --git a/server/src/server.ts b/server/src/server.ts index b9860b9..c16d0f5 100644 --- a/server/src/server.ts +++ b/server/src/server.ts @@ -220,8 +220,10 @@ app.get('/s/:code', async (req, res) => { const imageUrl = origin ? `${origin}/wariosynthlogo.png` : '/wariosynthlogo.png'; const sharedTitle = (payload.title || '').trim(); - const ogTitle = sharedTitle || 'WARIO SYNTH'; - const ogDescription = 'I made this in Wario Synth, click to listen or generate your own'; + const ogTitle = sharedTitle ? `${sharedTitle} - WARIO SYNTH` : 'WARIO SYNTH'; + const ogDescription = sharedTitle + ? `I made ${sharedTitle} game boy version. Click to listen or generate your own, made in Wario Synth by @b1rdmania.` + : 'Turn any song into retro game console music. Made by @b1rdmania.'; const html = ` @@ -239,7 +241,7 @@ app.get('/s/:code', async (req, res) => { - + diff --git a/src/main.ts b/src/main.ts index 8108e86..b9ea817 100644 --- a/src/main.ts +++ b/src/main.ts @@ -58,6 +58,7 @@ class MotifApp { private iosAudioState!: HTMLElement; private copyLinkBtn!: HTMLButtonElement; + private shareToXBtn!: HTMLButtonElement; private shareLinkBox!: HTMLElement; private shareLinkInput!: HTMLInputElement; @@ -135,6 +136,7 @@ class MotifApp { this.motifDuration = document.getElementById('motifDuration')!; this.copyLinkBtn = document.getElementById('copyLinkBtn') as HTMLButtonElement; + this.shareToXBtn = document.getElementById('shareToXBtn') as HTMLButtonElement; this.shareLinkBox = document.getElementById('shareLinkBox') as HTMLElement; this.shareLinkInput = document.getElementById('shareLinkInput') as HTMLInputElement; @@ -184,6 +186,7 @@ class MotifApp { this.motifProgressBar.addEventListener('change', seekHandler); this.copyLinkBtn.addEventListener('click', () => void this.handleCopyLink()); + this.shareToXBtn.addEventListener('click', () => void this.handleShareToX()); // Embed snippet copy (may be disabled / not-live) this.copyEmbedBtn?.addEventListener('click', () => void this.copyEmbedSnippet()); @@ -744,6 +747,47 @@ class MotifApp { } } + private async handleShareToX(): Promise { + if (!this.hasGenerated) return; + const result = this.searchResults[this.selectedResultIndex]; + if (!result?.midiUrl) return; + + const title = this.cleanSongTitle(result.title || 'a song'); + + // Get share URL (try short link first) + let shareUrl: string | null = null; + try { + let payload: any = null; + if (result.source === 'bitmidi') { + const m = String(result.midiUrl).match(/\/uploads\/(\d+)\.mid/i); + if (m?.[1]) payload = { src: 'bitmidi', id: m[1], title: result.title }; + } + if (!payload) payload = { u: result.midiUrl, title: result.title }; + + const resp = await fetch('/api/share', { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(payload), + }); + if (resp.ok) { + const data = await resp.json(); + if (data?.url) shareUrl = `${window.location.origin}${data.url}`; + } + } catch { + // Fall through + } + + if (!shareUrl) { + shareUrl = window.location.href; + } + + // Compose tweet text + const tweetText = `I made ${title} game boy version. Click to listen or generate your own, made in Wario Synth by @b1rdmania`; + const twitterUrl = `https://twitter.com/intent/tweet?text=${encodeURIComponent(tweetText)}&url=${encodeURIComponent(shareUrl)}`; + + window.open(twitterUrl, '_blank', 'width=550,height=420'); + } + private setState(state: 'idle' | 'results' | 'selected' | 'generated'): void { // results - keep visible in all states except idle so user can pick a different source const hasResults = state === 'results' || state === 'selected' || state === 'generated'; @@ -754,9 +798,11 @@ class MotifApp { const hasSelection = state === 'selected' || state === 'generated'; this.playerSection.classList.toggle('visible', hasSelection); - // share link only after generation + // share buttons only after generation this.copyLinkBtn.style.display = state === 'generated' ? 'inline-block' : 'none'; this.copyLinkBtn.disabled = !(state === 'generated' && this.hasGenerated); + this.shareToXBtn.style.display = state === 'generated' ? 'inline-block' : 'none'; + this.shareToXBtn.disabled = !(state === 'generated' && this.hasGenerated); // Dim results when selected/generated, but keep them interactive this.resultsSection.classList.toggle('collapsed', state === 'selected' || state === 'generated');