Skip to content

Commit

Permalink
Implement message federation and redesign message view (#830)
Browse files Browse the repository at this point in the history
Co-authored-by: Melroy van den Berg <[email protected]>
  • Loading branch information
BentiGorlich and melroy89 authored Jun 30, 2024
1 parent c3309ae commit 4266dab
Show file tree
Hide file tree
Showing 27 changed files with 600 additions and 104 deletions.
67 changes: 63 additions & 4 deletions assets/styles/components/_messages.scss
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,69 @@
gap: .5rem;
justify-content: space-between;
}
}

.page-messages {
.meta {
margin-bottom: 1.5rem;
.message-view {
max-height: calc(100vh - 11em);
overflow: auto;
position: relative;
}

.thread-participants {
position: absolute;
}

.section--top {
padding: .25em;
}

.message {
max-width: 75%;
width: fit-content;
min-width: 20%;
padding: .25em .5em;

p {
margin-bottom: .25em;
}
}

.message-self {
margin-left: auto;
}

.message-other {

}

.col {
flex: 1 1 auto;
margin-bottom: 0;
}

.col-auto {
flex: 0 0 auto;
margin-bottom: 0;
}

.message-form {
margin: 0;
display: flex;
position: relative;
bottom: 0;

form div {
margin-bottom: 0;
}

.message-input {
height: 3em;
padding: .75em;
}
}

.message-view-container {
position:absolute;
width:calc(100% - 1em);
height: calc(100vh - 4em);
}
}
45 changes: 25 additions & 20 deletions assets/styles/components/_sidebar.scss
Original file line number Diff line number Diff line change
Expand Up @@ -685,31 +685,36 @@
}
}

#sidebar.open {
#sidebar {
@include media-breakpoint-down(lg) {
background: var(--kbin-bg);
height: 100%;
left: 0;
overflow: auto;
padding-bottom: 100px !important;
position: fixed;
top: 3.25rem;
width: 100%;
z-index: 98;
&.open {
background: var(--kbin-bg);
height: 100%;
left: 0;
overflow: auto;
padding-bottom: 100px !important;
position: fixed;
top: 3.25rem;
width: 100%;
z-index: 98;

.topbar & {
top: 4.5rem;
}
.topbar & {
top: 4.5rem;
}

.mobile-close {
display: flex;
font-size: 1.5rem;
justify-content: space-between;
padding: 0.5em;
.mobile-close {
display: flex;
font-size: 1.5rem;
justify-content: space-between;
padding: 0.5em;

button {
height: auto;
button {
height: auto;
}
}
}
&:not(.open) {
display: none;
}
}
}
6 changes: 6 additions & 0 deletions config/kbin_routes/activity_pub.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,12 @@ ap_report:
methods: [GET]
condition: '%kbin_ap_route_condition%'

ap_message:
controller: App\Controller\ActivityPub\MessageController
path: /message/{uuid}
methods: [GET]
condition: '%kbin_ap_route_condition%'

ap_contexts:
controller: App\Controller\ActivityPub\ContextsController
path: /contexts.{_format}
Expand Down
36 changes: 36 additions & 0 deletions migrations/Version20240603190838.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace DoctrineMigrations;

use Doctrine\DBAL\Schema\Schema;
use Doctrine\Migrations\AbstractMigration;

final class Version20240603190838 extends AbstractMigration
{
public function getDescription(): string
{
return 'add a uuid and an ap_id to the message table';
}

public function up(Schema $schema): void
{
$this->addSql('ALTER TABLE message ADD uuid UUID NOT NULL DEFAULT gen_random_uuid()');
$this->addSql('ALTER TABLE message ADD ap_id VARCHAR(255) DEFAULT NULL');
$this->addSql('ALTER TABLE message ADD edited_at TIMESTAMP(0) WITH TIME ZONE DEFAULT NULL');
$this->addSql('COMMENT ON COLUMN message.uuid IS \'(DC2Type:uuid)\'');
$this->addSql('COMMENT ON COLUMN message.edited_at IS \'(DC2Type:datetimetz_immutable)\'');
$this->addSql('CREATE UNIQUE INDEX UNIQ_B6BD307FD17F50A6 ON message (uuid)');
$this->addSql('CREATE UNIQUE INDEX UNIQ_B6BD307F904F155E ON message (ap_id)');
}

public function down(Schema $schema): void
{
$this->addSql('DROP INDEX UNIQ_B6BD307FD17F50A6');
$this->addSql('DROP INDEX UNIQ_B6BD307F904F155E');
$this->addSql('ALTER TABLE message DROP uuid');
$this->addSql('ALTER TABLE message DROP ap_id');
$this->addSql('ALTER TABLE message DROP edited_at');
}
}
34 changes: 34 additions & 0 deletions src/Controller/ActivityPub/MessageController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php

declare(strict_types=1);

namespace App\Controller\ActivityPub;

use App\Controller\AbstractController;
use App\Entity\Message;
use App\Factory\ActivityPub\MessageFactory;
use Symfony\Bridge\Doctrine\Attribute\MapEntity;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;

class MessageController extends AbstractController
{
public function __construct(
private readonly MessageFactory $factory,
) {
}

public function __invoke(
#[MapEntity(mapping: ['uuid' => 'uuid'])]
Message $message,
Request $request,
): Response {
$json = $this->factory->build($message);

$response = new JsonResponse($json);
$response->headers->set('Content-Type', 'application/activity+json');

return $response;
}
}
4 changes: 0 additions & 4 deletions src/Controller/Message/MessageCreateThreadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,6 @@ public function __construct(private readonly MessageManager $manager)
#[IsGranted('message', subject: 'receiver')]
public function __invoke(User $receiver, Request $request): Response
{
if ($receiver->apId) {
throw $this->createAccessDeniedException();
}

$form = $this->createForm(MessageType::class);
$form->handleRequest($request);

Expand Down
5 changes: 1 addition & 4 deletions src/Controller/Message/MessageThreadController.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,10 +28,7 @@ public function __invoke(MessageThread $thread, Request $request): Response
if ($form->isSubmitted() && $form->isValid()) {
$this->manager->toMessage($form->getData(), $thread, $this->getUserOrThrow());

return $this->redirectToRoute(
'messages_front',
['id' => $thread->getId()]
);
return $this->redirectToRoute('messages_single', ['id' => $thread->getId()]);
}

$this->manager->readMessages($thread, $this->getUserOrThrow());
Expand Down
2 changes: 2 additions & 0 deletions src/DTO/MessageDto.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ class MessageDto
#[Assert\NotBlank]
#[Assert\Length(min: 2, max: 5000)]
public ?string $body = null;

public ?string $apId = null;
}
25 changes: 23 additions & 2 deletions src/Entity/Message.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,10 @@

namespace App\Entity;

use App\Entity\Contracts\ActivityPubActivityInterface;
use App\Entity\Traits\ActivityPubActivityTrait;
use App\Entity\Traits\CreatedAtTrait;
use App\Entity\Traits\EditedAtTrait;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
Expand All @@ -14,13 +17,16 @@
use Doctrine\ORM\Mapping\JoinColumn;
use Doctrine\ORM\Mapping\ManyToOne;
use Doctrine\ORM\Mapping\OneToMany;
use Symfony\Component\Uid\Uuid;

#[Entity]
class Message
class Message implements ActivityPubActivityInterface
{
use ActivityPubActivityTrait;
use CreatedAtTrait {
CreatedAtTrait::__construct as createdAtTraitConstruct;
}
use EditedAtTrait;
public const STATUS_NEW = 'new';
public const STATUS_READ = 'read';
public const STATUS_OPTIONS = [
Expand All @@ -38,19 +44,23 @@ class Message
public string $body;
#[Column(type: 'string', nullable: false)]
public string $status = self::STATUS_NEW;
#[Column(type: 'uuid', unique: true, nullable: false)]
public string $uuid;
#[Id]
#[GeneratedValue]
#[Column(type: 'integer')]
private int $id;
#[OneToMany(mappedBy: 'message', targetEntity: MessageNotification::class, cascade: ['remove'], orphanRemoval: true)]
private Collection $notifications;

public function __construct(MessageThread $thread, User $sender, string $body)
public function __construct(MessageThread $thread, User $sender, string $body, ?string $apId)
{
$this->thread = $thread;
$this->sender = $sender;
$this->body = $body;
$this->notifications = new ArrayCollection();
$this->uuid = Uuid::v4()->toRfc4122();
$this->apId = $apId;

$thread->addMessage($this);

Expand All @@ -61,4 +71,15 @@ public function getId(): int
{
return $this->id;
}

public function getTitle(): string
{
$firstLine = preg_replace('/^# |\R.*/', '', $this->body);

if (grapheme_strlen($firstLine) <= 80) {
return $firstLine;
}

return grapheme_substr($firstLine, 0, 80).'';
}
}
7 changes: 6 additions & 1 deletion src/Entity/MessageThread.php
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ class MessageThread
#[ManyToMany(targetEntity: User::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
public Collection $participants;
#[OneToMany(mappedBy: 'thread', targetEntity: Message::class, cascade: ['persist', 'remove'], orphanRemoval: true)]
#[OrderBy(['createdAt' => 'DESC'])]
#[OrderBy(['createdAt' => 'ASC'])]
public Collection $messages;
#[Id]
#[GeneratedValue]
Expand Down Expand Up @@ -104,6 +104,11 @@ public function removeMessage(Message $message): void
$this->messages->removeElement($message);
}

public function getLastMessage(): Message
{
return $this->messages[$this->messages->count() - 1];
}

public function getTitle(): string
{
$body = $this->messages[0]->body;
Expand Down
5 changes: 4 additions & 1 deletion src/Factory/ActivityPub/ActivityFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use App\Entity\Contracts\ActivityPubActivityInterface;
use App\Entity\Entry;
use App\Entity\EntryComment;
use App\Entity\Message;
use App\Entity\Post;
use App\Entity\PostComment;
use App\Repository\TagLinkRepository;
Expand All @@ -18,7 +19,8 @@ public function __construct(
private readonly EntryPageFactory $pageFactory,
private readonly EntryCommentNoteFactory $entryNoteFactory,
private readonly PostNoteFactory $postNoteFactory,
private readonly PostCommentNoteFactory $postCommentNoteFactory
private readonly PostCommentNoteFactory $postCommentNoteFactory,
private readonly MessageFactory $messageFactory,
) {
}

Expand All @@ -29,6 +31,7 @@ public function create(ActivityPubActivityInterface $activity, bool $context = f
$activity instanceof EntryComment => $this->entryNoteFactory->create($activity, $this->tagLinkRepository->getTagsOfEntryComment($activity), $context),
$activity instanceof Post => $this->postNoteFactory->create($activity, $this->tagLinkRepository->getTagsOfPost($activity), $context),
$activity instanceof PostComment => $this->postCommentNoteFactory->create($activity, $this->tagLinkRepository->getTagsOfPostComment($activity), $context),
$activity instanceof Message => $this->messageFactory->build($activity, $context),
default => throw new \LogicException(),
};
}
Expand Down
Loading

0 comments on commit 4266dab

Please sign in to comment.