From 1647c5391f30b93629011e4b8b524906b653f6e8 Mon Sep 17 00:00:00 2001 From: Eliseu Amaro Date: Wed, 11 Aug 2021 02:49:23 +0100 Subject: [PATCH] [Favourite][TWIG][CSS] Favourite now works. --- plugins/Favourite/Favourite.php | 52 ++++++++++++++++++++++-------- public/assets/css/base.css | 28 ++++++++++++++++ public/assets/css/left/left.css | 2 +- public/assets/css/reset.css | 1 + public/assets/icons/heart.svg | 9 ++++++ public/assets/icons/heart.svg.twig | 4 --- src/Core/Modules/Module.php | 17 +++++++++- templates/base.html.twig | 3 +- templates/note/view.html.twig | 18 +++++++---- 9 files changed, 106 insertions(+), 28 deletions(-) create mode 100644 public/assets/icons/heart.svg delete mode 100644 public/assets/icons/heart.svg.twig diff --git a/plugins/Favourite/Favourite.php b/plugins/Favourite/Favourite.php index 34d2745ad4..5494118354 100644 --- a/plugins/Favourite/Favourite.php +++ b/plugins/Favourite/Favourite.php @@ -28,6 +28,7 @@ use App\Core\Modules\Plugin; use App\Core\Router\RouteLoader; use App\Entity\Note; use App\Util\Common; +use App\Util\Exception\RedirectException; use App\Util\Formatting; use App\Util\Nickname; use Symfony\Component\Form\Extension\Core\Type\HiddenType; @@ -39,33 +40,58 @@ class Favourite extends Plugin /** * HTML rendering event that adds the favourite form as a note * action, if a user is logged in + * + * @param Request $request + * @param Note $note + * @param array $actions + * + * @throws RedirectException + * @throws \App\Util\Exception\InvalidFormException + * @throws \App\Util\Exception\NoSuchNoteException + * + * @return bool Event hook */ public function onAddNoteActions(Request $request, Note $note, array &$actions): bool { - if (($user = Common::user()) == null) { + if (($user = Common::user()) === null) { return Event::next; } + // if note is favourited, "is_set" is 1 $opts = ['note_id' => $note->getId(), 'gsactor_id' => $user->getId()]; $is_set = DB::find('favourite', $opts) != null; $form = Form::create([ ['is_set', HiddenType::class, ['data' => $is_set ? '1' : '0']], ['note_id', HiddenType::class, ['data' => $note->getId()]], - ['favourite', SubmitType::class, ['label' => ' ']], + ["favourite-{$note->getId()}", SubmitType::class, ['label' => ' ', 'attr' => ['class' => $is_set ? 'favourite-button-on' : 'favourite-button-off']]], ]); // Form handler - $ret = self::noteActionHandle($request, $form, $note, 'favourite', function ($note, $data) use ($opts) { - $fave = DB::find('favourite', $opts); - if (!$data['is_set'] && ($fave == null)) { - DB::persist(Entity\Favourite::create($opts)); - DB::flush(); - } else { - DB::remove($fave); - DB::flush(); - } - return Event::stop; - }); + $ret = self::noteActionHandle( + $request, $form, $note, "favourite-{$note->getId()}", /** + * Called from form handler + * + * @param $note Note to be favourited + * @param $data Form input + * + * @throws RedirectException Always thrown in order to prevent accidental form re-submit from browser + */ function ($note, $data) use ($opts, $request) { + $fave = DB::find('favourite', $opts); + if ($data['is_set'] === '0' && $fave === null) { + DB::persist(Entity\Favourite::create($opts)); + DB::flush(); + } else { + if ($data['is_set'] === '1' && $fave !== null) { + DB::remove($fave); + DB::flush(); + } + } + + // Prevent accidental refreshes from resubmitting the form + throw new RedirectException(); + + return Event::stop; + }); if ($ret != null) { return $ret; diff --git a/public/assets/css/base.css b/public/assets/css/base.css index fc050837c5..f23f21def3 100644 --- a/public/assets/css/base.css +++ b/public/assets/css/base.css @@ -190,6 +190,34 @@ height: var(--main-size); } +/* TODO: icons */ +.note-actions { + display: block; +} + +.favourite-button-off { + all: unset; + + cursor: pointer !important; + border: none !important; + width: 1em !important; + height: 1em !important; + background-size: cover !important; + background-image: url(../icons/heart.svg) !important; + filter: invert(26%) sepia(21%) saturate(580%) hue-rotate(201deg) brightness(96%) contrast(93%); +} +.favourite-button-on { + all: unset; + + cursor: pointer !important; + border: none !important; + width: 1em !important; + height: 1em !important; + background-size: cover !important; + background-image: url(../icons/heart.svg) !important; + filter: invert(100%); +} + .note-content { padding: var(--small-size); } diff --git a/public/assets/css/left/left.css b/public/assets/css/left/left.css index 47fda1d323..f44068c7d1 100644 --- a/public/assets/css/left/left.css +++ b/public/assets/css/left/left.css @@ -37,7 +37,7 @@ #user-avatar img { border-radius: 50%; - max-width: calc(3 * var(--main-size)); + width: calc(3 * var(--main-size)); height: auto; margin-right: var(--unit-size); diff --git a/public/assets/css/reset.css b/public/assets/css/reset.css index c5b3407206..9bdd9a1f2e 100644 --- a/public/assets/css/reset.css +++ b/public/assets/css/reset.css @@ -81,6 +81,7 @@ html { -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; text-rendering: optimizeLegibility; + scroll-behavior: smooth; background-attachment: fixed; color: var(--white); diff --git a/public/assets/icons/heart.svg b/public/assets/icons/heart.svg new file mode 100644 index 0000000000..f9d3f19865 --- /dev/null +++ b/public/assets/icons/heart.svg @@ -0,0 +1,9 @@ + + heart + + + + + + diff --git a/public/assets/icons/heart.svg.twig b/public/assets/icons/heart.svg.twig deleted file mode 100644 index 727ad722c5..0000000000 --- a/public/assets/icons/heart.svg.twig +++ /dev/null @@ -1,4 +0,0 @@ - -heart - - diff --git a/src/Core/Modules/Module.php b/src/Core/Modules/Module.php index 3a9910d5c1..740d0e45d8 100644 --- a/src/Core/Modules/Module.php +++ b/src/Core/Modules/Module.php @@ -19,8 +19,12 @@ namespace App\Core\Modules; +use App\Core\Event; +use App\Core\Log; use App\Entity\Note; use App\Util\Common; +use App\Util\Exception\InvalidFormException; +use App\Util\Exception\NoSuchNoteException; use Symfony\Component\Form\Form; use Symfony\Component\HttpFoundation\Request; @@ -51,6 +55,17 @@ abstract class Module * This function is called when a user interacts with a note, such as through favouriting or commenting * * @codeCoverageIgnore + * + * @param Request $request + * @param Form $form + * @param Note $note + * @param string $form_name + * @param callable $handle + * + * @throws InvalidFormException + * @throws NoSuchNoteException + * + * @return bool|void */ public static function noteActionHandle(Request $request, Form $form, Note $note, string $form_name, callable $handle) { @@ -65,7 +80,7 @@ abstract class Module $user = Common::user(); if (!$note->isVisibleTo($user)) { // ^ Ensure user isn't trying to trip us up - Log::error('Suspicious activity: user ' . $user->getNickname() . + Log::warning('Suspicious activity: user ' . $user->getNickname() . ' tried to interact with note ' . $note->getId() . ', but they shouldn\'t have access to it'); throw new NoSuchNoteException(); diff --git a/templates/base.html.twig b/templates/base.html.twig index 6f7134f388..630837138e 100644 --- a/templates/base.html.twig +++ b/templates/base.html.twig @@ -29,7 +29,7 @@ - {% block header %} +{% block header %} - diff --git a/templates/note/view.html.twig b/templates/note/view.html.twig index 9f6ee35243..c0595240f1 100644 --- a/templates/note/view.html.twig +++ b/templates/note/view.html.twig @@ -12,6 +12,16 @@ {% if reply_to is not null and not skip_reply_to is defined %} {% trans with {'%name%': reply_to} %} in reply to %name% {% endtrans %} {% endif %} + +
+ + {% if have_user %} + {% for act in get_note_actions(note) %} + {{ form(act) }} + {% endfor %} + {% endif %} +
+
{% block markdown %} @@ -32,13 +42,7 @@
{% endif %} -
- {# {% if have_user %} #} - {# {\#{% for act in get_note_actions(note) %}#\} #} - {# {\#{{ form(act) }}#\} #} - {# {\#{% endfor %}#\} #} - {# {% endif %} #} -
+ {% if replies is defined %}
{% for conversation in replies %}