improving upload page and conent guidelines

This commit is contained in:
x
2026-01-24 12:05:10 +01:00
parent f2b14739e3
commit 8397d4ed3f
3 changed files with 478 additions and 376 deletions

423
public/s/css/upload.css Normal file
View File

@@ -0,0 +1,423 @@
/* Upload Page Styles */
.upload-container {
max-width: 800px;
margin: 0 auto;
padding: 0 1rem;
}
.upload-container h2 {
margin-bottom: 1.5rem;
color: var(--accent);
text-align: center;
}
/* Guidelines */
.content-guidelines {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
margin-bottom: 2rem;
overflow: hidden;
}
.content-guidelines summary {
padding: 1rem 1.5rem;
cursor: pointer;
font-weight: 600;
color: var(--accent);
list-style: none;
/* Hide default triangle */
display: flex;
justify-content: space-between;
align-items: center;
}
.content-guidelines summary::-webkit-details-marker {
display: none;
}
.content-guidelines summary::after {
content: '+';
font-size: 1.2rem;
font-weight: bold;
}
.content-guidelines[open] summary::after {
content: '-';
}
.guidelines-content {
padding: 0 1.5rem 1.5rem 1.5rem;
border-top: 1px solid rgba(255, 255, 255, 0.05);
}
.guidelines-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
margin-top: 1rem;
}
.guidelines-dont h5 {
color: #ff6b6b;
margin-bottom: 0.5rem;
}
.guidelines-do h5 {
color: #51cf66;
margin-bottom: 0.5rem;
}
.guidelines-grid ul {
list-style: none;
padding: 0;
margin: 0;
}
.guidelines-grid li {
padding: 0.3rem 0;
font-size: 0.9rem;
opacity: 0.8;
}
/* Upload Form */
.upload-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
background: rgba(255, 255, 255, 0.02);
padding: 2rem;
border-radius: 8px;
border: 1px solid rgba(255, 255, 255, 0.05);
}
.form-section label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.required {
color: #ff6b6b;
}
/* Drop Zone */
.drop-zone {
border: 2px dashed rgba(255, 255, 255, 0.2);
border-radius: 8px;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.2s;
position: relative;
min-height: 200px;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.drop-zone:hover,
.drop-zone.dragover {
border-color: var(--accent);
background: rgba(255, 255, 255, 0.02);
}
.drop-zone input[type="file"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
.drop-zone-prompt {
color: rgba(255, 255, 255, 0.5);
pointer-events: none;
/* Let input handle clicks */
}
/* File Preview (Stacked) */
.file-preview {
display: flex;
flex-direction: column;
/* Stacked */
align-items: center;
gap: 1rem;
width: 100%;
}
.file-preview video {
max-width: 100%;
max-height: 500px;
border-radius: 4px;
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
outline: none;
margin-bottom: 1rem;
}
.file-meta-row {
display: flex;
align-items: center;
gap: 1rem;
width: 100%;
justify-content: center;
}
.file-info {
display: flex;
gap: 1rem;
align-items: center;
background: rgba(0, 0, 0, 0.3);
padding: 0.5rem 1rem;
border-radius: 20px;
}
.file-name {
font-weight: 500;
}
.file-size {
opacity: 0.6;
font-size: 0.9rem;
}
.btn-remove {
background: #ff6b6b;
color: white;
border: none;
padding: 0.5rem 1.5rem;
border-radius: 4px;
cursor: pointer;
font-weight: 600;
transition: background 0.2s;
/* remove margin-top as it's now in a flex row */
}
.btn-remove:hover {
background: #fa5252;
}
/* Ratings */
.rating-options {
display: flex;
gap: 1rem;
justify-content: center;
}
.rating-option input {
display: none;
}
.rating-label {
display: block;
padding: 0.75rem 2rem;
border-radius: 4px;
border: 2px solid transparent;
transition: all 0.2s;
font-weight: 600;
text-align: center;
}
.rating-label.sfw {
background: rgba(81, 207, 102, 0.1);
border-color: rgba(81, 207, 102, 0.3);
color: #51cf66;
}
.rating-label.nsfw {
background: rgba(255, 107, 107, 0.1);
border-color: rgba(255, 107, 107, 0.3);
color: #ff6b6b;
}
.rating-option input:checked+.rating-label.sfw {
background: rgba(81, 207, 102, 0.2);
border-color: #51cf66;
}
.rating-option input:checked+.rating-label.nsfw {
background: rgba(255, 107, 107, 0.2);
border-color: #ff6b6b;
}
/* Tags */
.tag-input-container {
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
padding: 0.5rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tags-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tag-chip {
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: var(--accent);
color: #000;
padding: 0.3rem 0.6rem;
border-radius: 3px;
font-size: 0.9rem;
font-weight: 500;
}
.tag-chip button {
background: none;
border: none;
color: inherit;
cursor: pointer;
padding: 0;
font-size: 1.1rem;
line-height: 1;
}
#tag-input {
flex: 1;
min-width: 120px;
background: transparent;
border: none;
color: inherit;
padding: 0.5rem;
outline: none;
}
.tag-count {
font-weight: normal;
font-size: 0.85rem;
opacity: 0.7;
}
.tag-count.valid {
color: #51cf66;
font-weight: bold;
opacity: 1;
}
.tag-suggestions {
/* (styles for dropdown remain similar, maybe cleaner shadow) */
position: absolute;
top: 100%;
left: 0;
right: 0;
background: #1e1e1e;
border: 1px solid rgba(255, 255, 255, 0.1);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.5);
border-radius: 0 0 4px 4px;
max-height: 200px;
overflow-y: auto;
display: none;
z-index: 100;
}
.tag-suggestions.show {
display: block;
}
.tag-suggestion {
padding: 0.5rem 1rem;
cursor: pointer;
}
.tag-suggestion:hover {
background: rgba(255, 255, 255, 0.1);
}
/* Submit Button */
.btn-upload {
background: var(--accent);
color: #000;
border: none;
padding: 1rem 2rem;
border-radius: 4px;
font-size: 1.1rem;
font-weight: 700;
cursor: pointer;
transition: all 0.2s;
width: 100%;
margin-top: 1rem;
}
.btn-upload:disabled {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.4);
cursor: not-allowed;
}
.btn-upload:not(:disabled):hover {
transform: translateY(-2px);
box-shadow: 0 4px 15px rgba(0, 0, 0, 0.4);
}
/* Progress */
.upload-progress {
display: flex;
align-items: center;
gap: 1rem;
background: rgba(0, 0, 0, 0.2);
padding: 1rem;
border-radius: 4px;
}
.progress-bar {
flex: 1;
height: 10px;
background: rgba(255, 255, 255, 0.1);
border-radius: 5px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width 0.2s;
}
.progress-text {
font-weight: bold;
font-family: monospace;
}
.upload-status {
text-align: center;
padding: 1rem;
font-weight: 600;
}
.upload-status.error {
color: #ff6b6b;
}
.upload-status.success {
color: #51cf66;
}
/* Login Required */
.login-required {
text-align: center;
padding: 4rem 2rem;
border: 1px dashed rgba(255, 255, 255, 0.2);
border-radius: 8px;
}
.btn-login {
display: inline-block;
margin-top: 1rem;
padding: 0.75rem 2rem;
background: var(--accent);
color: #000;
text-decoration: none;
border-radius: 4px;
font-weight: 700;
}

View File

@@ -82,7 +82,7 @@
if (!hasTags) {
submitBtn.querySelector('.btn-text').textContent = (3 - tags.length) + ' more tag' + (3 - tags.length !== 1 ? 's' : '') + ' required';
} else if (!hasFile) {
submitBtn.querySelector('.btn-text').textContent = 'Select a file';
submitBtn.querySelector('.btn-text').textContent = 'Upload (Select file first)';
} else if (!hasRating) {
submitBtn.querySelector('.btn-text').textContent = 'Select SFW or NSFW';
} else {
@@ -111,6 +111,10 @@
fileName.textContent = file.name;
fileSize.textContent = formatSize(file.size);
dropZonePrompt.style.display = 'none';
// Hide input so it doesn't intercept clicks on preview/remove button
fileInput.style.display = 'none';
filePreview.style.display = 'flex';
statusDiv.textContent = '';
statusDiv.className = 'upload-status';
@@ -126,13 +130,11 @@
const vid = document.createElement('video');
vid.src = URL.createObjectURL(file);
vid.controls = false;
vid.controls = true; // User might want to scrub to check if it's the right video
vid.autoplay = true;
vid.muted = true;
vid.loop = true;
vid.style.maxHeight = '100px';
vid.style.maxWidth = '150px';
vid.style.borderRadius = '4px';
// Styles handled by CSS now for "Big" preview
filePreview.prepend(vid);
@@ -172,6 +174,7 @@
selectedFile = null;
fileInput.value = '';
dropZonePrompt.style.display = 'block';
fileInput.style.display = 'block'; // Restore input visibility
filePreview.style.display = 'none';
// Clear preview video
const vid = filePreview.querySelector('video');

View File

@@ -1,55 +1,62 @@
@include(snippets/header)
<div class="upload-container">
<h2>Upload</h2>
<link rel="stylesheet" href="/s/css/upload.css">
<div class="content-guidelines">
<h4>Content Guideline</h4>
<p>w0bm follows strict principles when it comes to content, please keep this in mind.</p>
<div class="guidelines-grid">
<div class="guidelines-dont">
<h5>We do not want</h5>
<ul>
<li>Content glorifying Nazis</li>
<li>Sexualization of children/minors</li>
<li>Political content</li>
<li>Military glorification</li>
<li>Gore</li>
<li>Acts of terrorism</li>
<li>Violence against animals</li>
</ul>
</div>
<div class="guidelines-do">
<h5>We want</h5>
<ul>
<li>Cool content</li>
<li>Deeper value</li>
<li>Fun to watch</li>
<li>Has a vibe to it</li>
<li>Can be looped 5000 times</li>
</ul>
<div class="upload-container">
<h2>Upload Content</h2>
<details class="content-guidelines">
<summary>Content Guidelines (Click to expand)</summary>
<div class="guidelines-content">
<p>We want this place to be fun. Keep it cool, keep it legal.</p>
<div class="guidelines-grid">
<div class="guidelines-do">
<h5>Do's (Vibes & Hypnosis)</h5>
<ul>
<li>Cool, relaxing, or weird "vibing" content</li>
<li>Classic-style loops (Flash era vibes)</li>
<li>High-quality, hypnotic edits (PMVs welcome)</li>
<li>Interesting, freaky, or just plain cool stuff</li>
</ul>
</div>
<div class="guidelines-dont">
<h5>Don'ts (The Banhammer)</h5>
<ul>
<li>Political commentary, preaching, or "pol" bait</li>
<li>Gore, extreme violence, or animal cruelty (Instant Ban)</li>
<li>Illegal content (CP, Terror, etc.) (Instant Ban)</li>
<li>Boring, unedited, or lengthy videos</li>
</ul>
</div>
</div>
</div>
</div>
</details>
@if(session)
<form id="upload-form" class="upload-form" enctype="multipart/form-data">
<div class="form-section">
<label>Video File <span class="required">*</span></label>
<div class="drop-zone" id="drop-zone">
<input type="file" id="file-input" name="file" accept="video/mp4,video/webm" style="display: none;">
<label for="file-input" class="drop-zone-prompt"
style="cursor: pointer; display: block; width: 100%; height: 100%;">
<svg width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
<input type="file" id="file-input" name="file" accept="video/mp4,video/webm">
<div class="drop-zone-prompt">
<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5"
style="opacity: 0.7; margin-bottom: 1rem;">
<path d="M21 15v4a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-4"></path>
<polyline points="17 8 12 3 7 8"></polyline>
<line x1="12" y1="3" x2="12" y2="15"></line>
</svg>
<p>Drop your mp4 or webm here<br>or click to browse</p>
</label>
<p style="font-size: 1.1rem; font-weight: 500;">Drop your video here</p>
<p style="font-size: 0.9rem; opacity: 0.6;">(mp4 or webm)</p>
</div>
<!-- Preview Container -->
<div class="file-preview" id="file-preview" style="display: none;">
<span class="file-name" id="file-name"></span>
<span class="file-size" id="file-size"></span>
<button type="button" class="btn-remove" id="remove-file"></button>
<!-- Video will be injected here via JS -->
<div class="file-meta-row">
<div class="file-info">
<span class="file-name" id="file-name"></span>
<span class="file-size" id="file-size"></span>
</div>
<button type="button" class="btn-remove" id="remove-file" title="Remove File"></button>
</div>
</div>
</div>
</div>
@@ -81,7 +88,7 @@
<div class="form-actions">
<button type="submit" id="submit-btn" class="btn-upload" disabled>
<span class="btn-text">3 tags required</span>
<span class="btn-text">Select a file</span>
<span class="btn-loading" style="display: none;">Uploading...</span>
</button>
</div>
@@ -97,343 +104,12 @@
</form>
@else
<div class="login-required">
<p>You must be logged in to upload content.</p>
<h3>Authentication Required</h3>
<p>You must be logged in to upload content to w0bm.</p>
<a href="/login" class="btn-login">Login</a>
</div>
@endif
</div>
<style>
.upload-container {
margin: 0px 25px 0px 25px
}
.upload-container h2 {
margin-bottom: 1.5rem;
color: var(--accent);
}
.content-guidelines {
background: rgba(255, 255, 255, 0.03);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 8px;
padding: 1.5rem;
margin-bottom: 2rem;
}
.content-guidelines h4 {
margin-bottom: 0.5rem;
color: var(--accent);
}
.guidelines-grid {
display: grid;
grid-template-columns: 1fr 1fr;
gap: 1.5rem;
margin-top: 1rem;
}
.guidelines-dont h5 {
color: #ff6b6b;
}
.guidelines-do h5 {
color: #51cf66;
}
.guidelines-grid ul {
list-style: none;
padding: 0;
margin: 0.5rem 0 0 0;
}
.guidelines-grid li {
padding: 0.3rem 0;
font-size: 0.9rem;
opacity: 0.8;
}
.upload-form {
display: flex;
flex-direction: column;
gap: 1.5rem;
}
.form-section label {
display: block;
margin-bottom: 0.5rem;
font-weight: 500;
}
.required {
color: #ff6b6b;
}
.drop-zone {
border: 2px dashed rgba(255, 255, 255, 0.2);
border-radius: 8px;
padding: 2rem;
text-align: center;
cursor: pointer;
transition: all 0.2s;
position: relative;
}
.drop-zone:hover,
.drop-zone.dragover {
border-color: var(--accent);
background: rgba(255, 255, 255, 0.02);
}
.drop-zone input[type="file"] {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
opacity: 0;
cursor: pointer;
}
.drop-zone-prompt {
color: rgba(255, 255, 255, 0.5);
}
.drop-zone-prompt svg {
margin-bottom: 0.5rem;
}
.file-preview {
display: flex;
align-items: center;
gap: 1rem;
padding: 1rem;
background: rgba(255, 255, 255, 0.05);
border-radius: 4px;
}
.file-name {
font-weight: 500;
flex: 1;
}
.file-size {
opacity: 0.6;
font-size: 0.9rem;
}
.btn-remove {
background: rgba(255, 107, 107, 0.2);
border: none;
color: #ff6b6b;
width: 28px;
height: 28px;
border-radius: 4px;
cursor: pointer;
}
.rating-options {
display: flex;
gap: 1rem;
}
.rating-option {
cursor: pointer;
}
.rating-option input {
display: none;
}
.rating-label {
display: inline-block;
padding: 0.75rem 1.5rem;
border-radius: 4px;
border: 2px solid transparent;
transition: all 0.2s;
}
.rating-label.sfw {
background: rgba(81, 207, 102, 0.1);
border-color: rgba(81, 207, 102, 0.3);
}
.rating-label.nsfw {
background: rgba(255, 107, 107, 0.1);
border-color: rgba(255, 107, 107, 0.3);
}
.rating-option input:checked+.rating-label.sfw {
background: rgba(81, 207, 102, 0.3);
border-color: #51cf66;
}
.rating-option input:checked+.rating-label.nsfw {
background: rgba(255, 107, 107, 0.3);
border-color: #ff6b6b;
}
.tag-input-container {
position: relative;
background: rgba(255, 255, 255, 0.05);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 4px;
padding: 0.5rem;
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
align-items: center;
}
.tags-list {
display: flex;
flex-wrap: wrap;
gap: 0.5rem;
}
.tag-chip {
display: inline-flex;
align-items: center;
gap: 0.3rem;
background: var(--accent);
color: #000;
padding: 0.3rem 0.6rem;
border-radius: 3px;
font-size: 0.9rem;
}
.tag-chip button {
background: none;
border: none;
color: inherit;
cursor: pointer;
padding: 0;
font-size: 1rem;
line-height: 1;
}
#tag-input {
flex: 1;
min-width: 120px;
background: transparent;
border: none;
color: inherit;
padding: 0.5rem;
outline: none;
}
.tag-count {
font-weight: normal;
font-size: 0.85rem;
opacity: 0.7;
}
.tag-count.valid {
color: #51cf66;
}
.tag-suggestions {
position: absolute;
top: 100%;
left: 0;
right: 0;
background: var(--background, #1a1a1a);
border: 1px solid rgba(255, 255, 255, 0.1);
border-radius: 0 0 4px 4px;
max-height: 200px;
overflow-y: auto;
display: none;
z-index: 100;
}
.tag-suggestions.show {
display: block;
}
.tag-suggestion {
padding: 0.5rem 1rem;
cursor: pointer;
}
.tag-suggestion:hover {
background: rgba(255, 255, 255, 0.05);
}
.btn-upload {
background: var(--accent);
color: #000;
border: none;
padding: 1rem 2rem;
border-radius: 4px;
font-size: 1rem;
font-weight: 600;
cursor: pointer;
transition: all 0.2s;
}
.btn-upload:disabled {
background: rgba(255, 255, 255, 0.1);
color: rgba(255, 255, 255, 0.4);
cursor: not-allowed;
}
.btn-upload:not(:disabled):hover {
transform: translateY(-1px);
box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
}
.upload-progress {
display: flex;
align-items: center;
gap: 1rem;
}
.progress-bar {
flex: 1;
height: 8px;
background: rgba(255, 255, 255, 0.1);
border-radius: 4px;
overflow: hidden;
}
.progress-fill {
height: 100%;
background: var(--accent);
width: 0%;
transition: width 0.2s;
}
.upload-status {
text-align: center;
padding: 1rem;
}
.upload-status.success {
color: #51cf66;
}
.upload-status.error {
color: #ff6b6b;
}
.login-required {
text-align: center;
padding: 3rem;
background: rgba(255, 255, 255, 0.03);
border-radius: 8px;
}
.btn-login {
display: inline-block;
margin-top: 1rem;
padding: 0.75rem 2rem;
background: var(--accent);
color: #000;
text-decoration: none;
border-radius: 4px;
font-weight: 600;
}
</style>
<script src="/s/js/upload.js"></script>
@include(snippets/footer)