Add NAS file manager integration and all pending platform changes
- Installed p7h/nas-file-manager package via private VCS repo - Published config/nas-file-manager.php with super_admin middleware restriction - Added NAS env vars to .env.example - Created admin/nas-storage page with connection info panel and file browser widget - Added NAS Storage link to admin sidebar (super_admin only) - Added SuperAdminController@nasStorage method and admin.nas-storage route - Includes all accumulated branch changes: profile wall, 2FA, audit logs, settings panel, country/phone/timezone components, posts, slideshow, playlist shares, video downloads/shares, comment likes, notifications, social links, and more Co-Authored-By: Claude Sonnet 4.6 <[email protected]>
This commit is contained in:
1 parent
d44490dfe0
commit
0b2e95ea65
161 files changed
+27496
-7250
No files matched your search
@@ -4,19 +4,18 @@
|
||||
<div class="modal-content" style="background: var(--bg-secondary); border: 1px solid var(--border-color); border-radius: 16px;">
|
||||
<div class="modal-header" style="border-bottom: 1px solid var(--border-color); padding: 20px 24px;">
|
||||
<h5 class="modal-title" id="shareModalLabel" style="font-weight: 600; color: var(--text-primary);">
|
||||
<i class="bi bi-share me-2"></i>Share Video
|
||||
<i class="bi bi-share me-2"></i>Share
|
||||
</h5>
|
||||
<button type="button" class="btn-close btn-close-white" data-bs-dismiss="modal" aria-label="Close"></button>
|
||||
</div>
|
||||
<div class="modal-body" style="padding: 24px;">
|
||||
<p style="color: var(--text-secondary); margin-bottom: 16px;">Share this video with your friends:</p>
|
||||
<p style="color: var(--text-secondary); margin-bottom: 16px;">Share this link with your friends:</p>
|
||||
|
||||
<div class="share-link-container" style="display: flex; gap: 8px; align-items: center;">
|
||||
<input type="text" id="shareLinkInput" class="form-control" readonly
|
||||
style="background: var(--bg-primary); border: 1px solid var(--border-color); color: var(--text-primary); padding: 12px 16px; border-radius: 8px;">
|
||||
<button type="button" id="copyLinkBtn" class="btn-copy"
|
||||
style="background: var(--brand-red); color: white; border: none; padding: 12px 20px; border-radius: 8px; font-weight: 500; cursor: pointer; white-space: nowrap; transition: background 0.2s;">
|
||||
<i class="bi bi-clipboard me-1"></i> Copy
|
||||
<button type="button" id="copyLinkBtn" class="btn-copy action-btn action-btn-primary">
|
||||
<i class="bi bi-clipboard"></i> <span>Copy</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -58,67 +57,113 @@
|
||||
transform: scale(1.1);
|
||||
opacity: 0.9;
|
||||
}
|
||||
.btn-copy:hover {
|
||||
background: #cc1a1a !important;
|
||||
}
|
||||
.btn-copy.copied {
|
||||
background: #4caf50 !important;
|
||||
border-color: #4caf50 !important;
|
||||
}
|
||||
</style>
|
||||
|
||||
<script>
|
||||
function openShareModal(videoUrl, videoTitle) {
|
||||
document.getElementById('shareLinkInput').value = videoUrl;
|
||||
|
||||
// Update social share links
|
||||
var encodedUrl = encodeURIComponent(videoUrl);
|
||||
var encodedTitle = encodeURIComponent(videoTitle);
|
||||
|
||||
document.getElementById('shareFacebook').href = 'https://www.facebook.com/sharer/sharer.php?u=' + encodedUrl;
|
||||
document.getElementById('shareTwitter').href = 'https://twitter.com/intent/tweet?url=' + encodedUrl + '&text=' + encodedTitle;
|
||||
document.getElementById('shareWhatsApp').href = 'https://wa.me/?text=' + encodedTitle + ' ' + encodedUrl;
|
||||
document.getElementById('shareTelegram').href = 'https://t.me/share/url?url=' + encodedUrl + '&text=' + encodedTitle;
|
||||
|
||||
// Reset copy button state
|
||||
var copyBtn = document.getElementById('copyLinkBtn');
|
||||
copyBtn.innerHTML = '<i class="bi bi-clipboard me-1"></i> Copy';
|
||||
copyBtn.classList.remove('copied');
|
||||
document.getElementById('copySuccess').style.display = 'none';
|
||||
|
||||
// Show modal
|
||||
var modal = new bootstrap.Modal(document.getElementById('shareModal'));
|
||||
function _getLatestCsrf() {
|
||||
var match = document.cookie.match(/(?:^|;\s*)XSRF-TOKEN=([^;]+)/);
|
||||
if (match) return decodeURIComponent(match[1]);
|
||||
return (typeof csrf !== 'undefined') ? csrf : '';
|
||||
}
|
||||
|
||||
async function openShareModal(videoUrl, videoTitle, recordUrl) {
|
||||
var csrfToken = _getLatestCsrf();
|
||||
var shareUrl = videoUrl;
|
||||
|
||||
// Obtain a unique tracked share link from the server
|
||||
if (recordUrl) {
|
||||
try {
|
||||
var res = await fetch(recordUrl, {
|
||||
method: 'POST',
|
||||
headers: {
|
||||
'X-CSRF-TOKEN': csrfToken,
|
||||
'Accept': 'application/json',
|
||||
'X-Requested-With': 'XMLHttpRequest',
|
||||
},
|
||||
});
|
||||
if (res.ok) {
|
||||
var data = await res.json();
|
||||
if (data.url) shareUrl = data.url;
|
||||
}
|
||||
} catch (e) { /* fallback to plain URL */ }
|
||||
}
|
||||
|
||||
// Mobile: use native share sheet with the unique link
|
||||
if (window.innerWidth <= 768 && navigator.share) {
|
||||
navigator.share({ title: videoTitle, url: shareUrl }).catch(function() {});
|
||||
return;
|
||||
}
|
||||
|
||||
// Desktop: show modal
|
||||
_populateShareModal(shareUrl, videoTitle);
|
||||
var modal = new bootstrap.Modal(document.getElementById('shareModal'), { backdrop: true, keyboard: true });
|
||||
modal.show();
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
function _populateShareModal(shareUrl, videoTitle) {
|
||||
document.getElementById('shareLinkInput').value = shareUrl;
|
||||
|
||||
var encodedUrl = encodeURIComponent(shareUrl);
|
||||
var encodedTitle = encodeURIComponent(videoTitle);
|
||||
var waText = encodeURIComponent(videoTitle + '\n' + shareUrl);
|
||||
|
||||
document.getElementById('shareFacebook').href = 'https://www.facebook.com/sharer/sharer.php?u=' + encodedUrl;
|
||||
document.getElementById('shareTwitter').href = 'https://twitter.com/intent/tweet?url=' + encodedUrl + '&text=' + encodedTitle;
|
||||
document.getElementById('shareWhatsApp').href = 'https://wa.me/?text=' + waText;
|
||||
document.getElementById('shareTelegram').href = 'https://t.me/share/url?url=' + encodedUrl + '&text=' + encodedTitle;
|
||||
|
||||
var copyBtn = document.getElementById('copyLinkBtn');
|
||||
var shareInput = document.getElementById('shareLinkInput');
|
||||
var copySuccess = document.getElementById('copySuccess');
|
||||
|
||||
if (copyBtn && shareInput) {
|
||||
copyBtn.addEventListener('click', function() {
|
||||
shareInput.select();
|
||||
shareInput.setSelectionRange(0, 99999);
|
||||
|
||||
navigator.clipboard.writeText(shareInput.value).then(function() {
|
||||
copyBtn.innerHTML = '<i class="bi bi-check-lg me-1"></i> Copied!';
|
||||
copyBtn.classList.add('copied');
|
||||
copySuccess.style.display = 'block';
|
||||
|
||||
setTimeout(function() {
|
||||
copyBtn.innerHTML = '<i class="bi bi-clipboard me-1"></i> Copy';
|
||||
copyBtn.classList.remove('copied');
|
||||
copySuccess.style.display = 'none';
|
||||
}, 2000);
|
||||
}).catch(function(err) {
|
||||
console.error('Failed to copy: ', err);
|
||||
// Fallback for older browsers
|
||||
document.execCommand('copy');
|
||||
copyBtn.innerHTML = '<i class="bi bi-check-lg me-1"></i> Copied!';
|
||||
copySuccess.style.display = 'block';
|
||||
});
|
||||
});
|
||||
copyBtn.innerHTML = '<i class="bi bi-clipboard"></i> <span>Copy</span>';
|
||||
copyBtn.classList.remove('copied');
|
||||
document.getElementById('copySuccess').style.display = 'none';
|
||||
}
|
||||
|
||||
function _copyToClipboard(text) {
|
||||
// Prefer modern clipboard API (requires HTTPS)
|
||||
if (navigator.clipboard && window.isSecureContext) {
|
||||
return navigator.clipboard.writeText(text);
|
||||
}
|
||||
// Textarea fallback — works even inside Bootstrap modals
|
||||
return new Promise(function(resolve, reject) {
|
||||
var ta = document.createElement('textarea');
|
||||
ta.value = text;
|
||||
ta.setAttribute('readonly', '');
|
||||
ta.style.cssText = 'position:fixed;top:-9999px;left:-9999px;opacity:0;';
|
||||
document.body.appendChild(ta);
|
||||
ta.focus();
|
||||
ta.select();
|
||||
var ok = false;
|
||||
try { ok = document.execCommand('copy'); } catch(e) {}
|
||||
document.body.removeChild(ta);
|
||||
ok ? resolve() : reject();
|
||||
});
|
||||
}
|
||||
|
||||
document.addEventListener('DOMContentLoaded', function() {
|
||||
var copyBtn = document.getElementById('copyLinkBtn');
|
||||
var shareInput = document.getElementById('shareLinkInput');
|
||||
var copySuccess = document.getElementById('copySuccess');
|
||||
|
||||
if (!copyBtn || !shareInput) return;
|
||||
|
||||
copyBtn.addEventListener('click', function() {
|
||||
_copyToClipboard(shareInput.value).then(function() {
|
||||
copyBtn.innerHTML = '<i class="bi bi-check-lg"></i> <span>Copied!</span>';
|
||||
copyBtn.classList.add('copied');
|
||||
copySuccess.style.display = 'block';
|
||||
setTimeout(function() {
|
||||
copyBtn.innerHTML = '<i class="bi bi-clipboard"></i> <span>Copy</span>';
|
||||
copyBtn.classList.remove('copied');
|
||||
copySuccess.style.display = 'none';
|
||||
}, 2500);
|
||||
}).catch(function() {
|
||||
showToast('Could not copy — please copy the link manually.', 'error');
|
||||
});
|
||||
});
|
||||
});
|
||||
</script>
|
||||
|
||||
Reference in new issue
Block a user