mirror of
https://code.castopod.org/adaures/castopod
synced 2025-04-19 13:01:19 +00:00
feat: add replied to post or comment to reply element
This commit is contained in:
parent
8208ab6785
commit
d0f9c6018f
@ -47,6 +47,8 @@ class EpisodeComment extends UuidEntity
|
||||
*/
|
||||
protected ?array $replies = null;
|
||||
|
||||
protected bool $has_replies = false;
|
||||
|
||||
/**
|
||||
* @var string[]
|
||||
*/
|
||||
@ -115,6 +117,11 @@ class EpisodeComment extends UuidEntity
|
||||
return $this->replies;
|
||||
}
|
||||
|
||||
public function getHasReplies(): bool
|
||||
{
|
||||
return $this->getReplies() !== null;
|
||||
}
|
||||
|
||||
public function getReplyToComment(): ?self
|
||||
{
|
||||
if ($this->in_reply_to_id === null) {
|
||||
|
@ -1,4 +1,10 @@
|
||||
@layer components {
|
||||
.post-content {
|
||||
& a {
|
||||
@apply text-sm font-semibold text-pine-600 hover:underline;
|
||||
}
|
||||
}
|
||||
|
||||
.ring-castopod {
|
||||
@apply outline-none ring-2 ring-pine-500 ring-offset-2 ring-offset-pine-100;
|
||||
}
|
||||
|
@ -7,7 +7,6 @@
|
||||
@import "./radioBtn.css";
|
||||
@import "./switch.css";
|
||||
@import "./charts.css";
|
||||
@import "./post.css";
|
||||
@import "./radioToggler.css";
|
||||
@import "./formInputTabs.css";
|
||||
@import "./stickyHeader.css";
|
||||
|
@ -1,22 +0,0 @@
|
||||
@layer components {
|
||||
.post-content {
|
||||
& a {
|
||||
@apply text-sm font-semibold text-pine-600 hover:underline;
|
||||
}
|
||||
}
|
||||
|
||||
.post-replies > * {
|
||||
@apply relative;
|
||||
|
||||
& img {
|
||||
@apply z-20;
|
||||
}
|
||||
|
||||
&:not(:last-child)::before {
|
||||
@apply absolute z-10 h-full bg-gray-300 top-8;
|
||||
content: "";
|
||||
left: 3rem;
|
||||
width: 2px;
|
||||
}
|
||||
}
|
||||
}
|
@ -27,8 +27,8 @@
|
||||
) ?></label>
|
||||
<small class="max-w-md mb-2 text-gray-600"><?= lang('Episode.publish_form.post_hint') ?></small>
|
||||
<div class="mb-8 overflow-hidden bg-white shadow-md rounded-xl">
|
||||
<div class="flex px-4 py-3">
|
||||
<img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast->actor->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
<div class="flex px-4 py-3 gap-x-2">
|
||||
<img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast->actor->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col min-w-0">
|
||||
<p class="flex items-baseline min-w-0">
|
||||
<span class="mr-2 font-semibold truncate"><?= $podcast->actor->display_name ?></span>
|
||||
|
@ -28,8 +28,8 @@
|
||||
) ?></label>
|
||||
<small class="max-w-md mb-2 text-gray-600"><?= lang('Episode.publish_form.post_hint') ?></small>
|
||||
<div class="mb-8 overflow-hidden bg-white shadow-md rounded-xl">
|
||||
<div class="flex px-4 py-3">
|
||||
<img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast->actor->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
<div class="flex px-4 py-3 gap-x-2">
|
||||
<img src="<?= $podcast->actor->avatar_image_url ?>" alt="<?= $podcast->actor->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col min-w-0">
|
||||
<p class="flex items-baseline min-w-0">
|
||||
<span class="mr-2 font-semibold truncate"><?= $podcast->actor->display_name ?></span>
|
||||
|
@ -1,5 +1,5 @@
|
||||
<article class="relative z-10 flex w-full px-4 py-2 rounded-conditional-2xl">
|
||||
<img src="<?= $comment->actor->avatar_image_url ?>" alt="<?= $comment->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
<article class="relative z-10 flex w-full px-4 py-2 rounded-conditional-2xl gap-x-2">
|
||||
<img src="<?= $comment->actor->avatar_image_url ?>" alt="<?= $comment->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex-1">
|
||||
<header class="w-full mb-2 text-sm">
|
||||
<a href="<?= $comment->actor
|
||||
|
@ -1,5 +1,5 @@
|
||||
<article class="relative z-10 flex w-full p-4 bg-white shadow rounded-conditional-2xl">
|
||||
<img src="<?= $comment->actor->avatar_image_url ?>" alt="<?= $comment->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
<article class="relative z-10 flex w-full p-4 bg-white shadow rounded-conditional-2xl gap-x-2">
|
||||
<img src="<?= $comment->actor->avatar_image_url ?>" alt="<?= $comment->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex-1">
|
||||
<header class="w-full mb-2 text-sm">
|
||||
<a href="<?= $comment->actor->uri ?>" class="flex items-baseline hover:underline" <?= $comment->actor->is_local
|
||||
|
@ -1,6 +1,6 @@
|
||||
<article class="flex px-6 py-4 bg-gray-50">
|
||||
<article class="flex px-6 py-4 bg-gray-50 gap-x-2">
|
||||
<img src="<?= $reply->actor->avatar_image_url ?>" alt="<?= $reply->actor
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full ring-gray-50 ring-2" />
|
||||
->display_name ?>" class="z-10 w-10 h-10 rounded-full ring-gray-50 ring-2" />
|
||||
<div class="flex flex-col flex-1 min-w-0">
|
||||
<header class="flex items-center mb-2">
|
||||
<a href="<?= $reply->actor
|
||||
|
@ -6,7 +6,7 @@
|
||||
[
|
||||
'numberOfLikes' => $reply->likes_count,
|
||||
],
|
||||
) ?>"><?= icon('heart', 'text-xl mr-1 text-gray-400 group-hover:text-red-600') . $reply->likes_count ?></button>
|
||||
) ?>"><?= icon('heart', 'text-lg mr-1 text-gray-400 group-hover:text-red-600') . $reply->likes_count ?></button>
|
||||
<Button uri="<?= route_to('episode-comment', $reply->episode->podcast->handle, $reply->episode->slug, $reply->id) ?>" size="small"><?= lang('Comment.reply') ?></Button>
|
||||
</form>
|
||||
<?php else: ?>
|
||||
@ -15,7 +15,7 @@
|
||||
[
|
||||
'numberOfLikes' => $reply->likes_count,
|
||||
],
|
||||
) ?>"><?= icon('heart', 'text-xl mr-1 text-gray-500') . $reply->likes_count ?></button>
|
||||
) ?>"><?= icon('heart', 'text-lg mr-1 text-gray-500') . $reply->likes_count ?></button>
|
||||
<?php if ($reply->replies_count): ?>
|
||||
<?= anchor(
|
||||
route_to('episode-comment', $reply->episode->podcast->handle, $reply->episode->slug, $reply->id),
|
||||
|
@ -1,11 +1,21 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
if ($comment->in_reply_to_id): ?>
|
||||
<div class="relative -mb-2 overflow-hidden border-t border-l border-r rounded-t-xl">
|
||||
<div class="absolute z-0 w-[2px] h-full bg-gray-300 left-[43px] top-4"></div>
|
||||
<?= view('episode/_partials/comment_reply', [
|
||||
'reply' => $comment->reply_to_comment,
|
||||
]) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?= $this->include('episode/_partials/comment_card') ?>
|
||||
<div class="-mt-2 overflow-hidden border-b border-l border-r post-replies rounded-b-xl">
|
||||
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('comment-attempt-reply', $podcast->id, $episode->id, $comment->id) ?>" method="POST" class="flex px-6 pt-8 pb-4 bg-gray-50">
|
||||
<form action="<?= route_to('comment-attempt-reply', $podcast->id, $episode->id, $comment->id) ?>" method="POST" class="flex px-6 pt-8 pb-4 gap-x-2 bg-gray-50">
|
||||
<img src="<?= interact_as_actor()
|
||||
->avatar_image_url ?>" alt="<?= interact_as_actor()
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full ring-gray-50 ring-2" />
|
||||
->display_name ?>" class="w-10 h-10 rounded-full ring-gray-50 ring-2" />
|
||||
<div class="flex flex-col flex-1">
|
||||
<Forms.Textarea
|
||||
name="message"
|
||||
@ -20,10 +30,14 @@
|
||||
</form>
|
||||
<?php endif; ?>
|
||||
|
||||
<?php foreach ($comment->replies as $reply): ?>
|
||||
<?= view('episode/_partials/comment_reply', [
|
||||
'reply' => $reply,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
<?php if ($comment->has_replies): ?>
|
||||
<div class="border-t divide-y">
|
||||
<?php foreach ($comment->replies as $reply): ?>
|
||||
<?= view('episode/_partials/comment_reply', [
|
||||
'reply' => $reply,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
|
||||
</div>
|
||||
|
@ -35,14 +35,13 @@
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('post-attempt-create', $podcast->handle) ?>" method="POST" class="flex p-4 bg-white shadow rounded-conditional-2xl">
|
||||
<?= view('_message_block') ?>
|
||||
<form action="<?= route_to('post-attempt-create', $podcast->handle) ?>" method="POST" class="flex p-4 bg-white shadow gap-x-2 rounded-conditional-2xl">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<?= view('_message_block') ?>
|
||||
|
||||
<img src="<?= interact_as_actor()
|
||||
->avatar_image_url ?>" alt="<?= interact_as_actor()
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col flex-1 min-w-0 gap-y-2">
|
||||
<input name="episode_url" value="<?= $episode->link ?>" type="hidden" />
|
||||
<Forms.Textarea
|
||||
|
@ -37,14 +37,13 @@
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('comment-attempt-create', $podcast->id, $episode->id) ?>" method="POST" class="flex p-4">
|
||||
<?= view('_message_block') ?>
|
||||
<form action="<?= route_to('comment-attempt-create', $podcast->id, $episode->id) ?>" method="POST" class="flex p-4 gap-x-2">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<?= view('_message_block') ?>
|
||||
|
||||
<img src="<?= interact_as_actor()
|
||||
->avatar_image_url ?>" alt="<?= interact_as_actor()
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col flex-1 min-w-0 gap-y-2">
|
||||
<Forms.Textarea
|
||||
name="message"
|
||||
|
@ -28,14 +28,14 @@
|
||||
<?= $this->section('content') ?>
|
||||
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('post-attempt-create', interact_as_actor()->username) ?>" method="POST" class="flex p-4 bg-white shadow rounded-conditional-2xl">
|
||||
<form action="<?= route_to('post-attempt-create', interact_as_actor()->username) ?>" method="POST" class="flex p-4 bg-white shadow gap-x-2 rounded-conditional-2xl">
|
||||
<?= csrf_field() ?>
|
||||
|
||||
<?= view('_message_block') ?>
|
||||
|
||||
<img src="<?= interact_as_actor()
|
||||
->avatar_image_url ?>" alt="<?= interact_as_actor()
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col flex-1 min-w-0 gap-y-2">
|
||||
<Forms.Textarea
|
||||
name="message"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<article class="relative z-10 w-full bg-white shadow sm:rounded-conditional-2xl">
|
||||
<header class="flex px-6 py-4">
|
||||
<header class="flex px-6 py-4 gap-x-2">
|
||||
<img src="<?= $post->actor
|
||||
->avatar_image_url ?>" alt="<?= $post->actor->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
->avatar_image_url ?>" alt="<?= $post->actor->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col min-w-0">
|
||||
<a href="<?= $post->actor
|
||||
->uri ?>" class="flex items-baseline hover:underline" <?= $post
|
||||
|
@ -1,3 +1,14 @@
|
||||
<?php declare(strict_types=1);
|
||||
|
||||
if ($post->in_reply_to_id): ?>
|
||||
<div class="relative -mb-2 overflow-hidden border-t border-l border-r rounded-t-xl">
|
||||
<div class="absolute z-0 w-[2px] h-full bg-gray-300 left-[43px] top-4"></div>
|
||||
<?= view('post/_partials/reply', [
|
||||
'podcast' => $podcast,
|
||||
'reply' => $post->reply_to_post,
|
||||
]) ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
<?= view('post/_partials/card', [
|
||||
'index' => $index,
|
||||
'post' => $post,
|
||||
@ -6,10 +17,10 @@
|
||||
<div class="-mt-2 overflow-hidden border-b border-l border-r post-replies rounded-b-xl">
|
||||
<div class="px-6 pt-8 pb-4 bg-gray-50">
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('post-attempt-action', interact_as_actor()->username, $post->id) ?>" method="POST" class="flex" >
|
||||
<form action="<?= route_to('post-attempt-action', interact_as_actor()->username, $post->id) ?>" method="POST" class="flex gap-x-2" >
|
||||
<img src="<?= interact_as_actor()
|
||||
->avatar_image_url ?>" alt="<?= interact_as_actor()
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full ring-gray-50 ring-2" />
|
||||
->display_name ?>" class="w-10 h-10 rounded-full ring-gray-50 ring-2" />
|
||||
<div class="flex flex-col flex-1">
|
||||
<Forms.Textarea
|
||||
name="message"
|
||||
@ -39,11 +50,13 @@
|
||||
</div>
|
||||
|
||||
<?php if ($post->has_replies): ?>
|
||||
<div class="border-t divide-y">
|
||||
<?php foreach ($post->replies as $reply): ?>
|
||||
<?= view('post/_partials/reply', [
|
||||
'podcast' => $podcast,
|
||||
'reply' => $reply,
|
||||
]) ?>
|
||||
<?php endforeach; ?>
|
||||
</div>
|
||||
<?php endif; ?>
|
||||
</div>
|
@ -6,9 +6,9 @@
|
||||
lang('Post.actor_shared', [
|
||||
'actor' => $post->actor->display_name,
|
||||
]) ?></p>
|
||||
<header class="flex px-6 py-4">
|
||||
<header class="flex px-6 py-4 gap-x-2">
|
||||
<img src="<?= $post->actor
|
||||
->avatar_image_url ?>" alt="<?= $post->display_name ?>" class="w-10 h-10 mr-2 rounded-full" />
|
||||
->avatar_image_url ?>" alt="<?= $post->display_name ?>" class="w-10 h-10 rounded-full" />
|
||||
<div class="flex flex-col min-w-0">
|
||||
<a href="<?= $post->actor
|
||||
->uri ?>" class="flex items-baseline hover:underline" <?= $post
|
||||
|
@ -1,6 +1,6 @@
|
||||
<article class="flex px-6 py-4 bg-gray-50">
|
||||
<article class="flex px-6 py-4 bg-gray-50 gap-x-2">
|
||||
<img src="<?= $reply->actor->avatar_image_url ?>" alt="<?= $reply->actor
|
||||
->display_name ?>" class="w-10 h-10 mr-2 rounded-full ring-gray-50 ring-2" />
|
||||
->display_name ?>" class="z-10 w-10 h-10 rounded-full ring-gray-50 ring-2" />
|
||||
<div class="flex flex-col flex-1 min-w-0">
|
||||
<header class="flex items-center mb-2">
|
||||
<a href="<?= $reply->actor
|
||||
|
@ -1,30 +1,30 @@
|
||||
<footer>
|
||||
<?php if (can_user_interact()): ?>
|
||||
<form action="<?= route_to('post-attempt-action', interact_as_actor()->username, $reply->id) ?>" method="POST" class="flex items-start">
|
||||
<form action="<?= route_to('post-attempt-action', interact_as_actor()->username, $reply->id) ?>" method="POST" class="flex items-start gap-x-6">
|
||||
<?= csrf_field() ?>
|
||||
<?= anchor(
|
||||
route_to('post', $podcast->handle, $reply->id),
|
||||
icon('chat', 'text-xl mr-1 text-gray-400') . $reply->replies_count,
|
||||
icon('chat', 'text-lg mr-1 text-gray-400') . $reply->replies_count,
|
||||
[
|
||||
'class' => 'inline-flex items-center mr-6 hover:underline',
|
||||
'class' => 'inline-flex items-center hover:underline text-sm',
|
||||
'title' => lang('Post.replies', [
|
||||
'numberOfReplies' => $reply->replies_count,
|
||||
]),
|
||||
],
|
||||
) ?>
|
||||
<button type="submit" name="action" value="reblog" class="inline-flex items-center mr-6 hover:underline" title="<?= lang(
|
||||
<button type="submit" name="action" value="reblog" class="inline-flex items-center text-sm hover:underline" title="<?= lang(
|
||||
'Post.reblogs',
|
||||
[
|
||||
'numberOfReblogs' => $reply->reblogs_count,
|
||||
],
|
||||
) ?>"><?= icon('repeat', 'text-xl mr-1 text-gray-400') .
|
||||
) ?>"><?= icon('repeat', 'text-lg mr-1 text-gray-400') .
|
||||
$reply->reblogs_count ?></button>
|
||||
<button type="submit" name="action" value="favourite" class="inline-flex items-center mr-6 hover:underline" title="<?= lang(
|
||||
<button type="submit" name="action" value="favourite" class="inline-flex items-center text-sm hover:underline" title="<?= lang(
|
||||
'Post.favourites',
|
||||
[
|
||||
'numberOfFavourites' => $reply->favourites_count,
|
||||
],
|
||||
) ?>"><?= icon('heart', 'text-xl mr-1 text-gray-400') .
|
||||
) ?>"><?= icon('heart', 'text-lg mr-1 text-gray-400') .
|
||||
$reply->favourites_count ?></button>
|
||||
<button id="<?= $reply->id .
|
||||
'-more-dropdown' ?>" type="button" class="text-xl text-gray-500 focus:ring-castopod" data-dropdown="button" data-dropdown-target="<?= $reply->id .
|
||||
@ -88,9 +88,9 @@
|
||||
<?php else: ?>
|
||||
<?= anchor(
|
||||
route_to('post', $podcast->handle, $reply->id),
|
||||
icon('chat', 'text-xl mr-1 text-gray-400') . $reply->replies_count,
|
||||
icon('chat', 'text-lg mr-1 text-gray-400') . $reply->replies_count,
|
||||
[
|
||||
'class' => 'inline-flex items-center hover:underline',
|
||||
'class' => 'inline-flex items-center hover:underline text-sm',
|
||||
'title' => lang('Post.replies', [
|
||||
'numberOfReplies' => $reply->replies_count,
|
||||
]),
|
||||
@ -98,9 +98,9 @@
|
||||
) ?>
|
||||
<?= anchor_popup(
|
||||
route_to('post-remote-action', $podcast->handle, $reply->id, 'reblog'),
|
||||
icon('repeat', 'text-xl mr-1 text-gray-400') . $reply->reblogs_count,
|
||||
icon('repeat', 'text-lg mr-1 text-gray-400') . $reply->reblogs_count,
|
||||
[
|
||||
'class' => 'inline-flex items-center hover:underline',
|
||||
'class' => 'inline-flex items-center hover:underline text-sm',
|
||||
'width' => 420,
|
||||
'height' => 620,
|
||||
'title' => lang('Post.reblogs', [
|
||||
@ -110,9 +110,9 @@
|
||||
) ?>
|
||||
<?= anchor_popup(
|
||||
route_to('post-remote-action', $podcast->handle, $reply->id, 'favourite'),
|
||||
icon('heart', 'text-xl mr-1 text-gray-400') . $reply->favourites_count,
|
||||
icon('heart', 'text-lg mr-1 text-gray-400') . $reply->favourites_count,
|
||||
[
|
||||
'class' => 'inline-flex items-center hover:underline',
|
||||
'class' => 'inline-flex items-center hover:underline text-sm',
|
||||
'width' => 420,
|
||||
'height' => 620,
|
||||
'title' => lang('Post.favourites', [
|
||||
|
Loading…
x
Reference in New Issue
Block a user