users can remove profile pics (communities too)

This commit is contained in:
rimu 2024-05-26 18:24:13 +12:00
parent 11ce2919dd
commit d1f7d35a83
7 changed files with 127 additions and 5 deletions

View file

@ -506,8 +506,11 @@ def refresh_user_profile_task(user_id):
db.session.commit()
if user.avatar_id and avatar_changed:
make_image_sizes(user.avatar_id, 40, 250, 'users')
cache.delete_memoized(User.avatar_image, user)
cache.delete_memoized(User.avatar_thumbnail, user)
if user.cover_id and cover_changed:
make_image_sizes(user.cover_id, 700, 1600, 'users')
cache.delete_memoized(User.cover_image, user)
def refresh_community_profile(community_id):

View file

@ -1099,6 +1099,7 @@ def community_edit(community_id: int):
file = save_icon_file(icon_file)
if file:
community.icon = file
cache.delete_memoized(Community.icon_image, community)
banner_file = request.files['banner_file']
if banner_file and banner_file.filename != '':
if community.image_id:
@ -1106,6 +1107,7 @@ def community_edit(community_id: int):
file = save_banner_file(banner_file)
if file:
community.image = file
cache.delete_memoized(Community.header_image, community)
# Languages of the community
db.session.execute(text('DELETE FROM "community_language" WHERE community_id = :community_id'),
@ -1140,6 +1142,38 @@ def community_edit(community_id: int):
abort(401)
@bp.route('/community/<int:community_id>/remove_icon', methods=['GET', 'POST'])
@login_required
def remove_icon(community_id):
community = Community.query.get_or_404(community_id)
if community.icon_id:
community.icon.delete_from_disk()
if community.icon_id:
file = File.query.get(community.icon_id)
file.delete_from_disk()
community.icon_id = None
db.session.delete(file)
db.session.commit()
cache.delete_memoized(Community.icon_image, community)
return _('Icon removed!')
@bp.route('/community/<int:community_id>/remove_header', methods=['GET', 'POST'])
@login_required
def remove_header(community_id):
community = Community.query.get_or_404(community_id)
if community.image_id:
community.image.delete_from_disk()
if community.image_id:
file = File.query.get(community.image_id)
file.delete_from_disk()
community.image_id = None
db.session.delete(file)
db.session.commit()
cache.delete_memoized(Community.header_image, community)
return '<div> ' + _('Banner removed!') + '</div>'
@bp.route('/community/<int:community_id>/delete', methods=['GET', 'POST'])
@login_required
def community_delete(community_id: int):

View file

@ -669,7 +669,7 @@ class User(UserMixin, db.Model):
else:
return '[deleted]'
@cache.memoize(timeout=10)
@cache.memoize(timeout=500)
def avatar_thumbnail(self) -> str:
if self.avatar_id is not None:
if self.avatar.thumbnail_path is not None:
@ -681,7 +681,7 @@ class User(UserMixin, db.Model):
return self.avatar_image()
return ''
@cache.memoize(timeout=10)
@cache.memoize(timeout=500)
def avatar_image(self) -> str:
if self.avatar_id is not None:
if self.avatar.file_path is not None:
@ -696,6 +696,7 @@ class User(UserMixin, db.Model):
return self.avatar.source_url
return ''
@cache.memoize(timeout=500)
def cover_image(self) -> str:
if self.cover_id is not None:
if self.cover.thumbnail_path is not None:

View file

@ -12,8 +12,24 @@ document.addEventListener("DOMContentLoaded", function () {
setupConversationChooser();
setupMarkdownEditorEnabler();
setupAddPollChoice();
setupShowElementLinks();
});
// All elements with the class "showElement" will show the DOM element referenced by the data-id attribute
function setupShowElementLinks() {
var elements = document.querySelectorAll('.showElement');
elements.forEach(function(element) {
element.addEventListener('click', function(event) {
event.preventDefault();
var dataId = this.getAttribute('data-id');
var targetElement = document.getElementById(dataId);
if (targetElement) {
targetElement.style.display = 'inherit';
}
});
});
}
function renderMasonry(masonry, htmlSnippets) {
const mainPane = document.querySelector('.main_pane');
const mainPaneWidth = mainPane.offsetWidth;
@ -636,9 +652,12 @@ function setupMarkdownEditorEnabler() {
function setupAddPollChoice() {
const addChoiceButton = document.getElementById('addPollChoice');
const pollChoicesFieldset = document.getElementById('pollChoicesFieldset');
if(pollChoicesFieldset == null) {
return;
}
const formGroups = pollChoicesFieldset.getElementsByClassName('form-group');
if(addChoiceButton) {
if(addChoiceButton && addChoiceButton) {
addChoiceButton.addEventListener('click', function(event) {
// Loop through the form groups and show the first hidden one
for (let i = 0; i < formGroups.length; i++) {

View file

@ -31,15 +31,29 @@
{{ render_field(form.title) }}
{{ render_field(form.description) }}
{% if community.icon_id %}
<img class="community_icon_big rounded-circle" src="{{ community.icon_image() }}" />
<!-- <img class="community_icon_big rounded-circle" src="{{ community.icon_image() }}" /> -->
{% endif %}
{{ render_field(form.icon_file) }}
<small class="field_hint">Provide a square image that looks good when small.</small>
{% if community.image_id %}
<a href="{{ community.header_image() }}"><img class="community_icon_big" src="{{ community.header_image() }}" /></a>
<!-- <a href="{{ community.header_image() }}"><img class="community_icon_big" src="{{ community.header_image() }}" /></a> -->
{% endif %}
{% if community.icon_id %}
<p><a href="{{ community.icon_image() }}" class="btn btn-sm btn-primary showElement" data-id="icon_image">{{ _('View image') }}</a>
<a href="{{ url_for('community.remove_icon', community_id=community.id) }}" class="btn btn-sm btn-primary" hx-post="{{ url_for('community.remove_icon', community_id=community.id) }}" hx-target="#icon_image" hx-swap="outerHTML">{{ _('Delete image') }}</a>
</p>
<p><img id="icon_image" class="community_icon_big rounded-circle" loading="lazy" style="display: none;" src="{{ community.icon_image() }}" alt="{{ _('Profile pic') }}" /></p>
{% endif %}
{{ render_field(form.banner_file) }}
<small class="field_hint">Provide a wide image - letterbox orientation.</small>
{% if community.image_id %}
<p><a href="{{ community.header_image() }}" class="btn btn-sm btn-primary showElement" data-id="image_div">{{ _('View image') }}</a>
<a href="{{ url_for('community.remove_header', community_id=community.id) }}" class="btn btn-sm btn-primary"
hx-post="{{ url_for('community.remove_header', community_id=community.id) }}"
hx-target="#image_div" hx-swap="outerHTML">{{ _('Delete image') }}</a>
</p>
<div id="image_div" class="community_header mb-4" style="display: none; height: 240px; background-image: url({{ community.header_image() }});"></div>
{% endif %}
{{ render_field(form.rules) }}
{{ render_field(form.nsfw) }}
{{ render_field(form.restricted_to_mods) }}

View file

@ -50,8 +50,25 @@
<h5> Profile Images </h5>
{{ render_field(form.profile_file) }}
<small class="field_hint">Provide a square image that looks good when small.</small>
{% if user.avatar_id %}
<p><a href="{{ user.avatar_image() }}" class="btn btn-sm btn-primary showElement" data-id="avatar_image">{{ _('View image') }}</a>
<a href="{{ url_for('user.remove_avatar') }}" class="btn btn-sm btn-primary"
hx-post="{{ url_for('user.remove_avatar') }}"
hx-target="#avatar_image"
hx-swap="outerHTML">{{ _('Remove image') }}</a>
</p>
<p><img id="avatar_image" class="community_icon_big rounded-circle" loading="lazy" style="display: none;" src="{{ user.avatar_image() }}" alt="{{ _('Profile pic') }}" /></p>
{% endif %}
{{ render_field(form.banner_file) }}
<small class="field_hint">Provide a wide image - letterbox orientation.</small>
{% if user.cover_id %}
<p><a href="{{ user.cover_image() }}" class="btn btn-sm btn-primary showElement" data-id="cover_div">{{ _('View image') }}</a> |
<a href="{{ url_for('user.remove_cover') }}" class="btn btn-sm btn-primary"
hx-post="{{ url_for('user.remove_cover') }}"
hx-target="#cover_div"
hx-swap="outerHTML">{{ _('Remove image') }}</a></p>
<div id="cover_div" class="community_header mb-4" style="display: none; height: 240px; background-image: url({{ user.cover_image() }});"></div>
{% endif %}
{{ render_field(form.submit) }}
</form>
<p class="mt-4 pt-4">

View file

@ -138,6 +138,8 @@ def edit_profile(actor):
file = save_icon_file(profile_file, 'users')
if file:
current_user.avatar = file
cache.delete_memoized(User.avatar_image, current_user)
cache.delete_memoized(User.avatar_thumbnail, current_user)
banner_file = request.files['banner_file']
if banner_file and banner_file.filename != '':
# remove old cover
@ -151,6 +153,7 @@ def edit_profile(actor):
file = save_banner_file(banner_file, 'users')
if file:
current_user.cover = file
cache.delete_memoized(User.cover_image, current_user)
db.session.commit()
@ -171,6 +174,37 @@ def edit_profile(actor):
)
@bp.route('/user/remove_avatar', methods=['GET', 'POST'])
@login_required
def remove_avatar():
if current_user.avatar_id:
current_user.avatar.delete_from_disk()
if current_user.avatar_id:
file = File.query.get(current_user.avatar_id)
file.delete_from_disk()
current_user.avatar_id = None
db.session.delete(file)
db.session.commit()
cache.delete_memoized(User.avatar_image, current_user)
cache.delete_memoized(User.avatar_thumbnail, current_user)
return _('Avatar removed!')
@bp.route('/user/remove_cover', methods=['GET', 'POST'])
@login_required
def remove_cover():
if current_user.cover_id:
current_user.cover.delete_from_disk()
if current_user.cover_id:
file = File.query.get(current_user.cover_id)
file.delete_from_disk()
current_user.cover_id = None
db.session.delete(file)
db.session.commit()
cache.delete_memoized(User.cover_image, current_user)
return '<div> ' + _('Banner removed!') + '</div>'
@bp.route('/user/settings', methods=['GET', 'POST'])
@login_required
def change_settings():