[TEMPLATES][Cards][Profile] Provide both actor uri and url, as well as full mention guidance

This commit is contained in:
Diogo Peralta Cordeiro 2021-12-27 04:13:09 +00:00
parent eb761609aa
commit 80afc0fa6c
Signed by: diogo
GPG Key ID: 18D2D35001FBFAB0
9 changed files with 69 additions and 50 deletions

View File

@ -500,6 +500,11 @@ class FreeNetwork extends Component
return false; return false;
} }
public static function mentionToName(string $nickname, string $uri): string
{
return '@' . $nickname . '@' . parse_url($uri, \PHP_URL_HOST);
}
public function onPluginVersion(array &$versions): bool public function onPluginVersion(array &$versions): bool
{ {
$versions[] = [ $versions[] = [

View File

@ -55,13 +55,13 @@ use App\Util\TemporaryFile;
use Component\Attachment\Entity\ActorToAttachment; use Component\Attachment\Entity\ActorToAttachment;
use Component\Attachment\Entity\AttachmentToNote; use Component\Attachment\Entity\AttachmentToNote;
use Component\Conversation\Conversation; use Component\Conversation\Conversation;
use Component\FreeNetwork\FreeNetwork;
use Component\Language\Entity\Language; use Component\Language\Entity\Language;
use Component\Tag\Tag; use Component\Tag\Tag;
use DateTime; use DateTime;
use DateTimeInterface; use DateTimeInterface;
use Exception; use Exception;
use InvalidArgumentException; use InvalidArgumentException;
use const PHP_URL_HOST;
use Plugin\ActivityPub\ActivityPub; use Plugin\ActivityPub\ActivityPub;
use Plugin\ActivityPub\Entity\ActivitypubObject; use Plugin\ActivityPub\Entity\ActivitypubObject;
use Plugin\ActivityPub\Util\Model; use Plugin\ActivityPub\Util\Model;
@ -356,7 +356,7 @@ class Note extends Model
$attr['tag'][] = [ $attr['tag'][] = [
'type' => 'Mention', 'type' => 'Mention',
'href' => ($href = $mention->getUri()), 'href' => ($href = $mention->getUri()),
'name' => '@' . $mention->getNickname() . '@' . parse_url($href, PHP_URL_HOST), 'name' => FreeNetwork::mentionToName($mention->getNickname(), $href),
]; ];
$attr['to'][] = $href; $attr['to'][] = $href;
} }

View File

@ -139,9 +139,6 @@ embed header {
float: left; float: left;
margin-left: 4px; margin-left: 4px;
} }
.note-author-url::before {
content: '@';
}
.note-author-fullname { .note-author-fullname {
font-weight: bold; font-weight: bold;
} }

View File

@ -465,9 +465,9 @@ class Actor extends Entity
*/ */
public function getUrl(int $type = Router::ABSOLUTE_URL): string public function getUrl(int $type = Router::ABSOLUTE_URL): string
{ {
if ($this->getIsLocal()) {
$url = null; $url = null;
if (Event::handle('StartGetActorUrl', [$this, $type, &$url]) === Event::next) { if (Event::handle('StartGetActorUrl', [$this, $type, &$url]) === Event::next) {
if ($this->getIsLocal()) {
switch ($this->type) { switch ($this->type) {
case self::PERSON: case self::PERSON:
case self::ORGANIZATION: case self::ORGANIZATION:
@ -481,11 +481,11 @@ class Actor extends Entity
default: default:
throw new BugFoundException('Actor type added but `Actor::getUrl` was not updated'); throw new BugFoundException('Actor type added but `Actor::getUrl` was not updated');
} }
} else {
return $this->getUri($type);
}
Event::handle('EndGetActorUrl', [$this, $type, &$url]); Event::handle('EndGetActorUrl', [$this, $type, &$url]);
} }
} else {
return Router::url('actor_view_id', ['id' => $this->getId()], $type);
}
return $url; return $url;
} }

View File

@ -62,20 +62,21 @@ class Extension extends AbstractExtension
return [ return [
/** Twig function to output the 'active' class if the current route matches the given route */ /** Twig function to output the 'active' class if the current route matches the given route */
new TwigFunction('active', [Runtime::class, 'isCurrentRouteActive']), new TwigFunction('active', [Runtime::class, 'isCurrentRouteActive']),
new TwigFunction('is_route', [Runtime::class, 'isCurrentRoute']),
new TwigFunction('get_note_actions', [Runtime::class, 'getNoteActions']),
new TwigFunction('get_extra_note_actions', [Runtime::class, 'getExtraNoteActions']),
new TwigFunction('show_stylesheets', [Runtime::class, 'getShowStylesheets']),
new TwigFunction('handle_event', [Runtime::class, 'handleEvent']),
new TwigFunction('config', [Runtime::class, 'getConfig']), new TwigFunction('config', [Runtime::class, 'getConfig']),
new TwigFunction('dd', 'dd'),
new TwigFunction('die', 'die'),
new TwigFunction('get_extra_note_actions', [Runtime::class, 'getExtraNoteActions']),
new TwigFunction('get_feeds', [Runtime::class, 'getFeeds']),
new TwigFunction('get_note_actions', [Runtime::class, 'getNoteActions']),
new TwigFunction('handle_event', [Runtime::class, 'handleEvent']),
new TwigFunction('handle_override_stylesheet', [Runtime::class, 'handleOverrideStylesheet']),
new TwigFunction('handle_override_template_import', [Runtime::class, 'handleOverrideTemplateImport']),
new TwigFunction('icon', [Runtime::class, 'embedSvgIcon'], ['needs_environment' => true]), new TwigFunction('icon', [Runtime::class, 'embedSvgIcon'], ['needs_environment' => true]),
new TwigFunction('is_firefox', [Runtime::class, 'isFirefox']), new TwigFunction('is_firefox', [Runtime::class, 'isFirefox']),
new TwigFunction('handle_override_template_import', [Runtime::class, 'handleOverrideTemplateImport']), new TwigFunction('is_route', [Runtime::class, 'isCurrentRoute']),
new TwigFunction('handle_override_stylesheet', [Runtime::class, 'handleOverrideStylesheet']), new TwigFunction('mention', [Runtime::class, 'mention']),
new TwigFunction('open_details', [Runtime::class, 'openDetails']), new TwigFunction('open_details', [Runtime::class, 'openDetails']),
new TwigFunction('get_feeds', [Runtime::class, 'getFeeds']), new TwigFunction('show_stylesheets', [Runtime::class, 'getShowStylesheets']),
new TwigFunction('die', 'die'),
new TwigFunction('dd', 'dd'),
]; ];
} }
} }

View File

@ -33,11 +33,13 @@ declare(strict_types = 1);
namespace App\Twig; namespace App\Twig;
use App\Core\Event; use App\Core\Event;
use App\Core\Router\Router;
use App\Entity\Actor; use App\Entity\Actor;
use App\Entity\Feed; use App\Entity\Feed;
use App\Entity\Note; use App\Entity\Note;
use App\Util\Common; use App\Util\Common;
use App\Util\Formatting; use App\Util\Formatting;
use Component\FreeNetwork\FreeNetwork;
use Functional as F; use Functional as F;
use Symfony\Component\EventDispatcher\EventSubscriberInterface; use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use Symfony\Component\HttpFoundation\Request; use Symfony\Component\HttpFoundation\Request;
@ -162,6 +164,15 @@ class Runtime implements RuntimeExtensionInterface, EventSubscriberInterface
return Feed::getFeeds($actor); return Feed::getFeeds($actor);
} }
public function mention(Actor $actor): string
{
if ($actor->getIsLocal()) {
return "@{$actor->getNickname()}";
} else {
return FreeNetwork::mentionToName($actor->getNickname(), $actor->getUri(type: Router::ABSOLUTE_URL));
}
}
// ---------------------------------------------------------- // ----------------------------------------------------------
/** /**

View File

@ -1,7 +1,5 @@
{% extends 'feed/feed.html.twig' %} {% extends 'feed/feed.html.twig' %}
{% set nickname = nickname|escape %}
{% block title %}{% trans %}%nickname%'s profile{% endtrans %}{% endblock %} {% block title %}{% trans %}%nickname%'s profile{% endtrans %}{% endblock %}
{% block body %} {% block body %}

View File

@ -76,6 +76,7 @@
{% 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 }}">
<header class="note-author-fullname" tabindex="0" title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}" > <header class="note-author-fullname" tabindex="0" title="{{ 'Begin a note by the user: ' | trans }} {{ nickname }}" >
{% if fullname is not null %} {% if fullname is not null %}
{{ fullname }} {{ fullname }}
@ -83,9 +84,10 @@
{{ nickname }} {{ nickname }}
{% endif %} {% endif %}
</header> </header>
</a>
<small class="note-author-nickname"> <small class="note-author-nickname">
<a href="{{ actor_url }}" class="note-author-url u-url">{{ nickname }}</a> <a href="{{ actor_uri }}" class="note-author-url u-url">{{ mention }}</a>
</small> </small>
{% endblock note_author %} {% endblock note_author %}
@ -114,7 +116,9 @@
{% set actor = note.getActor() %} {% set actor = note.getActor() %}
{% set nickname = actor.getNickname() %} {% set nickname = actor.getNickname() %}
{% set fullname = actor.getFullname() %} {% set fullname = actor.getFullname() %}
{% set actor_uri = actor.getUri() %}
{% set actor_url = actor.getUrl() %} {% set actor_url = actor.getUrl() %}
{% set mention = mention(actor) %}
{% set note_language = note.getNoteLanguageShortDisplay() %} {% set note_language = note.getNoteLanguageShortDisplay() %}
<article class="h-entry hentry note" lang={{ note.getLanguageLocale() }}> <article class="h-entry hentry note" lang={{ note.getLanguageLocale() }}>
@ -147,7 +151,9 @@
{% set actor = note.getActor() %} {% set actor = note.getActor() %}
{% set nickname = actor.getNickname() %} {% set nickname = actor.getNickname() %}
{% set fullname = actor.getFullname() %} {% set fullname = actor.getFullname() %}
{% set actor_uri = actor.getUri() %}
{% set actor_url = actor.getUrl() %} {% set actor_url = actor.getUrl() %}
{% set mention = mention(actor) %}
<article class="h-entry hentry note"> <article class="h-entry hentry note">
{{ block('note_sidebar') }} {{ block('note_sidebar') }}

View File

@ -4,6 +4,9 @@
{% set actor_tags = actor.getSelfTags() %} {% set actor_tags = actor.getSelfTags() %}
{% set actor_has_bio = actor.hasBio() %} {% set actor_has_bio = actor.hasBio() %}
{% set actor_uri = actor.getUri() %} {% set actor_uri = actor.getUri() %}
{% set actor_url = actor.getUrl() %}
{% set actor_is_local = actor.getIsLocal() %}
{% set mention = mention(actor) %}
{% block profile_view %} {% block profile_view %}
<section id='profile-{{ actor.id }}' class='profile' title="{{ actor_nickname }}'s {{ 'profile information.' | trans }}"> <section id='profile-{{ actor.id }}' class='profile' title="{{ actor_nickname }}'s {{ 'profile information.' | trans }}">
@ -11,30 +14,28 @@
<div class="profile-info"> <div class="profile-info">
<img src="{{ actor_avatar }}" class="profile-avatar" alt="{% trans %} %actor_nickname%'s avatar. {% endtrans %}" width="{{actor_avatar_dimensions['width']}}" height="{{actor_avatar_dimensions['height']}}"> <img src="{{ actor_avatar }}" class="profile-avatar" alt="{% trans %} %actor_nickname%'s avatar. {% endtrans %}" width="{{actor_avatar_dimensions['width']}}" height="{{actor_avatar_dimensions['height']}}">
<strong class="profile-info-nickname" title="{{ actor_nickname }}{{ '\'s nickname.' | trans }}">{{ actor_nickname }}</strong> <strong class="profile-info-nickname" title="{{ actor_nickname }}{{ '\'s nickname.' | trans }}">{{ actor_nickname }}</strong>
<section class="profile-info-bio">
{% if actor_has_bio %}
<span>{{ actor.getBio() }}</span>
{% else %}
<span>{{ '(No bio)' | trans }}</span>
{% endif %}
</section>
</div> </div>
</a> </a>
{% if not actor_is_local %}
<section class="profile-info-remote">
<span>{{ mention }}</span>
</section>
{% endif %}
<section class="profile-info-bio">
<span>{{ actor.getBio() }}</span>
</section>
<section class="profile-info-stats"> <section class="profile-info-stats">
<div><strong>{{ 'Subscribed' | trans }}</strong>{{ actor.getSubscribedCount() }}</div> <div><strong>{{ 'Subscribed' | trans }}</strong>{{ actor.getSubscribedCount() }}</div>
<div><strong>{{ 'Subscribers' | trans }}</strong>{{ actor.getSubscribersCount() }}</div> <div><strong>{{ 'Subscribers' | trans }}</strong>{{ actor.getSubscribersCount() }}</div>
</section> </section>
<nav class="profile-info-tags"> <nav class="profile-info-tags">
{% if actor_tags %}
{% for tag in actor_tags %} {% for tag in actor_tags %}
{% include 'cards/tag/actor_tag.html.twig' with { 'tag': tag, 'actor': actor } %} {% include 'cards/tag/actor_tag.html.twig' with { 'tag': tag, 'actor': actor } %}
{% endfor %} {% endfor %}
{% else %}
{{ '(No tags)' | trans }}
{% endif %}
</nav> </nav>
{% for block in handle_event('AppendCardProfile', { 'actor': actor }) %} {% for block in handle_event('AppendCardProfile', { 'actor': actor }) %}