Centralised file input selection.
This commit is contained in:
parent
46bca5bfca
commit
f3ba61418d
13 changed files with 202 additions and 48 deletions
9
assets/less/animations.less
Normal file
9
assets/less/animations.less
Normal file
|
@ -0,0 +1,9 @@
|
|||
@keyframes background-slide {
|
||||
0% {
|
||||
background-position: 0 0;
|
||||
}
|
||||
|
||||
100% {
|
||||
background-position: var(--background-width) var(--background-height);
|
||||
}
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
.input__select {
|
||||
margin: 1px 0;
|
||||
border: 1px solid #222;
|
||||
padding: 5px 10px;
|
||||
background: #222;
|
||||
|
|
|
@ -1,7 +1,31 @@
|
|||
.input__upload {
|
||||
display: none;
|
||||
display: inline-block;
|
||||
cursor: pointer;
|
||||
margin: 1px 0;
|
||||
|
||||
&__label {
|
||||
.input__button();
|
||||
&__input {
|
||||
display: inline-block;
|
||||
position: absolute;
|
||||
z-index: -1000;
|
||||
}
|
||||
|
||||
&__selection {
|
||||
text-align: center;
|
||||
font-size: 1.2em;
|
||||
border: 1px solid #222;
|
||||
padding: 5px 10px;
|
||||
background: #222;
|
||||
color: #fff;
|
||||
border-radius: 2px;
|
||||
box-shadow: inset 0 0 4px #111;
|
||||
transition: border-color .2s;
|
||||
overflow: none;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
&:focus-within &__selection,
|
||||
&__input:focus ~ &__selection,
|
||||
&__input:active ~ &__selection {
|
||||
border-color: var(--accent-colour);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,6 +39,7 @@ body {
|
|||
background-color: var(--background-colour);
|
||||
font: 12px/20px @mio-font-regular;
|
||||
color: var(--text-colour);
|
||||
background-attachment: fixed;
|
||||
|
||||
&__wrapper {
|
||||
max-width: var(--site-max-width);
|
||||
|
@ -48,26 +49,34 @@ body {
|
|||
}
|
||||
|
||||
&--bg-blend {
|
||||
background-color: var(--accent-colour);
|
||||
background-blend-mode: multiply;
|
||||
}
|
||||
|
||||
/*&--bg-slide {
|
||||
}*/
|
||||
&--bg-slide {
|
||||
animation: background-slide infinite linear 2s;
|
||||
}
|
||||
|
||||
&--bg-cover {
|
||||
background-repeat: no-repeat;
|
||||
background-size: cover;
|
||||
}
|
||||
|
||||
&--bg-contain {
|
||||
background-size: contain;
|
||||
}
|
||||
|
||||
&--bg-stretch {
|
||||
background-size: 100% 100%;
|
||||
background-repeat: no-repeat;
|
||||
}
|
||||
|
||||
&--bg-tile {
|
||||
background-repeat: repeat;
|
||||
background-size: auto;
|
||||
}
|
||||
}
|
||||
|
||||
// Misc
|
||||
@import "animations";
|
||||
|
||||
// Input elements
|
||||
@import "classes/input/button";
|
||||
@import "classes/input/select";
|
||||
|
|
|
@ -262,7 +262,7 @@ switch ($mode) {
|
|||
SELECT
|
||||
u.`user_id`, u.`username`, u.`user_country`,
|
||||
u.`created_at`, u.`last_seen`,
|
||||
u.`user_about_parser`, u.`user_about_content`,
|
||||
u.`user_about_parser`, u.`user_about_content`, u.`user_background_settings`,
|
||||
%1$s,
|
||||
COALESCE(u.`user_title`, r.`role_title`) as `user_title`,
|
||||
COALESCE(u.`user_colour`, r.`role_colour`) as `user_colour`,
|
||||
|
@ -303,13 +303,27 @@ switch ($mode) {
|
|||
$getProfile->bindValue('user_id', $userId);
|
||||
$profile = $getProfile->execute() ? $getProfile->fetch(PDO::FETCH_ASSOC) : [];
|
||||
|
||||
$backgroundPath = build_path(MSZ_STORAGE, 'backgrounds/original', "{$profile['user_id']}.msz");
|
||||
|
||||
if (is_file($backgroundPath)) {
|
||||
$backgroundInfo = getimagesize($backgroundPath);
|
||||
|
||||
if ($backgroundInfo) {
|
||||
tpl_var('site_background', [
|
||||
'url' => "/profile.php?m=background&u={$userId}",
|
||||
'width' => $backgroundInfo[0],
|
||||
'height' => $backgroundInfo[1],
|
||||
'settings' => $profile['user_background_settings'],
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
echo tpl_render('user.profile', [
|
||||
'profile' => $profile,
|
||||
'profile_notices' => $notices,
|
||||
'can_edit' => $canEdit,
|
||||
'is_editing' => $isEditing,
|
||||
'profile_fields' => user_session_active() ? user_profile_fields_display($profile, !$isEditing) : [],
|
||||
'has_background' => is_file(build_path(MSZ_STORAGE, 'backgrounds/original', "{$profile['user_id']}.msz")),
|
||||
'friend_info' => user_session_active() ? user_relation_info(user_session_current('user_id', 0), $profile['user_id']) : [],
|
||||
]);
|
||||
break;
|
||||
|
|
|
@ -10,18 +10,21 @@ define('MSZ_USER_BACKGROUND_ATTACHMENT_NONE', 0);
|
|||
define('MSZ_USER_BACKGROUND_ATTACHMENT_COVER', 1);
|
||||
define('MSZ_USER_BACKGROUND_ATTACHMENT_STRETCH', 2);
|
||||
define('MSZ_USER_BACKGROUND_ATTACHMENT_TILE', 3);
|
||||
define('MSZ_USER_BACKGROUND_ATTACHMENT_CONTAIN', 4);
|
||||
|
||||
define('MSZ_USER_BACKGROUND_ATTACHMENTS', [
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_NONE,
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_COVER,
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_STRETCH,
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_TILE,
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_CONTAIN,
|
||||
]);
|
||||
|
||||
define('MSZ_USER_BACKGROUND_ATTACHMENTS_NAMES', [
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_COVER => 'cover',
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_STRETCH => 'stretch',
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_TILE => 'tile',
|
||||
MSZ_USER_BACKGROUND_ATTACHMENT_CONTAIN => 'contain',
|
||||
]);
|
||||
|
||||
define('MSZ_USER_BACKGROUND_ATTRIBUTE_BLEND', 0x10);
|
||||
|
@ -80,9 +83,11 @@ function user_background_delete(int $userId): void
|
|||
|
||||
define('MSZ_USER_BACKGROUND_TYPE_PNG', IMAGETYPE_PNG);
|
||||
define('MSZ_USER_BACKGROUND_TYPE_JPG', IMAGETYPE_JPEG);
|
||||
define('MSZ_USER_BACKGROUND_TYPE_GIF', IMAGETYPE_GIF);
|
||||
define('MSZ_USER_BACKGROUND_TYPES', [
|
||||
MSZ_USER_BACKGROUND_TYPE_PNG,
|
||||
MSZ_USER_BACKGROUND_TYPE_JPG,
|
||||
MSZ_USER_BACKGROUND_TYPE_GIF,
|
||||
]);
|
||||
|
||||
function user_background_is_allowed_type(int $type): bool
|
||||
|
|
|
@ -44,6 +44,8 @@
|
|||
{% endmacro %}
|
||||
|
||||
{% macro comments_entry(comment, indent, category, user, perms) %}
|
||||
{% from '_layout/input.twig' import input_checkbox_raw %}
|
||||
|
||||
{% if comment.comment_deleted is null or comment.comment_replies|length > 0 %}
|
||||
<div class="comment" id="comment-{{ comment.comment_id }}">
|
||||
<div class="comment__container">
|
||||
|
@ -114,7 +116,7 @@
|
|||
<div class="comment__replies comment__replies--indent-{{ indent }}" id="comment-{{ comment.comment_id }}-replies">
|
||||
{% from _self import comments_entry, comments_input %}
|
||||
{% if user|default(null) is not null and category|default(null) is not null and perms|default(null) is not null and perms.can_comment %}
|
||||
<input type="checkbox" class="comment__reply-toggle" id="comment-reply-toggle-{{ comment.comment_id }}">
|
||||
{{ input_checkbox_raw('', false, 'comment__reply-toggle', '', false, {'id':'comment-reply-toggle-' ~ comment.comment_id}) }}
|
||||
{{ comments_input(category, user, perms, comment) }}
|
||||
{% endif %}
|
||||
{% if comment.comment_replies is defined and comment.comment_replies|length > 0 %}
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
{% from '_layout/input.twig' import input_checkbox_raw %}
|
||||
{% set in_manage = manage_menu is defined %}
|
||||
|
||||
<nav class="header">
|
||||
|
@ -17,7 +18,7 @@
|
|||
for="toggle-mobile-header-user"></label>
|
||||
</div>
|
||||
|
||||
<input type="checkbox" class="header__menu-toggle" id="toggle-mobile-header-menu">
|
||||
{{ input_checkbox_raw('', false, 'header__menu-toggle', '', false, {'id':'toggle-mobile-header-menu'}) }}
|
||||
<ul class="header__menu">
|
||||
<li class="header__menu__item">
|
||||
<a href="/" class="header__menu__link">Home</a>
|
||||
|
@ -41,7 +42,7 @@
|
|||
<li class="header__menu__item"><a href="https://chat.flashii.net" class="header__menu__link">Chat</a></li>
|
||||
</ul>
|
||||
|
||||
<input type="checkbox" class="header__user-toggle" id="toggle-mobile-header-user">
|
||||
{{ input_checkbox_raw('', false, 'header__user-toggle', '', false, {'id':'toggle-mobile-header-user'}) }}
|
||||
<div class="header__user">
|
||||
{% if current_user is defined %}
|
||||
<a href="/profile.php?u={{ current_user.user_id }}"
|
||||
|
|
|
@ -23,13 +23,23 @@
|
|||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input_checkbox(name, text, checked, class, value, radio) %}
|
||||
{% macro input_checkbox_raw(name, checked, class, value, radio, attributes) %}
|
||||
{% spaceless %}
|
||||
<label class="input__checkbox{% if radio %} input__checkbox--radio{% endif %}{{ class|length > 0 ? ' ' ~ class : '' }}">
|
||||
<input type="{{ radio ? 'radio' : 'checkbox' }}" class="input__checkbox__input"
|
||||
<input type="{{ radio ? 'radio' : 'checkbox' }}" class="{{ class|length > 0 ? class : 'input__checkbox__input' }}"
|
||||
{% if name|length > 0 %}name="{{ name }}"{% endif %}
|
||||
{% if checked %}checked{% endif %}
|
||||
{% if value|length > 0 %}value="{{ value }}"{% endif %}>
|
||||
{% if value|length > 0 %}value="{{ value }}"{% endif %}
|
||||
{% for name, value in attributes|default([]) %}
|
||||
{{ name }}{% if value|length > 0 %}="{{ value }}"{% endif %}
|
||||
{% endfor %}>
|
||||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input_checkbox(name, text, checked, class, value, radio, attributes) %}
|
||||
{% from _self import input_checkbox_raw %}
|
||||
{% spaceless %}
|
||||
<label class="input__checkbox{% if radio %} input__checkbox--radio{% endif %}{{ class|length > 0 ? ' ' ~ class : '' }}">
|
||||
{{ input_checkbox_raw(name, checked, '', value, radio, attributes) }}
|
||||
<div class="input__checkbox__display">
|
||||
<div class="input__checkbox__display__icon"></div>
|
||||
</div>
|
||||
|
@ -41,3 +51,32 @@
|
|||
</label>
|
||||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input_file_raw(name, class, accepts, attributes) %}
|
||||
{% spaceless %}
|
||||
<input type="file" {% if name|length > 0 %}name="{{ name }}"{% endif %}
|
||||
class="{{ class|length > 0 ? class : 'input__upload__input' }}"
|
||||
{% if accepts|length > 0 %}accept="{{ accepts|join(',') }}"{% endif %}
|
||||
{% for name, value in attributes|default([]) %}
|
||||
{{ name }}{% if value|length > 0 %}="{{ value }}"{% endif %}
|
||||
{% endfor %}>
|
||||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
||||
{% macro input_file(name, class, accepts, attributes) %}
|
||||
{% from _self import input_file_raw %}
|
||||
{% spaceless %}
|
||||
<label class="input__upload">
|
||||
{{ input_file_raw(name, class, accepts, attributes) }}
|
||||
<div class="input__upload__selection">
|
||||
Click here to select a file!
|
||||
</div>
|
||||
<script>
|
||||
const parent = document.currentScript.parentNode,
|
||||
input = parent.querySelector('input[type="file"]'),
|
||||
display = parent.querySelector('.input__upload__selection');
|
||||
input.addEventListener('change', ev => display.textContent = Array.from(ev.target.files).map(f => f.name).join(', '));
|
||||
</script>
|
||||
</label>
|
||||
{% endspaceless %}
|
||||
{% endmacro %}
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
{% extends 'manage/users/master.twig' %}
|
||||
{% from 'macros.twig' import container_title %}
|
||||
{% from 'manage/macros.twig' import permissions_table %}
|
||||
{% from '_layout/input.twig' import input_csrf, input_text, input_checkbox %}
|
||||
{% from '_layout/input.twig' import input_csrf, input_text, input_checkbox, input_file %}
|
||||
|
||||
{% set site_link = '/profile.php?u=' ~ view_user.user_id %}
|
||||
|
||||
|
@ -76,7 +76,7 @@
|
|||
<label class="form__label">
|
||||
<div class="form__label__text">New Avatar</div>
|
||||
<div class="form__label__input">
|
||||
<input class="input__text" type="file" name="avatar[file]">
|
||||
{{ input_file('avatar[file]') }}
|
||||
</div>
|
||||
</label>
|
||||
|
||||
|
|
|
@ -6,17 +6,19 @@
|
|||
{% include '_layout/meta.twig' %}
|
||||
<link href="{{ '/css/style.css'|asset_url }}" rel="stylesheet">
|
||||
<link href="{{ '/css/libraries.css'|asset_url }}" rel="stylesheet">
|
||||
{% if site_background_url is defined %}
|
||||
{% if site_background is defined %}
|
||||
<style>
|
||||
:root {
|
||||
--background-image: url('{{ site_background_url|raw }}');
|
||||
--background-width: {{ site_background.width }}px;
|
||||
--background-height: {{ site_background.height }}px;
|
||||
--background-image: url('{{ site_background.url|raw }}');
|
||||
}
|
||||
</style>
|
||||
{% endif %}
|
||||
</head>
|
||||
|
||||
<body
|
||||
class="main main--default{% if current_user.user_background_settings is defined %} {{ current_user.user_background_settings|bg_settings('main--bg-%s')|join(' ') }}{% endif %}"
|
||||
class="main{% if site_background is defined %} {{ site_background.settings|bg_settings('main--bg-%s')|join(' ') }}{% endif %}"
|
||||
style="{% if global_accent_colour is defined %}{{ global_accent_colour|html_colour('--accent-colour') }}{% endif %}">
|
||||
{% include '_layout/header.twig' %}
|
||||
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
{% from '_layout/input.twig' import input_checkbox_raw %}
|
||||
|
||||
<div class="container profile__header">
|
||||
<div class="profile__header__details">
|
||||
<div class="profile__header__avatar">
|
||||
|
||||
{% if is_editing and perms.edit_avatar %}
|
||||
<label class="avatar profile__header__avatar__image profile__header__avatar__image--edit"
|
||||
style="background-image:url('{{ image }}')"
|
||||
|
@ -13,10 +14,7 @@
|
|||
Select
|
||||
</label>
|
||||
|
||||
<input type="checkbox"
|
||||
class="profile__header__avatar__check"
|
||||
name="avatar[delete]"
|
||||
id="avatar-delete">
|
||||
{{ input_checkbox_raw('avatar[delete]', false, 'profile__header__avatar__check', '', false, {'id':'avatar-delete'}) }}
|
||||
<label class="profile__header__avatar__option profile__header__avatar__option--delete"
|
||||
for="avatar-delete">
|
||||
Remove
|
||||
|
|
|
@ -1,16 +1,12 @@
|
|||
{% extends 'user/master.twig' %}
|
||||
{% from 'macros.twig' import container_title %}
|
||||
{% from '_layout/input.twig' import input_hidden, input_csrf, input_text, input_checkbox %}
|
||||
{% from '_layout/input.twig' import input_hidden, input_csrf, input_text, input_checkbox, input_file, input_file_raw %}
|
||||
|
||||
{% set image = '/profile.php?u=' ~ profile.user_id ~ '&m=avatar' %}
|
||||
{% set canonical_url = '/profile.php?u=' ~ profile.user_id %}
|
||||
{% set title = 'Profile of ' ~ profile.username %}
|
||||
{% set manage_link = '/manage/users.php?v=view&u=' ~ profile.user_id %}
|
||||
|
||||
{% if has_background %}
|
||||
{% set site_background_url = '/profile.php?m=background&u=' ~ profile.user_id %}
|
||||
{% endif %}
|
||||
|
||||
{% set stats = [
|
||||
{
|
||||
'title': 'Joined',
|
||||
|
@ -47,11 +43,7 @@
|
|||
{{ input_csrf('profile') }}
|
||||
|
||||
{% if perms.edit_avatar %}
|
||||
<input class="profile__hidden"
|
||||
accept="image/png,image/jpeg,image/gif"
|
||||
type="file"
|
||||
name="avatar[file]"
|
||||
id="avatar-selection">
|
||||
{{ input_file_raw('avatar[file]', 'profile__hidden', ['image/png', 'image/jpeg', 'image/gif'], {'id':'avatar-selection'}) }}
|
||||
|
||||
<script>
|
||||
function updateAvatarPreview(name, url, preview) {
|
||||
|
@ -118,15 +110,9 @@
|
|||
{{ container_title('Background') }}
|
||||
|
||||
<div class="profile__background-settings__content">
|
||||
<label>
|
||||
<input
|
||||
accept="image/png,image/jpeg,image/gif"
|
||||
type="file"
|
||||
name="background[file]"
|
||||
id="background-selection">
|
||||
</label>
|
||||
{{ input_file('background[file]', '', ['image/png', 'image/jpeg', 'image/gif'], {'id':'background-selection'}) }}
|
||||
|
||||
<select name="background[attach]" class="input__select">
|
||||
<select name="background[attach]" class="input__select" onchange="profileChangeBackgroundAttach(this.value)">
|
||||
{% for key, value in background_attachments %}
|
||||
<option value="{{ value }}"{% if profile.user_background_attachment == key %} selected{% endif %}>
|
||||
{{ value|capitalize }}
|
||||
|
@ -134,9 +120,9 @@
|
|||
{% endfor %}
|
||||
</select>
|
||||
|
||||
{{ input_checkbox('background[delete]', 'Delete') }}
|
||||
{{ input_checkbox('background[attr][blend]', 'Blend', profile.user_background_blend) }}
|
||||
{{ input_checkbox('background[attr][slide]', 'Slide', profile.user_background_slide) }}
|
||||
{{ input_checkbox('background[delete]', 'Delete', false, '', '', false, {'onchange':'profileToggleBackground(this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][blend]', 'Blend', profile.user_background_blend, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
||||
{{ input_checkbox('background[attr][slide]', 'Slide', profile.user_background_slide, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
|
@ -201,6 +187,70 @@
|
|||
</div>
|
||||
{% if is_editing %}
|
||||
</form>
|
||||
<script>
|
||||
let profilePreviousBackground = null;
|
||||
|
||||
function profileToggleBackground(checked) {
|
||||
let currentBg = document.body.style.getPropertyValue('--background-image');
|
||||
|
||||
if (currentBg != 'initial' && checked) {
|
||||
profilePreviousBackground = currentBg;
|
||||
currentBg = 'initial';
|
||||
} else if (!checked) {
|
||||
currentBg = profilePreviousBackground;
|
||||
}
|
||||
|
||||
document.body.style.setProperty('--background-image', currentBg);
|
||||
}
|
||||
|
||||
function profileChangeBackgroundAttach(mode) {
|
||||
const modes = [
|
||||
'cover',
|
||||
'stretch',
|
||||
'tile',
|
||||
'contain',
|
||||
];
|
||||
|
||||
if (modes.indexOf(mode) < 0)
|
||||
return;
|
||||
|
||||
for (let i = 0; i < modes.length; i++)
|
||||
document.body.classList.remove('main--bg-' + modes[i]);
|
||||
|
||||
document.body.classList.add('main--bg-' + mode);
|
||||
}
|
||||
|
||||
function profileToggleBackgroundAttr(attr, mode) {
|
||||
let className = '';
|
||||
|
||||
switch (attr) {
|
||||
case 'blend':
|
||||
className = 'main--bg-blend';
|
||||
break;
|
||||
|
||||
case 'slide':
|
||||
className = 'main--bg-slide';
|
||||
break;
|
||||
}
|
||||
|
||||
if (className) {
|
||||
if (mode)
|
||||
document.body.classList.add(className);
|
||||
else
|
||||
document.body.classList.remove(className);
|
||||
}
|
||||
}
|
||||
|
||||
document.getElementById('background-selection').addEventListener('change', ev => {
|
||||
const image = new Image();
|
||||
image.src = URL.createObjectURL(ev.target.files[0]);
|
||||
image.addEventListener('load', () => {
|
||||
document.body.style.setProperty('--background-image', 'url(%)'.replace('%', image.src));
|
||||
document.body.style.setProperty('--background-width', '%px'.replace('%', image.width));
|
||||
document.body.style.setProperty('--background-height', '%px'.replace('%', image.height));
|
||||
});
|
||||
});
|
||||
</script>
|
||||
{% else %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
|
Loading…
Add table
Reference in a new issue