forked from GNUsocial/gnu-social
[PLUGINS][Favourite] Remove favourite action properly removes note_favourite Entity now [COMPONENTS][Collection] Simplyfying feed-action-details template section
[COMPONENTS] Documentation work [PLUGINS] Documentation work
This commit is contained in:
parent
adf484f58a
commit
117549bf1e
@ -30,13 +30,11 @@
|
|||||||
<summary>
|
<summary>
|
||||||
{{ icon('filter', 'icon icon-feed-actions') | raw }} {# button-container #}
|
{{ icon('filter', 'icon icon-feed-actions') | raw }} {# button-container #}
|
||||||
</summary>
|
</summary>
|
||||||
<div class="feed-actions-details-dropdown">
|
<menu class="feed-actions-details-dropdown">
|
||||||
<menu>
|
|
||||||
{% for block in handle_event('AddFeedActions', app.request, notes is defined and notes is not empty) %}
|
{% for block in handle_event('AddFeedActions', app.request, notes is defined and notes is not empty) %}
|
||||||
{{ block | raw }}
|
{{ block | raw }}
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</menu>
|
</menu>
|
||||||
</div>
|
|
||||||
</details>
|
</details>
|
||||||
</nav>
|
</nav>
|
||||||
</header>
|
</header>
|
||||||
|
@ -1,9 +1,7 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
declare(strict_types = 1);
|
declare(strict_types = 1);
|
||||||
|
|
||||||
// {{{ License
|
// {{{ License
|
||||||
|
|
||||||
// This file is part of GNU social - https://www.gnu.org/software/social
|
// This file is part of GNU social - https://www.gnu.org/software/social
|
||||||
//
|
//
|
||||||
// GNU social is free software: you can redistribute it and/or modify
|
// GNU social is free software: you can redistribute it and/or modify
|
||||||
@ -18,9 +16,15 @@ declare(strict_types = 1);
|
|||||||
//
|
//
|
||||||
// You should have received a copy of the GNU Affero General Public License
|
// You should have received a copy of the GNU Affero General Public License
|
||||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Hugo Sales <hugo@hsal.es>
|
||||||
|
* @author Eliseu Amaro <mail@eliseuama.ro>
|
||||||
|
* @copyright 2021-2022 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
namespace Component\Conversation;
|
namespace Component\Conversation;
|
||||||
|
|
||||||
use App\Core\Cache;
|
use App\Core\Cache;
|
||||||
@ -34,7 +38,6 @@ use App\Entity\Activity;
|
|||||||
use App\Entity\Actor;
|
use App\Entity\Actor;
|
||||||
use App\Entity\Note;
|
use App\Entity\Note;
|
||||||
use App\Util\Common;
|
use App\Util\Common;
|
||||||
use App\Util\Exception\RedirectException;
|
|
||||||
use App\Util\Formatting;
|
use App\Util\Formatting;
|
||||||
use Component\Conversation\Entity\Conversation as ConversationEntity;
|
use Component\Conversation\Entity\Conversation as ConversationEntity;
|
||||||
use Component\Conversation\Entity\ConversationMute;
|
use Component\Conversation\Entity\ConversationMute;
|
||||||
@ -101,6 +104,8 @@ class Conversation extends Component
|
|||||||
* 'id' (HTML markup id used to redirect user to this anchor upon performing the action)
|
* 'id' (HTML markup id used to redirect user to this anchor upon performing the action)
|
||||||
*
|
*
|
||||||
* @throws \App\Util\Exception\ServerException
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
||||||
{
|
{
|
||||||
@ -134,7 +139,14 @@ class Conversation extends Component
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Posting event to add extra info to a note
|
* Posting event to add extra information to Component\Posting form data
|
||||||
|
*
|
||||||
|
* @param array $data Transport data to be filled with reply_to_id
|
||||||
|
*
|
||||||
|
* @throws \App\Util\Exception\ClientException
|
||||||
|
* @throws \App\Util\Exception\NoSuchNoteException
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onPostingModifyData(Request $request, Actor $actor, array &$data): bool
|
public function onPostingModifyData(Request $request, Actor $actor, array &$data): bool
|
||||||
{
|
{
|
||||||
@ -153,6 +165,8 @@ class Conversation extends Component
|
|||||||
*
|
*
|
||||||
* @param array $vars Contains information related to Note currently being rendered
|
* @param array $vars Contains information related to Note currently being rendered
|
||||||
* @param array $result Contains keys 'actors', and 'action'. Needed to construct a string, stating who ($result['actors']), has already performed a reply ($result['action']), in the given Note (vars['note'])
|
* @param array $result Contains keys 'actors', and 'action'. Needed to construct a string, stating who ($result['actors']), has already performed a reply ($result['action']), in the given Note (vars['note'])
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onAppendCardNote(array $vars, array &$result): bool
|
public function onAppendCardNote(array $vars, array &$result): bool
|
||||||
{
|
{
|
||||||
@ -184,8 +198,10 @@ class Conversation extends Component
|
|||||||
*
|
*
|
||||||
* @param \App\Entity\Actor $actor The Actor currently attempting to post a Note
|
* @param \App\Entity\Actor $actor The Actor currently attempting to post a Note
|
||||||
* @param null|\App\Entity\Actor $context_actor The 'owner' of the current route (e.g. Group or Actor), used to target it
|
* @param null|\App\Entity\Actor $context_actor The 'owner' of the current route (e.g. Group or Actor), used to target it
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onPostingGetContextActor(Request $request, Actor $actor, ?Actor &$context_actor)
|
public function onPostingGetContextActor(Request $request, Actor $actor, ?Actor &$context_actor): bool
|
||||||
{
|
{
|
||||||
$to_note_id = $request->query->get('reply_to_id');
|
$to_note_id = $request->query->get('reply_to_id');
|
||||||
if (!\is_null($to_note_id)) {
|
if (!\is_null($to_note_id)) {
|
||||||
@ -198,10 +214,8 @@ class Conversation extends Component
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Add minimal Note card to RightPanel template
|
* Add minimal Note card to RightPanel template
|
||||||
*
|
|
||||||
* @throws RedirectException
|
|
||||||
*/
|
*/
|
||||||
public function onPrependPostingForm(Request $request, array &$elements)
|
public function onPrependPostingForm(Request $request, array &$elements): bool
|
||||||
{
|
{
|
||||||
$elements[] = Formatting::twigRenderFile('cards/note/macro_note_minimal_wrapper.html.twig', ['note' => Note::getById((int) $request->query->get('reply_to_id'))]);
|
$elements[] = Formatting::twigRenderFile('cards/note/macro_note_minimal_wrapper.html.twig', ['note' => Note::getById((int) $request->query->get('reply_to_id'))]);
|
||||||
return Event::next;
|
return Event::next;
|
||||||
@ -213,6 +227,8 @@ class Conversation extends Component
|
|||||||
*
|
*
|
||||||
* @param \App\Entity\Note $note Note being deleted
|
* @param \App\Entity\Note $note Note being deleted
|
||||||
* @param \App\Entity\Actor $actor Actor that performed the delete action
|
* @param \App\Entity\Actor $actor Actor that performed the delete action
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
||||||
{
|
{
|
||||||
@ -233,7 +249,7 @@ class Conversation extends Component
|
|||||||
*
|
*
|
||||||
* @return bool EventHook
|
* @return bool EventHook
|
||||||
*/
|
*/
|
||||||
public function onAddExtraNoteActions(Request $request, Note $note, array &$actions)
|
public function onAddExtraNoteActions(Request $request, Note $note, array &$actions): bool
|
||||||
{
|
{
|
||||||
if (\is_null($user = Common::user())) {
|
if (\is_null($user = Common::user())) {
|
||||||
return Event::next;
|
return Event::next;
|
||||||
@ -261,7 +277,14 @@ class Conversation extends Component
|
|||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onNewNotificationShould(Activity $activity, Actor $actor)
|
/**
|
||||||
|
* Prevents new Notifications to appear for muted conversations
|
||||||
|
*
|
||||||
|
* @param Activity $activity Notification Activity
|
||||||
|
*
|
||||||
|
* @return bool EventHook
|
||||||
|
*/
|
||||||
|
public function onNewNotificationShould(Activity $activity, Actor $actor): bool
|
||||||
{
|
{
|
||||||
if ($activity->getObjectType() === 'note' && ConversationMute::isMuted($activity, $actor)) {
|
if ($activity->getObjectType() === 'note' && ConversationMute::isMuted($activity, $actor)) {
|
||||||
return Event::stop;
|
return Event::stop;
|
||||||
|
@ -26,7 +26,6 @@ namespace Component\Conversation\Entity;
|
|||||||
use App\Core\DB\DB;
|
use App\Core\DB\DB;
|
||||||
use App\Core\Entity;
|
use App\Core\Entity;
|
||||||
use App\Core\Router\Router;
|
use App\Core\Router\Router;
|
||||||
use App\Entity\Note;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Entity class for Conversations
|
* Entity class for Conversations
|
||||||
|
@ -42,7 +42,12 @@ class LeftPanel extends Component
|
|||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onAppendFeed(Actor $actor, string $title, string $route, array $route_params)
|
/**
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
* @throws ClientException
|
||||||
|
*/
|
||||||
|
public function onAppendFeed(Actor $actor, string $title, string $route, array $route_params): bool
|
||||||
{
|
{
|
||||||
$cache_key = Feed::cacheKey($actor);
|
$cache_key = Feed::cacheKey($actor);
|
||||||
$feeds = Feed::getFeeds($actor);
|
$feeds = Feed::getFeeds($actor);
|
||||||
|
@ -21,6 +21,13 @@ declare(strict_types = 1);
|
|||||||
|
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eliseu Amaro <mail@eliseuama.ro>
|
||||||
|
* @author Diogo Peralta Cordeiro <@diogo.site>
|
||||||
|
* @copyright 2021-2022 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
namespace Plugin\Favourite;
|
namespace Plugin\Favourite;
|
||||||
|
|
||||||
use App\Core\Cache;
|
use App\Core\Cache;
|
||||||
@ -49,10 +56,10 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
*
|
*
|
||||||
* A new notification is then handled, informing all interested Actors of this action
|
* A new notification is then handled, informing all interested Actors of this action
|
||||||
*
|
*
|
||||||
|
* @param int $note_id Note id being favoured
|
||||||
|
* @param int $actor_id Actor performing favourite Activity
|
||||||
|
*
|
||||||
* @throws \App\Util\Exception\ServerException
|
* @throws \App\Util\Exception\ServerException
|
||||||
* @throws \Doctrine\ORM\OptimisticLockException
|
|
||||||
* @throws \Doctrine\ORM\ORMException
|
|
||||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
|
||||||
*/
|
*/
|
||||||
public static function favourNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
public static function favourNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
||||||
{
|
{
|
||||||
@ -84,20 +91,21 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
*
|
*
|
||||||
* Informs all interested Actors of this action, handling out the NewNotification event
|
* Informs all interested Actors of this action, handling out the NewNotification event
|
||||||
*
|
*
|
||||||
|
* @param int $note_id Note id being unfavoured
|
||||||
|
* @param int $actor_id Actor undoing favourite Activity
|
||||||
|
*
|
||||||
* @throws \App\Util\Exception\ServerException
|
* @throws \App\Util\Exception\ServerException
|
||||||
* @throws \Doctrine\ORM\OptimisticLockException
|
|
||||||
* @throws \Doctrine\ORM\ORMException
|
|
||||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
|
||||||
*/
|
*/
|
||||||
public static function unfavourNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
public static function unfavourNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
||||||
{
|
{
|
||||||
$note_already_favoured = Cache::get(
|
$note_already_favoured = Cache::get(
|
||||||
FavouriteEntity::cacheKeys($note_id, $actor_id)['favourite'],
|
FavouriteEntity::cacheKeys($note_id, $actor_id)['favourite'],
|
||||||
fn () => DB::findOneBy('note_favourite', ['note_id' => $note_id, 'actor_id' => $actor_id], return_null: true),
|
static fn () => DB::findOneBy('note_favourite', ['note_id' => $note_id, 'actor_id' => $actor_id], return_null: true),
|
||||||
);
|
);
|
||||||
$activity = null;
|
$activity = null;
|
||||||
if (!\is_null($note_already_favoured)) {
|
if (!\is_null($note_already_favoured)) {
|
||||||
DB::remove($note_already_favoured);
|
DB::removeBy(FavouriteEntity::class, ['note_id' => $note_id, 'actor_id' => $actor_id]);
|
||||||
|
|
||||||
Cache::delete(FavouriteEntity::cacheKeys($note_id, $actor_id)['favourite']);
|
Cache::delete(FavouriteEntity::cacheKeys($note_id, $actor_id)['favourite']);
|
||||||
$favourite_activity = DB::findBy('activity', ['verb' => 'favourite', 'object_type' => 'note', 'actor_id' => $actor_id, 'object_id' => $note_id], order_by: ['created' => 'DESC'])[0];
|
$favourite_activity = DB::findBy('activity', ['verb' => 'favourite', 'object_type' => 'note', 'actor_id' => $actor_id, 'object_id' => $note_id], order_by: ['created' => 'DESC'])[0];
|
||||||
$activity = Activity::create([
|
$activity = Activity::create([
|
||||||
@ -118,11 +126,10 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
* HTML rendering event that adds the favourite form as a note
|
* HTML rendering event that adds the favourite form as a note
|
||||||
* action, if a user is logged in
|
* action, if a user is logged in
|
||||||
*
|
*
|
||||||
* @throws \Doctrine\ORM\OptimisticLockException
|
* @param Note $note Current Note being rendered
|
||||||
* @throws \Doctrine\ORM\ORMException
|
* @param array $actions Array containing all Note actions to be rendered
|
||||||
* @throws \Doctrine\ORM\TransactionRequiredException
|
|
||||||
*
|
*
|
||||||
* @return bool Event hook
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
||||||
{
|
{
|
||||||
@ -135,7 +142,7 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
$is_favourite = !\is_null(
|
$is_favourite = !\is_null(
|
||||||
Cache::get(
|
Cache::get(
|
||||||
FavouriteEntity::cacheKeys($note->getId(), $user->getId())['favourite'],
|
FavouriteEntity::cacheKeys($note->getId(), $user->getId())['favourite'],
|
||||||
fn () => DB::findOneBy('note_favourite', $opts, return_null: true),
|
static fn () => DB::findOneBy('note_favourite', $opts, return_null: true),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -162,7 +169,15 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onAppendCardNote(array $vars, array &$result)
|
/**
|
||||||
|
* Appends on Note currently being rendered complementary information regarding whom (subject) performed which Activity (verb) on aforementioned Note (object)
|
||||||
|
*
|
||||||
|
* @param array $vars Array containing necessary info to process event. In this case, contains the current Note being rendered
|
||||||
|
* @param array $result Contains a hashmap for each Activity performed on Note (object)
|
||||||
|
*
|
||||||
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
|
*/
|
||||||
|
public function onAppendCardNote(array $vars, array &$result): bool
|
||||||
{
|
{
|
||||||
// If note is the original and user isn't the one who repeated, append on end "user repeated this"
|
// If note is the original and user isn't the one who repeated, append on end "user repeated this"
|
||||||
// If user is the one who repeated, append on end "you repeated this, remove repeat?"
|
// If user is the one who repeated, append on end "you repeated this, remove repeat?"
|
||||||
@ -198,6 +213,9 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Maps Routes to their respective Controllers
|
||||||
|
*/
|
||||||
public function onAddRoute(RouteLoader $r): bool
|
public function onAddRoute(RouteLoader $r): bool
|
||||||
{
|
{
|
||||||
// Add/remove note to/from favourites
|
// Add/remove note to/from favourites
|
||||||
@ -214,7 +232,14 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function onCreateDefaultFeeds(int $actor_id, LocalUser $user, int &$ordering)
|
/**
|
||||||
|
* Creates two feeds, including reverse favourites or favourites performed by given Actor
|
||||||
|
*
|
||||||
|
* @param int $actor_id Whom the favourites belong to
|
||||||
|
*
|
||||||
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
*/
|
||||||
|
public function onCreateDefaultFeeds(int $actor_id, LocalUser $user, int &$ordering): bool
|
||||||
{
|
{
|
||||||
DB::persist(Feed::create([
|
DB::persist(Feed::create([
|
||||||
'actor_id' => $actor_id,
|
'actor_id' => $actor_id,
|
||||||
@ -243,6 +268,15 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
* @param mixed $type_object Activity's Object
|
* @param mixed $type_object Activity's Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\ClientException
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
private function activitypub_handler(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
private function activitypub_handler(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
@ -262,8 +296,7 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
} else {
|
} else {
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
} else { // Undo Favourite
|
} elseif ($type_object instanceof \ActivityPhp\Type\AbstractObject) {
|
||||||
if ($type_object instanceof \ActivityPhp\Type\AbstractObject) {
|
|
||||||
$ap_prev_favourite_act = \Plugin\ActivityPub\Util\Model\Activity::fromJson($type_object);
|
$ap_prev_favourite_act = \Plugin\ActivityPub\Util\Model\Activity::fromJson($type_object);
|
||||||
$prev_favourite_act = $ap_prev_favourite_act->getActivity();
|
$prev_favourite_act = $ap_prev_favourite_act->getActivity();
|
||||||
if ($prev_favourite_act->getVerb() === 'favourite' && $prev_favourite_act->getObjectType() === 'note') {
|
if ($prev_favourite_act->getVerb() === 'favourite' && $prev_favourite_act->getObjectType() === 'note') {
|
||||||
@ -280,7 +313,6 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
} else {
|
} else {
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ($type_activity->get('type') === 'Like') {
|
if ($type_activity->get('type') === 'Like') {
|
||||||
$activity = self::favourNote($note_id, $actor->getId(), source: 'ActivityPub');
|
$activity = self::favourNote($note_id, $actor->getId(), source: 'ActivityPub');
|
||||||
@ -308,6 +340,15 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
* @param \ActivityPhp\Type\AbstractObject $type_object Activity Streams 2.0 Object
|
* @param \ActivityPhp\Type\AbstractObject $type_object Activity Streams 2.0 Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\ClientException
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
public function onNewActivityPubActivity(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, \ActivityPhp\Type\AbstractObject $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
public function onNewActivityPubActivity(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, \ActivityPhp\Type\AbstractObject $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
@ -323,6 +364,15 @@ class Favourite extends NoteHandlerPlugin
|
|||||||
* @param mixed $type_object Object
|
* @param mixed $type_object Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\ClientException
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\ServerException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
public function onNewActivityPubActivityWithObject(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
public function onNewActivityPubActivityWithObject(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
|
@ -49,7 +49,7 @@ use Symfony\Component\HttpFoundation\Request;
|
|||||||
class Oomox extends Plugin
|
class Oomox extends Plugin
|
||||||
{
|
{
|
||||||
/**
|
/**
|
||||||
* Map URLs to actions
|
* Maps Routes to their respective Controllers
|
||||||
*/
|
*/
|
||||||
public function onAddRoute(RouteLoader $r): bool
|
public function onAddRoute(RouteLoader $r): bool
|
||||||
{
|
{
|
||||||
@ -108,10 +108,8 @@ class Oomox extends Plugin
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds to array $styles the generated CSS according to user settings, if any are present.
|
* Adds to array $styles the generated CSS according to user settings, if any are present.
|
||||||
*
|
|
||||||
* @return bool
|
|
||||||
*/
|
*/
|
||||||
public function onEndShowStyles(array &$styles, string $route)
|
public function onEndShowStyles(array &$styles, string $route): bool
|
||||||
{
|
{
|
||||||
$user = Common::user();
|
$user = Common::user();
|
||||||
if (!\is_null($user) && !\is_null(Cache::get(self::cacheKey($user), fn () => self::getEntity($user)))) {
|
if (!\is_null($user) && !\is_null(Cache::get(self::cacheKey($user), fn () => self::getEntity($user)))) {
|
||||||
|
@ -33,7 +33,6 @@ use App\Entity\Note;
|
|||||||
use App\Util\Common;
|
use App\Util\Common;
|
||||||
use App\Util\Exception\ClientException;
|
use App\Util\Exception\ClientException;
|
||||||
use App\Util\Exception\NoLoggedInUser;
|
use App\Util\Exception\NoLoggedInUser;
|
||||||
use App\Util\Exception\NoSuchNoteException;
|
|
||||||
use App\Util\Exception\RedirectException;
|
use App\Util\Exception\RedirectException;
|
||||||
use App\Util\Exception\ServerException;
|
use App\Util\Exception\ServerException;
|
||||||
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
use Symfony\Component\Form\Extension\Core\Type\SubmitType;
|
||||||
@ -44,9 +43,11 @@ class Repeat extends Controller
|
|||||||
/**
|
/**
|
||||||
* Controller for the note repeat non-JS page
|
* Controller for the note repeat non-JS page
|
||||||
*
|
*
|
||||||
|
* @param int $note_id Note being repeated
|
||||||
|
*
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws NoLoggedInUser
|
* @throws NoLoggedInUser
|
||||||
* @throws NoSuchNoteException
|
|
||||||
* @throws RedirectException
|
* @throws RedirectException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
*/
|
*/
|
||||||
@ -79,15 +80,14 @@ class Repeat extends Controller
|
|||||||
if (Router::isAbsolute($from)) {
|
if (Router::isAbsolute($from)) {
|
||||||
Log::warning("Actor {$actor_id} attempted to reply to a note and then get redirected to another host, or the URL was invalid ({$from})");
|
Log::warning("Actor {$actor_id} attempted to reply to a note and then get redirected to another host, or the URL was invalid ({$from})");
|
||||||
throw new ClientException(_m('Can not redirect to outside the website from here'), 400); // 400 Bad request (deceptive)
|
throw new ClientException(_m('Can not redirect to outside the website from here'), 400); // 400 Bad request (deceptive)
|
||||||
} else {
|
}
|
||||||
// TODO anchor on element id
|
// TODO anchor on element id
|
||||||
throw new RedirectException(url: $from);
|
throw new RedirectException(url: $from);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If we don't have a URL to return to, go to the instance root
|
// If we don't have a URL to return to, go to the instance root
|
||||||
throw new RedirectException('root');
|
throw new RedirectException('root');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'_template' => 'repeat/add_to_repeats.html.twig',
|
'_template' => 'repeat/add_to_repeats.html.twig',
|
||||||
@ -97,9 +97,14 @@ class Repeat extends Controller
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* Controller for the note unrepeat non-JS page
|
||||||
|
*
|
||||||
|
* @param int $note_id Note being unrepeated
|
||||||
|
*
|
||||||
|
* @throws \App\Util\Exception\DuplicateFoundException
|
||||||
|
* @throws \App\Util\Exception\NotFoundException
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws NoLoggedInUser
|
* @throws NoLoggedInUser
|
||||||
* @throws NoSuchNoteException
|
|
||||||
* @throws RedirectException
|
* @throws RedirectException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
*/
|
*/
|
||||||
@ -134,15 +139,14 @@ class Repeat extends Controller
|
|||||||
if (Router::isAbsolute($from)) {
|
if (Router::isAbsolute($from)) {
|
||||||
Log::warning("Actor {$actor_id} attempted to reply to a note and then get redirected to another host, or the URL was invalid ({$from})");
|
Log::warning("Actor {$actor_id} attempted to reply to a note and then get redirected to another host, or the URL was invalid ({$from})");
|
||||||
throw new ClientException(_m('Can not redirect to outside the website from here'), 400); // 400 Bad request (deceptive)
|
throw new ClientException(_m('Can not redirect to outside the website from here'), 400); // 400 Bad request (deceptive)
|
||||||
} else {
|
}
|
||||||
// TODO anchor on element id
|
// TODO anchor on element id
|
||||||
throw new RedirectException(url: $from);
|
throw new RedirectException(url: $from);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
// If we don't have a URL to return to, go to the instance root
|
// If we don't have a URL to return to, go to the instance root
|
||||||
throw new RedirectException('root');
|
throw new RedirectException('root');
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return [
|
return [
|
||||||
'_template' => 'repeat/remove_from_repeats.html.twig',
|
'_template' => 'repeat/remove_from_repeats.html.twig',
|
||||||
|
@ -19,6 +19,13 @@ declare(strict_types = 1);
|
|||||||
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
// along with GNU social. If not, see <http://www.gnu.org/licenses/>.
|
||||||
// }}}
|
// }}}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Eliseu Amaro <mail@eliseuama.ro>
|
||||||
|
* @author Diogo Peralta Cordeiro <@diogo.site>
|
||||||
|
* @copyright 2021-2022 Free Software Foundation, Inc http://www.fsf.org
|
||||||
|
* @license https://www.gnu.org/licenses/agpl.html GNU AGPL v3 or later
|
||||||
|
*/
|
||||||
|
|
||||||
namespace Plugin\RepeatNote;
|
namespace Plugin\RepeatNote;
|
||||||
|
|
||||||
use App\Core\Cache;
|
use App\Core\Cache;
|
||||||
@ -32,7 +39,6 @@ use App\Entity\Activity;
|
|||||||
use App\Entity\Actor;
|
use App\Entity\Actor;
|
||||||
use App\Entity\Note;
|
use App\Entity\Note;
|
||||||
use App\Util\Common;
|
use App\Util\Common;
|
||||||
use App\Util\Exception\BugFoundException;
|
|
||||||
use App\Util\Exception\ClientException;
|
use App\Util\Exception\ClientException;
|
||||||
use App\Util\Exception\DuplicateFoundException;
|
use App\Util\Exception\DuplicateFoundException;
|
||||||
use App\Util\Exception\ServerException;
|
use App\Util\Exception\ServerException;
|
||||||
@ -57,7 +63,9 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* In the end, the Activity is created, and a new notification for the
|
* In the end, the Activity is created, and a new notification for the
|
||||||
* repeat Activity created
|
* repeat Activity created
|
||||||
*
|
*
|
||||||
* @throws BugFoundException
|
* @param Note $note Note being repeated
|
||||||
|
* @param int $actor_id Actor id of whom is performing the repeat Activity
|
||||||
|
*
|
||||||
* @throws ClientException
|
* @throws ClientException
|
||||||
* @throws DuplicateFoundException
|
* @throws DuplicateFoundException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
@ -116,6 +124,11 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* Finally, creates a new Activity, undoing the repeat, and the respective
|
* Finally, creates a new Activity, undoing the repeat, and the respective
|
||||||
* Notification is handled.
|
* Notification is handled.
|
||||||
*
|
*
|
||||||
|
* @param int $note_id Note id being unrepeated
|
||||||
|
* @param int $actor_id Actor undoing repeat Activity
|
||||||
|
*
|
||||||
|
* @throws \App\Util\Exception\NotFoundException
|
||||||
|
* @throws DuplicateFoundException
|
||||||
* @throws ServerException
|
* @throws ServerException
|
||||||
*/
|
*/
|
||||||
public static function unrepeatNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
public static function unrepeatNote(int $note_id, int $actor_id, string $source = 'web'): ?Activity
|
||||||
@ -176,6 +189,10 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
/**
|
/**
|
||||||
* Filters repeats out of Conversations, and replaces a repeat with the
|
* Filters repeats out of Conversations, and replaces a repeat with the
|
||||||
* original Note on Actor feed
|
* original Note on Actor feed
|
||||||
|
*
|
||||||
|
* @param array $notes List of Notes to be filtered
|
||||||
|
*
|
||||||
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onFilterNoteList(?Actor $actor, array &$notes, Request $request): bool
|
public function onFilterNoteList(?Actor $actor, array &$notes, Request $request): bool
|
||||||
{
|
{
|
||||||
@ -183,7 +200,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
// it's pretty cool
|
// it's pretty cool
|
||||||
if (str_starts_with($request->get('_route'), 'actor_view_')) {
|
if (str_starts_with($request->get('_route'), 'actor_view_')) {
|
||||||
$notes = array_map(
|
$notes = array_map(
|
||||||
fn (Note $note) => RepeatEntity::isNoteRepeat($note)
|
static fn (Note $note) => RepeatEntity::isNoteRepeat($note)
|
||||||
? Note::getById(RepeatEntity::getByPK($note->getId())->getRepeatOf())
|
? Note::getById(RepeatEntity::getByPK($note->getId())->getRepeatOf())
|
||||||
: $note,
|
: $note,
|
||||||
$notes,
|
$notes,
|
||||||
@ -192,7 +209,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Filter out repeats altogether
|
// Filter out repeats altogether
|
||||||
$notes = array_filter($notes, fn (Note $note) => !RepeatEntity::isNoteRepeat($note));
|
$notes = array_filter($notes, static fn (Note $note) => !RepeatEntity::isNoteRepeat($note));
|
||||||
return Event::next;
|
return Event::next;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -200,7 +217,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* HTML rendering event that adds the repeat form as a note
|
* HTML rendering event that adds the repeat form as a note
|
||||||
* action, if a user is logged in
|
* action, if a user is logged in
|
||||||
*
|
*
|
||||||
* @return bool Event hook
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
public function onAddNoteActions(Request $request, Note $note, array &$actions): bool
|
||||||
{
|
{
|
||||||
@ -244,7 +261,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* @param array $result Rendered String containing anchors for Actors that
|
* @param array $result Rendered String containing anchors for Actors that
|
||||||
* repeated the Note
|
* repeated the Note
|
||||||
*
|
*
|
||||||
* @return bool
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onAppendCardNote(array $vars, array &$result)
|
public function onAppendCardNote(array $vars, array &$result)
|
||||||
{
|
{
|
||||||
@ -278,6 +295,11 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
/**
|
/**
|
||||||
* Deletes every repeat entity that is related to a deleted Note in its
|
* Deletes every repeat entity that is related to a deleted Note in its
|
||||||
* respective table
|
* respective table
|
||||||
|
*
|
||||||
|
* @param Note $note Note to be deleted
|
||||||
|
* @param Actor $actor Who performed the Delete action
|
||||||
|
*
|
||||||
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
public function onNoteDeleteRelated(Note &$note, Actor $actor): bool
|
||||||
{
|
{
|
||||||
@ -299,7 +321,7 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* - **repeat_remove**
|
* - **repeat_remove**
|
||||||
* same as above, except that it undoes the aforementioned action
|
* same as above, except that it undoes the aforementioned action
|
||||||
*
|
*
|
||||||
* @return bool Event hook
|
* @return bool Event hook, Event::next (true) is returned to allow Event to be handled by other handlers
|
||||||
*/
|
*/
|
||||||
public function onAddRoute(RouteLoader $r): bool
|
public function onAddRoute(RouteLoader $r): bool
|
||||||
{
|
{
|
||||||
@ -320,6 +342,16 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* @param mixed $type_object Activity's Object
|
* @param mixed $type_object Activity's Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\NotFoundException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
* @throws ClientException
|
||||||
|
* @throws DuplicateFoundException
|
||||||
|
* @throws ServerException
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
private function activitypub_handler(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
private function activitypub_handler(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
@ -387,6 +419,16 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* @param \ActivityPhp\Type\AbstractObject $type_object Activity Streams 2.0 Object
|
* @param \ActivityPhp\Type\AbstractObject $type_object Activity Streams 2.0 Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\NotFoundException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
* @throws ClientException
|
||||||
|
* @throws DuplicateFoundException
|
||||||
|
* @throws ServerException
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
public function onNewActivityPubActivity(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, \ActivityPhp\Type\AbstractObject $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
public function onNewActivityPubActivity(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, \ActivityPhp\Type\AbstractObject $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
@ -402,6 +444,16 @@ class RepeatNote extends NoteHandlerPlugin
|
|||||||
* @param mixed $type_object Object
|
* @param mixed $type_object Object
|
||||||
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
* @param null|\Plugin\ActivityPub\Entity\ActivitypubActivity $ap_act Resulting ActivitypubActivity
|
||||||
*
|
*
|
||||||
|
* @throws \App\Util\Exception\NoSuchActorException
|
||||||
|
* @throws \App\Util\Exception\NotFoundException
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ClientExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\RedirectionExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\ServerExceptionInterface
|
||||||
|
* @throws \Symfony\Contracts\HttpClient\Exception\TransportExceptionInterface
|
||||||
|
* @throws ClientException
|
||||||
|
* @throws DuplicateFoundException
|
||||||
|
* @throws ServerException
|
||||||
|
*
|
||||||
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
* @return bool Returns `Event::stop` if handled, `Event::next` otherwise
|
||||||
*/
|
*/
|
||||||
public function onNewActivityPubActivityWithObject(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
public function onNewActivityPubActivityWithObject(Actor $actor, \ActivityPhp\Type\AbstractObject $type_activity, mixed $type_object, ?\Plugin\ActivityPub\Entity\ActivitypubActivity &$ap_act): bool
|
||||||
|
@ -98,10 +98,11 @@
|
|||||||
|
|
||||||
.feed-actions-details[open] > .feed-actions-details-dropdown, .note-actions-extra-details[open] > summary + * {
|
.feed-actions-details[open] > .feed-actions-details-dropdown, .note-actions-extra-details[open] > summary + * {
|
||||||
background: var(--background-card);
|
background: var(--background-card);
|
||||||
border: 2px solid var(--border);
|
border: 1px solid var(--border);
|
||||||
border-radius: var(--s);
|
border-radius: var(--s);
|
||||||
box-shadow: var(--shadow);
|
box-shadow: var(--shadow);
|
||||||
display: flex;
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
padding: 4px 8px;
|
padding: 4px 8px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
right: 0;
|
right: 0;
|
||||||
@ -167,14 +168,16 @@
|
|||||||
text-decoration: underline;
|
text-decoration: underline;
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-entry figure {
|
.h-entry figure,
|
||||||
|
.note-attachments-unit figure {
|
||||||
background: var(--gradient);
|
background: var(--gradient);
|
||||||
border-radius: var(--s);
|
border-radius: var(--s);
|
||||||
margin: unset;
|
margin: unset;
|
||||||
padding: var(--s);
|
padding: var(--s);
|
||||||
}
|
}
|
||||||
|
|
||||||
.h-entry img {
|
.h-entry img,
|
||||||
|
.note-attachments-unit figure img {
|
||||||
background: repeating-conic-gradient(#ffffff66 0deg 90deg, #ffffff33 0deg 180deg) 0 0/40px 40px round;
|
background: repeating-conic-gradient(#ffffff66 0deg 90deg, #ffffff33 0deg 180deg) 0 0/40px 40px round;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,7 +282,7 @@ embed header {
|
|||||||
.note-actions-extra-details summary {
|
.note-actions-extra-details summary {
|
||||||
opacity: 0.5;
|
opacity: 0.5;
|
||||||
}
|
}
|
||||||
.note-actions-extra-details[open] > summary + * > li {
|
.note-actions-extra-details[open] > summary + * > a {
|
||||||
font-size: 0.937rem;
|
font-size: 0.937rem;
|
||||||
line-height: 2;
|
line-height: 2;
|
||||||
}
|
}
|
||||||
|
@ -1,10 +1,9 @@
|
|||||||
{% extends 'stdgrid.html.twig' %}
|
{% extends 'stdgrid.html.twig' %}
|
||||||
|
|
||||||
{% block body %}
|
{% block body %}
|
||||||
<div class="page">
|
|
||||||
<section class="frame-section frame-section-padding">
|
<section class="frame-section frame-section-padding">
|
||||||
|
<h1>{{ 'Attachment' | trans }} {{ title }}</h1>
|
||||||
{% include '/cards/attachments/view.html.twig' with {'attachment': attachment, 'note': note, 'title': title} only %}
|
{% include '/cards/attachments/view.html.twig' with {'attachment': attachment, 'note': note, 'title': title} only %}
|
||||||
<a class="frame-section-button-like" href="{{ download }}"> {{ 'Download link' | trans }}</a>
|
<a class="frame-section-button-like" href="{{ download }}"> {{ 'Original attachment link' | trans }}</a>
|
||||||
</section>
|
</section>
|
||||||
</div>
|
|
||||||
{% endblock body %}
|
{% endblock body %}
|
@ -4,29 +4,20 @@
|
|||||||
<li class="note-actions-extra">
|
<li class="note-actions-extra">
|
||||||
<details class="note-actions-extra-details">
|
<details class="note-actions-extra-details">
|
||||||
<summary>
|
<summary>
|
||||||
{{ icon('kebab', 'icon icon-note-actions-extra') | raw }} {# button-container #}
|
{{ icon('kebab', 'icon icon-note-actions-extra') | raw }}
|
||||||
</summary>
|
</summary>
|
||||||
<ul>
|
<menu>
|
||||||
<li>
|
|
||||||
<a href="{{ note.getUrl() }}">{{ 'Permalink' | trans }}</a>
|
<a href="{{ note.getUrl() }}">{{ 'Permalink' | trans }}</a>
|
||||||
</li>
|
|
||||||
<hr>
|
<hr>
|
||||||
{% for current_action in get_extra_note_actions(note) %}
|
{% for current_action in get_extra_note_actions(note) %}
|
||||||
<li>
|
<a class="{{ current_action["classes"] }}" href="{{ current_action["url"] }}">{{ current_action['title'] }}</a>
|
||||||
<a class="{{ current_action["classes"] }}"
|
|
||||||
href="{{ current_action["url"] }}">{{ current_action['title'] }}</a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</ul>
|
</menu>
|
||||||
</details>
|
</details>
|
||||||
</li>
|
</li>
|
||||||
<span class="note-actions-separator"></span>
|
<span class="note-actions-separator"></span>
|
||||||
{% for current_action in get_note_actions(note) %}
|
{% for current_action in get_note_actions(note) %}
|
||||||
<li>
|
<li><a title="{{ current_action["title"] | trans }}" class="{{ current_action["classes"] }}" href="{{ current_action["url"] }}"></a></li>
|
||||||
<a title="{{ current_action["title"] | trans }}"
|
|
||||||
class="{{ current_action["classes"] }}"
|
|
||||||
href="{{ current_action["url"] }}"></a>
|
|
||||||
</li>
|
|
||||||
{% endfor %}
|
{% endfor %}
|
||||||
</menu>
|
</menu>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
@ -79,7 +70,8 @@
|
|||||||
|
|
||||||
{% block note_author %}
|
{% block note_author %}
|
||||||
{# Microformat's h-card properties indicates a face icon is a "u-logo" #}
|
{# Microformat's h-card properties indicates a face icon is a "u-logo" #}
|
||||||
<a href="{{ actor_url }}" class="note-author-url u-url" tabindex="0" title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}">
|
<a href="{{ actor_url }}" class="note-author-url u-url" tabindex="0"
|
||||||
|
title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}">
|
||||||
{% if fullname is not null %}
|
{% if fullname is not null %}
|
||||||
{{ fullname }}
|
{{ fullname }}
|
||||||
{% else %}
|
{% else %}
|
||||||
|
Loading…
Reference in New Issue
Block a user