Spaces:
Running on Zero
Running on Zero
refactor: simplify link panel — always-visible download button
Browse files- src/ui/event_wiring.py +23 -54
- src/ui/interface.py +1 -2
src/ui/event_wiring.py
CHANGED
|
@@ -18,7 +18,7 @@ from src.ui.progress_bar import pipeline_progress_bar_html
|
|
| 18 |
from src.ui.handlers import (
|
| 19 |
wire_presets, toggle_resegment_panel,
|
| 20 |
on_mode_change, on_verse_toggle, restore_anim_settings,
|
| 21 |
-
|
| 22 |
)
|
| 23 |
|
| 24 |
_EMPTY_PLACEHOLDER = ""
|
|
@@ -64,16 +64,16 @@ def _wire_input_mode_toggle(c):
|
|
| 64 |
gr.update(visible=is_upload), # upload_panel
|
| 65 |
gr.update(visible=is_record), # record_panel
|
| 66 |
# Clear link panel state so returning starts fresh
|
| 67 |
-
gr.update(value=""),
|
| 68 |
-
gr.update(
|
| 69 |
-
|
| 70 |
-
gr.update(visible=False),
|
| 71 |
)
|
| 72 |
|
| 73 |
_toggle_outputs = [
|
| 74 |
c.mode_link, c.mode_upload, c.mode_record,
|
| 75 |
c.link_panel, c.upload_panel, c.record_panel,
|
| 76 |
-
c.url_input, c.
|
| 77 |
]
|
| 78 |
c.mode_link.click(fn=lambda: _switch_to("Link"), inputs=[], outputs=_toggle_outputs, api_name=False)
|
| 79 |
c.mode_upload.click(fn=lambda: _switch_to("Upload"), inputs=[], outputs=_toggle_outputs, api_name=False)
|
|
@@ -82,77 +82,46 @@ def _wire_input_mode_toggle(c):
|
|
| 82 |
|
| 83 |
|
| 84 |
def _wire_url_input(c):
|
| 85 |
-
"""Wire URL
|
| 86 |
-
|
| 87 |
-
def _on_url_change(url):
|
| 88 |
-
"""Auto-fetch metadata when a URL is pasted."""
|
| 89 |
-
_hide_all = (
|
| 90 |
-
gr.update(visible=False), # url_info_html
|
| 91 |
-
gr.update(visible=False), # url_download_btn
|
| 92 |
-
gr.update(visible=False), # url_audio_player
|
| 93 |
-
)
|
| 94 |
-
if not url or not url.strip():
|
| 95 |
-
return _hide_all
|
| 96 |
-
|
| 97 |
-
try:
|
| 98 |
-
info_html, warning = fetch_url_info(url)
|
| 99 |
-
if info_html is None:
|
| 100 |
-
yield _hide_all
|
| 101 |
-
return
|
| 102 |
-
if warning:
|
| 103 |
-
info_html += f'<div style="padding:6px 8px;font-size:12px;opacity:0.7;color:var(--body-text-color);">{warning}</div>'
|
| 104 |
-
yield (
|
| 105 |
-
gr.update(value=info_html, visible=True),
|
| 106 |
-
gr.update(visible=True), # show Download button
|
| 107 |
-
gr.update(visible=False),
|
| 108 |
-
)
|
| 109 |
-
except Exception as e:
|
| 110 |
-
yield (
|
| 111 |
-
gr.update(
|
| 112 |
-
value=f'<div style="color:var(--error-text-color);padding:8px;">{str(e)[:300]}</div>',
|
| 113 |
-
visible=True,
|
| 114 |
-
),
|
| 115 |
-
gr.update(visible=False),
|
| 116 |
-
gr.update(visible=False),
|
| 117 |
-
)
|
| 118 |
|
| 119 |
-
|
| 120 |
c.url_input.change(
|
| 121 |
-
fn=
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 122 |
api_name=False, show_progress="hidden",
|
| 123 |
)
|
| 124 |
|
| 125 |
def _on_download(url):
|
| 126 |
-
"""Download audio
|
| 127 |
-
# Yield 1:
|
| 128 |
yield (
|
| 129 |
gr.update(), # audio_input
|
| 130 |
-
gr.update(visible=False), # hide info
|
| 131 |
gr.update(value="Downloading…", interactive=False), # animate btn
|
| 132 |
-
gr.update(),
|
| 133 |
)
|
| 134 |
|
| 135 |
-
# Yield 2: result
|
| 136 |
try:
|
| 137 |
wav_path, _info_html = download_url_audio(url)
|
| 138 |
yield (
|
| 139 |
wav_path, # set audio_input
|
| 140 |
-
gr.update(
|
| 141 |
-
|
| 142 |
gr.update(value=wav_path, visible=True), # show audio player
|
| 143 |
)
|
| 144 |
except Exception as e:
|
| 145 |
yield (
|
| 146 |
gr.update(),
|
| 147 |
-
gr.update(
|
| 148 |
-
|
| 149 |
-
value=f"Download failed: {str(e)[:120]}",
|
| 150 |
-
variant="stop", interactive=True,
|
| 151 |
-
),
|
| 152 |
gr.update(),
|
| 153 |
)
|
| 154 |
|
| 155 |
-
_dl_outputs = [c.audio_input, c.
|
| 156 |
c.url_download_btn.click(
|
| 157 |
fn=_on_download, inputs=[c.url_input], outputs=_dl_outputs,
|
| 158 |
api_name=False, show_progress="hidden",
|
|
|
|
| 18 |
from src.ui.handlers import (
|
| 19 |
wire_presets, toggle_resegment_panel,
|
| 20 |
on_mode_change, on_verse_toggle, restore_anim_settings,
|
| 21 |
+
download_url_audio,
|
| 22 |
)
|
| 23 |
|
| 24 |
_EMPTY_PLACEHOLDER = ""
|
|
|
|
| 64 |
gr.update(visible=is_upload), # upload_panel
|
| 65 |
gr.update(visible=is_record), # record_panel
|
| 66 |
# Clear link panel state so returning starts fresh
|
| 67 |
+
gr.update(value=""), # url_input
|
| 68 |
+
gr.update(value="Download", variant="secondary",
|
| 69 |
+
interactive=False), # url_download_btn
|
| 70 |
+
gr.update(visible=False), # url_audio_player
|
| 71 |
)
|
| 72 |
|
| 73 |
_toggle_outputs = [
|
| 74 |
c.mode_link, c.mode_upload, c.mode_record,
|
| 75 |
c.link_panel, c.upload_panel, c.record_panel,
|
| 76 |
+
c.url_input, c.url_download_btn, c.url_audio_player,
|
| 77 |
]
|
| 78 |
c.mode_link.click(fn=lambda: _switch_to("Link"), inputs=[], outputs=_toggle_outputs, api_name=False)
|
| 79 |
c.mode_upload.click(fn=lambda: _switch_to("Upload"), inputs=[], outputs=_toggle_outputs, api_name=False)
|
|
|
|
| 82 |
|
| 83 |
|
| 84 |
def _wire_url_input(c):
|
| 85 |
+
"""Wire URL input → enable download button, download on click."""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 86 |
|
| 87 |
+
# Enable/disable download button based on whether URL is present
|
| 88 |
c.url_input.change(
|
| 89 |
+
fn=lambda url: gr.update(
|
| 90 |
+
interactive=bool(url and url.strip()),
|
| 91 |
+
variant="primary" if url and url.strip() else "secondary",
|
| 92 |
+
value="Download",
|
| 93 |
+
),
|
| 94 |
+
inputs=[c.url_input],
|
| 95 |
+
outputs=[c.url_download_btn],
|
| 96 |
api_name=False, show_progress="hidden",
|
| 97 |
)
|
| 98 |
|
| 99 |
def _on_download(url):
|
| 100 |
+
"""Download audio from URL."""
|
| 101 |
+
# Yield 1: button shows downloading state
|
| 102 |
yield (
|
| 103 |
gr.update(), # audio_input
|
|
|
|
| 104 |
gr.update(value="Downloading…", interactive=False), # animate btn
|
| 105 |
+
gr.update(visible=False), # hide prev player
|
| 106 |
)
|
| 107 |
|
|
|
|
| 108 |
try:
|
| 109 |
wav_path, _info_html = download_url_audio(url)
|
| 110 |
yield (
|
| 111 |
wav_path, # set audio_input
|
| 112 |
+
gr.update(value="Download", variant="primary",
|
| 113 |
+
interactive=True), # reset btn
|
| 114 |
gr.update(value=wav_path, visible=True), # show audio player
|
| 115 |
)
|
| 116 |
except Exception as e:
|
| 117 |
yield (
|
| 118 |
gr.update(),
|
| 119 |
+
gr.update(value=f"Error: {str(e)[:100]}",
|
| 120 |
+
variant="stop", interactive=True), # error on btn
|
|
|
|
|
|
|
|
|
|
| 121 |
gr.update(),
|
| 122 |
)
|
| 123 |
|
| 124 |
+
_dl_outputs = [c.audio_input, c.url_download_btn, c.url_audio_player]
|
| 125 |
c.url_download_btn.click(
|
| 126 |
fn=_on_download, inputs=[c.url_input], outputs=_dl_outputs,
|
| 127 |
api_name=False, show_progress="hidden",
|
src/ui/interface.py
CHANGED
|
@@ -128,8 +128,7 @@ def _build_left_column(c):
|
|
| 128 |
info='e.g. TikTok · SoundCloud · [MP3Quran](https://www.mp3quran.net/) · [all supported sites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)',
|
| 129 |
lines=1,
|
| 130 |
)
|
| 131 |
-
c.
|
| 132 |
-
c.url_download_btn = gr.Button("Download", size="sm", variant="primary", visible=False)
|
| 133 |
c.url_audio_player = gr.Audio(label="Downloaded Audio", visible=False, interactive=False)
|
| 134 |
|
| 135 |
# Upload panel
|
|
|
|
| 128 |
info='e.g. TikTok · SoundCloud · [MP3Quran](https://www.mp3quran.net/) · [all supported sites](https://github.com/yt-dlp/yt-dlp/blob/master/supportedsites.md)',
|
| 129 |
lines=1,
|
| 130 |
)
|
| 131 |
+
c.url_download_btn = gr.Button("Download", size="sm", variant="secondary", interactive=False)
|
|
|
|
| 132 |
c.url_audio_player = gr.Audio(label="Downloaded Audio", visible=False, interactive=False)
|
| 133 |
|
| 134 |
# Upload panel
|