Merge pull request 'Adjusting the post editing for images to display the existing image' (#297) from JollyDevelopment/pyfedi:jollydev/edit-image-posts-uses-existing-image into main

Reviewed-on: https://codeberg.org/rimu/pyfedi/pulls/297
This commit is contained in:
rimu 2024-08-18 01:55:52 +00:00
commit 0f4863afcf
5 changed files with 86 additions and 50 deletions

View file

@ -176,6 +176,16 @@ class CreateImageForm(CreatePostForm):
return True 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): 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'}) mode = SelectField(_('Mode'), validators=[DataRequired()], choices=[('single', _l('Voters choose one option')), ('multiple', _l('Voters choose many options'))], render_kw={'class': 'form-select'})

View file

@ -613,9 +613,13 @@ def add_post(actor, type):
form.finish_in.data = '3d' form.finish_in.data = '3d'
if community.posting_warning: if community.posting_warning:
flash(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, 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, markdown_editor=current_user.markdown_editor, low_bandwidth=False, actor=actor,
moderating_communities=moderating_communities(current_user.get_id()), moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.id), joined_communities=joined_communities(current_user.id),

View file

@ -301,60 +301,64 @@ def save_post(form, post: Post, type: int):
elif type == POST_TYPE_IMAGE: elif type == POST_TYPE_IMAGE:
post.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 alt_text = form.image_alt_text.data if form.image_alt_text.data else form.title.data
uploaded_file = request.files['image_file'] if post.image_id is not None:
if uploaded_file and uploaded_file.filename != '': # editing an existing image post, dont try an upload
if post.image_id: pass
remove_old_file(post.image_id) else:
post.image_id = None 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 # check if this is an allowed type of file
file_ext = os.path.splitext(uploaded_file.filename)[1] file_ext = os.path.splitext(uploaded_file.filename)[1]
if file_ext.lower() not in allowed_extensions: if file_ext.lower() not in allowed_extensions:
abort(400) abort(400)
new_filename = gibberish(15) new_filename = gibberish(15)
# set up the storage directory # set up the storage directory
directory = 'app/static/media/posts/' + new_filename[0:2] + '/' + new_filename[2:4] directory = 'app/static/media/posts/' + new_filename[0:2] + '/' + new_filename[2:4]
ensure_directory_exists(directory) ensure_directory_exists(directory)
# save the file # save the file
final_place = os.path.join(directory, new_filename + file_ext) final_place = os.path.join(directory, new_filename + file_ext)
final_place_medium = os.path.join(directory, new_filename + '_medium.webp') final_place_medium = os.path.join(directory, new_filename + '_medium.webp')
final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp') final_place_thumbnail = os.path.join(directory, new_filename + '_thumbnail.webp')
uploaded_file.seek(0) uploaded_file.seek(0)
uploaded_file.save(final_place) uploaded_file.save(final_place)
if file_ext.lower() == '.heic': if file_ext.lower() == '.heic':
register_heif_opener() register_heif_opener()
Image.MAX_IMAGE_PIXELS = 89478485 Image.MAX_IMAGE_PIXELS = 89478485
# resize if necessary # resize if necessary
img = Image.open(final_place) img = Image.open(final_place)
if '.' + img.format.lower() in allowed_extensions: if '.' + img.format.lower() in allowed_extensions:
img = ImageOps.exif_transpose(img) 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)
img_width = img.width img_width = img.width
img_height = img.height img_height = img.height
# save a second, smaller, version as a thumbnail img.thumbnail((2000, 2000))
img.thumbnail((170, 170)) img.save(final_place)
img.save(final_place_thumbnail, format="WebP", quality=93) if img.width > 512 or img.height > 512:
thumbnail_width = img.width img.thumbnail((512, 512))
thumbnail_height = img.height 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, 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, width=img_width, height=img_height, thumbnail_width=thumbnail_width,
thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail, thumbnail_height=thumbnail_height, thumbnail_path=final_place_thumbnail,
source_url=final_place.replace('app/static/', f"https://{current_app.config['SERVER_NAME']}/static/")) source_url=final_place.replace('app/static/', f"https://{current_app.config['SERVER_NAME']}/static/"))
db.session.add(file) db.session.add(file)
db.session.commit() db.session.commit()
post.image_id = file.id post.image_id = file.id
elif type == POST_TYPE_VIDEO: elif type == POST_TYPE_VIDEO:
form.video_url.data = form.video_url.data.strip() form.video_url.data = form.video_url.data.strip()
url_changed = post.id is None or form.video_url.data != post.url url_changed = post.id is None or form.video_url.data != post.url

View file

@ -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.community.util import save_post, send_to_remote_instance
from app.inoculation import inoculation from app.inoculation import inoculation
from app.post.forms import NewReplyForm, ReportPostForm, MeaCulpaForm 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, \ 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 generate_archive_link, body_has_no_archive_link
from app.constants import SUBSCRIPTION_MEMBER, SUBSCRIPTION_OWNER, SUBSCRIPTION_MODERATOR, POST_TYPE_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: elif post.type == POST_TYPE_LINK:
form = CreateLinkForm() form = CreateLinkForm()
elif post.type == POST_TYPE_IMAGE: elif post.type == POST_TYPE_IMAGE:
form = CreateImageForm() form = EditImageForm()
elif post.type == POST_TYPE_VIDEO: elif post.type == POST_TYPE_VIDEO:
form = CreateVideoForm() form = CreateVideoForm()
elif post.type == POST_TYPE_POLL: elif post.type == POST_TYPE_POLL:
@ -978,6 +978,7 @@ def post_edit(post_id: int):
if post.type == POST_TYPE_LINK: if post.type == POST_TYPE_LINK:
form.link_url.data = post.url form.link_url.data = post.url
elif post.type == POST_TYPE_IMAGE: elif post.type == POST_TYPE_IMAGE:
# existing_image = True
form.image_alt_text.data = post.image.alt_text form.image_alt_text.data = post.image.alt_text
elif post.type == POST_TYPE_VIDEO: elif post.type == POST_TYPE_VIDEO:
form.video_url.data = post.url 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()): if not (post.community.is_moderator() or post.community.is_owner() or current_user.is_admin()):
form.sticky.render_kw = {'disabled': True} form.sticky.render_kw = {'disabled': True}
return render_template('post/post_edit.html', title=_('Edit post'), form=form, 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, markdown_editor=current_user.markdown_editor, mods=mod_list,
moderating_communities=moderating_communities(current_user.get_id()), moderating_communities=moderating_communities(current_user.get_id()),
joined_communities=joined_communities(current_user.get_id()), joined_communities=joined_communities(current_user.get_id()),

View file

@ -17,7 +17,24 @@
{{ render_field(form.link_url) }} {{ render_field(form.link_url) }}
<div id="urlUsed"></div> <div id="urlUsed"></div>
{% elif post_type == POST_TYPE_IMAGE %} {% elif post_type == POST_TYPE_IMAGE %}
{{ render_field(form.image_file) }} {% if post.image_id -%}
<div class="post_image">
{% if low_bandwidth -%}
<a href="{{ post.image.view_url(resize=True) }}" rel="nofollow ugc"><img src="{{ post.image.medium_url() }}"
alt="{{ post.image.alt_text if post.image.alt_text else post.title }}" fetchpriority="high" referrerpolicy="same-origin"
width="{{ post.image.width }}" height="{{ post.image.height }}" /></a>
{% else -%}
<a href="{{ post.image.view_url() }}" rel="nofollow ugc">
<img src="{{ post.image.view_url(resize=True) }}" lowsrc="{{ post.image.medium_url() }}"
sizes="(max-width: 512px) 100vw, 854px" srcset="{{ post.image.medium_url() }} 512w, {{ post.image.view_url(resize=True) }} 1024w"
alt="{{ post.image.alt_text if post.image.alt_text else post.title }}"
fetchpriority="high" referrerpolicy="same-origin" >
</a>
{% endif -%}
</div>
{% else %}
{{ render_field(form.image_file) }}
{% endif %}
{{ render_field(form.image_alt_text) }} {{ render_field(form.image_alt_text) }}
<small class="field_hint">{{ _('Describe the image, to help visually impaired people.') }}</small> <small class="field_hint">{{ _('Describe the image, to help visually impaired people.') }}</small>
{% elif post_type == POST_TYPE_VIDEO %} {% elif post_type == POST_TYPE_VIDEO %}