diff --git a/README.md b/README.md index ac0254c..35218ee 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,7 @@ +> **IMPORTANT** +> This project is maintained irregularly and is still in rapid development. +> Things maybe here now, but not again in a few weeks +
diff --git a/onlylegs/api.py b/onlylegs/api.py index 44c187c..0c68f82 100644 --- a/onlylegs/api.py +++ b/onlylegs/api.py @@ -3,7 +3,6 @@ Onlylegs - API endpoints """ import os import pathlib -import re import logging from uuid import uuid4 @@ -23,88 +22,13 @@ from flask_login import login_required, current_user from colorthief import ColorThief from onlylegs.extensions import db -from onlylegs.models import Users, Pictures, Exif +from onlylegs.models import Pictures, Exif from onlylegs.utils.generate_image import generate_thumbnail blueprint = Blueprint("api", __name__, url_prefix="/api") -@blueprint.route("/account/picture/", methods=["POST"]) -@login_required -def account_picture(user_id): - """ - Returns the profile of a user - """ - user = db.get_or_404(Users, user_id) - file = request.files.get("file", None) - - # If no image is uploaded, return 404 error - if not file: - return jsonify({"error": "No file uploaded"}), 400 - if user.id != current_user.id: - return jsonify({"error": "You are not allowed to do this, go away"}), 403 - - # Get file extension, generate random name and set file path - img_ext = pathlib.Path(file.filename).suffix.replace(".", "").lower() - img_name = str(user.id) - img_path = os.path.join(current_app.config["PFP_FOLDER"], img_name + "." + img_ext) - - # Check if file extension is allowed - if img_ext not in current_app.config["ALLOWED_EXTENSIONS"].keys(): - logging.info("File extension not allowed: %s", img_ext) - return jsonify({"error": "File extension not allowed"}), 403 - - if user.picture: - # Delete cached files and old image - os.remove(os.path.join(current_app.config["PFP_FOLDER"], user.picture)) - cache_name = user.picture.rsplit(".")[0] - for cache_file in pathlib.Path(current_app.config["CACHE_FOLDER"]).glob( - cache_name + "*" - ): - os.remove(cache_file) - - # Save file - try: - file.save(img_path) - except OSError as err: - logging.info("Error saving file %s because of %s", img_path, err) - return jsonify({"error": "Error saving file"}), 500 - - img_colors = ColorThief(img_path).get_color() - - # Save to database - user.colour = img_colors - user.picture = str(img_name + "." + img_ext) - db.session.commit() - - return jsonify({"message": "File uploaded"}), 200 - - -@blueprint.route("/account/username/", methods=["POST"]) -@login_required -def account_username(user_id): - """ - Returns the profile of a user - """ - user = db.get_or_404(Users, user_id) - new_name = request.form["name"] - - username_regex = re.compile(r"\b[A-Za-z0-9._-]+\b") - - # Validate the form - if not new_name or not username_regex.match(new_name): - return jsonify({"error": "Username is invalid"}), 400 - if user.id != current_user.id: - return jsonify({"error": "You are not allowed to do this, go away"}), 403 - - # Save to database - user.username = new_name - db.session.commit() - - return jsonify({"message": "Username changed"}), 200 - - @blueprint.route("/media/", methods=["GET"]) def media(path): """ diff --git a/onlylegs/app.py b/onlylegs/app.py index 0dd4349..5e1e632 100644 --- a/onlylegs/app.py +++ b/onlylegs/app.py @@ -1,136 +1,179 @@ """ Onlylegs Gallery -This is the main app file, it loads all the other files and sets up the app +This is the main app file, checks on app stability and runs all da shit """ import os import logging +from flask import Flask, render_template, abort, request +from werkzeug.security import generate_password_hash +from werkzeug.exceptions import HTTPException from flask_assets import Bundle from flask_migrate import init as migrate_init -from flask import Flask, render_template, abort -from werkzeug.exceptions import HTTPException -from werkzeug.security import generate_password_hash from onlylegs.extensions import db, migrate, login_manager, assets, compress, cache -from onlylegs.config import INSTANCE_DIR, MIGRATIONS_DIR -from onlylegs.models import Users -from onlylegs.views import ( - index as view_index, - image as view_image, - group as view_group, - settings as view_settings, - profile as view_profile, +from onlylegs.config import ( + INSTANCE_DIR, + MIGRATIONS_DIR, + APPLICATION_ROOT, + DATABASE_NAME, ) -from onlylegs import api -from onlylegs import auth as view_auth -from onlylegs import filters +from onlylegs.models import Users + +from onlylegs.views.index import blueprint as view_index +from onlylegs.views.image import blueprint as view_image +from onlylegs.views.group import blueprint as view_group +from onlylegs.views.settings import blueprint as view_settings +from onlylegs.views.profile import blueprint as view_profile +from onlylegs.api import blueprint as api +from onlylegs.auth import blueprint as view_auth +from onlylegs.filters import blueprint as filters + + +def set_logger(): + file_name = os.path.join(APPLICATION_ROOT, "only.log") + logging_level = logging.INFO + date_format = "%Y-%m-%d %H:%M:%S" + log_format = "%(asctime)s %(levelname)s %(name)s %(threadName)s : %(message)s" + + logging.getLogger("werkzeug").disabled = True + logging.basicConfig( + filename=file_name, + level=logging_level, + datefmt=date_format, + format=log_format, + encoding="utf-8", + ) + + +def create_db(): + path_to_database = os.path.join(INSTANCE_DIR, DATABASE_NAME) + + if not os.path.exists(path_to_database): + print("Database not found, creating...") + + user = Users( + username=app.config["ADMIN_CONF"]["username"], + email=app.config["ADMIN_CONF"]["email"], + password=generate_password_hash("changeme!", method="scrypt"), + ) + + with app.app_context(): + db.create_all() + db.session.add(user) + db.session.commit() + migrate_init(directory=MIGRATIONS_DIR) + + print( + "####################################################", + "# DEFAULT ADMIN USER GENERATED WITH GIVEN USERNAME #", + '# THE DEFAULT PASSWORD "changeme!" HAS BEEN USED, #', + "# PLEASE RESET IT IN THE SETTINGS! #", + "####################################################", + sep="\n", + ) + + return + + print("Database found, continuing...") + + +def set_login_manager(): + """ + LOGIN MANAGER + can also set session_protection to "strong" + this would protect against session hijacking + """ + login_manager.init_app(app) + login_manager.login_view = "onlylegs.index" + + @login_manager.user_loader + def load_user(user_id): + return Users.query.filter_by(alt_id=user_id).first() + + @login_manager.unauthorized_handler + def unauthorized(): + error = 401 + msg = "You are not authorized to view this page!!!!" + return render_template("error.html", error=error, msg=msg), error + + +def page_assets(): + """ + ASSETS + bundles all the sass and js and minifies them + """ + assets.init_app(app) + + page_scripts = Bundle( + "js/*.js", filters="jsmin", output="gen/main.js", depends="js/*.js" + ) + page_styling = Bundle( + "sass/style.sass", + filters="libsass, cssmin", + output="gen/styles.css", + depends="sass/**/*.sass", + ) + + assets.register("scripts", page_scripts) + assets.register("styles", page_styling) + + +def handle_errors(): + """ + ERROR HANDLER + handles all the errors and returns a nice error page + Code errors are displayed as 500 errors so no + sensitive information is leaked + """ + + @app.errorhandler(Exception) + def error_page(err): + if not isinstance(err, HTTPException): + abort(500) + + if request.method == "GET": + return ( + render_template("error.html", error=err.code, msg=err.description), + err.code, + ) + else: + return str(err.code) + ": " + err.description, err.code + + +def register_blueprints(): + """ + BLUEPRINTS + registers all the blueprints + """ + app.register_blueprint(view_auth) + app.register_blueprint(view_index) + app.register_blueprint(view_image) + app.register_blueprint(view_group) + app.register_blueprint(view_profile) + app.register_blueprint(view_settings) + app.register_blueprint(api) + app.register_blueprint(filters) + app = Flask(__name__, instance_path=INSTANCE_DIR) app.config.from_pyfile("config.py") -# DATABASE db.init_app(app) migrate.init_app(app, db, directory=MIGRATIONS_DIR) -# If database file doesn't exist, create it -if not os.path.exists(os.path.join(INSTANCE_DIR, "gallery.sqlite3")): - print("Creating database") - with app.app_context(): - db.create_all() +create_db() - register_user = Users( - username=app.config["ADMIN_CONF"]["username"], - email=app.config["ADMIN_CONF"]["email"], - password=generate_password_hash("changeme!", method="sha256"), - ) - db.session.add(register_user) - db.session.commit() +set_logger() +set_login_manager() +page_assets() +handle_errors() +register_blueprints() - print( - """ -#################################################### -# DEFAULT ADMIN USER GENERATED WITH GIVEN USERNAME # -# THE DEFAULT PASSWORD "changeme!" HAS BEEN USED, # -# PLEASE UPDATE IT IN THE SETTINGS! # -#################################################### - """ - ) - -# Check if migrations directory exists, if not create it -with app.app_context(): - if not os.path.exists(MIGRATIONS_DIR): - print("Creating migrations directory") - migrate_init(directory=MIGRATIONS_DIR) - -# LOGIN MANAGER -# can also set session_protection to "strong" -# this would protect against session hijacking -login_manager.init_app(app) -login_manager.login_view = "onlylegs.index" - - -@login_manager.user_loader -def load_user(user_id): - return Users.query.filter_by(alt_id=user_id).first() - - -@login_manager.unauthorized_handler -def unauthorized(): - error = 401 - msg = "You are not authorized to view this page!!!!" - return render_template("error.html", error=error, msg=msg), error - - -# ERROR HANDLERS -@app.errorhandler(Exception) -def error_page(err): - """ - Error handlers, if the error is not a HTTP error, return 500 - """ - if not isinstance(err, HTTPException): - abort(500) - return ( - render_template("error.html", error=err.code, msg=err.description), - err.code, - ) - - -# ASSETS -assets.init_app(app) - -scripts = Bundle( - "js/*.js", output="gen/js.js", depends="js/*.js" -) # filter jsmin is broken :c -styles = Bundle( - "sass/style.sass", - filters="libsass, cssmin", - output="gen/styles.css", - depends="sass/**/*.sass", -) - -assets.register("scripts", scripts) -assets.register("styles", styles) - -# BLUEPRINTS -app.register_blueprint(view_auth.blueprint) -app.register_blueprint(view_index.blueprint) -app.register_blueprint(view_image.blueprint) -app.register_blueprint(view_group.blueprint) -app.register_blueprint(view_profile.blueprint) -app.register_blueprint(view_settings.blueprint) - -app.register_blueprint(api.blueprint) - -# FILTERS -app.register_blueprint(filters.blueprint) - -# CACHE AND COMPRESS cache.init_app(app) compress.init_app(app) -# Yupee! We got there :3 -print("Done!") logging.info("Gallery started successfully!") diff --git a/onlylegs/auth.py b/onlylegs/auth.py index c3d0698..4394b31 100644 --- a/onlylegs/auth.py +++ b/onlylegs/auth.py @@ -105,5 +105,5 @@ def logout(): Clear the current session, including the stored user id """ logout_user() - flash(["Goodbye!!!", "4"]) + flash("Goodbye!!!", "4") return redirect(url_for("gallery.index")) diff --git a/onlylegs/config.py b/onlylegs/config.py index 06cd271..a24c24d 100644 --- a/onlylegs/config.py +++ b/onlylegs/config.py @@ -6,42 +6,43 @@ import platformdirs import importlib.metadata from dotenv import load_dotenv from yaml import safe_load +from utils import startup + + +# App Sanity Checks +startup.check_dirs() +startup.check_env() +startup.check_conf() # Set dirs -user_dir = platformdirs.user_config_dir("onlylegs") -instance_dir = os.path.join(user_dir, "instance") +APPLICATION_ROOT = platformdirs.user_config_dir("onlylegs") +UPLOAD_FOLDER = os.path.join(APPLICATION_ROOT, "media", "uploads") +MEDIA_FOLDER = os.path.join(APPLICATION_ROOT, "media") +CACHE_FOLDER = os.path.join(APPLICATION_ROOT, "media", "cache") +PFP_FOLDER = os.path.join(APPLICATION_ROOT, "media", "pfp") +BANNER_FOLDER = os.path.join(APPLICATION_ROOT, "media", "banner") -# Load environment variables -# print("Loading environment variables...") -load_dotenv(os.path.join(user_dir, ".env")) +# Load env and config files +load_dotenv(os.path.join(APPLICATION_ROOT, ".env")) -# Load config from user dir -# print("Loading config...") -with open(os.path.join(user_dir, "conf.yml"), encoding="utf-8", mode="r") as file: +config_file = os.path.join(APPLICATION_ROOT, "conf.yml") +with open(config_file, encoding="utf-8", mode="r") as file: conf = safe_load(file) - # Flask config SECRET_KEY = os.environ.get("FLASK_SECRET") -SQLALCHEMY_DATABASE_URI = "sqlite:///gallery.sqlite3" MAX_CONTENT_LENGTH = 1024 * 1024 * conf["upload"]["max-size"] ALLOWED_EXTENSIONS = conf["upload"]["allowed-extensions"] +APP_VERSION = importlib.metadata.version("OnlyLegs") + +# Database +DATABASE_NAME = "gallery.sqlite3" +SQLALCHEMY_DATABASE_URI = "sqlite:///" + DATABASE_NAME +INSTANCE_DIR = os.path.join(APPLICATION_ROOT, "instance") +MIGRATIONS_DIR = os.path.join(INSTANCE_DIR, "migrations") # Pass YAML config to app ADMIN_CONF = conf["admin"] UPLOAD_CONF = conf["upload"] WEBSITE_CONF = conf["website"] - -# Directories -UPLOAD_FOLDER = os.path.join(user_dir, "media", "uploads") -CACHE_FOLDER = os.path.join(user_dir, "media", "cache") -PFP_FOLDER = os.path.join(user_dir, "media", "pfp") -MEDIA_FOLDER = os.path.join(user_dir, "media") - -# Database -INSTANCE_DIR = instance_dir -MIGRATIONS_DIR = os.path.join(INSTANCE_DIR, "migrations") - -# App -APP_VERSION = importlib.metadata.version("OnlyLegs") diff --git a/onlylegs/filters.py b/onlylegs/filters.py index 765003b..1f4515b 100644 --- a/onlylegs/filters.py +++ b/onlylegs/filters.py @@ -4,6 +4,7 @@ Custom Jinja2 filters """ from flask import Blueprint from onlylegs.utils import colour as colour_utils +import colorsys blueprint = Blueprint("filters", __name__) @@ -17,4 +18,32 @@ def colour_contrast(colour): "color: var(--fg-white);" or "color: var(--fg-black);" """ colour_obj = colour_utils.Colour(colour) - return "rgb(var(--fg-black));" if colour_obj.is_light() else "rgb(var(--fg-white));" + return ( + "var(--foreground-black);" + if colour_obj.is_light() + else "var(--foreground-white);" + ) + + +@blueprint.app_template_filter() +def hsl_hue(rgb): + """ + Pass in a rgb value and will return the hue value + """ + r, g, b = rgb + r /= 255 + g /= 255 + b /= 255 + return colorsys.rgb_to_hls(r, g, b)[0] * 360 + + +@blueprint.app_template_filter() +def hsl_saturation(rgb): + """ + Pass in a rgb value and will return the saturation value + """ + r, g, b = rgb + r /= 255 + g /= 255 + b /= 255 + return colorsys.rgb_to_hls(r, g, b)[1] * 100 diff --git a/onlylegs/models.py b/onlylegs/models.py index 565b130..2aca5c0 100644 --- a/onlylegs/models.py +++ b/onlylegs/models.py @@ -64,7 +64,7 @@ class Exif(db.Model): picture_id = db.Column(db.Integer, db.ForeignKey("pictures.id")) key = db.Column(db.String, nullable=False) - value = db.Column(db.String, nullable=False) + value = db.Column(db.PickleType, nullable=False) class Albums(db.Model): diff --git a/onlylegs/static/js/imagePage.js b/onlylegs/static/js/imagePage.js index a1eb24c..43dd207 100644 --- a/onlylegs/static/js/imagePage.js +++ b/onlylegs/static/js/imagePage.js @@ -14,47 +14,6 @@ function imageFullscreen() { } function imageShowOptionsPopup(obj) { - // let title = 'Options'; - // let subtitle = null; - // - // let body = document.createElement('div'); - // body.style.cssText = 'display: flex; flex-direction: column; gap: 0.5rem;'; - // - // let copyBtn = document.createElement('button'); - // copyBtn.classList.add('btn-block'); - // copyBtn.innerHTML = 'Copy URL'; - // copyBtn.onclick = () => { - // copyToClipboard(window.location.href) - // } - // - // let downloadBtn = document.createElement('a'); - // downloadBtn.classList.add('btn-block'); - // downloadBtn.innerHTML = 'Download'; - // downloadBtn.href = '/api/media/uploads/' + image_data["filename"]; - // downloadBtn.download = ''; - // - // body.appendChild(copyBtn); - // body.appendChild(downloadBtn); - // - // if (image_data["owner"]) { - // let editBtn = document.createElement('button'); - // editBtn.classList.add('btn-block'); - // editBtn.classList.add('critical'); - // editBtn.innerHTML = 'Edit'; - // editBtn.onclick = imageEditPopup; - // - // let deleteBtn = document.createElement('button'); - // deleteBtn.classList.add('btn-block'); - // deleteBtn.classList.add('critical'); - // deleteBtn.innerHTML = 'Delete'; - // deleteBtn.onclick = imageDeletePopup; - // - // body.appendChild(editBtn); - // body.appendChild(deleteBtn); - // } - // - // popupShow(title, subtitle, body, [popupCancelButton]); - showContextMenu(obj, [ { 'value': 'Edit', @@ -62,7 +21,8 @@ function imageShowOptionsPopup(obj) { dissmissContextMenu(); imageEditPopup(); }, - 'type': 'critical' + 'type': 'critical', + 'icon': '' }, { 'value': 'Delete', @@ -70,7 +30,8 @@ function imageShowOptionsPopup(obj) { dissmissContextMenu(); imageDeletePopup(); }, - 'type': 'critical' + 'type': 'critical', + 'icon': '' } ], 'button') } diff --git a/onlylegs/static/js/uploadTab.js b/onlylegs/static/js/uploadTab.js index a27e57f..2526a8a 100644 --- a/onlylegs/static/js/uploadTab.js +++ b/onlylegs/static/js/uploadTab.js @@ -141,41 +141,14 @@ function clearUpload() { } -// function createJob(file) { -// jobContainer = document.createElement("div"); -// jobContainer.classList.add("job"); - -// jobStatus = document.createElement("span"); -// jobStatus.classList.add("job__status"); -// jobStatus.innerHTML = "Uploading..."; - -// jobProgress = document.createElement("span"); -// jobProgress.classList.add("progress"); - -// jobImg = document.createElement("img"); -// jobImg.src = URL.createObjectURL(file); - -// jobImgFilter = document.createElement("span"); -// jobImgFilter.classList.add("img-filter"); - -// jobContainer.appendChild(jobStatus); -// jobContainer.appendChild(jobProgress); -// jobContainer.appendChild(jobImg); -// jobContainer.appendChild(jobImgFilter); - -// return jobContainer; -// } - - document.addEventListener('DOMContentLoaded', () => { // Function to upload images const uploadTab = document.querySelector(".upload-panel"); - if (!uploadTab) { return; } // If upload tab doesn't exist, don't run this code :3 + if (!uploadTab) { return } const uploadTabDrag = uploadTab.querySelector("#dragIndicator"); const uploadForm = uploadTab.querySelector('#uploadForm'); - // let jobList = document.querySelector(".upload-jobs"); const fileDrop = uploadForm.querySelector('.fileDrop-block'); const fileDropTitle = fileDrop.querySelector('.status'); @@ -228,54 +201,6 @@ document.addEventListener('DOMContentLoaded', () => { formData.append("description", fileDescription.value); formData.append("tags", fileTags.value); - // jobItem = createJob(fileUpload.files[0]); - // jobStatus = jobItem.querySelector(".job__status"); - - // Upload the information - // $.ajax({ - // url: '/api/upload', - // type: 'post', - // data: formData, - // contentType: false, - // processData: false, - // beforeSend: function () { - // // Add job to list - // jobList.appendChild(jobItem); - // }, - // success: function (response) { - // jobItem.classList.add("success"); - // jobStatus.innerHTML = "Uploaded successfully"; - // if (!document.querySelector(".upload-panel").classList.contains("open")) { - // addNotification("Image uploaded successfully", 1); - // } - // }, - // error: function (response) { - // jobItem.classList.add("critical"); - // switch (response.status) { - // case 500: - // jobStatus.innerHTML = "Server exploded, F's in chat"; - // break; - // case 400: - // case 404: - // jobStatus.innerHTML = "Error uploading. Blame yourself"; - // break; - // case 403: - // jobStatus.innerHTML = "None but devils play past here..."; - // break; - // case 413: - // jobStatus.innerHTML = "File too large!!!!!!"; - // break; - // default: - // jobStatus.innerHTML = "Error uploading file, blame someone"; - // break; - // } - // if (!document.querySelector(".upload-panel").classList.contains("open")) { - // addNotification("Error uploading file", 2); - // } - // }, - // }); - - fetch('/api/media/upload', { method: 'POST', body: formData diff --git a/onlylegs/static/sass/components/banner.sass b/onlylegs/static/sass/components/banner.sass index 037e38d..724a5ee 100644 --- a/onlylegs/static/sass/components/banner.sass +++ b/onlylegs/static/sass/components/banner.sass @@ -2,7 +2,7 @@ .banner-small width: 100% position: relative - color: RGB($fg-white) + color: var(--foreground-white) .link padding: 0.1rem 0.3rem @@ -10,15 +10,15 @@ text-decoration: none font-weight: 500 - background-color: RGB($fg-white) - color: RGB($fg-black) - border-radius: $rad-inner + background-color: var(--foreground-white) + color: var(--foreground-black) + border-radius: calc(var(--radius) / 2) cursor: pointer &:hover - background-color: RGB($fg-black) - color: RGB($fg-white) + background-color: var(--foreground-black) + color: var(--foreground-white) .banner height: 30rem @@ -26,7 +26,8 @@ img position: absolute - inset: 0 + top: 0 + left: 0 width: 100% height: 100% @@ -43,7 +44,7 @@ width: 100% height: 100% - background: linear-gradient(to right, RGB($bg-100), transparent) + background: linear-gradient(to right, var(--background-100), transparent 80%, var(--background-100) 100%) z-index: +1 @@ -79,7 +80,7 @@ font-size: 6.9rem font-weight: 700 - color: RGB($primary) + color: var(--primary) .banner-info grid-area: info @@ -104,8 +105,8 @@ width: 6.9rem height: 6.9rem - background-color: RGB($primary) - border-radius: $rad + background-color: var(--primary) + border-radius: var(--rad) overflow: hidden .banner-small @@ -144,7 +145,7 @@ font-weight: 700 font-size: 1.5rem - color: RGB($primary) + color: var(--primary) .banner-info margin-right: 0.6rem @@ -156,7 +157,7 @@ margin-left: auto width: auto -@media (max-width: $breakpoint) +@media (max-width: 800px) .banner, .banner-small &::after @@ -168,7 +169,7 @@ max-height: 30vh .banner-filter - background: linear-gradient(to bottom, RGB($bg-100), transparent) + background: linear-gradient(to top, var(--background-100), transparent) .banner-content padding: 0.5rem @@ -192,7 +193,7 @@ display: none .pill-row - margin-top: 0rem + margin-top: 0 .banner-picture margin: 0 auto diff --git a/onlylegs/static/sass/components/buttons/block.sass b/onlylegs/static/sass/components/buttons/block.sass index f16f96e..7994647 100644 --- a/onlylegs/static/sass/components/buttons/block.sass +++ b/onlylegs/static/sass/components/buttons/block.sass @@ -1,14 +1,3 @@ -@mixin btn-block($color) - background-color: RGBA($color, 0.1) - color: RGB($color) - // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) - - &:hover, &:focus-visible - background-color: RGBA($color, 0.15) - color: RGB($color) - // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($color, 0.2) - - .btn-block padding: 0.4rem 0.7rem @@ -26,19 +15,17 @@ font-weight: 400 text-align: center - background-color: RGBA($white, 0.1) - color: RGB($white) + background-color: var(--white-transparent) + color: var(--white) border: none - border-radius: $rad-inner - // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) + border-radius: calc(var(--rad) / 2) outline: none cursor: pointer transition: background-color 0.15s ease-in-out, color 0.15s ease-in-out, box-shadow 0.15s ease-in-out &:hover, &:focus-visible - background-color: RGBA($white, 0.2) - // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) + background-color: var(--white-transparent) &.transparent background-color: transparent @@ -47,20 +34,50 @@ text-decoration: underline &.primary - @include btn-block($primary) - &.critical - @include btn-block($critical) - &.warning - @include btn-block($warning) + background-color: var(--primary-transparent) + color: var(--primary) + + &:hover, &:focus-visible + background-color: var(--primary) + color: var(--black) &.success - @include btn-block($success) + background-color: var(--success-transparent) + color: var(--success) + + &:hover, &:focus-visible + background-color: var(--success) + color: var(--black) + &.warning + background-color: var(--warning-transparent) + color: var(--warning) + + &:hover, &:focus-visible + background-color: var(--warning) + color: var(--black) + &.critical + background-color: var(--danger-transparent) + color: var(--danger) + + &:hover, &:focus-visible + background-color: var(--danger) + color: var(--black) &.info - @include btn-block($info) + background-color: var(--info-transparent) + color: var(--info) + + &:hover, &:focus-visible + background-color: var(--info) + color: var(--black) &.black - @include btn-block($black) + background-color: var(--black-transparent) + color: var(--white) + + &:hover, &:focus-visible + background-color: var(--black) + color: var(--white) &.disabled, &:disabled - color: RGB($fg-dim) + color: var(--foreground-gray) cursor: unset .input-checkbox @@ -77,7 +94,7 @@ font-weight: 400 text-align: left - color: RGB($fg-white) + color: var(--foreground-white) .input-block padding: 0.4rem 0.7rem @@ -95,28 +112,32 @@ font-weight: 400 text-align: left - background-color: RGBA($white, 0.1) - color: RGB($white) + background-color: var(--white-transparent) + color: var(--white) border: none - border-bottom: 3px solid RGBA($white, 0.1) - border-radius: $rad-inner - // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) + border-bottom: 3px solid var(--white-transparent) + border-radius: calc(var(--rad) / 2) outline: none cursor: pointer transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out &:not(:focus):not([value=""]):not(:placeholder-shown) - border-color: RGBA($white, 0.3) + border-color: var(--white-transparent) &:hover - border-color: RGBA($white, 0.3) + border-color: var(--white-transparent) &:focus - border-color: RGB($primary) + border-color: var(--primary) &.black - @include btn-block($black) + background-color: var(--black-transparent) + color: var(--white) + + &:hover, &:focus-visible + background-color: var(--black) + color: var(--white) .fileDrop-block padding: 1rem 1.25rem @@ -136,11 +157,10 @@ font-weight: 400 text-align: center - background-color: RGBA($white, 0.1) - color: RGB($white) + background-color: var(--white-transparent) + color: var(--white) border: none - border-radius: $rad-inner - // box-shadow: 0 1px 0 RGBA($black, 0.2), 0 -1px 0 RGBA($white, 0.2) + border-radius: calc(var(--rad) / 2) outline: none cursor: pointer @@ -164,24 +184,21 @@ overflow: hidden &:hover, &:focus-visible - background-color: RGBA($white, 0.2) - color: RGB($white) - // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) + background-color: var(--white-transparent) + color: var(--white) &.active - background-color: RGBA($primary, 0.2) - color: RGB($primary) - // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($primary, 0.3) + background-color: var(--primary-transparent) + color: var(--primary) &.edging - background-color: RGBA($white, 0.2) - color: RGB($white) - // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($white, 0.3) + background-color: var(--white-transparent) + color: var(--white) input - display: none // So it doesnt get in the way of the drop as that breaks things + // So it doesnt get in the way of the drop as that breaks things + display: none &.error - background-color: RGBA($critical, 0.2) - color: RGB($critical) - // box-shadow: 0 1px 0 RGBA($black, 0.3), 0 -1px 0 RGBA($critical, 0.3) + background-color: var(--danger) + color: var(--black) diff --git a/onlylegs/static/sass/components/buttons/info-button.sass b/onlylegs/static/sass/components/buttons/info-button.sass deleted file mode 100644 index 4805c59..0000000 --- a/onlylegs/static/sass/components/buttons/info-button.sass +++ /dev/null @@ -1,39 +0,0 @@ -.info-button - margin: 0 - padding: 0 - - width: auto - height: auto - - position: fixed - bottom: 0.75rem - right: -3rem - - display: flex - justify-content: center - align-items: center - - background-color: RGB($bg-300) - color: RGB($fg-white) - border-radius: $rad - border: none - opacity: 0 - - z-index: 20 - cursor: pointer - transition: all 0.2s cubic-bezier(.86, 0, .07, 1) - - i - margin: 0.5rem - font-size: 1.25rem - - &:hover - color: RGB($info) - - &.show - right: 0.75rem - opacity: 1 - -@media (max-width: $breakpoint) - .info-button - bottom: 4.25rem diff --git a/onlylegs/static/sass/components/buttons/pill.sass b/onlylegs/static/sass/components/buttons/pill.sass index 3767c01..25fc812 100644 --- a/onlylegs/static/sass/components/buttons/pill.sass +++ b/onlylegs/static/sass/components/buttons/pill.sass @@ -16,9 +16,8 @@ display: flex - background-color: RGB($bg-200) - border-radius: $rad - // box-shadow: 0 1px 0 RGB($bg-100), 0 -1px 0 RGB($bg-300) + background-color: var(--background-200) + border-radius: var(--rad) .pill-text margin: 0 @@ -37,9 +36,9 @@ font-size: 1rem font-weight: 400 - background-color: RGB($bg-200) - color: RGB($fg-white) - border-radius: $rad + background-color: var(--background-200) + color: var(--foreground-white) + border-radius: var(--rad) .pill-item margin: 0 @@ -58,42 +57,41 @@ border: none background-color: transparent - color: RGB($fg-white) + color: var(--foreground-white) i font-size: 1.25rem &:hover cursor: pointer + color: var(--primary) - color: RGB($primary) - - &.disabled, &:disabled - color: RGB($fg-dim) - cursor: unset + &:disabled, &[disabled], &.disabled + color: var(--foreground-gray) + cursor: default .pill__critical - color: RGB($critical) + color: var(--danger) span - background: RGB($critical) - color: RGB($fg-white) + background: var(--danger) + color: var(--foreground-white) i - color: RGB($critical) + color: var(--danger) &:hover - color: RGB($fg-white) + color: var(--foreground-white) .pill__info - color: RGB($info) + color: var(--info) span - color: RGB($info) + color: var(--info) &:hover - color: RGB($fg-white) + color: var(--foreground-white) -@media (max-width: $breakpoint) +@media (max-width: var(--breakpoint)) .tool-tip display: none \ No newline at end of file diff --git a/onlylegs/static/sass/components/buttons/top-of-page.sass b/onlylegs/static/sass/components/buttons/top-of-page.sass index 918356d..dd356ba 100644 --- a/onlylegs/static/sass/components/buttons/top-of-page.sass +++ b/onlylegs/static/sass/components/buttons/top-of-page.sass @@ -13,9 +13,9 @@ justify-content: center align-items: center - background-color: RGB($bg-300) - color: RGB($fg-white) - border-radius: $rad + background-color: var(--background-100) + color: var(--foreground-white) + border-radius: calc(var(--rad) / 2) border: none opacity: 0 @@ -28,12 +28,12 @@ font-size: 1.25rem &:hover - color: RGB($primary) + color: var(--primary) &.show right: 0.75rem opacity: 1 -@media (max-width: $breakpoint) +@media (max-width: 800px) .top-of-page bottom: 4.25rem diff --git a/onlylegs/static/sass/components/context-menu.sass b/onlylegs/static/sass/components/context-menu.sass index 15ab78b..8d4b4aa 100644 --- a/onlylegs/static/sass/components/context-menu.sass +++ b/onlylegs/static/sass/components/context-menu.sass @@ -25,13 +25,13 @@ align-items: flex-start gap: 0.25rem - background-color: RGB($bg-300) - border: 1px solid RGB($bg-200) + background-color: var(--background-300) + border: 1px solid var(--background-200) border-radius: 6px overflow: hidden - transition: transform 0.2s ease-in-out, opacity 0.2s ease-in-out + transition: transform 0.35s var(--animation-bounce), opacity 0.35s var(--animation-bounce) transform-origin: center center opacity: 0.5 transform: scale(0, 0) @@ -46,7 +46,7 @@ text-align: center font-size: 1.2rem font-weight: 400 - color: RGB($fg-white) + color: var(--foreground-white) .contextMenuItem margin: 0 @@ -61,22 +61,22 @@ align-items: center gap: 0.5rem - background-color: RGB($bg-300) - color: RGB($fg-white) + background-color: var(--background-300) + color: var(--foreground-white) border: none border-radius: 3px cursor: pointer .contextMenuItem:hover - background-color: RGB($bg-200) + background-color: var(--background-200) .contextMenuItem__critical - color: RGB($critical) + color: var(--danger) .contextMenuItem__warning - color: RGB($warning) + color: var(--warning) .contextMenuItem__success - color: RGB($success) + color: var(--success) .contextMenuItem__info - color: RGB($primary) + color: var(--primary) .contextMenuText margin: 0 @@ -104,7 +104,7 @@ height: 1px border: none - background-color: RGB($bg-200) + background-color: var(--background-200) .contextMenu__show opacity: 1 diff --git a/onlylegs/static/sass/components/gallery.sass b/onlylegs/static/sass/components/gallery.sass index 87d63ca..081af88 100644 --- a/onlylegs/static/sass/components/gallery.sass +++ b/onlylegs/static/sass/components/gallery.sass @@ -12,26 +12,21 @@ font-weight: 700 .gallery-grid - margin: 0 - padding: 0.35rem - width: 100% display: grid grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)) + gap: 0.5rem .gallery-item - margin: 0.35rem - padding: 0 - position: relative - border-radius: $rad-inner - box-shadow: 0 0.15rem 0.4rem 0.1rem RGBA($bg-100, 0.4) + border-radius: calc(var(--rad) / 2) + box-shadow: 0 0.15rem 0.4rem 0.1rem var(--black-transparent) box-sizing: border-box overflow: hidden - transition: box-shadow 0.2s cubic-bezier(.79, .14, .15, .86) + transition: box-shadow 0.2s var(--animation-smooth) .image-filter margin: 0 @@ -48,11 +43,11 @@ flex-direction: column justify-content: flex-end - background-image: linear-gradient(to top, rgba($bg-100, 0.69), transparent) + background-image: linear-gradient(to top, var(--black-transparent), transparent) opacity: 0 // hide z-index: +4 - transition: opacity 0.2s cubic-bezier(.79, .14, .15, .86) + transition: opacity 0.2s var(--animation-smooth) .image-title, .image-subtitle @@ -63,8 +58,8 @@ text-overflow: ellipsis overflow: hidden - color: RGB($fg-white) - text-shadow: 0px 0px 2px RGB($fg-black) + color: var(--foreground-white) + text-shadow: 0 0 2px var(--foreground-black) .image-title font-size: 0.9rem @@ -84,21 +79,20 @@ object-fit: cover object-position: center - background-color: RGB($bg-bright) + background-color: var(--background-bright) &:hover - box-shadow: 0 0.2rem 0.4rem 0.1rem RGBA($bg-100, 0.6) + box-shadow: 0 0.2rem 0.4rem 0.1rem var(--black-transparent) .image-filter opacity: 1 .group-item - margin: 0.35rem padding: 0 position: relative - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) box-sizing: border-box overflow: hidden @@ -119,7 +113,7 @@ flex-direction: column justify-content: flex-end - background-image: linear-gradient(to top, rgba($bg-100, 0.8), transparent) + background-image: linear-gradient(to top, var(--black-transparent), transparent) z-index: +4 @@ -132,8 +126,8 @@ text-overflow: ellipsis overflow: hidden - color: RGB($fg-white) - text-shadow: 0px 0px 2px RGB($fg-black) + color: var(--foreground-white) + text-shadow: 0 0 2px var(--foreground-black) .image-title font-size: 0.9rem @@ -165,11 +159,11 @@ object-fit: cover object-position: center - background-color: RGB($bg-bright) - border-radius: $rad-inner - box-shadow: 0 0 0.4rem 0.25rem RGBA($bg-100, 0.1) + background-color: var(--background-800) + border-radius: calc(var(--rad) / 2) + box-shadow: 0 0 0.4rem 0.25rem var(--black-transparent) - transition: transform 0.2s cubic-bezier(.79, .14, .15, .86) + transition: transform 0.2s var(--animation-smooth) &.size-1 .data-1 @@ -224,5 +218,5 @@ grid-template-columns: auto auto auto .gallery-item - margin: 0.35rem + margin: 0.1rem position: relative \ No newline at end of file diff --git a/onlylegs/static/sass/components/image-view.sass b/onlylegs/static/sass/components/image-view.sass index 1439670..249f04c 100644 --- a/onlylegs/static/sass/components/image-view.sass +++ b/onlylegs/static/sass/components/image-view.sass @@ -1,11 +1,11 @@ .info-container - padding: 0.5rem 0 0 0.5rem + padding: 0.5rem 0 0.5rem 0.5rem width: 27rem position: absolute top: 0 left: 0 bottom: 0 - background-image: linear-gradient(90deg, $bg-transparent, transparent) + background-image: linear-gradient(90deg, var(--background-shade), transparent) overflow-y: auto transition: left 0.3s cubic-bezier(0.76, 0, 0.17, 1) z-index: 2 @@ -18,7 +18,7 @@ left: -27rem @media (max-width: 1100px) .info-container - padding: 0 0.5rem 0 0.5rem + padding: 0 width: 100% position: relative background: none @@ -32,9 +32,9 @@ details padding: 0.5rem display: flex flex-direction: column - background-color: RGB($bg-300) - color: RGB($fg-white) - border-radius: $rad + background-color: var(--background-300) + color: var(--foreground-white) + border-radius: var(--rad) overflow: hidden summary @@ -44,7 +44,7 @@ details justify-content: flex-start align-items: center position: relative - color: RGB($primary) + color: var(--primary) > i margin-right: 0 @@ -58,13 +58,6 @@ details font-size: 1.1rem font-weight: 500 - &[open] - summary - margin-bottom: 0.5rem - - > i.collapse-indicator - transform: rotate(90deg) - p margin: 0 padding: 0 @@ -79,7 +72,7 @@ details margin: 0 padding: 0 - color: RGB($primary) + color: var(--primary) cursor: pointer text-decoration: none @@ -91,7 +84,7 @@ details width: 1.1rem height: 1.1rem - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) object-fit: cover @@ -137,6 +130,16 @@ details tr:last-of-type td padding-bottom: 0 + &[open] + summary + margin-bottom: 0.5rem + + > i.collapse-indicator + transform: rotate(90deg) + + &:last-of-type + margin-bottom: 0 + .img-colours width: 100% @@ -154,7 +157,7 @@ details justify-content: center align-items: center - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) border: none i @@ -197,7 +200,9 @@ details max-height: 100% object-fit: contain object-position: center - border-radius: $rad + border-radius: var(--rad) + + transition: border-radius 0.3s cubic-bezier(0.76, 0, 0.17, 1) &.collapsed padding: 0 @@ -207,6 +212,7 @@ details border-radius: 0 @media (max-width: 1100px) .image-container + padding: 0 0 0.5rem 0 position: relative left: 0 @@ -218,17 +224,17 @@ details max-height: 69vh &.collapsed - padding: 0.5rem + padding: 0 0 0.5rem 0 left: 0 picture img - border-radius: $rad + border-radius: var(--rad) .background position: absolute inset: 0 - background-color: RGB($bg-300) - background-image: linear-gradient(to right, RGB($bg-400) 15%, RGB($bg-200) 35%, RGB($bg-400) 50%) + background-color: var(--background-300) + background-image: linear-gradient(to right, var(--background-400) 15%, var(--background-200) 35%, var(--background-400) 50%) background-size: 1000px 640px animation: imgLoading 1.8s linear infinite forwards user-select: none @@ -240,7 +246,7 @@ details inset: 0 width: 100% height: 100% - background-color: RGB($fg-white) + background-color: var(--foreground-white) filter: blur(3rem) saturate(1.2) brightness(0.7) transform: scale(1.1) object-fit: cover diff --git a/onlylegs/static/sass/components/navigation.sass b/onlylegs/static/sass/components/navigation.sass index 760a7d3..9ea4332 100644 --- a/onlylegs/static/sass/components/navigation.sass +++ b/onlylegs/static/sass/components/navigation.sass @@ -42,27 +42,27 @@ nav > i padding: 0.5rem font-size: 1.3rem - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) color: inherit > .nav-pfp padding: 0.4rem width: 2.3rem height: 2.3rem - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) img width: 100% height: 100% object-fit: cover - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) &:hover > i, .nav-pfp - background: RGBA($fg-white, 0.1) + background: var(--white-transparent) &.selected - color: RGB($primary) + color: var(--primary) &::before content: '' @@ -76,9 +76,9 @@ nav height: calc(100% - 1rem) background-color: currentColor - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) -@media (max-width: $breakpoint) +@media (max-width: 800px) nav width: 100vw height: 3.5rem @@ -91,7 +91,7 @@ nav bottom: 0 left: 0 - background-color: RGB($background) + background-color: var(--background-100) > span display: none diff --git a/onlylegs/static/sass/components/notification.sass b/onlylegs/static/sass/components/notification.sass index feea589..d7a3de5 100644 --- a/onlylegs/static/sass/components/notification.sass +++ b/onlylegs/static/sass/components/notification.sass @@ -1,23 +1,9 @@ @keyframes notificationTimeout 0% - left: -100% - height: 3px - 90% - left: 0% - height: 3px - 95% - left: 0% - height: 0 + width: 0 100% - left: 0% - height: 0 - -@mixin notification($color) - color: RGB($color) + width: 100% - &::after - background-color: RGB($color) - .notifications margin: 0 padding: 0 @@ -46,9 +32,9 @@ position: relative - background-color: RGB($bg-300) - border-radius: $rad-inner - color: RGB($fg-white) + background-color: var(--background-400) + border-radius: calc(var(--rad) / 2) + color: var(--foreground-white) opacity: 0 transform: scale(0.8) @@ -60,26 +46,34 @@ &::after content: "" - width: 100% + width: 0 height: 3px position: absolute - bottom: 0px - left: 0px + bottom: 0 + left: 0 - background-color: RGB($fg-white) + background-color: var(--foreground-white) z-index: +2 - animation: notificationTimeout 5.1s linear + animation: notificationTimeout 5.1s ease-out forwards &.success - @include notification($success) + color: var(--success) + &::after + background-color: var(--success) &.warning - @include notification($warning) + color: var(--warning) + &::after + background-color: var(--warning) &.critical - @include notification($critical) + color: var(--danger) + &::after + background-color: var(--danger) &.info - @include notification($info) + color: var(--info) + &::after + background-color: var(--info) &.show opacity: 1 @@ -89,7 +83,7 @@ margin: 0 max-height: 0 opacity: 0 - transform: translateX(100%) + transform: translateY(1rem) transition: all 0.4s ease-in-out, max-height 0.2s ease-in-out .sniffle__notification-icon @@ -103,7 +97,7 @@ justify-content: center align-items: center - background-color: RGB($bg-200) + background-color: var(--background-300) i font-size: 1.25rem @@ -125,7 +119,7 @@ line-height: 1 text-align: left -@media (max-width: $breakpoint) +@media (max-width: 800px) .notifications bottom: 3.8rem width: calc(100vw - 0.6rem) @@ -133,10 +127,6 @@ .sniffle__notification width: 100% - - &.hide - opacity: 0 - transform: translateY(1rem) .sniffle__notification-time width: 100% diff --git a/onlylegs/static/sass/components/pop-up.sass b/onlylegs/static/sass/components/pop-up.sass index 0e6974b..9542f13 100644 --- a/onlylegs/static/sass/components/pop-up.sass +++ b/onlylegs/static/sass/components/pop-up.sass @@ -7,7 +7,7 @@ display: none - background-color: $bg-transparent + background-color: var(--background-shade) opacity: 0 z-index: 101 @@ -38,12 +38,12 @@ display: flex flex-direction: column - background-color: RGB($bg-200) - border-radius: $rad + background-color: var(--background-400) + border-radius: var(--rad) overflow: hidden z-index: +2 - transition: transform 0.2s $animation-smooth + transition: transform 0.2s var(--animation-bounce) .pop-up-header margin: 0 0 0.5rem 0 @@ -73,7 +73,7 @@ font-weight: 700 text-align: left - color: RGB($fg-white) + color: var(--foreground-white) p margin: 0 @@ -84,7 +84,7 @@ font-weight: 400 text-align: left - color: RGB($fg-white) + color: var(--foreground-white) svg width: 1rem @@ -94,7 +94,7 @@ vertical-align: middle a, .link - color: RGB($primary) + color: var(--primary) cursor: pointer text-decoration: none @@ -127,15 +127,13 @@ justify-content: flex-end gap: 0.5rem - // background-color: RGB($bg-100) - &.active opacity: 1 .pop-up-wrapper transform: translate(-50%, 50%) scale(1) -@media (max-width: $breakpoint) +@media (max-width: 800px) .pop-up .pop-up-wrapper max-width: calc(100% - 0.75rem) diff --git a/onlylegs/static/sass/components/settings.sass b/onlylegs/static/sass/components/settings.sass index 8587a76..1bf56e0 100644 --- a/onlylegs/static/sass/components/settings.sass +++ b/onlylegs/static/sass/components/settings.sass @@ -9,10 +9,10 @@ justify-content: center gap: 1rem - background-color: RGB($bg-400) - color: RGB($fg-white) - border: 2px solid RGB($bg-200) - border-radius: $rad-inner + background-color: var(--background-400) + color: var(--foreground-white) + border: 2px solid var(--background-200) + border-radius: calc(var(--rad) / 2) h2 margin: 0 diff --git a/onlylegs/static/sass/components/tags.sass b/onlylegs/static/sass/components/tags.sass index 6da6e67..b45b630 100644 --- a/onlylegs/static/sass/components/tags.sass +++ b/onlylegs/static/sass/components/tags.sass @@ -11,10 +11,10 @@ font-weight: 500 text-decoration: none - border-radius: $rad-inner + border-radius: calc(var(--rad) / 2) border: none - background-color: RGBA($primary, 0.1) - color: RGB($primary) + background-color: var(--primary-transparent) + color: var(--primary) cursor: pointer transition: background-color 0.2s ease-in-out, color 0.2s ease-in-out @@ -23,4 +23,4 @@ font-size: 1.15rem &:hover - background-color: RGBA($primary, 0.2) + background-color: var(--primary-transparent) diff --git a/onlylegs/static/sass/components/upload-panel.sass b/onlylegs/static/sass/components/upload-panel.sass index ed090f0..e4fb816 100644 --- a/onlylegs/static/sass/components/upload-panel.sass +++ b/onlylegs/static/sass/components/upload-panel.sass @@ -9,11 +9,11 @@ height: 100vh background-color: transparent - color: RGB($fg-white) + color: var(--foreground-white) overflow: hidden z-index: 68 - transition: background-color 0.25s cubic-bezier(0.76, 0, 0.17, 1) + transition: background-color 0.25s var(--animation-smooth) h3 margin: 0 @@ -66,11 +66,11 @@ flex-direction: column gap: 1rem - background-color: RGB($bg-200) + background-color: var(--background-200) z-index: +2 - transition: left 0.25s cubic-bezier(0.76, 0, 0.17, 1), bottom 0.25s cubic-bezier(0.76, 0, 0.17, 1) + transition: left 0.25s var(--animation-smooth), bottom 0.25s var(--animation-smooth) #dragIndicator display: none @@ -94,21 +94,21 @@ left: 50% transform: translate(-50%, -50%) - background-color: RGB($bg-400) - border-radius: $rad-inner + background-color: var(--background-400) + border-radius: calc(var(--rad) / 2) - transition: width 0.25s $animation-bounce + transition: width 0.25s var(--animation-smooth) &.dragging #dragIndicator::after width: 9rem - background-color: RGB($primary) + background-color: var(--primary) .upload-jobs display: flex flex-direction: column gap: 0.5rem - border-radius: $rad + border-radius: var(--rad) overflow-y: auto @@ -123,8 +123,8 @@ align-items: center gap: 0.5rem - background-color: RGB($bg-200) - border-radius: $rad + background-color: var(--background-200) + border-radius: var(--rad) overflow: hidden @@ -146,7 +146,7 @@ width: 100% height: 100% - background-image: linear-gradient(to right, RGB($bg-100), transparent) + background-image: linear-gradient(to right, var(--background-100), transparent) .job__status margin: 0 @@ -159,51 +159,51 @@ font-size: 1rem font-weight: 600 - color: RGB($fg-white) + color: var(--foreground-white) z-index: +3 - transition: color 0.25s cubic-bezier(0.76, 0, 0.17, 1) + transition: color 0.25s var(--animation-smooth) .progress width: 100% - height: $rad-inner + height: calc(var(--rad) / 2) position: absolute bottom: 0 left: -100% - background-color: RGB($primary) + background-color: var(--primary) - animation: uploadingLoop 1s cubic-bezier(0.76, 0, 0.17, 1) infinite + animation: uploadingLoop 1s var(--animation-smooth) infinite z-index: +5 - transition: left 1s cubic-bezier(0.76, 0, 0.17, 1) + transition: left 1s var(--animation-smooth) &.critical .job__status, .progress - color: RGB($critical) + color: var(--critical) &.success .job__status - color: RGB($success) + color: var(--success) .progress height: 0 animation: none &.warning .job__status, .progress - color: RGB($warning) + color: var(--warning) &.critical, &.success, &.warning .progress height: 0 &.open - background-color: $bg-transparent + background-color: var(--background-shade) .container left: 0 -@media (max-width: $breakpoint) +@media (max-width: 800px) .upload-panel width: 100% height: calc(100vh - 3.5rem) @@ -219,7 +219,7 @@ left: 0 bottom: -100vh - border-radius: $rad $rad 0 0 + border-radius: var(--rad) var(--rad) 0 0 #dragIndicator display: block diff --git a/onlylegs/static/sass/style.sass b/onlylegs/static/sass/style.sass index c363234..159aa1e 100644 --- a/onlylegs/static/sass/style.sass +++ b/onlylegs/static/sass/style.sass @@ -1,6 +1,7 @@ // Default theme for OnlyLegs by FluffyBean // Mockup link: https://www.figma.com/file/IMZT5kZr3sAngrSHSGu5di/OnlyLegs?node-id=0%3A1 + @import "variables" @import "animations" @@ -15,7 +16,6 @@ @import "components/gallery" @import "components/buttons/top-of-page" -@import "components/buttons/info-button" @import "components/buttons/pill" @import "components/buttons/block" @@ -24,17 +24,17 @@ * box-sizing: border-box - scrollbar-color: RGB($primary) transparent - font-family: $font + scrollbar-color: var(--primary) transparent + font-family: var(--font-family) ::-webkit-scrollbar width: 0.5rem ::-webkit-scrollbar-track - background: RGB($bg-200) + background: var(--background-200) ::-webkit-scrollbar-thumb - background: RGB($primary) + background: var(--primary) ::-webkit-scrollbar-thumb:hover - background: RGB($fg-white) + background: var(--foreground-white) html margin: 0 @@ -51,25 +51,35 @@ body display: grid grid-template-rows: auto 1fr auto - background-color: RGB($background) - color: RGB($foreground) + font-family: var(--font-family) + + background-color: var(--background-100) + color: var(--foreground-white) overflow-x: hidden -@media (max-width: $breakpoint) +@media (max-width: 800px) body padding: 0 0 3.5rem 0 main + margin: 0 0.5rem 0.5rem 0 + padding: 0.5rem display: flex flex-direction: column position: relative - background: RGBA($white, 1) - color: RGB($fg-black) - border-top-left-radius: $rad + background: var(--background-800) + color: var(--foreground-black) + border-radius: var(--rad) overflow: hidden -@media (max-width: $breakpoint) +@media (max-width: 800px) main - border-top-left-radius: 0 + margin: 0 0.5rem + +// This is very broken, as it breaks when you open any context menu/popup +// I need to fix this at some point as it looks really nice +//header +// position: sticky +// top: 0 .error-page min-height: 100% @@ -86,7 +96,7 @@ main font-weight: 900 text-align: center - color: $primary + color: var(--primary) p margin: 0 2rem @@ -95,7 +105,7 @@ main font-size: 1.25rem font-weight: 400 text-align: center -@media (max-width: $breakpoint) +@media (max-width: 800px) .error-page h1 font-size: 4.5rem diff --git a/onlylegs/static/sass/variables.sass b/onlylegs/static/sass/variables.sass index e3fcd83..a31a7bd 100644 --- a/onlylegs/static/sass/variables.sass +++ b/onlylegs/static/sass/variables.sass @@ -1,80 +1,56 @@ -$bg-transparent: rgba(var(--bg-dim), 0.8) -$bg-dim: var(--bg-dim) -$bg-bright: var(--bg-bright) -$bg-100: var(--bg-100) -$bg-200: var(--bg-200) -$bg-300: var(--bg-300) -$bg-400: var(--bg-400) -$bg-500: var(--bg-500) -$bg-600: var(--bg-600) - -$fg-dim: var(--fg-dim) -$fg-white: var(--fg-white) -$fg-black: var(--fg-black) - -$black: var(--black) -$white: var(--white) -$red: var(--red) -$orange: var(--orange) -$yellow: var(--yellow) -$green: var(--green) -$blue: var(--blue) -$purple: var(--purple) - -$primary: var(--primary) -$warning: var(--warning) -$critical: var(--critical) -$success: var(--success) -$info: var(--info) - -$rad: var(--rad) -$rad-inner: var(--rad-inner) - -$animation-smooth: var(--animation-smooth) -$animation-bounce: var(--animation-bounce) - -$font: 'Rubik', sans-serif -$breakpoint: 800px - - -// New variables, Slowly moving over to them because I suck at planning ahead and coding reeee -$background: var(--bg-100) -$foreground: var(--fg-white) - - \:root - --bg-dim: 16, 16, 16 - --bg-bright: 232, 227, 227 - --bg-100: 21, 21, 21 - --bg-200: #{red(adjust-color(rgb(21, 21, 21), $lightness: 2%)), green(adjust-color(rgb(21, 21, 21), $lightness: 2%)), blue(adjust-color(rgb(21, 21, 21), $lightness: 2%))} - --bg-300: #{red(adjust-color(rgb(21, 21, 21), $lightness: 4%)), green(adjust-color(rgb(21, 21, 21), $lightness: 4%)), blue(adjust-color(rgb(21, 21, 21), $lightness: 4%))} - --bg-400: #{red(adjust-color(rgb(21, 21, 21), $lightness: 6%)), green(adjust-color(rgb(21, 21, 21), $lightness: 6%)), blue(adjust-color(rgb(21, 21, 21), $lightness: 6%))} - --bg-500: #{red(adjust-color(rgb(21, 21, 21), $lightness: 8%)), green(adjust-color(rgb(21, 21, 21), $lightness: 8%)), blue(adjust-color(rgb(21, 21, 21), $lightness: 8%))} - --bg-600: #{red(adjust-color(rgb(21, 21, 21), $lightness: 10%)), green(adjust-color(rgb(21, 21, 21), $lightness: 10%)), blue(adjust-color(rgb(21, 21, 21), $lightness: 10%))} + --background-hsl-hue: 69 + --background-hsl-saturation: 25% - --fg-dim: 102, 102, 102 - --fg-white: 232, 227, 227 - --fg-black: 16, 16, 16 + --background-100: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 6%) + --background-200: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 8%) + --background-300: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 10%) + --background-400: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 12%) + --background-500: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 14%) + --background-600: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 16%) + --background-700: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 18%) + --background-800: rgb(232, 227, 227) - --black: 21, 21, 21 - --white: 232, 227, 227 - --red: 182, 100, 103 - --orange: 217, 140, 95 - --yellow: 217, 188, 140 - --green: 140, 151, 125 - --blue: 141, 163, 185 - --purple: 169, 136, 176 + --background-shade: hsl(var(--background-hsl-hue), var(--background-hsl-saturation), 6%, 0.5) + + --foreground-white: rgb(232, 227, 227) + --foreground-gray: rgb(102, 102, 102) + --foreground-black: rgb(16, 16, 16) + + --black: rgb(20, 20, 20) + --black-transparent: rgba(20, 20, 20, 0.2) + --white: rgb(232, 227, 227) + --white-transparent: rgba(232, 227, 227, 0.2) + + --red: rgb(182, 100, 103) + --red-transparent: rgba(182, 100, 103, 0.1) + --orange: rgb(217, 140, 95) + --orange-transparent: rgba(217, 140, 95, 0.1) + --yellow: rgb(198, 185, 166) + --yellow-transparent: rgba(198, 185, 166, 0.1) + --green: rgb(140, 151, 125) + --green-transparent: rgba(140, 151, 125, 0.1) + --blue: rgb(141, 163, 185) + --blue-transparent: rgba(141, 163, 185, 0.1) + --purple: rgb(169, 136, 176) + --purple-transparent: rgba(169, 136, 176, 0.1) + --primary: rgb(183, 169, 151) + --primary-transparent: rgba(183, 169, 151, 0.1) - --primary: var(--green) // 183, 169, 151 --warning: var(--orange) - --critical: var(--red) + --warning-transparent: var(--orange-transparent) + --danger: var(--red) + --danger-transparent: var(--red-transparent) --success: var(--green) + --success-transparent: var(--green-transparent) --info: var(--blue) + --info-transparent: var(--blue-transparent) - --rad: 0.5rem - --rad-inner: calc(var(--rad) / 2) + --rad: 0.4rem --animation-smooth: cubic-bezier(0.76, 0, 0.17, 1) --animation-bounce: cubic-bezier(.68,-0.55,.27,1.55) --breakpoint: 800px + + --font-family: 'Switzer', sans-serif diff --git a/onlylegs/templates/base.html b/onlylegs/templates/base.html index b580c7f..3fb4855 100644 --- a/onlylegs/templates/base.html +++ b/onlylegs/templates/base.html @@ -17,9 +17,7 @@ - - - + @@ -29,6 +27,23 @@ {% assets "scripts" %} {% endassets %} {% assets "styles" %} {% endassets %} + + + {% block head %}{% endblock %} @@ -123,6 +138,10 @@ {% block script %}{% endblock %} diff --git a/onlylegs/templates/group.html b/onlylegs/templates/group.html index 67cfb1f..afaec5c 100644 --- a/onlylegs/templates/group.html +++ b/onlylegs/templates/group.html @@ -20,40 +20,9 @@ diff --git a/onlylegs/templates/image.html b/onlylegs/templates/image.html index edb8a12..725a363 100644 --- a/onlylegs/templates/image.html +++ b/onlylegs/templates/image.html @@ -18,6 +18,10 @@