mirror of
https://code.castopod.org/adaures/castopod
synced 2025-08-26 14:29:28 +00:00
fix(fediverse): add is_private field to posts to flag private posts and hide them from public views
This commit is contained in:
parent
346c00e7b5
commit
8ec42c33ff
@ -5,13 +5,11 @@ declare(strict_types=1);
|
|||||||
use CodeIgniter\Router\RouteCollection;
|
use CodeIgniter\Router\RouteCollection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @var RouteCollection
|
|
||||||
*
|
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
* Placeholder definitions
|
* Placeholder definitions
|
||||||
* --------------------------------------------------------------------
|
* --------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
/** @var RouteCollection $routes */
|
||||||
$routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}');
|
$routes->addPlaceholder('podcastHandle', '[a-zA-Z0-9\_]{1,32}');
|
||||||
$routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,128}');
|
$routes->addPlaceholder('slug', '[a-zA-Z0-9\-]{1,128}');
|
||||||
$routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}');
|
$routes->addPlaceholder('base64', '[A-Za-z0-9\.\_]+\-{0,2}');
|
||||||
|
@ -69,6 +69,11 @@ class PostController extends FediversePostController
|
|||||||
|
|
||||||
$this->post = $post;
|
$this->post = $post;
|
||||||
|
|
||||||
|
// show 404 if post is private
|
||||||
|
if ($this->post->is_private && ! can_user_interact()) {
|
||||||
|
throw PageNotFoundException::forPageNotFound();
|
||||||
|
}
|
||||||
|
|
||||||
unset($params[0]);
|
unset($params[0]);
|
||||||
unset($params[1]);
|
unset($params[1]);
|
||||||
|
|
||||||
@ -185,6 +190,7 @@ class PostController extends FediversePostController
|
|||||||
'actor_id' => interact_as_actor_id(),
|
'actor_id' => interact_as_actor_id(),
|
||||||
'in_reply_to_id' => $this->post->id,
|
'in_reply_to_id' => $this->post->id,
|
||||||
'message' => $validData['message'],
|
'message' => $validData['message'],
|
||||||
|
'is_private' => $this->post->is_private,
|
||||||
'published_at' => Time::now(),
|
'published_at' => Time::now(),
|
||||||
'created_by' => user_id(),
|
'created_by' => user_id(),
|
||||||
]);
|
]);
|
||||||
|
@ -34,6 +34,7 @@ class Post extends FediversePost
|
|||||||
'episode_id' => '?integer',
|
'episode_id' => '?integer',
|
||||||
'message' => 'string',
|
'message' => 'string',
|
||||||
'message_html' => 'string',
|
'message_html' => 'string',
|
||||||
|
'is_private' => 'boolean',
|
||||||
'favourites_count' => 'integer',
|
'favourites_count' => 'integer',
|
||||||
'reblogs_count' => 'integer',
|
'reblogs_count' => 'integer',
|
||||||
'replies_count' => 'integer',
|
'replies_count' => 'integer',
|
||||||
|
@ -37,4 +37,7 @@ return [
|
|||||||
'block_actor' => 'Block user @{actorUsername}',
|
'block_actor' => 'Block user @{actorUsername}',
|
||||||
'block_domain' => 'Block domain @{actorDomain}',
|
'block_domain' => 'Block domain @{actorDomain}',
|
||||||
'delete' => 'Delete post',
|
'delete' => 'Delete post',
|
||||||
|
'is_public' => 'Post is public',
|
||||||
|
'is_private' => 'Post is private',
|
||||||
|
'cannot_reblog' => 'This private post cannot be shared.',
|
||||||
];
|
];
|
||||||
|
@ -204,7 +204,7 @@ class EpisodeCommentModel extends UuidModel
|
|||||||
{
|
{
|
||||||
// TODO: merge with replies from posts linked to episode linked
|
// TODO: merge with replies from posts linked to episode linked
|
||||||
$episodeCommentsBuilder = $this->builder();
|
$episodeCommentsBuilder = $this->builder();
|
||||||
$episodeComments = $episodeCommentsBuilder->select('*, 0 as is_from_post')
|
$episodeComments = $episodeCommentsBuilder->select('*, 0 as is_private, 0 as is_from_post')
|
||||||
->where([
|
->where([
|
||||||
'episode_id' => $episodeId,
|
'episode_id' => $episodeId,
|
||||||
'in_reply_to_id' => null,
|
'in_reply_to_id' => null,
|
||||||
@ -214,7 +214,7 @@ class EpisodeCommentModel extends UuidModel
|
|||||||
$postModel = new PostModel();
|
$postModel = new PostModel();
|
||||||
$episodePostsRepliesBuilder = $postModel->builder();
|
$episodePostsRepliesBuilder = $postModel->builder();
|
||||||
$episodePostsReplies = $episodePostsRepliesBuilder->select(
|
$episodePostsReplies = $episodePostsRepliesBuilder->select(
|
||||||
'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, favourites_count as likes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post',
|
'id, uri, episode_id, actor_id, in_reply_to_id, message, message_html, is_private, favourites_count as likes_count, replies_count, published_at as created_at, created_by, 1 as is_from_post',
|
||||||
)
|
)
|
||||||
->whereIn('in_reply_to_id', static function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
|
->whereIn('in_reply_to_id', static function (BaseBuilder $builder) use (&$episodeId): BaseBuilder {
|
||||||
return $builder->select('id')
|
return $builder->select('id')
|
||||||
@ -224,8 +224,14 @@ class EpisodeCommentModel extends UuidModel
|
|||||||
'in_reply_to_id' => null,
|
'in_reply_to_id' => null,
|
||||||
]);
|
]);
|
||||||
})
|
})
|
||||||
->where('`created_at` <= UTC_TIMESTAMP()', null, false)
|
->where('`created_at` <= UTC_TIMESTAMP()', null, false);
|
||||||
->getCompiledSelect();
|
|
||||||
|
// do not get private replies if public
|
||||||
|
if (! can_user_interact()) {
|
||||||
|
$episodePostsRepliesBuilder->where('is_private', false);
|
||||||
|
}
|
||||||
|
|
||||||
|
$episodePostsReplies = $episodePostsRepliesBuilder->getCompiledSelect();
|
||||||
|
|
||||||
/** @var BaseResult $allEpisodeComments */
|
/** @var BaseResult $allEpisodeComments */
|
||||||
$allEpisodeComments = $this->db->query(
|
$allEpisodeComments = $this->db->query(
|
||||||
|
@ -32,6 +32,7 @@ class PostModel extends FediversePostModel
|
|||||||
'episode_id',
|
'episode_id',
|
||||||
'message',
|
'message',
|
||||||
'message_html',
|
'message_html',
|
||||||
|
'is_private',
|
||||||
'favourites_count',
|
'favourites_count',
|
||||||
'reblogs_count',
|
'reblogs_count',
|
||||||
'replies_count',
|
'replies_count',
|
||||||
|
7
app/Resources/icons/custom/_index.php
Normal file
7
app/Resources/icons/custom/_index.php
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @icon("custom:repeat-off")
|
||||||
|
*/
|
1
app/Resources/icons/custom/repeat-off.svg
Normal file
1
app/Resources/icons/custom/repeat-off.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg fill="currentColor" viewBox="0 0 24 24" width="1em" height="1em"><path d="m23 19-5 4v-3H8.02l2-2H18v-3l5 4ZM6 4h12.586l2.606-2.606 1.414 1.414L2.414 23 1 21.586l1.65-1.65A1 1 0 0 1 2 19v-7h2v6h.586l12-12H6v3L1 5l5-4v3Zm16 8h-2V8.02l2-2V12Z"/></svg>
|
After Width: | Height: | Size: 253 B |
@ -39,22 +39,22 @@ project generated for you!
|
|||||||
|
|
||||||
2. add a manifest.json file
|
2. add a manifest.json file
|
||||||
|
|
||||||
<FileTree>
|
<FileTree>
|
||||||
- hello-world
|
- hello-world
|
||||||
- **manifest.json**
|
- **manifest.json**
|
||||||
|
|
||||||
</FileTree>
|
</FileTree>
|
||||||
|
|
||||||
See the [manifest reference](./manifest).
|
See the [manifest reference](./manifest).
|
||||||
|
|
||||||
3. add the Plugin.php class
|
3. add the Plugin.php class
|
||||||
|
|
||||||
<FileTree>
|
<FileTree>
|
||||||
- hello-world
|
- hello-world
|
||||||
- manifest.json
|
- manifest.json
|
||||||
- **Plugin.php**
|
- **Plugin.php**
|
||||||
|
|
||||||
</FileTree>
|
</FileTree>
|
||||||
|
|
||||||
</Steps>
|
</Steps>
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@ namespace Modules\Auth\Config;
|
|||||||
|
|
||||||
use CodeIgniter\Router\RouteCollection;
|
use CodeIgniter\Router\RouteCollection;
|
||||||
|
|
||||||
/**
|
/** @var RouteCollection $routes */
|
||||||
* @var RouteCollection
|
|
||||||
*/
|
|
||||||
|
|
||||||
service('auth')
|
service('auth')
|
||||||
->routes($routes);
|
->routes($routes);
|
||||||
|
|
||||||
|
@ -111,6 +111,7 @@ class ActorController extends Controller
|
|||||||
'actor_id' => $payloadActor->id,
|
'actor_id' => $payloadActor->id,
|
||||||
'in_reply_to_id' => $replyToPost->id,
|
'in_reply_to_id' => $replyToPost->id,
|
||||||
'message' => $message,
|
'message' => $message,
|
||||||
|
'is_private' => ! is_note_public($payload->object),
|
||||||
'published_at' => Time::parse($payload->object->published),
|
'published_at' => Time::parse($payload->object->published),
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
@ -28,4 +28,17 @@ class UpdateActivitiesStatus extends BaseMigration
|
|||||||
|
|
||||||
$this->forge->modifyColumn('fediverse_activities', $fields);
|
$this->forge->modifyColumn('fediverse_activities', $fields);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$fields = [
|
||||||
|
'status' => [
|
||||||
|
'type' => 'ENUM',
|
||||||
|
'constraint' => ['queued', 'delivered'],
|
||||||
|
'null' => true,
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->forge->modifyColumn('fediverse_activities', $fields);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,35 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @copyright 2024 Ad Aures
|
||||||
|
* @license https://www.gnu.org/licenses/agpl-3.0.en.html AGPL3
|
||||||
|
* @link https://castopod.org/
|
||||||
|
*/
|
||||||
|
|
||||||
|
namespace Modules\Fediverse\Migrations;
|
||||||
|
|
||||||
|
use App\Database\Migrations\BaseMigration;
|
||||||
|
|
||||||
|
class AddIsPrivateToPosts extends BaseMigration
|
||||||
|
{
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
$fields = [
|
||||||
|
'is_private' => [
|
||||||
|
'type' => 'TINYINT',
|
||||||
|
'constraint' => 1,
|
||||||
|
'default' => 0,
|
||||||
|
'after' => 'message_html',
|
||||||
|
],
|
||||||
|
];
|
||||||
|
|
||||||
|
$this->forge->addColumn('fediverse_posts', $fields);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
$this->forge->dropColumn('fediverse_posts', 'is_private');
|
||||||
|
}
|
||||||
|
}
|
@ -25,9 +25,12 @@ use RuntimeException;
|
|||||||
* @property Post|null $reblog_of_post
|
* @property Post|null $reblog_of_post
|
||||||
* @property string $message
|
* @property string $message
|
||||||
* @property string $message_html
|
* @property string $message_html
|
||||||
|
* @property bool $is_private
|
||||||
|
*
|
||||||
* @property int $favourites_count
|
* @property int $favourites_count
|
||||||
* @property int $reblogs_count
|
* @property int $reblogs_count
|
||||||
* @property int $replies_count
|
* @property int $replies_count
|
||||||
|
*
|
||||||
* @property Time $published_at
|
* @property Time $published_at
|
||||||
* @property Time $created_at
|
* @property Time $created_at
|
||||||
*
|
*
|
||||||
@ -80,6 +83,7 @@ class Post extends UuidEntity
|
|||||||
'reblog_of_id' => '?string',
|
'reblog_of_id' => '?string',
|
||||||
'message' => 'string',
|
'message' => 'string',
|
||||||
'message_html' => 'string',
|
'message_html' => 'string',
|
||||||
|
'is_private' => 'boolean',
|
||||||
'favourites_count' => 'integer',
|
'favourites_count' => 'integer',
|
||||||
'reblogs_count' => 'integer',
|
'reblogs_count' => 'integer',
|
||||||
'replies_count' => 'integer',
|
'replies_count' => 'integer',
|
||||||
|
@ -59,6 +59,8 @@ class FediverseFilter implements FilterInterface
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log_message('critical', 'ITS HEEEEEEEEEEEERE');
|
||||||
|
|
||||||
if (in_array('verify-signature', $params, true)) {
|
if (in_array('verify-signature', $params, true)) {
|
||||||
try {
|
try {
|
||||||
// securityCheck: check activity signature before handling it
|
// securityCheck: check activity signature before handling it
|
||||||
|
@ -345,7 +345,7 @@ if (! function_exists('get_message_from_object')) {
|
|||||||
*/
|
*/
|
||||||
function get_message_from_object(stdClass $object): string | false
|
function get_message_from_object(stdClass $object): string | false
|
||||||
{
|
{
|
||||||
if (property_exists($object, 'content')) {
|
if (property_exists($object, 'content') && is_string($object->content)) {
|
||||||
extract_text_from_html($object->content);
|
extract_text_from_html($object->content);
|
||||||
return $object->content;
|
return $object->content;
|
||||||
}
|
}
|
||||||
@ -365,6 +365,29 @@ if (! function_exists('get_message_from_object')) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (! function_exists('is_note_public')) {
|
||||||
|
/**
|
||||||
|
* Check whether note is public or not
|
||||||
|
*/
|
||||||
|
function is_note_public(stdClass $object): bool
|
||||||
|
{
|
||||||
|
$isPublic = false;
|
||||||
|
if (property_exists($object, 'to') && is_array($object->to)) {
|
||||||
|
$isPublic = in_array('https://www.w3.org/ns/activitystreams#Public', $object->to, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($isPublic) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (property_exists($object, 'cc') && is_array($object->cc)) {
|
||||||
|
return in_array('https://www.w3.org/ns/activitystreams#Public', $object->cc, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $isPublic;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (! function_exists('linkify')) {
|
if (! function_exists('linkify')) {
|
||||||
/**
|
/**
|
||||||
* Turn all link elements in clickable links. Transforms urls and handles
|
* Turn all link elements in clickable links. Transforms urls and handles
|
||||||
|
@ -52,6 +52,7 @@ class PostModel extends UuidModel
|
|||||||
'reblog_of_id',
|
'reblog_of_id',
|
||||||
'message',
|
'message',
|
||||||
'message_html',
|
'message_html',
|
||||||
|
'is_private',
|
||||||
'favourites_count',
|
'favourites_count',
|
||||||
'reblogs_count',
|
'reblogs_count',
|
||||||
'replies_count',
|
'replies_count',
|
||||||
@ -183,6 +184,12 @@ class PostModel extends UuidModel
|
|||||||
$this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes())
|
$this->where('in_reply_to_id', $this->uuid->fromString($postId) ->getBytes())
|
||||||
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
->where('`published_at` <= UTC_TIMESTAMP()', null, false)
|
||||||
->orderBy('published_at', 'ASC');
|
->orderBy('published_at', 'ASC');
|
||||||
|
|
||||||
|
// do not get private replies if public
|
||||||
|
if (! can_user_interact()) {
|
||||||
|
$this->where('is_private', false);
|
||||||
|
}
|
||||||
|
|
||||||
$found = $this->findAll();
|
$found = $this->findAll();
|
||||||
|
|
||||||
cache()
|
cache()
|
||||||
@ -284,6 +291,10 @@ class PostModel extends UuidModel
|
|||||||
->set('actor', $post->actor->uri)
|
->set('actor', $post->actor->uri)
|
||||||
->set('object', new $noteObjectClass($post));
|
->set('object', new $noteObjectClass($post));
|
||||||
|
|
||||||
|
if ($post->in_reply_to_id !== null && $post->is_private) {
|
||||||
|
$createActivity->set('to', [$post->reply_to_post->actor->uri]);
|
||||||
|
}
|
||||||
|
|
||||||
$activityId = model('ActivityModel', false)
|
$activityId = model('ActivityModel', false)
|
||||||
->newActivity(
|
->newActivity(
|
||||||
'Create',
|
'Create',
|
||||||
@ -410,11 +421,13 @@ class PostModel extends UuidModel
|
|||||||
|
|
||||||
Events::trigger('on_post_remove', $post);
|
Events::trigger('on_post_remove', $post);
|
||||||
} elseif ($post->in_reply_to_id !== null) {
|
} elseif ($post->in_reply_to_id !== null) {
|
||||||
// Post to remove is a reply
|
if (! $post->is_private) {
|
||||||
model('PostModel', false)
|
// Post to remove is a reply
|
||||||
->builder()
|
model('PostModel', false)
|
||||||
->where('id', $this->uuid->fromString($post->in_reply_to_id) ->getBytes())
|
->builder()
|
||||||
->decrement('replies_count');
|
->where('id', $this->uuid->fromString($post->in_reply_to_id) ->getBytes())
|
||||||
|
->decrement('replies_count');
|
||||||
|
}
|
||||||
|
|
||||||
Events::trigger('on_reply_remove', $post);
|
Events::trigger('on_reply_remove', $post);
|
||||||
}
|
}
|
||||||
@ -442,10 +455,12 @@ class PostModel extends UuidModel
|
|||||||
|
|
||||||
$postId = $this->addPost($reply, $createPreviewCard, $registerActivity);
|
$postId = $this->addPost($reply, $createPreviewCard, $registerActivity);
|
||||||
|
|
||||||
model('PostModel', false)
|
if (! $reply->is_private) {
|
||||||
->builder()
|
model('PostModel', false)
|
||||||
->where('id', $this->uuid->fromString($reply->in_reply_to_id) ->getBytes())
|
->builder()
|
||||||
->increment('replies_count');
|
->where('id', $this->uuid->fromString($reply->in_reply_to_id) ->getBytes())
|
||||||
|
->increment('replies_count');
|
||||||
|
}
|
||||||
|
|
||||||
Events::trigger('on_post_reply', $reply);
|
Events::trigger('on_post_reply', $reply);
|
||||||
|
|
||||||
@ -458,6 +473,11 @@ class PostModel extends UuidModel
|
|||||||
|
|
||||||
public function reblog(Actor $actor, Post $post, bool $registerActivity = true): string | false
|
public function reblog(Actor $actor, Post $post, bool $registerActivity = true): string | false
|
||||||
{
|
{
|
||||||
|
// cannot reblog a private post
|
||||||
|
if ($post->is_private) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
$this->db->transStart();
|
$this->db->transStart();
|
||||||
|
|
||||||
$userId = null;
|
$userId = null;
|
||||||
|
@ -39,13 +39,19 @@ class NoteObject extends ObjectType
|
|||||||
$this->attributedTo = $post->actor->uri;
|
$this->attributedTo = $post->actor->uri;
|
||||||
|
|
||||||
if ($post->in_reply_to_id !== null) {
|
if ($post->in_reply_to_id !== null) {
|
||||||
$this->to[] = $post->reply_to_post->actor->uri;
|
if ($post->is_private) {
|
||||||
|
$this->to = [$post->reply_to_post->actor->uri];
|
||||||
|
} else {
|
||||||
|
$this->to[] = $post->reply_to_post->actor->uri;
|
||||||
|
}
|
||||||
|
|
||||||
$this->inReplyTo = $post->reply_to_post->uri;
|
$this->inReplyTo = $post->reply_to_post->uri;
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->replies = url_to('post-replies', esc($post->actor->username), $post->id);
|
$this->replies = url_to('post-replies', esc($post->actor->username), $post->id);
|
||||||
|
|
||||||
$this->cc = [$post->actor->followers_url];
|
if (! $post->is_private) {
|
||||||
|
$this->cc = [$post->actor->followers_url];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,9 +7,10 @@ use PHPIcons\Config\PHPIconsConfig;
|
|||||||
return PHPIconsConfig::configure()
|
return PHPIconsConfig::configure()
|
||||||
->withPaths([__DIR__ . '/app', __DIR__ . '/themes', __DIR__ . '/resources'])
|
->withPaths([__DIR__ . '/app', __DIR__ . '/themes', __DIR__ . '/resources'])
|
||||||
->withLocalIconSets([
|
->withLocalIconSets([
|
||||||
'funding' => __DIR__ . '/resources/icons/funding',
|
'funding' => __DIR__ . '/app/Resources/icons/funding',
|
||||||
'podcasting' => __DIR__ . '/resources/icons/podcasting',
|
'podcasting' => __DIR__ . '/app/Resources/icons/podcasting',
|
||||||
'social' => __DIR__ . '/resources/icons/social',
|
'social' => __DIR__ . '/app/Resources/icons/social',
|
||||||
|
'custom' => __DIR__ . '/app/Resources/icons/custom',
|
||||||
])
|
])
|
||||||
->withDefaultIconPerSet([
|
->withDefaultIconPerSet([
|
||||||
'funding' => 'funding:default',
|
'funding' => 'funding:default',
|
||||||
|
8
pnpm-lock.yaml
generated
8
pnpm-lock.yaml
generated
@ -4400,10 +4400,10 @@ packages:
|
|||||||
engines: { node: ">=0.10.0" }
|
engines: { node: ">=0.10.0" }
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
electron-to-chromium@1.5.208:
|
electron-to-chromium@1.5.209:
|
||||||
resolution:
|
resolution:
|
||||||
{
|
{
|
||||||
integrity: sha512-ozZyibehoe7tOhNaf16lKmljVf+3npZcJIEbJRVftVsmAg5TeA1mGS9dVCZzOwr2xT7xK15V0p7+GZqSPgkuPg==,
|
integrity: sha512-Xoz0uMrim9ZETCQt8UgM5FxQF9+imA7PBpokoGcZloA1uw2LeHzTlip5cb5KOAsXZLjh/moN2vReN3ZjJmjI9A==,
|
||||||
}
|
}
|
||||||
|
|
||||||
emoji-regex@10.4.0:
|
emoji-regex@10.4.0:
|
||||||
@ -12024,7 +12024,7 @@ snapshots:
|
|||||||
browserslist@4.25.3:
|
browserslist@4.25.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
caniuse-lite: 1.0.30001737
|
caniuse-lite: 1.0.30001737
|
||||||
electron-to-chromium: 1.5.208
|
electron-to-chromium: 1.5.209
|
||||||
node-releases: 2.0.19
|
node-releases: 2.0.19
|
||||||
update-browserslist-db: 1.1.3(browserslist@4.25.3)
|
update-browserslist-db: 1.1.3(browserslist@4.25.3)
|
||||||
|
|
||||||
@ -12631,7 +12631,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
jake: 10.9.4
|
jake: 10.9.4
|
||||||
|
|
||||||
electron-to-chromium@1.5.208: {}
|
electron-to-chromium@1.5.209: {}
|
||||||
|
|
||||||
emoji-regex@10.4.0: {}
|
emoji-regex@10.4.0: {}
|
||||||
|
|
||||||
|
@ -6,7 +6,9 @@
|
|||||||
<a href="<?= route_to('episode', esc($podcast->handle), esc($episode->slug)) ?>"
|
<a href="<?= route_to('episode', esc($podcast->handle), esc($episode->slug)) ?>"
|
||||||
class="inline-flex items-center px-4 py-2 text-sm"><?= icon(
|
class="inline-flex items-center px-4 py-2 text-sm"><?= icon(
|
||||||
'arrow-left-line',
|
'arrow-left-line',
|
||||||
'mr-2 text-lg',
|
[
|
||||||
|
'class' => 'mr-2 text-lg',
|
||||||
|
],
|
||||||
) . lang('Comment.back_to_comments') ?></a>
|
) . lang('Comment.back_to_comments') ?></a>
|
||||||
</nav>
|
</nav>
|
||||||
<div class="pb-12">
|
<div class="pb-12">
|
||||||
|
@ -14,14 +14,22 @@
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
) ?>
|
) ?>
|
||||||
<button type="submit" name="action" value="reblog" class="inline-flex items-center hover:underline" title="<?= lang(
|
<?php if ($post->is_private): ?>
|
||||||
'Post.reblogs',
|
<button type="button" class="inline-flex items-center cursor-not-allowed" title="<?= lang(
|
||||||
[
|
'Post.cannot_reblog',
|
||||||
'numberOfReblogs' => $post->reblogs_count,
|
) ?>"><?= icon('custom:repeat-off', [
|
||||||
],
|
'class' => 'text-2xl mr-1 opacity-40',
|
||||||
) ?>"><?= icon('repeat-fill', [
|
]) ?></button>
|
||||||
'class' => 'text-2xl mr-1 opacity-40',
|
<?php else: ?>
|
||||||
]) . $post->reblogs_count ?></button>
|
<button type="submit" name="action" value="reblog" class="inline-flex items-center hover:underline" title="<?= lang(
|
||||||
|
'Post.reblogs',
|
||||||
|
[
|
||||||
|
'numberOfReblogs' => $post->reblogs_count,
|
||||||
|
],
|
||||||
|
) ?>"><?= icon('repeat-fill', [
|
||||||
|
'class' => 'text-2xl mr-1 opacity-40',
|
||||||
|
]) . $post->reblogs_count ?></button>
|
||||||
|
<?php endif; ?>
|
||||||
<button type="submit" name="action" value="favourite" class="inline-flex items-center hover:underline" title="<?= lang(
|
<button type="submit" name="action" value="favourite" class="inline-flex items-center hover:underline" title="<?= lang(
|
||||||
'Post.favourites',
|
'Post.favourites',
|
||||||
[
|
[
|
||||||
@ -33,8 +41,8 @@
|
|||||||
<button id="<?= $post->id . '-more-dropdown' ?>" type="button" class="px-2 py-1 text-2xl text-skin-muted" data-dropdown="button" data-dropdown-target="<?= $post->id . '-more-dropdown-menu' ?>" aria-label="<?= lang('Common.more') ?>" aria-haspopup="true" aria-expanded="false"><?= icon('more-2-fill') ?></button>
|
<button id="<?= $post->id . '-more-dropdown' ?>" type="button" class="px-2 py-1 text-2xl text-skin-muted" data-dropdown="button" data-dropdown-target="<?= $post->id . '-more-dropdown-menu' ?>" aria-label="<?= lang('Common.more') ?>" aria-haspopup="true" aria-expanded="false"><?= icon('more-2-fill') ?></button>
|
||||||
</form>
|
</form>
|
||||||
<nav id="<?= $post->id .
|
<nav id="<?= $post->id .
|
||||||
'-more-dropdown-menu' ?>" class="flex flex-col py-2 text-sm rounded-lg shadow border-3 border-subtle bg-elevated" aria-labelledby="<?= $post->id .
|
'-more-dropdown-menu' ?>" class="flex flex-col py-2 text-sm rounded-lg shadow border-3 border-subtle bg-elevated" aria-labelledby="<?= $post->id .
|
||||||
'-more-dropdown' ?>" data-dropdown="menu" data-dropdown-placement="bottom">
|
'-more-dropdown' ?>" data-dropdown="menu" data-dropdown-placement="bottom">
|
||||||
<?= anchor(
|
<?= anchor(
|
||||||
route_to('post', esc($podcast->handle), $post->id),
|
route_to('post', esc($podcast->handle), $post->id),
|
||||||
lang('Post.expand'),
|
lang('Post.expand'),
|
||||||
|
@ -17,8 +17,8 @@
|
|||||||
: '@' . esc($post->actor->domain)) ?></span>
|
: '@' . esc($post->actor->domain)) ?></span>
|
||||||
</a>
|
</a>
|
||||||
<a href="<?= route_to('post', esc($podcast->handle), $post->id) ?>"
|
<a href="<?= route_to('post', esc($podcast->handle), $post->id) ?>"
|
||||||
class="text-xs text-skin-muted">
|
class="text-xs text-skin-muted inline-flex items-center">
|
||||||
<?= relative_time($post->published_at) ?>
|
<?= relative_time($post->published_at) ?><span class="ml-1" data-tooltip="bottom" title="<?= $post->is_private ? lang('Post.is_private') : lang('Post.is_public') ?>"><?= $post->is_private ? icon('lock-fill') : icon('earth-fill') ?></span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
</div>
|
||||||
</header>
|
</header>
|
||||||
|
@ -11,7 +11,9 @@
|
|||||||
->display_name) ?><span class="ml-1 text-sm font-normal text-skin-muted">@<?= esc($reply
|
->display_name) ?><span class="ml-1 text-sm font-normal text-skin-muted">@<?= esc($reply
|
||||||
->actor->username) .
|
->actor->username) .
|
||||||
($reply->actor->is_local ? '' : '@' . esc($reply->actor->domain)) ?></span></a>
|
($reply->actor->is_local ? '' : '@' . esc($reply->actor->domain)) ?></span></a>
|
||||||
<?= relative_time($reply->published_at, 'flex-shrink-0 ml-auto text-xs text-skin-muted') ?>
|
<a href="<?= route_to('post', esc($podcast->handle), $reply->id) ?>" class="flex-shrink-0 ml-auto text-xs text-skin-muted inline-flex items-center gap-x-1">
|
||||||
|
<?= relative_time($reply->published_at) ?><span data-tooltip="bottom" title="<?= $reply->is_private ? lang('Post.is_private') : lang('Post.is_public') ?>"><?= $reply->is_private ? icon('lock-fill') : icon('earth-fill') ?></span>
|
||||||
|
</a>
|
||||||
</header>
|
</header>
|
||||||
<p class="mb-2 post-content"><?= $reply->message_html ?></p>
|
<p class="mb-2 post-content"><?= $reply->message_html ?></p>
|
||||||
<?php if ($reply->preview_card_id): ?>
|
<?php if ($reply->preview_card_id): ?>
|
||||||
|
@ -16,14 +16,22 @@ if (can_user_interact()): ?>
|
|||||||
]),
|
]),
|
||||||
],
|
],
|
||||||
) ?>
|
) ?>
|
||||||
<button type="submit" name="action" value="reblog" class="inline-flex items-center text-sm hover:underline" title="<?= lang(
|
<?php if ($reply->is_private): ?>
|
||||||
'Post.reblogs',
|
<button type="button" class="inline-flex items-center text-sm cursor-not-allowed" title="<?= lang(
|
||||||
[
|
'Post.cannot_reblog',
|
||||||
'numberOfReblogs' => $reply->reblogs_count,
|
) ?>"><?= icon('custom:repeat-off', [
|
||||||
],
|
'class' => 'text-lg mr-1 opacity-40',
|
||||||
) ?>"><?= icon('repeat-fill', [
|
]) ?></button>
|
||||||
'class' => 'text-lg mr-1 opacity-40',
|
<?php else: ?>
|
||||||
]) . $reply->reblogs_count ?></button>
|
<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-fill', [
|
||||||
|
'class' => 'text-lg mr-1 opacity-40',
|
||||||
|
]) . $reply->reblogs_count ?></button>
|
||||||
|
<?php endif; ?>
|
||||||
<button type="submit" name="action" value="favourite" class="inline-flex items-center text-sm hover:underline" title="<?= lang(
|
<button type="submit" name="action" value="favourite" class="inline-flex items-center text-sm hover:underline" title="<?= lang(
|
||||||
'Post.favourites',
|
'Post.favourites',
|
||||||
[
|
[
|
||||||
|
Loading…
x
Reference in New Issue
Block a user