diff --git a/app/community/forms.py b/app/community/forms.py index 88a77cf1..da7ded93 100644 --- a/app/community/forms.py +++ b/app/community/forms.py @@ -176,6 +176,16 @@ class CreateImageForm(CreatePostForm): return True +class EditImageForm(CreatePostForm): + image_alt_text = StringField(_l('Alt text'), validators=[Optional(), Length(min=3, max=1500)]) + + def validate(self, extra_validators=None) -> bool: + if self.communities: + community = Community.query.get(self.communities.data) + if community.is_local() and g.site.allow_local_image_posts is False: + self.communities.errors.append(_l('Images cannot be posted to local communities.')) + + return True class CreatePollForm(CreatePostForm): mode = SelectField(_('Mode'), validators=[DataRequired()], choices=[('single', _l('Voters choose one option')), ('multiple', _l('Voters choose many options'))], render_kw={'class': 'form-select'}) diff --git a/app/community/routes.py b/app/community/routes.py index b0d73684..a59e34d3 100644 --- a/app/community/routes.py +++ b/app/community/routes.py @@ -613,9 +613,13 @@ def add_post(actor, type): form.finish_in.data = '3d' if community.posting_warning: flash(community.posting_warning) + + # empty post to pass since add_post.html extends edit_post.html + # and that one checks for a post.image_id for editing image posts + post = None return render_template('community/add_post.html', title=_('Add post to community'), form=form, - post_type=post_type, community=community, + post_type=post_type, community=community, post=post, markdown_editor=current_user.markdown_editor, low_bandwidth=False, actor=actor, moderating_communities=moderating_communities(current_user.get_id()), joined_communities=joined_communities(current_user.id), diff --git a/app/community/util.py b/app/community/util.py index 9115449b..10866585 100644 --- a/app/community/util.py +++ b/app/community/util.py @@ -301,60 +301,64 @@ def save_post(form, post: Post, type: int): elif type == POST_TYPE_IMAGE: post.type = POST_TYPE_IMAGE alt_text = form.image_alt_text.data if form.image_alt_text.data else form.title.data - uploaded_file = request.files['image_file'] - if uploaded_file and uploaded_file.filename != '': - if post.image_id: - remove_old_file(post.image_id) - post.image_id = None + if post.image_id is not None: + # editing an existing image post, dont try an upload + pass + else: + uploaded_file = request.files['image_file'] + if uploaded_file and uploaded_file.filename != '': + if post.image_id: + remove_old_file(post.image_id) + post.image_id = None - # check if this is an allowed type of file - file_ext = os.path.splitext(uploaded_file.filename)[1] - if file_ext.lower() not in allowed_extensions: - abort(400) - new_filename = gibberish(15) + # check if this is an allowed type of file + file_ext = os.path.splitext(uploaded_file.filename)[1] + if file_ext.lower() not in allowed_extensions: + abort(400) + new_filename = gibberish(15) - # set up the storage directory - directory = 'app/static/media/posts/' + new_filename[0:2] + '/' + new_filename[2:4] - ensure_directory_exists(directory) + # set up the storage directory + directory = 'app/static/media/posts/' + new_filename[0:2] + '/' + new_filename[2:4] + ensure_directory_exists(directory) - # save the file - final_place = os.path.join(directory, new_filename + file_ext) - final_place_medium = os.path.join(directory, new_filename + '_medium.webp') - final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp') - uploaded_file.seek(0) - uploaded_file.save(final_place) + # save the file + final_place = os.path.join(directory, new_filename + file_ext) + final_place_medium = os.path.join(directory, new_filename + '_medium.webp') + final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp') + uploaded_file.seek(0) + uploaded_file.save(final_place) - if file_ext.lower() == '.heic': - register_heif_opener() + if file_ext.lower() == '.heic': + register_heif_opener() - Image.MAX_IMAGE_PIXELS = 89478485 + Image.MAX_IMAGE_PIXELS = 89478485 - # resize if necessary - img = Image.open(final_place) - if '.' + img.format.lower() in allowed_extensions: - img = ImageOps.exif_transpose(img) - img_width = img.width - img_height = img.height - img.thumbnail((2000, 2000)) - img.save(final_place) - if img.width > 512 or img.height > 512: - img.thumbnail((512, 512)) - img.save(final_place_medium, format="WebP", quality=93) + # resize if necessary + img = Image.open(final_place) + if '.' + img.format.lower() in allowed_extensions: + img = ImageOps.exif_transpose(img) img_width = img.width img_height = img.height - # save a second, smaller, version as a thumbnail - img.thumbnail((170, 170)) - img.save(final_place_thumbnail, format="WebP", quality=93) - thumbnail_width = img.width - thumbnail_height = img.height + img.thumbnail((2000, 2000)) + img.save(final_place) + if img.width > 512 or img.height > 512: + img.thumbnail((512, 512)) + img.save(final_place_medium, format="WebP", quality=93) + img_width = img.width + img_height = img.height + # save a second, smaller, version as a thumbnail + img.thumbnail((170, 170)) + img.save(final_place_thumbnail, format="WebP", quality=93) + thumbnail_width = img.width + thumbnail_height = img.height - file = File(file_path=final_place_medium, file_name=new_filename + file_ext, alt_text=alt_text, - width=img_width, height=img_height, thumbnail_width=thumbnail_width, - thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail, - source_url=final_place.replace('app/static/', f"https://{current_app.config['SERVER_NAME']}/static/")) - db.session.add(file) - db.session.commit() - post.image_id = file.id + file = File(file_path=final_place_medium, file_name=new_filename + file_ext, alt_text=alt_text, + width=img_width, height=img_height, thumbnail_width=thumbnail_width, + thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail, + source_url=final_place.replace('app/static/', f"https://{current_app.config['SERVER_NAME']}/static/")) + db.session.add(file) + db.session.commit() + post.image_id = file.id elif type == POST_TYPE_VIDEO: form.video_url.data = form.video_url.data.strip() url_changed = post.id is None or form.video_url.data != post.url diff --git a/app/post/routes.py b/app/post/routes.py index 160dde99..88b12548 100644 --- a/app/post/routes.py +++ b/app/post/routes.py @@ -14,7 +14,7 @@ from app.activitypub.util import notify_about_post_reply, inform_followers_of_po from app.community.util import save_post, send_to_remote_instance from app.inoculation import inoculation from app.post.forms import NewReplyForm, ReportPostForm, MeaCulpaForm -from app.community.forms import CreateLinkForm, CreateImageForm, CreateDiscussionForm, CreateVideoForm, CreatePollForm +from app.community.forms import CreateLinkForm, CreateImageForm, CreateDiscussionForm, CreateVideoForm, CreatePollForm, EditImageForm from app.post.util import post_replies, get_comment_branch, post_reply_count, tags_to_string, url_needs_archive, \ generate_archive_link, body_has_no_archive_link from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, SUBSCRIPTION_MODERATOR, POST_TYPE_LINK, \ @@ -898,7 +898,7 @@ def post_edit(post_id: int): elif post.type == POST_TYPE_LINK: form = CreateLinkForm() elif post.type == POST_TYPE_IMAGE: - form = CreateImageForm() + form = EditImageForm() elif post.type == POST_TYPE_VIDEO: form = CreateVideoForm() elif post.type == POST_TYPE_POLL: @@ -978,6 +978,7 @@ def post_edit(post_id: int): if post.type == POST_TYPE_LINK: form.link_url.data = post.url elif post.type == POST_TYPE_IMAGE: + # existing_image = True form.image_alt_text.data = post.image.alt_text elif post.type == POST_TYPE_VIDEO: form.video_url.data = post.url @@ -994,7 +995,7 @@ def post_edit(post_id: int): if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()): form.sticky.render_kw = {'disabled': True} return render_template('post/post_edit.html', title=_('Edit post'), form=form, - post_type=post.type, community=post.community, + post_type=post.type, community=post.community, post=post, markdown_editor=current_user.markdown_editor, mods=mod_list, moderating_communities=moderating_communities(current_user.get_id()), joined_communities=joined_communities(current_user.get_id()), diff --git a/app/templates/post/post_edit.html b/app/templates/post/post_edit.html index 7cf05a66..1fc96591 100644 --- a/app/templates/post/post_edit.html +++ b/app/templates/post/post_edit.html @@ -17,7 +17,24 @@ {{ render_field(form.link_url) }}
{% elif post_type == POST_TYPE_IMAGE %} - {{ render_field(form.image_file) }} + {% if post.image_id -%} +
+ {% if low_bandwidth -%} + {{ post.image.alt_text if post.image.alt_text else post.title }} + {% else -%} + + {{ post.image.alt_text if post.image.alt_text else post.title }} + + {% endif -%} +
+ {% else %} + {{ render_field(form.image_file) }} + {% endif %} {{ render_field(form.image_alt_text) }} {{ _('Describe the image, to help visually impaired people.') }} {% elif post_type == POST_TYPE_VIDEO %}