From d1f7d35a836e1ba82fdb890a516df35d757a9c62 Mon Sep 17 00:00:00 2001 From: rimu <3310831+rimu@users.noreply.github.com> Date: Sun, 26 May 2024 18:24:13 +1200 Subject: [PATCH] users can remove profile pics (communities too) --- app/activitypub/util.py | 3 ++ app/community/routes.py | 34 +++++++++++++++++++++ app/models.py | 5 +-- app/static/js/scripts.js | 21 ++++++++++++- app/templates/community/community_edit.html | 18 +++++++++-- app/templates/user/edit_profile.html | 17 +++++++++++ app/user/routes.py | 34 +++++++++++++++++++++ 7 files changed, 127 insertions(+), 5 deletions(-) diff --git a/app/activitypub/util.py b/app/activitypub/util.py index 8d30901e..9e137da4 100644 --- a/app/activitypub/util.py +++ b/app/activitypub/util.py @@ -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): diff --git a/app/community/routes.py b/app/community/routes.py index 067baae2..b1c76f3a 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -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//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//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 '
' + _('Banner removed!') + '
' + + @bp.route('/community//delete', methods=['GET', 'POST']) @login_required def community_delete(community_id: int): diff --git a/app/models.py b/app/models.py index dce7e51d..dc2b92ec 100644 --- a/app/models.py +++ b/app/models.py @@ -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: diff --git a/app/static/js/scripts.js b/app/static/js/scripts.js index 23a6ff1b..f7128841 100644 --- a/app/static/js/scripts.js +++ b/app/static/js/scripts.js @@ -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++) { diff --git a/app/templates/community/community_edit.html b/app/templates/community/community_edit.html index ca4ea2c6..a5267cd6 100644 --- a/app/templates/community/community_edit.html +++ b/app/templates/community/community_edit.html @@ -31,15 +31,29 @@ {{ render_field(form.title) }} {{ render_field(form.description) }} {% if community.icon_id %} - + {% endif %} {{ render_field(form.icon_file) }} Provide a square image that looks good when small. {% if community.image_id %} - + + {% endif %} + {% if community.icon_id %} +

{{ _('View image') }} + {{ _('Delete image') }} +

+

{% endif %} {{ render_field(form.banner_file) }} Provide a wide image - letterbox orientation. + {% if community.image_id %} +

{{ _('View image') }} + {{ _('Delete image') }} +

+ + {% endif %} {{ render_field(form.rules) }} {{ render_field(form.nsfw) }} {{ render_field(form.restricted_to_mods) }} diff --git a/app/templates/user/edit_profile.html b/app/templates/user/edit_profile.html index c3731876..55e1e364 100644 --- a/app/templates/user/edit_profile.html +++ b/app/templates/user/edit_profile.html @@ -50,8 +50,25 @@
Profile Images
{{ render_field(form.profile_file) }} Provide a square image that looks good when small. + {% if user.avatar_id %} +

{{ _('View image') }} + {{ _('Remove image') }} +

+

+ {% endif %} {{ render_field(form.banner_file) }} Provide a wide image - letterbox orientation. + {% if user.cover_id %} +

{{ _('View image') }} | + {{ _('Remove image') }}

+ + {% endif %} {{ render_field(form.submit) }}

diff --git a/app/user/routes.py b/app/user/routes.py index a530d12c..75a18acf 100644 --- a/app/user/routes.py +++ b/app/user/routes.py @@ -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 '

' + _('Banner removed!') + '
' + + @bp.route('/user/settings', methods=['GET', 'POST']) @login_required def change_settings():