This commit is contained in:
2026-08-07 21:42:12 +02:00
parent c7414e4b21
commit feb408338a
40 changed files with 927 additions and 229 deletions

View File

@@ -908,7 +908,7 @@ window.initUploadForm = (selector) => {
}
lines.forEach(url => {
if (!selectedFiles.some(item => item.type === 'url' && item.url === url)) {
selectedFiles.push({ type: 'url', url, rating: '', tags: [], comment: '', title: '', is_oc: false });
selectedFiles.push({ type: 'url', url, rating: '', visibility: '', tags: [], comment: '', title: '', is_oc: false });
}
});
urlInput.value = '';
@@ -931,7 +931,7 @@ window.initUploadForm = (selector) => {
const val = urlInput.value.trim();
if (!val || !/^https?:\/\//i.test(val)) return;
if (!selectedFiles.some(item => item.type === 'url' && item.url === val)) {
selectedFiles.push({ type: 'url', url: val, rating: '', tags: [], comment: '', title: '', is_oc: false });
selectedFiles.push({ type: 'url', url: val, rating: '', visibility: '', tags: [], comment: '', title: '', is_oc: false });
}
urlInput.value = '';
if (urlBadge) urlBadge.style.display = 'none';
@@ -1177,7 +1177,7 @@ window.initUploadForm = (selector) => {
if (!selectedFiles.some(f => (f.file || f).name === file.name && (f.file || f).size === file.size)) {
if (isShitpost) {
selectedFiles.push({ type: 'file', file: file, rating: '', tags: [], comment: '', title: '', is_oc: false });
selectedFiles.push({ type: 'file', file: file, rating: '', visibility: '', tags: [], comment: '', title: '', is_oc: false });
} else {
selectedFiles.push(file); // Legacy single file mode uses raw File
}
@@ -1490,6 +1490,7 @@ window.initUploadForm = (selector) => {
infoRow.className = 'file-meta-row-small';
let ratingSwitch = '';
let visibilitySwitch = '';
let tagsUI = '';
let ocUI = '';
let commentUI = '';
@@ -1517,6 +1518,26 @@ window.initUploadForm = (selector) => {
</div>
`;
const globalVis = form.querySelector('input[name="visibility"]:checked')?.value || '0';
const visValue = (item.visibility !== undefined && item.visibility !== '') ? item.visibility : globalVis;
item.visibility = visValue;
visibilitySwitch = `
<div class="item-visibility-container item-rating-container" style="margin-top: 4px;">
<label class="item-rating-option">
<input type="radio" name="visibility_${index}" value="0" ${visValue === '0' || visValue === 0 ? 'checked' : ''}>
<span class="item-rating-label sfw" style="display: inline-flex; align-items: center; gap: 4px;"><i class="fa-solid fa-globe"></i> Public</span>
</label>
<label class="item-rating-option">
<input type="radio" name="visibility_${index}" value="1" ${visValue === '1' || visValue === 1 ? 'checked' : ''}>
<span class="item-rating-label nsfw" style="display: inline-flex; align-items: center; gap: 4px;"><i class="fa-solid fa-link"></i> Unlisted</span>
</label>
<label class="item-rating-option">
<input type="radio" name="visibility_${index}" value="2" ${visValue === '2' || visValue === 2 ? 'checked' : ''}>
<span class="item-rating-label nsfl" style="display: inline-flex; align-items: center; gap: 4px;"><i class="fa-solid fa-lock"></i> Private</span>
</label>
</div>
`;
const tagsPlaceholder = window.f0ckI18n?.upload_tags_placeholder || 'Tags...';
const minTagsHint = shitpostMinTags > 0 ? ` (min ${shitpostMinTags})` : '';
tagsUI = `
@@ -1560,19 +1581,27 @@ window.initUploadForm = (selector) => {
</div>
${titleUI}
${ratingSwitch}
${visibilitySwitch}
${tagsUI}
${commentUI}
`;
if (isShitpost) {
// Handle Rating
infoRow.querySelectorAll('.item-rating-option input').forEach(radio => {
infoRow.querySelectorAll('.item-rating-container:not(.item-visibility-container) input').forEach(radio => {
radio.onchange = () => {
item.rating = radio.value;
updateSubmitButton();
};
});
// Handle Visibility
infoRow.querySelectorAll('.item-visibility-container input').forEach(radio => {
radio.onchange = () => {
item.visibility = radio.value;
};
});
// Handle Comment
const commentInput = infoRow.querySelector('.item-comment-input');
const emojiTrigger = infoRow.querySelector('.item-emoji-trigger');
@@ -2436,6 +2465,8 @@ window.initUploadForm = (selector) => {
}
try {
const globalVisEl = form.querySelector('input[name="visibility"]:checked');
const visibilityVal = globalVisEl ? globalVisEl.value : '0';
const resp = await fetch('/api/v2/upload-url', {
method: 'POST',
headers: {
@@ -2445,7 +2476,8 @@ window.initUploadForm = (selector) => {
},
body: JSON.stringify({
url,
rating: globalRatingEl.value,
rating: globalRatingEl ? globalRatingEl.value : 'sfw',
visibility: visibilityVal,
tags: tags.join(','),
comment: comment,
is_oc: isOc,
@@ -2552,9 +2584,11 @@ window.initUploadForm = (selector) => {
for (let i = 0; i < selectedFiles.length; i++) {
const item = selectedFiles[i];
const globalVisEl = form.querySelector('input[name="visibility"]:checked');
const isUrlItem = isShitpost && item.type === 'url';
const file = !isUrlItem ? (isShitpost ? item.file : item) : null;
const fileRating = isShitpost ? item.rating : (globalRatingEl ? globalRatingEl.value : 'sfw');
const fileVisibility = isShitpost ? (item.visibility || globalVisEl?.value || '0') : (globalVisEl?.value || '0');
const fileTags = isShitpost ? item.tags : tags;
const fileComment = isShitpost ? item.comment : comment;
const fileTitle = isShitpost ? (item.title || '') : titleVal;
@@ -2571,6 +2605,7 @@ window.initUploadForm = (selector) => {
formData.append('file', file);
}
formData.append('rating', fileRating);
formData.append('visibility', fileVisibility);
formData.append('tags', fileTags.join(','));
formData.append('is_oc', (isShitpost ? item.is_oc : isOc) ? 'true' : 'false');
if (isShitpost) formData.append('is_shitpost', 'true');
@@ -2622,6 +2657,7 @@ window.initUploadForm = (selector) => {
xhr.send(JSON.stringify({
url: item.url,
rating: fileRating,
visibility: fileVisibility,
tags: fileTags.join(','),
is_oc: (isShitpost ? item.is_oc : isOc),
comment: fileComment,
@@ -2738,17 +2774,14 @@ window.initUploadForm = (selector) => {
// Skip redirect if every item was a background URL job
const allPending = lastData?.pending && selectedFiles.every(i => i.type === 'url');
if (!allPending) {
// Inject now if the grid is already in the DOM (upload modal open on main page)
injectNewItem();
// Navigate to main page, then inject again after the grid has loaded.
// Awaiting loadPageAjax ensures the .posts grid DOM is present before the
// handleNewItem call — this covers the item-page drag-and-upload scenario
// where no grid exists until after navigation completes.
const targetUrl = (lastData && (lastData.visibility > 0 || lastData.redirect || lastData.slug))
? (lastData.redirect || `/${lastData.slug || lastData.itemid}`)
: '/';
if (typeof window.loadPageAjax === 'function') {
await window.loadPageAjax('/', true, { bypassCache: true });
injectNewItem();
await window.loadPageAjax(targetUrl, true, { bypassCache: true });
if (targetUrl === '/') injectNewItem();
} else {
window.location.href = '/';
window.location.href = targetUrl;
}
}
} else {