400 lines
26 KiB
Twig
400 lines
26 KiB
Twig
{% extends 'profile/master.twig' %}
|
|
{% from 'macros.twig' import container_title %}
|
|
{% from '_layout/input.twig' import input_hidden, input_csrf, input_text, input_checkbox, input_file, input_file_raw, input_select %}
|
|
|
|
{% if profile_user is defined %}
|
|
{% set canonical_url = url('user-profile', {'user': profile_user.id}) %}
|
|
{% set title = profile_user.username %}
|
|
{% else %}
|
|
{% set title = 'User not found!' %}
|
|
{% endif %}
|
|
|
|
{% block content %}
|
|
{% if profile_is_editing %}
|
|
<form class="profile" method="post" action="{{ url('user-profile', {'user': profile_user.id}) }}" enctype="multipart/form-data">
|
|
{{ input_csrf('profile') }}
|
|
|
|
{% if perms.edit_avatar %}
|
|
{{ input_file_raw('avatar[file]', 'profile__hidden', ['image/png', 'image/jpeg', 'image/gif'], {'id':'avatar-selection'}) }}
|
|
|
|
<script>
|
|
function updateAvatarPreview(name, url, preview) {
|
|
url = url || "{{ url('user-avatar', {'user': profile_user.id, 'res': 240})|raw }}";
|
|
preview = preview || document.getElementById('avatar-preview');
|
|
preview.src = url;
|
|
preview.title = name;
|
|
}
|
|
|
|
document.getElementById('avatar-selection').addEventListener('change', function (ev) {
|
|
updateAvatarPreview(ev.target.files[0].name, URL.createObjectURL(ev.target.files[0]));
|
|
});
|
|
</script>
|
|
{% endif %}
|
|
{% else %}
|
|
<div class="profile">
|
|
{% endif %}
|
|
|
|
{% include 'profile/_layout/header.twig' %}
|
|
|
|
{% if profile_is_editing %}
|
|
<div class="container profile__container profile__guidelines">
|
|
<ul class="profile__guidelines__section">
|
|
<li class="profile__guidelines__line profile__guidelines__line--header">General</li>
|
|
<li class="profile__guidelines__line">Keep things sane and generally suitable for all ages.</li>
|
|
<li class="profile__guidelines__line">Make sure to adhere to the <a href="{{ url('info', {'title': 'rules'}) }}" class="profile__guidelines__link">rules</a>.</li>
|
|
</ul>
|
|
|
|
{% if perms.edit_avatar %}
|
|
<ul class="profile__guidelines__section">
|
|
<li class="profile__guidelines__line profile__guidelines__line--header">Avatar</li>
|
|
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ byte_symbol(profile_user.avatarInfo.maxBytes) }}</span> file size limit.</li>
|
|
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_user.avatarInfo.maxWidth }}x{{ profile_user.avatarInfo.maxHeight }}</span>.</li>
|
|
<li class="profile__guidelines__line">Will be centre cropped and scaled to at most <span class="profile__guidelines__emphasis">240x240</span>.</li>
|
|
<li class="profile__guidelines__line">Animated GIF images are allowed.</li>
|
|
</ul>
|
|
{% endif %}
|
|
|
|
{% if perms.edit_background %}
|
|
<ul class="profile__guidelines__section">
|
|
<li class="profile__guidelines__line profile__guidelines__line--header">Background</li>
|
|
<li class="profile__guidelines__line">May not exceed the <span class="profile__guidelines__emphasis">{{ byte_symbol(profile_user.backgroundInfo.maxBytes) }}</span> file size limit.</li>
|
|
<li class="profile__guidelines__line">May not be larger than <span class="profile__guidelines__emphasis">{{ profile_user.backgroundInfo.maxWidth }}x{{ profile_user.backgroundInfo.maxHeight }}</span>.</li>
|
|
<li class="profile__guidelines__line">GIF images, in general, are only allowed when tiling.</li>
|
|
</ul>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if profile_notices|length > 0 %}
|
|
<div class="warning">
|
|
<div class="warning__content">
|
|
{% for notice in profile_notices %}
|
|
<p>{{ notice }}</p>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
|
|
<div class="profile__content">
|
|
{% set show_profile_fields = not profile_is_guest and (profile_is_editing ? perms.edit_profile : profile_fields_display_values|default([]) is not empty) %}
|
|
{% set show_background_settings = profile_is_editing and perms.edit_background %}
|
|
{% set show_birthdate = profile_is_editing and perms.edit_birthdate %}
|
|
{% set show_active_forum_info = not profile_is_editing and (profile_active_category_info.forum_id|default(0) > 0 or profile_active_topic_info.topic_id|default(0) > 0) %}
|
|
{% set show_warnings = profile_warnings is defined and profile_warnings|length > 0 %}
|
|
{% set show_sidebar = (not profile_is_banned or profile_can_edit) and (profile_is_guest or show_profile_fields or show_background_settings or show_birthdate or show_active_forum_info or show_warnings) %}
|
|
|
|
{% if show_sidebar %}
|
|
<div class="profile__content__side">
|
|
{% if show_background_settings %}
|
|
<div class="container profile__container profile__background-settings">
|
|
{{ container_title('Background') }}
|
|
|
|
<div class="profile__background-settings__content">
|
|
{{ input_file('background[file]', '', ['image/png', 'image/jpeg', 'image/gif'], {'id':'background-selection'}) }}
|
|
|
|
{{ input_checkbox('background[attach]', 'None', true, '', 0, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
|
{% for key, value in background_attachments %}
|
|
{{ input_checkbox('background[attach]', value, key == profile_user.backgroundInfo.attachment, '', key, true, {'onchange':'profileChangeBackgroundAttach(this.value)'}) }}
|
|
{% endfor %}
|
|
|
|
{{ input_checkbox('background[attr][blend]', 'Blend', profile_user.backgroundInfo.blend, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'blend\', this.checked)'}) }}
|
|
{{ input_checkbox('background[attr][slide]', 'Slide', profile_user.backgroundInfo.slide, '', '', false, {'onchange':'profileToggleBackgroundAttr(\'slide\', this.checked)'}) }}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if current_user is not defined and not profile_is_deleted %}
|
|
<div class="container profile__container">
|
|
<div class="profile__accounts__notice">
|
|
You must <a href="{{ url('auth-login') }}" class="profile__accounts__link">log in</a> to view full profiles!
|
|
</div>
|
|
</div>
|
|
{% elseif show_profile_fields %}
|
|
<div class="container profile__container profile__accounts">
|
|
{{ container_title('Elsewhere') }}
|
|
|
|
<div class="profile__accounts__content">
|
|
{% for fieldInfo in profile_fields_infos %}
|
|
{% if profile_is_editing or profile_fields_display_values[fieldInfo.name] is defined %}
|
|
<label class="profile__accounts__item">
|
|
<div class="profile__accounts__title">
|
|
{{ fieldInfo.title }}
|
|
</div>
|
|
|
|
{% if profile_is_editing %}
|
|
{{ input_text('profile[' ~ fieldInfo.name ~ ']', 'profile__accounts__input', profile_fields_raw_values[fieldInfo.name]|default('')) }}
|
|
{% else %}
|
|
<div class="profile__accounts__value">
|
|
{% if profile_fields_link_values[fieldInfo.name] is defined %}
|
|
<a href="{{ profile_fields_link_values[fieldInfo.name] }}" class="profile__accounts__link" target="_blank" rel="noreferrer noopener">{{ profile_fields_display_values[fieldInfo.name] }}</a>
|
|
{% else %}
|
|
{{ profile_fields_display_values[fieldInfo.name] }}
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
</label>
|
|
{% endif %}
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if show_active_forum_info %}
|
|
<div class="container profile__container profile__forum-activity">
|
|
{{ container_title('Forum Activity') }}
|
|
|
|
<div class="profile__forum-activity__content">
|
|
{% if profile_active_category_info is not empty %}
|
|
<div class="profile__forum-activity__category">
|
|
{% set forum = profile_active_category_info %}
|
|
{% if forum.forum_icon is defined and forum.forum_icon is not empty %}
|
|
{% set forum_icon = forum.forum_icon %}
|
|
{% elseif forum.forum_archived is defined and forum.forum_archived %}
|
|
{% set forum_icon = 'fas fa-archive fa-fw' %}
|
|
{% elseif forum.forum_type is defined and forum.forum_type != constant('MSZ_FORUM_TYPE_DISCUSSION') %}
|
|
{% if forum.forum_type == constant('MSZ_FORUM_TYPE_LINK') %}
|
|
{% set forum_icon = 'fas fa-link fa-fw' %}
|
|
{% elseif forum.forum_type == constant('MSZ_FORUM_TYPE_CATEGORY') %}
|
|
{% set forum_icon = 'fas fa-folder fa-fw' %}
|
|
{% endif %}
|
|
{% else %}
|
|
{% set forum_icon = 'fas fa-comments fa-fw' %}
|
|
{% endif %}
|
|
|
|
<div class="profile__forum-activity__leader">
|
|
Most active category
|
|
</div>
|
|
|
|
<div class="forum__category">
|
|
<a href="{{ url('forum-category', {'forum': forum.forum_id}) }}" class="forum__category__link"></a>
|
|
|
|
<div class="forum__category__container">
|
|
<div class="forum__category__icon">
|
|
<span class="{{ forum_icon }}"></span>
|
|
</div>
|
|
|
|
<div class="forum__category__details">
|
|
<div class="forum__category__title">
|
|
{{ forum.forum_name }}
|
|
</div>
|
|
|
|
<div class="forum__category__description">
|
|
{{ profile_active_category_stats.post_count|number_format }} post{{ profile_active_category_stats.post_count == 1 ? '' : 's' }}
|
|
/ {{ ((profile_active_category_stats.post_count / profile_stats.forum_post_count) * 100)|number_format(2) }}% of total posts
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if profile_active_topic_info is not empty %}
|
|
<div class="profile__forum-activity__topic">
|
|
{% set topic = profile_active_topic_info %}
|
|
{% if topic.topic_deleted is defined and topic.topic_deleted is not null %}
|
|
{% set topic_icon = 'fas fa-trash-alt' %}
|
|
{% elseif topic.topic_type is defined and topic.topic_type != constant('MSZ_TOPIC_TYPE_DISCUSSION') %}
|
|
{% if topic.topic_type == constant('MSZ_TOPIC_TYPE_ANNOUNCEMENT') or topic.topic_type == constant('MSZ_TOPIC_TYPE_GLOBAL_ANNOUNCEMENT') %}
|
|
{% set topic_icon = 'fas fa-bullhorn' %}
|
|
{% elseif topic.topic_type == constant('MSZ_TOPIC_TYPE_STICKY') %}
|
|
{% set topic_icon = 'fas fa-thumbtack' %}
|
|
{% endif %}
|
|
{% elseif topic.topic_locked is defined and topic.topic_locked is not null %}
|
|
{% set topic_icon = 'fas fa-lock' %}
|
|
{% else %}
|
|
{% set topic_icon = 'fas fa-comment' %}
|
|
{% endif %}
|
|
|
|
<div class="profile__forum-activity__leader">
|
|
Most active topic
|
|
</div>
|
|
|
|
<div class="forum__topic{% if topic.topic_locked is not null %} forum__topic--locked{% endif %}">
|
|
<a href="{{ url('forum-topic', {'topic': topic.topic_id}) }}" class="forum__topic__link"></a>
|
|
|
|
<div class="forum__topic__container">
|
|
<div class="forum__topic__icon">
|
|
<i class="{{ topic_icon }} fa-fw"></i>
|
|
</div>
|
|
|
|
<div class="forum__topic__details">
|
|
<div class="forum__topic__title">
|
|
<span class="forum__topic__title__inner">
|
|
{{ topic.topic_title }}
|
|
</span>
|
|
</div>
|
|
|
|
<div class="forum__topic__info">
|
|
{{ profile_active_topic_stats.post_count|number_format }} post{{ profile_active_topic_stats.post_count == 1 ? '' : 's' }}
|
|
/ {{ ((profile_active_topic_stats.post_count / profile_stats.forum_post_count) * 100)|number_format(2) }}% of total posts
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if show_birthdate %}
|
|
<div class="container profile__container profile__birthdate">
|
|
{{ container_title('Birthdate') }}
|
|
|
|
<div class="profile__birthdate__content">
|
|
<div class="profile__birthdate__date">
|
|
<label class="profile__birthdate__label">
|
|
<div class="profile__birthdate__title">
|
|
Day
|
|
</div>
|
|
{{ input_select('birthdate[day]', ['-']|merge(range(1, 31)), profile_user.hasBirthdate ? profile_user.birthdate.format('d') : 0, '', '', true, 'profile__birthdate__select profile__birthdate__select--day') }}
|
|
</label>
|
|
|
|
<label class="profile__birthdate__label">
|
|
<div class="profile__birthdate__title">
|
|
Month
|
|
</div>
|
|
{{ input_select('birthdate[month]', ['-']|merge(range(1, 12)), profile_user.hasBirthdate ? profile_user.birthdate.format('m') : 0, '', '', true, 'profile__birthdate__select profile__birthdate__select--month') }}
|
|
</label>
|
|
</div>
|
|
|
|
<div class="profile__birthdate__year">
|
|
<label class="profile__birthdate__label">
|
|
<div class="profile__birthdate__title">
|
|
Year (may be left empty)
|
|
</div>
|
|
{{ input_select('birthdate[year]', ['-']|merge(range(null|date('Y'), null|date('Y') - 100)), profile_user.birthdate.format('Y'), '', '', true, 'profile__birthdate__select profile__birthdate__select--year') }}
|
|
</label>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
{% if show_warnings %}
|
|
<div class="container profile__container" style="--accent-colour: #c84;">
|
|
{{ container_title('Warnings') }}
|
|
|
|
<div class="profile__warnings">
|
|
{% for warning in profile_warnings %}
|
|
<div class="profile__warnings__item">
|
|
<div class="profile__warnings__datetime">
|
|
<time datetime="{{ warning.createdTime|date('c') }}" title="{{ warning.createdTime|date('r') }}">{{ warning.createdTime|time_format }}</time>
|
|
</div>
|
|
<div class="profile__warnings__body">
|
|
{% for line in warning.bodyLines %}
|
|
<p>{{ line }}</p>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endfor %}
|
|
</div>
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if profile_user is defined %}
|
|
<div class="profile__content__main">
|
|
{% if (not profile_is_banned or profile_can_edit) and ((profile_is_editing and perms.edit_about) or profile_user.hasProfileAbout) %}
|
|
<div class="container profile__container profile__about" id="about">
|
|
{{ container_title('About ' ~ profile_user.username) }}
|
|
|
|
{% if profile_is_editing %}
|
|
<div class="profile__signature__editor">
|
|
{{ input_select('about[parser]', constant('\\Misuzu\\Parsers\\Parser::NAMES'), profile_user.profileAboutParser, '', '', false, 'profile__about__select') }}
|
|
<textarea name="about[text]" class="input__textarea profile__about__text" id="about-textarea">{{ profile_user.profileAboutText }}</textarea>
|
|
</div>
|
|
{% else %}
|
|
<div class="profile__about__content{% if profile_is_editing %} profile__about__content--edit{% elseif profile_user.profileAboutParser == constant('\\Misuzu\\Parsers\\Parser::MARKDOWN') %} markdown{% endif %}">
|
|
{{ profile_user.profileAboutParsed|raw }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
|
|
{% if (not profile_is_banned or profile_can_edit) and ((profile_is_editing and perms.edit_signature) or profile_user.hasForumSignature) %}
|
|
<div class="container profile__container profile__signature" id="signature">
|
|
{{ container_title('Signature') }}
|
|
|
|
{% if profile_is_editing %}
|
|
<div class="profile__signature__editor">
|
|
{{ input_select('signature[parser]', constant('\\Misuzu\\Parsers\\Parser::NAMES'), profile_user.forumSignatureParser, '', '', false, 'profile__signature__select') }}
|
|
<textarea name="signature[text]" class="input__textarea profile__signature__text" id="signature-textarea">{{ profile_user.forumSignatureText }}</textarea>
|
|
</div>
|
|
{% else %}
|
|
<div class="profile__signature__content{% if profile_is_editing %} profile__signature__content--edit{% elseif profile_user.forumSignatureParser == constant('\\Misuzu\\Parsers\\Parser::MARKDOWN') %} markdown{% endif %}">
|
|
{{ profile_user.forumSignatureParsed|raw }}
|
|
</div>
|
|
{% endif %}
|
|
</div>
|
|
{% endif %}
|
|
{% endif %}
|
|
</div>
|
|
</div>
|
|
{% if profile_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(currentBg == 'initial' && !checked) {
|
|
currentBg = profilePreviousBackground;
|
|
}
|
|
|
|
document.body.style.setProperty('--background-image', currentBg);
|
|
}
|
|
|
|
function profileChangeBackgroundAttach(mode) {
|
|
const modes = {
|
|
1: 'cover',
|
|
2: 'stretch',
|
|
3: 'tile',
|
|
4: 'contain',
|
|
};
|
|
|
|
profileToggleBackground(mode == 0);
|
|
|
|
for(let i = 1; i <= Object.keys(modes).length; i++)
|
|
document.body.classList.remove('main--bg-' + modes[i]);
|
|
|
|
if(!modes[mode])
|
|
return;
|
|
|
|
document.body.classList.add('main--bg-' + modes[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 %}
|
|
{% endblock %}
|