Added possibility to edit images in Image posts

This commit is contained in:
mtyton 2024-12-14 23:30:45 +01:00
parent 2fa98b26ef
commit 79b3797b5f
6 changed files with 82 additions and 59 deletions

View file

@ -178,9 +178,9 @@ class CreateImageForm(CreatePostForm):
return True
class EditImageForm(CreatePostForm):
image_alt_text = StringField(_l('Alt text'), validators=[Optional(), Length(min=3, max=1500)])
class EditImageForm(CreateImageForm):
image_file = FileField(_l('Replace Image'), validators=[DataRequired()], render_kw={'accept': 'image/*'})
def validate(self, extra_validators=None) -> bool:
if self.communities:
community = Community.query.get(self.communities.data)

View file

@ -688,8 +688,13 @@ def add_post(actor, type):
img.thumbnail((2000, 2000))
img.save(final_place)
request_json['object']['attachment'] = [{'type': 'Image', 'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}',
'name': form.image_alt_text.data}]
request_json['object']['attachment'] = [{
'type': 'Image',
'url': f'https://{current_app.config["SERVER_NAME"]}/{final_place.replace("app/", "")}',
'name': form.image_alt_text.data,
'file_path': final_place
}]
elif type == 'video':
request_json['object']['attachment'] = [{'type': 'Document', 'url': form.video_url.data}]
elif type == 'poll':

View file

@ -304,66 +304,72 @@ 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
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
uploaded_file = request.files['image_file']
# If we are uploading new file in the place of existing one just remove the old one
if post.image_id is not None and uploaded_file:
post.image.delete_from_disk()
image_id = post.image_id
post.image_id = None
db.session.add(post)
db.session.commit()
File.query.filter_by(id=image_id).delete()
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)
# resize if necessary
img = Image.open(final_place)
if '.' + img.format.lower() in allowed_extensions:
img = ImageOps.exif_transpose(img)
# limit full sized version to 2000px
img_width = img.width
img_height = img.height
img.thumbnail((2000, 2000))
img.save(final_place)
# limit full sized version to 2000px
img_width = img.width
img_height = img.height
img.thumbnail((2000, 2000))
img.save(final_place)
# medium sized version
img.thumbnail((512, 512))
img.save(final_place_medium, format="WebP", quality=93)
# medium sized version
img.thumbnail((512, 512))
img.save(final_place_medium, format="WebP", quality=93)
# save a third, 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
# save a third, 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

View file

@ -323,7 +323,6 @@ class File(db.Model):
if purge_from_cache:
flush_cdn_cache(purge_from_cache)
def filesize(self):
size = 0
if self.file_path and os.path.exists(self.file_path):
@ -1242,9 +1241,10 @@ class Post(db.Model):
if 'name' in request_json['object']['attachment'][0]:
alt_text = request_json['object']['attachment'][0]['name']
if request_json['object']['attachment'][0]['type'] == 'Image':
post.url = request_json['object']['attachment'][0]['url'] # PixelFed, PieFed, Lemmy >= 0.19.4
if 'name' in request_json['object']['attachment'][0]:
alt_text = request_json['object']['attachment'][0]['name']
attachment = request_json['object']['attachment'][0]
post.url = attachment['url'] # PixelFed, PieFed, Lemmy >= 0.19.4
alt_text = attachment.get("name")
file_path = attachment.get("file_path")
if 'attachment' in request_json['object'] and isinstance(request_json['object']['attachment'], dict): # a.gup.pe (Mastodon)
alt_text = None
@ -1256,6 +1256,8 @@ class Post(db.Model):
image = File(source_url=post.url)
if alt_text:
image.alt_text = alt_text
if file_path:
image.file_path = file_path
db.session.add(image)
post.image = image
elif is_video_url(post.url): # youtube is detected later

View file

@ -817,6 +817,15 @@ def post_edit(post_id: int):
elif post.type == POST_TYPE_IMAGE:
# existing_image = True
form.image_alt_text.data = post.image.alt_text
path = post.image.file_path
# This is fallback for existing entries
if not path:
path = "app/" + post.image.source_url.replace(
f"https://{current_app.config['SERVER_NAME']}/", ""
)
with open(path, "rb")as file:
form.image_file.data = file.read()
elif post.type == POST_TYPE_VIDEO:
form.video_url.data = post.url
elif post.type == POST_TYPE_POLL:

View file

@ -35,6 +35,7 @@
{% else %}
{{ render_field(form.image_file) }}
{% endif %}
{{ render_field(form.image_file) }}
{{ render_field(form.image_alt_text) }}
<small class="field_hint">{{ _('Describe the image, to help visually impaired people.') }}</small>
{% elif post_type == POST_TYPE_VIDEO %}