When DELETE_FILE_ON_TRASHCAN is enabled and a download that never produced a file
is cleared, dl.info.filename is unset, so os.remove(...) raises AttributeError.
It is caught and logged as a misleading 'deleting file ... failed' warning even
though there is nothing on disk to remove. Guard with getattr and skip deletion
when there is no filename.
iOS doesn't have hover, so the tooltip only ever showed on desktop —
where the share-arrow glyph is universally recognised anyway. Aria-
label stays for screen readers.
Web Share fails silently when iOS' share sheet refuses the payload,
typically because the file exceeds the platform's soft size limit
(~50–100 MB depending on iOS version). The previous patch logged to
the console but the user saw nothing — staring at a button that
'does nothing' is poor UX.
Adds two layers of feedback:
1. Pre-flight size check (SHARE_SIZE_WARN_BYTES = 80 MB, conservative
relative to iOS' actual limit) with a confirm() dialog before the
fetch. Avoids spending bandwidth pulling a 150 MB blob into the
browser only for navigator.canShare to reject it.
2. Surfaces canShare-rejection AND share()-failure as a visible
alert() suggesting the user fall back to the download link next
to the share button.
Tested locally with files from 0.7 MB up to 150.7 MB: small files
share unchanged, the 150 MB file now produces a pre-flight warning
the user can dismiss, and any subsequent rejection produces a clear
alert instead of silently no-op'ing.
Adds a share button to the completed-list action row that hands the
downloaded file off to the platform share sheet via navigator.share().
On iOS Safari/Chrome this surfaces the native Save-to-Photos / Save-to-
Files / AirDrop options for videos and images, and Files / 3rd-party
app targets for audio. On platforms without Web Share support (Desktop
Firefox/Chrome/Safari) the button hides itself; the existing download
link remains the universal fallback.
Implementation notes:
- canShareDownloads() requires both navigator.share AND navigator.canShare
(Desktop Safari has the former without the latter; we always intend
to share a file, not a URL)
- shareDownload() fetches the file via the existing buildDownloadLink()
helper, wraps it in a File, then runs canShare() before share() so we
can bail out cleanly on platforms that reject the MIME type
- AbortError (user dismisses sheet) is silenced; other errors logged
- Tooltip on the button explains the iOS behaviour briefly
Refs alexta69/metube#582 — addresses the 'add to Photos.app' request
without depending on the iOS Shortcut, which has had reliability issues
(cf #763).
The on_prepare handler unconditionally reflected the Origin request
header into Access-Control-Allow-Origin, and Socket.IO was configured
with cors_allowed_origins='*'. This allowed any website to make
authenticated cross-origin requests to all API endpoints, enabling
cross-origin download initiation, cookie overwrite, and data deletion.
Replace the blanket origin reflection with an explicit allowlist via
the CORS_ALLOWED_ORIGINS environment variable. When unset, cross-origin
requests are denied by default. Users who need cross-origin access can
set CORS_ALLOWED_ORIGINS to a comma-separated list of trusted origins.