Move contrast checking into Python
Change banner size dependent on group content Tidy up inline JS for some files Correct spelling
|
@ -67,7 +67,6 @@ def create_app(test_config=None):
|
||||||
assets.register('js_all', js_scripts)
|
assets.register('js_all', js_scripts)
|
||||||
|
|
||||||
# Error handlers
|
# Error handlers
|
||||||
|
|
||||||
@app.errorhandler(Exception)
|
@app.errorhandler(Exception)
|
||||||
def error_page(err):
|
def error_page(err):
|
||||||
# If the error is a HTTP error, return the error page
|
# If the error is a HTTP error, return the error page
|
||||||
|
|
|
@ -29,7 +29,7 @@ db_session = db_session()
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/file/<file_name>', methods=['GET'])
|
@blueprint.route('/file/<file_name>', methods=['GET'])
|
||||||
def get_file(file_name):
|
def file(file_name):
|
||||||
"""
|
"""
|
||||||
Returns a file from the uploads folder
|
Returns a file from the uploads folder
|
||||||
r for resolution, 400x400 or thumb for thumbnail
|
r for resolution, 400x400 or thumb for thumbnail
|
||||||
|
|
|
@ -7,6 +7,7 @@ from flask import Blueprint, abort, render_template, url_for
|
||||||
|
|
||||||
from sqlalchemy.orm import sessionmaker
|
from sqlalchemy.orm import sessionmaker
|
||||||
from gallery import db
|
from gallery import db
|
||||||
|
from gallery.utils import contrast
|
||||||
|
|
||||||
|
|
||||||
blueprint = Blueprint('group', __name__, url_prefix='/group')
|
blueprint = Blueprint('group', __name__, url_prefix='/group')
|
||||||
|
@ -59,8 +60,13 @@ def group(group_id):
|
||||||
for image in group_images:
|
for image in group_images:
|
||||||
image = db_session.query(db.Posts).filter(db.Posts.id == image[0]).first()
|
image = db_session.query(db.Posts).filter(db.Posts.id == image[0]).first()
|
||||||
images.append(image)
|
images.append(image)
|
||||||
|
|
||||||
|
if images:
|
||||||
|
text_colour = contrast.contrast(images[0].image_colours[0], 'rgb(var(--fg-black))', 'rgb(var(--fg-white))')
|
||||||
|
else:
|
||||||
|
text_colour = 'rgb(var(--fg-black))'
|
||||||
|
|
||||||
return render_template('groups/group.html', group=group_item, images=images)
|
return render_template('groups/group.html', group=group_item, images=images, text_colour=text_colour)
|
||||||
|
|
||||||
|
|
||||||
@blueprint.route('/<int:group_id>/<int:image_id>')
|
@blueprint.route('/<int:group_id>/<int:image_id>')
|
||||||
|
|
Before Width: | Height: | Size: 134 KiB After Width: | Height: | Size: 134 KiB |
Before Width: | Height: | Size: 29 KiB After Width: | Height: | Size: 29 KiB |
Before Width: | Height: | Size: 225 KiB |
|
@ -47,8 +47,8 @@ function loadOnView() {
|
||||||
window.onload = function () {
|
window.onload = function () {
|
||||||
loadOnView();
|
loadOnView();
|
||||||
|
|
||||||
const darkColor = '#151515';
|
const darkColor = 'rgb(var(--black))';
|
||||||
const lightColor = '#E8E3E3';
|
const lightColor = 'rgb(var(--white))';
|
||||||
let contrastCheck = document.querySelectorAll('#contrast-check');
|
let contrastCheck = document.querySelectorAll('#contrast-check');
|
||||||
for (let i = 0; i < contrastCheck.length; i++) {
|
for (let i = 0; i < contrastCheck.length; i++) {
|
||||||
let bgColor = contrastCheck[i].getAttribute('data-color');
|
let bgColor = contrastCheck[i].getAttribute('data-color');
|
||||||
|
@ -94,7 +94,7 @@ window.onload = function () {
|
||||||
infoButton.classList.add('show');
|
infoButton.classList.add('show');
|
||||||
}
|
}
|
||||||
infoButton.onclick = function () {
|
infoButton.onclick = function () {
|
||||||
popUpShow('OnlyLegs Gallery',
|
popUpShow('OnlyLegs on Flask',
|
||||||
'Using <a href="https://phosphoricons.com/">Phosphoricons</a> and <a href="https://www.gent.media/manrope">Manrope</a> <br>' +
|
'Using <a href="https://phosphoricons.com/">Phosphoricons</a> and <a href="https://www.gent.media/manrope">Manrope</a> <br>' +
|
||||||
'Made by Fluffy and others with ❤️ <br>' +
|
'Made by Fluffy and others with ❤️ <br>' +
|
||||||
'<a href="https://github.com/Fluffy-Bean/onlylegs">V23.03.25</a>');
|
'<a href="https://github.com/Fluffy-Bean/onlylegs">V23.03.25</a>');
|
||||||
|
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
Before Width: | Height: | Size: 8.1 KiB After Width: | Height: | Size: 8.1 KiB |
|
@ -1,8 +1,7 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
|
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<span class="error-page">
|
<span class="error-page">
|
||||||
<h1>{{error}}</h1>
|
<h1>{{error}}</h1>
|
||||||
<p>{{msg}}</p>
|
<p>{{msg}}</p>
|
||||||
</span>
|
</span>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
|
@ -1,29 +1,44 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
{% block nav_groups %}selected{% endblock %}
|
{% block nav_groups %}selected{% endblock %}
|
||||||
{% block content %}
|
{% block head %}
|
||||||
<div class="banner">
|
<style>
|
||||||
{% if images %}
|
{% if images %}
|
||||||
<img
|
.banner-content p {
|
||||||
src="/api/file/{{ images.0.file_name }}?w=1920&h=1080"
|
color: {{ text_colour }} !important;
|
||||||
onload="imgFade(this)"
|
}
|
||||||
style="opacity:0; background-color:rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})"
|
.banner-content h1 {
|
||||||
/>
|
color: {{ text_colour }} !important;
|
||||||
<span
|
}
|
||||||
class="banner-filter"
|
|
||||||
style="background: linear-gradient(to right, rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }}), transparent)"
|
.banner-filter {
|
||||||
></span>
|
background: linear-gradient(to right, rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }}), transparent) !important;
|
||||||
|
}
|
||||||
|
@media (max-width: 800px) {
|
||||||
|
.banner-filter {
|
||||||
|
background: linear-gradient(to bottom, rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }}), transparent) !important;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
|
{% block content %}
|
||||||
|
<div class="banner {% if not images %}small{% endif %}">
|
||||||
|
{% if not images %}
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
<p><span id="contrast-check" data-color="rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})">{{ group.description }}</span></p>
|
<h1>{{ group.name }}</h1>
|
||||||
<h1><span id="contrast-check" data-color="rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})">{{ group.name }}</span></h1>
|
<p>By {{ group.author_username }}</p>
|
||||||
<p><span id="contrast-check" data-color="rgb({{ images.0.image_colours.0.0 }}, {{ images.0.image_colours.0.1 }}, {{ images.0.image_colours.0.2 }})">By {{ group.author_username }} - {{ images|length }} Images</span></p>
|
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img
|
||||||
<span></span>
|
src="/api/file/{{ images.0.file_name }}?r=1920x1080"
|
||||||
|
onload="imgFade(this)"
|
||||||
|
style="opacity:0;"
|
||||||
|
/>
|
||||||
|
<span class="banner-filter" ></span>
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
<p>{{ group.description }}</p>
|
|
||||||
<h1>{{ group.name }}</h1>
|
|
||||||
<p>By {{ group.author_username }} - {{ images|length }} Images</p>
|
<p>By {{ group.author_username }} - {{ images|length }} Images</p>
|
||||||
|
<h1>{{ group.name }}</h1>
|
||||||
|
<p>{{ group.description }}</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
|
@ -49,11 +64,11 @@
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="big-text">
|
<div class="big-text">
|
||||||
<h1>No image!</h1>
|
<h1>*crickets chirping*</h1>
|
||||||
{% if g.user %}
|
{% if g.user %}
|
||||||
<p>You can get started by uploading an image!</p>
|
<p>Add some images to the group!</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Login to start uploading images!</p>
|
<p>Login to start managing this image group!</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
|
|
@ -37,23 +37,19 @@
|
||||||
<p class="image-subtitle"></p>
|
<p class="image-subtitle"></p>
|
||||||
<p class="image-title">{{ group.name }}</p>
|
<p class="image-title">{{ group.name }}</p>
|
||||||
</div>
|
</div>
|
||||||
<img src="{{ url_for('static', filename='images/error.png') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='error.png') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
</a>
|
</a>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</div>
|
</div>
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="big-text">
|
<div class="big-text">
|
||||||
<h1>No image groups!</h1>
|
<h1>*crickets chirping*</h1>
|
||||||
{% if g.user %}
|
{% if g.user %}
|
||||||
<p>You can get started by creating a new image group!</p>
|
<p>You can get started by creating a new image group!</p>
|
||||||
{% else %}
|
{% else %}
|
||||||
<p>Login to get started!</p>
|
<p>Login to start seeing anything here!</p>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block script %}
|
|
||||||
<script></script>
|
|
||||||
{% endblock %}
|
|
|
@ -1,33 +1,96 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
|
|
||||||
{% block head %}
|
|
||||||
<meta property="og:image" content="/api/file/{{ image.file_name }}"/>
|
|
||||||
<meta name="theme-color" content="#{{ image.image_colours.0.0 }}{{ image.image_colours.0.1 }}{{ image.image_colours.0.2 }}"/>
|
|
||||||
{% endblock %}
|
|
||||||
|
|
||||||
{% block wrapper_class %}image-wrapper{% endblock %}
|
{% block wrapper_class %}image-wrapper{% endblock %}
|
||||||
|
{% block head %}
|
||||||
|
<meta property="og:image" content="{{ url_for('api.file', file_name=image.file_name) }}"/>
|
||||||
|
<meta name="theme-color" content="#{{ image.image_colours.0.0 }}{{ image.image_colours.0.1 }}{{ image.image_colours.0.2 }}"/>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
function imageFullscreenOff() {
|
||||||
|
document.querySelector("html").style.overflow = "auto";
|
||||||
|
let fullscreen = document.querySelector('.image-fullscreen')
|
||||||
|
|
||||||
|
fullscreen.classList.remove('active');
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
fullscreen.style.display = 'none';
|
||||||
|
}, 200);
|
||||||
|
}
|
||||||
|
function imageFullscreenOn() {
|
||||||
|
document.querySelector("html").style.overflow = "hidden";
|
||||||
|
let fullscreen = document.querySelector('.image-fullscreen')
|
||||||
|
|
||||||
|
fullscreen.querySelector('img').src = '{{ url_for('api.file', file_name=image.file_name) }}';
|
||||||
|
fullscreen.style.display = 'flex';
|
||||||
|
|
||||||
|
setTimeout(function() {
|
||||||
|
fullscreen.classList.add('active');
|
||||||
|
}, 10);
|
||||||
|
}
|
||||||
|
function imageShare() {
|
||||||
|
try {
|
||||||
|
navigator.clipboard.writeText(window.location.href)
|
||||||
|
addNotification("Copied link!", 4);
|
||||||
|
} catch (err) {
|
||||||
|
addNotification("Failed to copy link! Are you on HTTP?", 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
{% if g.user['id'] == image['author_id'] %}
|
||||||
|
function imageDelete() {
|
||||||
|
popUpShow(
|
||||||
|
'DESTRUCTION!!!!!!',
|
||||||
|
'Do you want to delete this image along with all of its data??? This action is irreversible!',
|
||||||
|
'<button class="btn-block" onclick="popupDissmiss()">Nuuu</button>' +
|
||||||
|
'<button class="btn-block critical" onclick="deleteConfirm()">Dewww eeeet!</button>'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
function deleteConfirm() {
|
||||||
|
popupDissmiss();
|
||||||
|
|
||||||
|
$.ajax({
|
||||||
|
url: '{{ url_for('api.delete_image', image_id=image['id']) }}',
|
||||||
|
type: 'post',
|
||||||
|
data: {
|
||||||
|
action: 'delete'
|
||||||
|
},
|
||||||
|
success: function (response) {
|
||||||
|
window.location.href = '/';
|
||||||
|
},
|
||||||
|
error: function (response) {
|
||||||
|
addNotification(`Image *clings*: ${response}`, 2);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function imageEdit() {
|
||||||
|
addNotification("Not an option, oops!", 3);
|
||||||
|
}
|
||||||
|
{% endif %}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
.background span {
|
||||||
|
background-image: linear-gradient(to top, rgba({{ image.image_colours.0.0 }}, {{ image.image_colours.0.1 }}, {{ image.image_colours.0.2 }}, 1), transparent);
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="background">
|
<div class="background">
|
||||||
<img src="/api/file/{{ image.file_name }}?r=prev" alt="{{ image.post_alt }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('api.file', file_name=image.file_name) }}?r=prev" alt="{{ image.post_alt }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
<span style="background-image: linear-gradient(to top, rgba({{ image.image_colours.0.0 }}, {{ image.image_colours.0.1 }}, {{ image.image_colours.0.2 }}, 1), transparent);"></span>
|
<span></span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="image-fullscreen">
|
<div class="image-fullscreen" onclick="imageFullscreenOff()">
|
||||||
<img src="" alt="{{ image.post_alt }}" onload="imgFade(this);" style="opacity:0;" />
|
<img src="" alt="{{ image.post_alt }}" onload="imgFade(this);" style="opacity:0;" />
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="image-grid">
|
<div class="image-grid">
|
||||||
<div class="image-container" id="image-container">
|
<div class="image-container" id="image-container">
|
||||||
<img
|
<img
|
||||||
src="/api/file/{{ image.file_name }}?r=prev"
|
src="{{ url_for('api.file', file_name=image.file_name) }}?r=prev"
|
||||||
alt="{{ image.post_alt }}"
|
alt="{{ image.post_alt }}"
|
||||||
onload="imgFade(this)" style="opacity:0;"
|
onload="imgFade(this)" style="opacity:0;"
|
||||||
onerror="this.src='/static/images/error.png'"
|
onerror="this.src='{{ url_for('static', filename='error.png')}}'"
|
||||||
{% if "File" in image.image_exif %}
|
|
||||||
width="{{ image.image_exif.File.Width.raw }}"
|
|
||||||
height="{{ image.image_exif.File.Height.raw }}"
|
|
||||||
{% endif %}
|
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
@ -44,14 +107,14 @@
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<div>
|
<div>
|
||||||
<button class="pill-item" id="img-fullscreen">
|
<button class="pill-item" onclick="imageFullscreenOn()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M117.66,138.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l34.34-34.35A8,8,0,0,1,117.66,138.34ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72l-34.35,34.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M117.66,138.34a8,8,0,0,1,0,11.32L83.31,184l18.35,18.34A8,8,0,0,1,96,216H48a8,8,0,0,1-8-8V160a8,8,0,0,1,13.66-5.66L72,172.69l34.34-34.35A8,8,0,0,1,117.66,138.34ZM208,40H160a8,8,0,0,0-5.66,13.66L172.69,72l-34.35,34.34a8,8,0,0,0,11.32,11.32L184,83.31l18.34,18.35A8,8,0,0,0,216,96V48A8,8,0,0,0,208,40Z"></path></svg>
|
||||||
<span class="tool-tip">
|
<span class="tool-tip">
|
||||||
Fullscreen
|
Fullscreen
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z"></path></svg>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="pill-item" id="img-share">
|
<button class="pill-item" onclick="imageShare()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M212,200a36,36,0,1,1-69.85-12.25l-53-34.05a36,36,0,1,1,0-51.4l53-34a36.09,36.09,0,1,1,8.67,13.45l-53,34.05a36,36,0,0,1,0,24.5l53,34.05A36,36,0,0,1,212,200Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M212,200a36,36,0,1,1-69.85-12.25l-53-34.05a36,36,0,1,1,0-51.4l53-34a36.09,36.09,0,1,1,8.67,13.45l-53,34.05a36,36,0,0,1,0,24.5l53,34.05A36,36,0,0,1,212,200Z"></path></svg>
|
||||||
<span class="tool-tip">
|
<span class="tool-tip">
|
||||||
Share
|
Share
|
||||||
|
@ -68,14 +131,14 @@
|
||||||
</div>
|
</div>
|
||||||
{% if image.author_id == g.user.id %}
|
{% if image.author_id == g.user.id %}
|
||||||
<div>
|
<div>
|
||||||
<button class="pill-item pill__critical" id="img-delete">
|
<button class="pill-item pill__critical" onclick="imageDelete()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM112,168a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm0-120H96V40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M216,48H176V40a24,24,0,0,0-24-24H104A24,24,0,0,0,80,40v8H40a8,8,0,0,0,0,16h8V208a16,16,0,0,0,16,16H192a16,16,0,0,0,16-16V64h8a8,8,0,0,0,0-16ZM112,168a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm48,0a8,8,0,0,1-16,0V104a8,8,0,0,1,16,0Zm0-120H96V40a8,8,0,0,1,8-8h48a8,8,0,0,1,8,8Z"></path></svg>
|
||||||
<span class="tool-tip">
|
<span class="tool-tip">
|
||||||
Delete
|
Delete
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M213.66,101.66l-80,80a8,8,0,0,1-11.32,0l-80-80A8,8,0,0,1,48,88H208a8,8,0,0,1,5.66,13.66Z"></path></svg>
|
||||||
</span>
|
</span>
|
||||||
</button>
|
</button>
|
||||||
<button class="pill-item pill__critical" id="img-edit">
|
<button class="pill-item pill__critical" onclick="imageEdit()">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM51.31,160l90.35-90.35,16.68,16.69L68,176.68ZM48,179.31,76.69,208H48Zm48,25.38L79.31,188l90.35-90.35h0l16.68,16.69Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M227.31,73.37,182.63,28.68a16,16,0,0,0-22.63,0L36.69,152A15.86,15.86,0,0,0,32,163.31V208a16,16,0,0,0,16,16H92.69A15.86,15.86,0,0,0,104,219.31L227.31,96a16,16,0,0,0,0-22.63ZM51.31,160l90.35-90.35,16.68,16.69L68,176.68ZM48,179.31,76.69,208H48Zm48,25.38L79.31,188l90.35-90.35h0l16.68,16.69Z"></path></svg>
|
||||||
<span class="tool-tip">
|
<span class="tool-tip">
|
||||||
Edit
|
Edit
|
||||||
|
@ -215,76 +278,11 @@
|
||||||
|
|
||||||
{% block script %}
|
{% block script %}
|
||||||
<script>
|
<script>
|
||||||
var infoTab = document.querySelectorAll('.info-tab');
|
let infoTab = document.querySelectorAll('.info-tab');
|
||||||
for (var i = 0; i < infoTab.length; i++) {
|
for (let i = 0; i < infoTab.length; i++) {
|
||||||
infoTab[i].querySelector('.info-header').addEventListener('click', function() {
|
infoTab[i].querySelector('.info-header').addEventListener('click', function() {
|
||||||
this.parentNode.classList.toggle('collapsed');
|
this.parentNode.classList.toggle('collapsed');
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
$('.image-fullscreen').click(function() {
|
|
||||||
// un-Stop scrolling
|
|
||||||
document.querySelector("html").style.overflow = "auto";
|
|
||||||
let fullscreen = document.querySelector('.image-fullscreen')
|
|
||||||
|
|
||||||
fullscreen.classList.remove('active');
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
fullscreen.style.display = 'none';
|
|
||||||
}, 200);
|
|
||||||
});
|
|
||||||
$('#img-fullscreen').click(function() {
|
|
||||||
// Stop scrolling
|
|
||||||
document.querySelector("html").style.overflow = "hidden";
|
|
||||||
let fullscreen = document.querySelector('.image-fullscreen')
|
|
||||||
|
|
||||||
fullscreen.querySelector('img').src = '/api/file/{{ image.file_name }}';
|
|
||||||
fullscreen.style.display = 'flex';
|
|
||||||
|
|
||||||
setTimeout(function() {
|
|
||||||
fullscreen.classList.add('active');
|
|
||||||
}, 10);
|
|
||||||
});
|
|
||||||
|
|
||||||
$('#img-share').click(function() {
|
|
||||||
try {
|
|
||||||
navigator.clipboard.writeText(window.location.href);
|
|
||||||
addNotification("Copied link!", 4);
|
|
||||||
} catch (err) {
|
|
||||||
addNotification("Failed to copy link! Are you on HTTP?", 2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
{% if g.user['id'] == image['author_id'] %}
|
|
||||||
$('#img-delete').click(function() {
|
|
||||||
popUpShow(
|
|
||||||
'DESTRUCTION!!!!!!',
|
|
||||||
'Do you want to delete this image along with all of its data??? This action is irreversible!',
|
|
||||||
'<button class="btn-block" onclick="popupDissmiss()">Nuuu</button>' +
|
|
||||||
'<button class="btn-block critical" onclick="deleteImage()">Dewww eeeet!</button>'
|
|
||||||
);
|
|
||||||
});
|
|
||||||
function deleteImage() {
|
|
||||||
popupDissmiss();
|
|
||||||
|
|
||||||
$.ajax({
|
|
||||||
url: '{{ url_for('api.delete_image', image_id=image['id']) }}',
|
|
||||||
type: 'post',
|
|
||||||
data: {
|
|
||||||
action: 'delete'
|
|
||||||
},
|
|
||||||
success: function (response) {
|
|
||||||
window.location.href = '/';
|
|
||||||
},
|
|
||||||
error: function (response) {
|
|
||||||
addNotification(`Image *clings*: ${response}`, 2);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
$('#img-edit').click(function() {
|
|
||||||
window.location.href = '/image/{{ image.id }}/edit';
|
|
||||||
});
|
|
||||||
{% endif %}
|
|
||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
|
@ -1,7 +1,24 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
|
|
||||||
{% block nav_home %}selected{% endblock %}
|
{% block nav_home %}selected{% endblock %}
|
||||||
|
{% block head %}
|
||||||
|
<script>
|
||||||
|
if (document.referrer.includes('image')) {
|
||||||
|
try {
|
||||||
|
let referrerId = document.referrer.split('/').pop();
|
||||||
|
|
||||||
|
let imgOffset = document.getElementById('image-' + referrerId).offsetTop;
|
||||||
|
let imgHeight = document.getElementById('image-' + referrerId).offsetHeight;
|
||||||
|
let windowHeight = window.innerHeight;
|
||||||
|
|
||||||
|
document.querySelector('html').style.scrollBehavior = 'auto';
|
||||||
|
window.scrollTo(0, imgOffset + (imgHeight / 2) - (windowHeight / 2));
|
||||||
|
document.querySelector('html').style.scrollBehavior = 'smooth';
|
||||||
|
} catch (e) {
|
||||||
|
console.log(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="banner small">
|
<div class="banner small">
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
|
@ -19,7 +36,7 @@
|
||||||
{% if images %}
|
{% if images %}
|
||||||
<div class="gallery-grid">
|
<div class="gallery-grid">
|
||||||
{% for image in images %}
|
{% for image in images %}
|
||||||
<a id="image-{{ image.id }}" class="gallery-item" href="/image/{{ image.id }}" style="background-color: rgb({{ image.image_colours.0.0 }}, {{ image.image_colours.0.1 }}, {{ image.image_colours.0.2 }})">
|
<a id="image-{{ image.id }}" class="gallery-item" href="{{ url_for('gallery.image', image_id=image.id) }}" style="background-color: rgb({{ image.image_colours.0.0 }}, {{ image.image_colours.0.1 }}, {{ image.image_colours.0.2 }})">
|
||||||
<div class="image-filter">
|
<div class="image-filter">
|
||||||
<p class="image-subtitle"></p>
|
<p class="image-subtitle"></p>
|
||||||
<p class="image-title"><span class="time">{{ image.created_at }}</span></p>
|
<p class="image-title"><span class="time">{{ image.created_at }}</span></p>
|
||||||
|
@ -31,26 +48,7 @@
|
||||||
{% else %}
|
{% else %}
|
||||||
<div class="big-text">
|
<div class="big-text">
|
||||||
<h1>*crickets chirping*</h1>
|
<h1>*crickets chirping*</h1>
|
||||||
|
<p>There are no images here yet, upload some!</p>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
|
||||||
{% block script %}
|
|
||||||
<script>
|
|
||||||
if (document.referrer.includes('image')) {
|
|
||||||
try {
|
|
||||||
let referrerId = document.referrer.split('/').pop();
|
|
||||||
|
|
||||||
let imgOffset = document.getElementById('image-' + referrerId).offsetTop;
|
|
||||||
let imgHeight = document.getElementById('image-' + referrerId).offsetHeight;
|
|
||||||
let windowHeight = window.innerHeight;
|
|
||||||
|
|
||||||
document.querySelector('html').style.scrollBehavior = 'auto';
|
|
||||||
window.scrollTo(0, imgOffset + (imgHeight / 2) - (windowHeight / 2));
|
|
||||||
document.querySelector('html').style.scrollBehavior = 'smooth';
|
|
||||||
} catch (e) {
|
|
||||||
console.log(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
{% endblock %}
|
|
|
@ -17,12 +17,12 @@
|
||||||
<meta name="twitter:card" content="summary_large_image">
|
<meta name="twitter:card" content="summary_large_image">
|
||||||
|
|
||||||
<link
|
<link
|
||||||
href="{{url_for('static', filename='images/logo-black.svg')}}"
|
href="{{url_for('static', filename='logo-black.svg')}}"
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/svg+xml"
|
type="image/svg+xml"
|
||||||
media="(prefers-color-scheme: light)"/>
|
media="(prefers-color-scheme: light)"/>
|
||||||
<link
|
<link
|
||||||
href="{{url_for('static', filename='images/logo-white.svg')}}"
|
href="{{url_for('static', filename='logo-white.svg')}}"
|
||||||
rel="icon"
|
rel="icon"
|
||||||
type="image/svg+xml"
|
type="image/svg+xml"
|
||||||
media="(prefers-color-scheme: dark)"/>
|
media="(prefers-color-scheme: dark)"/>
|
||||||
|
@ -33,8 +33,7 @@
|
||||||
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
|
<script type="text/javascript" src="{{ ASSET_URL }}"></script>
|
||||||
{% endassets %}
|
{% endassets %}
|
||||||
|
|
||||||
<style>
|
{% block head %}{% endblock %}
|
||||||
</style>
|
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class="notifications"></div>
|
<div class="notifications"></div>
|
||||||
|
@ -62,7 +61,7 @@
|
||||||
<div class="wrapper">
|
<div class="wrapper">
|
||||||
|
|
||||||
<div class="navigation">
|
<div class="navigation">
|
||||||
<img src="{{url_for('static', filename='images/icon.png')}}" alt="Logo" class="logo" onload="imgFade(this)" style="opacity:0;">
|
<img src="{{url_for('static', filename='icon.png')}}" alt="Logo" class="logo" onload="imgFade(this)" style="opacity:0;">
|
||||||
|
|
||||||
<a href="{{url_for('gallery.index')}}" class="navigation-item {% block nav_home %}{% endblock %}">
|
<a href="{{url_for('gallery.index')}}" class="navigation-item {% block nav_home %}{% endblock %}">
|
||||||
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M208,32H80A16,16,0,0,0,64,48V64H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V192h16a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM80,48H208v69.38l-16.7-16.7a16,16,0,0,0-22.62,0L93.37,176H80Zm96,160H48V80H64v96a16,16,0,0,0,16,16h96ZM104,88a16,16,0,1,1,16,16A16,16,0,0,1,104,88Z"></path></svg>
|
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" fill="currentColor" viewBox="0 0 256 256"><path d="M208,32H80A16,16,0,0,0,64,48V64H48A16,16,0,0,0,32,80V208a16,16,0,0,0,16,16H176a16,16,0,0,0,16-16V192h16a16,16,0,0,0,16-16V48A16,16,0,0,0,208,32ZM80,48H208v69.38l-16.7-16.7a16,16,0,0,0-22.62,0L93.37,176H80Zm96,160H48V80H64v96a16,16,0,0,0,16,16h96ZM104,88a16,16,0,1,1,16,16A16,16,0,0,1,104,88Z"></path></svg>
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
{% extends 'layout.html' %}
|
{% extends 'layout.html' %}
|
||||||
|
|
||||||
{% block nav_profile %}navigation-item__selected{% endblock %}
|
{% block nav_profile %}selected{% endblock %}
|
||||||
{% block content %}
|
{% block content %}
|
||||||
<div class="banner">
|
<div class="banner">
|
||||||
<img src="{{ url_for('static', filename='images/bg.svg') }}" onload="imgFade(this)" style="opacity:0;"/>
|
<img src="{{ url_for('static', filename='') }}" onload="imgFade(this)" style="opacity:0;"/>
|
||||||
<span></span>
|
<span></span>
|
||||||
|
|
||||||
<div class="banner-content">
|
<div class="banner-content">
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
width: 100%
|
width: 100%
|
||||||
height: 100%
|
height: 100%
|
||||||
|
|
||||||
background-color: RGB($bg-200)
|
background-color: RGB($bg-300)
|
||||||
|
|
||||||
object-fit: cover
|
object-fit: cover
|
||||||
object-position: center center
|
object-position: center center
|
||||||
|
@ -64,7 +64,7 @@
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
font-size: 1rem
|
font-size: 1rem
|
||||||
font-weight: 500
|
font-weight: 600
|
||||||
line-height: 1
|
line-height: 1
|
||||||
text-align: left
|
text-align: left
|
||||||
|
|
||||||
|
|
|
@ -12,7 +12,6 @@
|
||||||
|
|
||||||
.info-tab
|
.info-tab
|
||||||
width: 100%
|
width: 100%
|
||||||
max-height: 100%
|
|
||||||
|
|
||||||
display: flex
|
display: flex
|
||||||
flex-direction: column
|
flex-direction: column
|
||||||
|
@ -114,7 +113,7 @@
|
||||||
margin: 0
|
margin: 0
|
||||||
padding: 0
|
padding: 0
|
||||||
|
|
||||||
max-width: 100%
|
width: 100%
|
||||||
|
|
||||||
overflow-x: hidden
|
overflow-x: hidden
|
||||||
border-collapse: collapse
|
border-collapse: collapse
|
||||||
|
|
|
@ -72,6 +72,8 @@ $breakpoint: 800px
|
||||||
--animation-smooth: cubic-bezier(0.76, 0, 0.17, 1)
|
--animation-smooth: cubic-bezier(0.76, 0, 0.17, 1)
|
||||||
--animation-bounce: cubic-bezier(.68,-0.55,.27,1.55)
|
--animation-bounce: cubic-bezier(.68,-0.55,.27,1.55)
|
||||||
|
|
||||||
|
--breakpoint: 800px
|
||||||
|
|
||||||
|
|
||||||
@font-face
|
@font-face
|
||||||
font-family: 'Work Sans'
|
font-family: 'Work Sans'
|
||||||
|
|
18
gallery/utils/contrast.py
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
def contrast(background, light, dark, threshold = 0.179):
|
||||||
|
"""
|
||||||
|
Calculate the contrast between two colors
|
||||||
|
background: tuple of (r, g, b) values
|
||||||
|
light: color to use if the background is light
|
||||||
|
dark: color to use if the background is dark
|
||||||
|
threshold: the threshold to use for determining lightness, the default is w3 recommended
|
||||||
|
"""
|
||||||
|
r = background[0]
|
||||||
|
g = background[1]
|
||||||
|
b = background[2]
|
||||||
|
|
||||||
|
# Calculate contrast
|
||||||
|
uicolors = [r / 255, g / 255, b / 255]
|
||||||
|
c = [col / 12.92 if col <= 0.03928 else ((col + 0.055) / 1.055) ** 2.4 for col in uicolors]
|
||||||
|
l = (0.2126 * c[0]) + (0.7152 * c[1]) + (0.0722 * c[2])
|
||||||
|
|
||||||
|
return light if l > threshold else dark
|
16
run.py
|
@ -6,13 +6,15 @@ from setup.configuration import Configuration
|
||||||
|
|
||||||
|
|
||||||
print("""
|
print("""
|
||||||
___ _ _
|
:::::::: :::: ::: ::: ::: ::: ::: ::::::::: ::::::::: ::::::::
|
||||||
/ _ \\ _ __ | |_ _| | ___ __ _ ___
|
:+: :+: :+:+: :+: :+: :+: :+: :+: :+: :+: :+: :+: :+:
|
||||||
| | | | '_ \\| | | | | | / _ \\/ _` / __|
|
+:+ +:+ :+:+:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+ +:+
|
||||||
| |_| | | | | | |_| | |__| __/ (_| \\__ \\
|
+#+ +:+ +#+ +:+ +#+ +#+ +#++: +#+ +#++:++# :#: +#++:++#++
|
||||||
\\___/|_| |_|_|\\__, |_____\\___|\\__, |___/
|
+#+ +#+ +#+ +#+#+# +#+ +#+ +#+ +#+ +#+ +#+# +#+
|
||||||
|___/ |___/
|
#+# #+# #+# #+#+# #+# #+# #+# #+# #+# #+# #+# #+#
|
||||||
Created by Fluffy Bean - Version 23.03.25
|
######## ### #### ########## ### ########## ######### ######### ########
|
||||||
|
|
||||||
|
Created by Fluffy Bean - Version 23.03.25
|
||||||
""")
|
""")
|
||||||
|
|
||||||
|
|
||||||
|
|