WIP: storage-fix-local-nas work before playlist controls feature
Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
6b3ab5b65e
commit
c160242dbc
46 files changed
+5365
-815
No files matched your search
@@ -277,6 +277,42 @@
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
{{-- ── Replace File panel (outside main form, separate POST) ── --}}
|
||||
<div id="replace-file-panel" style="margin-top:24px;padding-top:20px;border-top:1px solid #3a3a3a;">
|
||||
<div style="display:flex;align-items:center;gap:8px;margin-bottom:12px;">
|
||||
<i class="bi bi-arrow-repeat" style="color:#f87171;font-size:16px;"></i>
|
||||
<span style="font-size:13px;font-weight:700;color:#f87171;text-transform:uppercase;letter-spacing:.05em;">Replace Media File</span>
|
||||
</div>
|
||||
<p style="font-size:12px;color:#888;margin:0 0 14px;line-height:1.5;">
|
||||
Upload a new file to fix a corrupted or missing video/audio. All views, likes, and comments are preserved.
|
||||
</p>
|
||||
|
||||
<div id="rfl-dropzone" onclick="document.getElementById('rfl-input').click()"
|
||||
style="border:2px dashed #444;border-radius:10px;padding:20px;text-align:center;cursor:pointer;transition:border-color .15s,background .15s;"
|
||||
onmouseenter="this.style.borderColor='#ef4444';this.style.background='rgba(239,68,68,.05)'"
|
||||
onmouseleave="this.style.borderColor='#444';this.style.background='transparent'">
|
||||
<i class="bi bi-cloud-upload" style="font-size:28px;color:#666;display:block;margin-bottom:8px;"></i>
|
||||
<span id="rfl-drop-label" style="font-size:13px;color:#888;">Click to choose replacement file</span>
|
||||
<input type="file" id="rfl-input" accept="video/*,audio/*,.mp4,.webm,.ogg,.mov,.avi,.wmv,.flv,.mkv,.mp3,.m4a,.aac,.wav,.flac,.opus" style="display:none;" onchange="rflFileSelected(this)">
|
||||
</div>
|
||||
|
||||
<div id="rfl-file-info" style="display:none;margin-top:10px;background:#1a1a1a;border:1px solid #333;border-radius:8px;padding:10px 14px;display:none;align-items:center;gap:10px;">
|
||||
<i class="bi bi-file-earmark-play" style="font-size:22px;color:#ef4444;flex-shrink:0;"></i>
|
||||
<div style="flex:1;min-width:0;">
|
||||
<div id="rfl-file-name" style="font-size:13px;font-weight:600;color:#e5e5e5;overflow:hidden;text-overflow:ellipsis;white-space:nowrap;"></div>
|
||||
<div id="rfl-file-size" style="font-size:11px;color:#888;margin-top:2px;"></div>
|
||||
</div>
|
||||
<button type="button" onclick="rflClearFile()" style="background:none;border:none;color:#888;cursor:pointer;font-size:16px;flex-shrink:0;padding:0;"><i class="bi bi-x-lg"></i></button>
|
||||
</div>
|
||||
|
||||
<div id="rfl-status" style="display:none;margin-top:10px;font-size:12px;padding:8px 12px;border-radius:6px;"></div>
|
||||
|
||||
<button type="button" id="rfl-submit-btn" onclick="rflSubmit()" disabled
|
||||
class="action-btn action-btn-danger" style="width:100%;justify-content:center;margin-top:12px;">
|
||||
<i class="bi bi-arrow-repeat"></i> <span>Replace File</span>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1403,6 +1439,75 @@
|
||||
submitBtn.innerHTML = '<i class="bi bi-check-lg"></i> Save Changes';
|
||||
});
|
||||
});
|
||||
|
||||
// ── Replace File ──────────────────────────────────────────────────────
|
||||
let _rflFile = null;
|
||||
const _rflFmtSize = b => b >= 1073741824 ? (b/1073741824).toFixed(1)+' GB' : b >= 1048576 ? (b/1048576).toFixed(1)+' MB' : Math.round(b/1024)+' KB';
|
||||
|
||||
function rflFileSelected(input) {
|
||||
_rflFile = input.files[0] || null;
|
||||
const info = document.getElementById('rfl-file-info');
|
||||
if (_rflFile) {
|
||||
document.getElementById('rfl-file-name').textContent = _rflFile.name;
|
||||
document.getElementById('rfl-file-size').textContent = _rflFmtSize(_rflFile.size);
|
||||
document.getElementById('rfl-drop-label').textContent = _rflFile.name;
|
||||
info.style.display = 'flex';
|
||||
} else {
|
||||
info.style.display = 'none';
|
||||
document.getElementById('rfl-drop-label').textContent = 'Click to choose replacement file';
|
||||
}
|
||||
document.getElementById('rfl-submit-btn').disabled = !_rflFile;
|
||||
document.getElementById('rfl-status').style.display = 'none';
|
||||
}
|
||||
|
||||
function rflClearFile() {
|
||||
_rflFile = null;
|
||||
document.getElementById('rfl-input').value = '';
|
||||
document.getElementById('rfl-file-info').style.display = 'none';
|
||||
document.getElementById('rfl-drop-label').textContent = 'Click to choose replacement file';
|
||||
document.getElementById('rfl-submit-btn').disabled = true;
|
||||
document.getElementById('rfl-status').style.display = 'none';
|
||||
}
|
||||
|
||||
function rflSubmit() {
|
||||
if (!_rflFile || !window.currentVideoId) return;
|
||||
const btn = document.getElementById('rfl-submit-btn');
|
||||
const status = document.getElementById('rfl-status');
|
||||
|
||||
btn.disabled = true;
|
||||
btn.innerHTML = '<i class="bi bi-arrow-repeat"></i> Uploading…';
|
||||
status.style.display = 'none';
|
||||
|
||||
const fd = new FormData();
|
||||
fd.append('_token', '{{ csrf_token() }}');
|
||||
fd.append('replacement_file', _rflFile);
|
||||
|
||||
fetch(`/videos/${window.currentVideoId}/replace-file`, {
|
||||
method: 'POST',
|
||||
headers: { 'Accept': 'application/json', 'X-Requested-With': 'XMLHttpRequest' },
|
||||
body: fd
|
||||
})
|
||||
.then(r => r.json())
|
||||
.then(data => {
|
||||
if (data.success) {
|
||||
status.style.cssText = 'display:block;background:rgba(74,222,128,.1);border:1px solid rgba(74,222,128,.25);color:#4ade80;';
|
||||
status.innerHTML = '<i class="bi bi-check-circle-fill"></i> ' + data.message;
|
||||
rflClearFile();
|
||||
setTimeout(() => location.reload(), 2000);
|
||||
} else {
|
||||
status.style.cssText = 'display:block;background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.25);color:#f87171;';
|
||||
status.textContent = data.message || 'Upload failed. Please try again.';
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="bi bi-arrow-repeat"></i> <span>Replace File</span>';
|
||||
}
|
||||
})
|
||||
.catch(() => {
|
||||
status.style.cssText = 'display:block;background:rgba(239,68,68,.1);border:1px solid rgba(239,68,68,.25);color:#f87171;';
|
||||
status.textContent = 'Upload failed. Please try again.';
|
||||
btn.disabled = false;
|
||||
btn.innerHTML = '<i class="bi bi-arrow-repeat"></i> <span>Replace File</span>';
|
||||
});
|
||||
}
|
||||
</script>
|
||||
|
||||
<x-image-cropper
|
||||
|
||||
Reference in new issue
Block a user