
changed in it the comments.html template (along with submission.html) has numerous undesirable properties which i will describe now. unless you are very familiar with the codebase, it can be extremely difficult to grok. this is pretty insane as there is nothing fundamentally complex about the goal of comments.html: return a component that shows a username and info, reports if any, comment content, and actions a user can take. this behemeoth was initially 886 lines in the old version of this codebase, and this is with awards and a lot of other cruft removed. anyway, the maintainability of this file is about on par with some legacy application that keels over and dies if you sneeze vaguely in its direction. the nicest thing i can say about it is that it isn't currently crashing. anyway some of the problems include: * large, splittable components, are not split into separate files. this makes it incredibly difficult to find or make changes across the template and makes it nearly impossible to find or change a specific thing. this is most easily exemplified in the modals, which should by all accounts be separate templates, just inlined into comments.html. * the nesting is oftentimes incorrect. inexplicably, probably out of laziness from when the code was first written, things will end up fully left aligned, while multiple layers deep into a nesting context. if an if statement or an endif is changed, it is *incredibly* difficult to figure out where the error was. you can't trust the nesting. * multiple repeated checks for things that are always true. this is probably a symptom of the above two problems but it's very noticeable once you fix the nesting. for example there is a block near the very top of the actions bar which checks for parent_submission which effectively checks "is this in a post" (this commit won't complain about parent_submission checks but i do have opinions on those). all of the action buttons further down the chain also check for parent_submission, or even check inconsistently (by using if c.post) within this context this is a completely unnecessary check in this context. while it is potentially useful (and in fact because #251 requires we dismantle the assumption a little bit) to have these checks now, the fact that they were initially added shows that when the code was all initial written, there was little care into thinking about comment state. * mobile actions are duplicated and duplicated inline. i actually do find it probably pretty hard to support this normally given the codebase's DOM so whatever, duplicate the things, *but* if we're going to do that, inlining it into the middle of an incredibly long template is really difficult to comprehend as a design decision. ...anyway yeah this PR intends to fix these problems and enable work to be done on #251. this is a "perfect is the enemy of good" commit. it doesn't change much fundamental and is not intended to erase the sins of the original file, but at least make it maintainable. this also fixes a minor bug with #473 where the GIF modal was left in by accident.
471 lines
18 KiB
HTML
471 lines
18 KiB
HTML
{% extends "settings.html" %}
|
|
|
|
{% block pagetitle %}Profile Settings - {{SITE_TITLE}}{% endblock %}
|
|
|
|
{% block content %}
|
|
|
|
<style>
|
|
.bg-image {
|
|
padding: 0.25rem;
|
|
width: 15rem;
|
|
height: 10rem;
|
|
object-fit: cover;
|
|
}
|
|
.bg-button {
|
|
margin: 0.25rem;
|
|
padding: 0;
|
|
}
|
|
</style>
|
|
|
|
<div id="posts" class="row">
|
|
|
|
<div class="col col-lg-10">
|
|
|
|
<div class="settings">
|
|
|
|
<h2 class="h5" name="referral">Theme</h2>
|
|
|
|
<div class="settings-section rounded">
|
|
|
|
<div class="d-lg-flex border-bottom">
|
|
|
|
<div class="title w-lg-25">
|
|
<label for="cardview">Card View</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<div class="custom-control custom-switch">
|
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="cardview" name="cardview"{% if v.cardview %} checked{% endif %} onchange="post_toast(this,'/settings/profile?cardview='+document.getElementById('cardview').checked);">
|
|
<label class="custom-control-label" for="cardview"></label>
|
|
</div>
|
|
|
|
<span class="text-small-extra text-muted">Enable if you would like to display images and videos in full size on the frontpage.</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="d-lg-flex border-bottom">
|
|
|
|
<div class="title w-lg-25">
|
|
<label for="highlightcomments">Highlight New Comments</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<div class="custom-control custom-switch">
|
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="highlightcomments" name="highlightcomments"{% if v.highlightcomments %} checked{% endif %} onchange="post_toast(this,'/settings/profile?highlightcomments='+document.getElementById('highlightcomments').checked);">
|
|
<label class="custom-control-label" for="highlightcomments"></label>
|
|
</div>
|
|
|
|
<span class="text-small-extra text-muted">Enable if you would like to highlight comments made after the last time you visited a thread.</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="d-lg-flex border-bottom">
|
|
<div class="title w-lg-25">
|
|
<label for="theme">Website Theme</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
<p>Change the theme for the website.</p>
|
|
<div class="input-group mb2">
|
|
<select autocomplete="off" id='theme' class="form-control" form="profile-settings" name="theme" onchange="post_toast(this,'/settings/profile?theme='+document.getElementById('theme').value, '1')">
|
|
{% for entry in THEMES %}
|
|
<option value="{{entry}}" {% if v.theme==entry %} selected {% endif %}>
|
|
{{entry}}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="d-lg-flex border-bottom">
|
|
<div class="title w-lg-25">
|
|
<label for="theme">Website Backgrounds</label>
|
|
</div>
|
|
<div class="body w-lg-100">
|
|
<p>Change the background for the website.</p>
|
|
<div class="input-group mb2">
|
|
<select autocomplete="off" id='backgroundSelector' class="form-control" form="profile-settings" name="background" onchange="updatebgselection();">
|
|
{% for entry in ["space"] %}
|
|
<option value="{{entry}}" {% if v.background and v.background.startswith(entry) %}selected{% endif %}>
|
|
{{entry}}
|
|
</option>
|
|
{% endfor %}
|
|
</select>
|
|
</div>
|
|
{% if v.background %}
|
|
<div class="d-flex mt-2">
|
|
<a class="btn btn-primary ml-auto" role="button" onclick="post_toast(this,'/settings/removebackground','1')">Remove Background</a>
|
|
<pre></pre>
|
|
</div>
|
|
{% endif %}
|
|
<div id="bgcontainer"></div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
<h2 class="h5">Profile Picture</h2>
|
|
|
|
<div class="settings-section rounded">
|
|
|
|
<div class="d-flex">
|
|
|
|
<div class="title w-lg-25 text-md-center">
|
|
<img loading="lazy" alt="your profile picture" src="{{v.profile_url}}" class="profile-pic-75">
|
|
</div>
|
|
|
|
<div class="body w-lg-100 my-auto">
|
|
|
|
<div class="d-flex">
|
|
|
|
<div>
|
|
<form action="/settings/images/profile" method="post" enctype="multipart/form-data">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<label class="btn btn-secondary text-capitalize mr-2 mb-0">
|
|
Update<input autocomplete="off" type="file" accept="image/*" {% if request.headers.get('cf-ipcountry')=="T1" %}disabled{% endif %} hidden name="profile" onchange="form.submit()">
|
|
</label>
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="text-small-extra text-muted mt-3">JPG, PNG, GIF files are supported. Max file size is {% if v and v.patron %}8{% else %}4{% endif %} MB.</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<h2 class="h5">Profile Banner</h2>
|
|
|
|
<div class="settings-section rounded">
|
|
|
|
<div class="d-flex">
|
|
|
|
<div class="title w-lg-75 text-md-center">
|
|
<img loading="lazy" alt="your banner" src="{{v.banner_url}}" class="banner-pic-135">
|
|
</div>
|
|
|
|
<div class="body w-lg-100 my-auto">
|
|
|
|
<div class="d-flex">
|
|
|
|
<div>
|
|
<form action="/settings/images/banner" method="post" enctype="multipart/form-data">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<label class="btn btn-secondary text-capitalize mr-2 mb-0">
|
|
Update<input autocomplete="off" type="file" {% if request.headers.get('cf-ipcountry')=="T1" %}disabled{% endif %} accept="image/*" hidden name="banner" onchange="form.submit()">
|
|
</label>
|
|
</form>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="text-small-extra text-muted mt-3">JPG, PNG, GIF files are supported. Max file size is {% if v and v.patron %}8{% else %}4{% endif %} MB.</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<h2 class="h5" id="referral" name="referral">Referrals</h2>
|
|
|
|
<p class="text-small text-muted">Invite a friend.</p>
|
|
|
|
<div class="settings-section rounded">
|
|
|
|
<div class="d-lg-flex">
|
|
|
|
<div class="title w-lg-25">
|
|
<label for="referral_code">Referral code</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<div class="input-group">
|
|
|
|
<input autocomplete="off" type="text" readonly="" class="form-control copy-link" id="referral_code" value="{{SITE_FULL}}/signup?ref={{v.username}}" data-clipboard-text="{{SITE_FULL}}/signup?ref={{v.username}}">
|
|
|
|
<span class="input-group-append" data-bs-toggle="tooltip" data-bs-placement="top" title="You have referred {{v.referral_count}} user{{'s' if v.referral_count != 1 else ''}} so far. {% if v.referral_count==0 %}¯\_(ツ)_/¯{% elif v.referral_count>10%}Wow!{% endif %}">
|
|
<span class="input-group-text text-primary border-0">
|
|
<i class="far fa-user mr-1" aria-hidden="true"></i>{{v.referral_count}}</span>
|
|
</span>
|
|
|
|
</div>
|
|
|
|
<div class="text-small-extra text-muted mt-3">Share this link with a friend. {% if v.referral_count==0 %} When they sign up, you'll get the bronze recruitment badge.{% elif v.referral_count<10 %} When you refer 10 friends, you'll receive the silver recruitment badge.{% elif v.referral_count<100 %} When you refer 100 friends, you'll receive the gold recruitment badge.{% endif %}</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<h2 class="h5" name="referral">RSS Feed</h2>
|
|
|
|
<p class="text-small text-muted">Subscribe to the {{SITE_TITLE}} RSS feed.</p>
|
|
|
|
<div class="settings-section rounded">
|
|
|
|
<div class="d-lg-flex">
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<input autocomplete="off" type="text" readonly="" class="form-control copy-link" id="rss_feed" value="{{SITE_FULL}}/rss/new/all" data-clipboard-text="{{SITE_FULL}}/rss/new/all">
|
|
|
|
<div class="text-small-extra text-muted mt-3">You can change the feed by replacing "new" with whatever sorting you want and "all" with whatever time filter you want.</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<h2 class="h5" id="bio" name="bio">Your Profile</h2>
|
|
|
|
<p class="text-small text-muted">Edit how others see you on {{SITE_TITLE}}.</p>
|
|
|
|
<div class="settings-section rounded mb-0">
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Username</label>
|
|
|
|
<div class="w-lg-100">
|
|
<p>Your original username will always stay reserved for you: <code>{{v.original_username}}</code></p>
|
|
|
|
<form action="/settings/name_change" method="post">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<input autocomplete="off" type="text" name="name" class="form-control" value="{{v.username}}">
|
|
<small>3-25 characters, including letters, numbers, _ , and -</small>
|
|
<div class="d-flex mt-2">
|
|
<input autocomplete="off" class="btn btn-primary ml-auto" type="submit" value="Change Display Name">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Flair</label>
|
|
|
|
<div class="w-lg-100">
|
|
|
|
<form id="profile-settings" action="/settings/title_change" method="post">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<input maxlength=100 {% if v.flairchanged %}disabled{% endif %} autocomplete="off" id="customtitlebody" type="text" name="title" class="form-control" placeholder='Enter a flair here' value="{% if v.flairchanged %}Your flair has been locked until {{ti}}{% elif v.customtitleplain %}{{v.customtitleplain}}{% endif %}">
|
|
<div class="d-flex mt-2">
|
|
<small>Limit of 100 characters</small>
|
|
<input {% if v.flairchanged %}disabled{% endif %} autocomplete="off" class="btn btn-primary ml-auto" id="titleSave" type="submit" value="Change Flair">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Flair Color</label>
|
|
|
|
<div class="d-flex">
|
|
|
|
<form action="/settings/titlecolor" id="titlecolor-form" method="post" class="color-picker" style="line-height: 0">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
|
|
{% for titlecolor in COLORS %}
|
|
<input autocomplete="off" type="radio" name="titlecolor" id="titlecolor-{{titlecolor}}" value="{{titlecolor}}" {% if v.titlecolor == titlecolor %}checked{% endif %} onclick="document.getElementById('titlecolor-form').submit()">
|
|
<label class="color-radio" for="titlecolor-{{titlecolor}}">
|
|
<span style="background-color: #{{titlecolor}}">
|
|
{% if v.titlecolor.lower() == titlecolor %}
|
|
<i class="fas fa-check text-white"></i>
|
|
{% else %}
|
|
|
|
{% endif %}
|
|
</span>
|
|
</label>
|
|
{% endfor %}
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
<p class="text-small mb-2">Or type a color code:</p>
|
|
<div class="d-flex">
|
|
<form action="/settings/titlecolor" id="color-code-form" method="post">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<input autocomplete="off" class="form-control" type="text" name="titlecolor" id="color-code" maxlength="6" value="{% if v.titlecolor %}{{v.titlecolor}}{% endif %}">
|
|
<label class="btn btn-secondary text-capitalize mr-2 mt-2 mb-0">Update<input autocomplete="off" type="text" for="color-code" onclick="form.submit()" hidden=""></label>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
|
|
{% if v.verified %}
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Bluecheck Color</label>
|
|
|
|
<div class="d-flex">
|
|
|
|
<form action="/settings/verifiedcolor" id="verifiedcolor-form" method="post" class="color-picker" style="line-height: 0">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
|
|
{% for verifiedcolor in COLORS %}
|
|
<input autocomplete="off" type="radio" name="verifiedcolor" id="verifiedcolor-{{verifiedcolor}}" value="{{verifiedcolor}}" {% if v.verifiedcolor == verifiedcolor %}checked{% endif %} onclick="document.getElementById('verifiedcolor-form').submit()">
|
|
<label class="color-radio" for="verifiedcolor-{{verifiedcolor}}">
|
|
<span style="background-color: #{{verifiedcolor}}">
|
|
{% if v.verifiedcolor and v.verifiedcolor.lower() == verifiedcolor %}
|
|
<i class="fas fa-check text-white"></i>
|
|
{% else %}
|
|
|
|
{% endif %}
|
|
</span>
|
|
</label>
|
|
{% endfor %}
|
|
|
|
</form>
|
|
|
|
</div>
|
|
|
|
<p class="text-small mb-2">Or type a color code:</p>
|
|
<div class="d-flex">
|
|
<form action="/settings/verifiedcolor" id="color-code-form" method="post">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<input autocomplete="off" class="form-control" type="text" name="verifiedcolor" id="color-code" maxlength="6" value="{% if v.verifiedcolor %}{{v.verifiedcolor}}{% endif %}">
|
|
<label class="btn btn-secondary text-capitalize mr-2 mt-2 mb-0">Update<input autocomplete="off" type="text" for="color-code" onclick="form.submit()" hidden=""></label>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
{% endif %}
|
|
|
|
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Bio</label>
|
|
|
|
<div class="w-lg-100">
|
|
<form id="profile-bio" action="/settings/profile" method="post" enctype="multipart/form-data">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<div class="input-group mb-2">
|
|
<textarea autocomplete="off" id="bio-text" class="form-control rounded" aria-label="With textarea" placeholder="Tell the community a bit about yourself." rows="3" name="bio" form="profile-bio" maxlength="1500">{% if v.bio %}{{v.bio}}{% endif %}</textarea>
|
|
</div>
|
|
<div class="d-flex">
|
|
<pre style="padding-top:0.7rem" class="btn btn-secondary format d-inline-block m-0 fas fa-bold" aria-hidden="true" onclick="makeBold('bio-text')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Bold"></pre>
|
|
|
|
<pre style="padding-top:0.7rem" class="btn btn-secondary format d-inline-block m-0 fas fa-italic" aria-hidden="true" onclick="makeItalics('bio-text')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Italicize"></pre>
|
|
|
|
<pre style="padding-top:0.7rem" class="btn btn-secondary format d-inline-block m-0 fas fa-quote-right" aria-hidden="true" onclick="makeQuote('bio-text')" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Quote"></pre>
|
|
|
|
<pre style="padding-top:0.7rem;line-height:1" class="btn btn-secondary format d-inline-block m-0 font-weight-bolder text-uppercase" onclick="commentForm('bio-text');getGif()" aria-hidden="true" data-bs-toggle="modal" data-bs-target="#gifModal" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Add GIF">GIF</pre>
|
|
|
|
<label class="btn btn-secondary format d-inline-block m-0">
|
|
<div id="filename-show"><i class="far fa-image"></i></div>
|
|
<input autocomplete="off" id="file-upload" type="file" name="file" {% if request.headers.get('cf-ipcountry')=="T1" %}disabled{% endif %} accept="image/*" onchange="changename('filename-show','file-upload')" hidden>
|
|
</label>
|
|
</div>
|
|
<pre></pre>
|
|
<div class="d-flex">
|
|
<small>Limit of 1500 characters</small>
|
|
<input autocomplete="off" class="btn btn-primary ml-auto" id="bioSave" type="submit" value="Save Changes">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="body d-lg-flex border-bottom">
|
|
|
|
<label class="text-black w-lg-25">Friends</label>
|
|
|
|
<div class="w-lg-100">
|
|
<form id="profile-friends" action="/settings/profile" method="post" enctype="multipart/form-data">
|
|
<input type="hidden" name="formkey" value="{{v.formkey}}">
|
|
<div class="input-group mb-2">
|
|
<textarea autocomplete="off" id="friends-text" class="form-control rounded" aria-label="With textarea" placeholder="Enter your friends on the site..." rows="3" name="friends" form="profile-friends" maxlength="1500">{% if v.friends %}{{v.friends}}{% endif %}</textarea>
|
|
</div>
|
|
<pre></pre>
|
|
<div class="d-flex">
|
|
<small>Limit of 500 characters</small>
|
|
<input autocomplete="off" class="btn btn-primary ml-auto" id="friendsSave" type="submit" value="Save Changes">
|
|
</div>
|
|
</form>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
|
|
<div class="d-lg-flex border-bottom">
|
|
|
|
<div class="title w-lg-25">
|
|
<label for="privateswitch">Private Mode</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<div class="custom-control custom-switch">
|
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="privateswitch" name="private"{% if v.is_private%} checked{% endif %} onchange="post_toast(this,'/settings/profile?private='+document.getElementById('privateswitch').checked)">
|
|
<label class="custom-control-label" for="privateswitch"></label>
|
|
</div>
|
|
|
|
<span class="text-small-extra text-muted">This will hide your post and comment history from others. We will also ask search engines to not index your profile page. (Your content will still be accessible via direct link.)</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<div class="d-lg-flex border-bottom">
|
|
|
|
<div class="title w-lg-25">
|
|
<label for="nofollowswitch">Disable Subscriptions</label>
|
|
</div>
|
|
|
|
<div class="body w-lg-100">
|
|
|
|
<div class="custom-control custom-switch">
|
|
<input autocomplete="off" type="checkbox" class="custom-control-input" id="nofollowswitch" name="nofollow"{% if v.is_nofollow%} checked{% endif %} onchange="post_toast(this,'/settings/profile?nofollow='+document.getElementById('nofollowswitch').checked)">
|
|
<label class="custom-control-label" for="nofollowswitch"></label>
|
|
</div>
|
|
|
|
<span class="text-small-extra text-muted">Prevent other users from following you.</span>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
</div>
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
|
|
</div>
|
|
<script src="{{ 'js/settings_profile.js' | asset }}"></script>
|
|
{% endblock %}
|