Compare commits
4 Commits
60f6c639e5
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| a18e2bb095 | |||
| 40fe75d9b7 | |||
| 4199a19dc3 | |||
| 1f582d71d6 |
@@ -14,9 +14,15 @@ class CommentPresenter
|
|||||||
$this->comment = $comment;
|
$this->comment = $comment;
|
||||||
}
|
}
|
||||||
|
|
||||||
public function markdownBody()
|
public function markdownBody(?int $limit = null)
|
||||||
{
|
{
|
||||||
return Str::of($this->comment->body)->markdown([
|
$body = $this->comment->body;
|
||||||
|
|
||||||
|
if ($limit !== null) {
|
||||||
|
$body = Str::limit($body, $limit);
|
||||||
|
}
|
||||||
|
|
||||||
|
return Str::of($body)->markdown([
|
||||||
'html_input' => 'strip',
|
'html_input' => 'strip',
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
@props(['active'])
|
@props(['active' => false, 'label' => null])
|
||||||
|
|
||||||
@php
|
@php
|
||||||
$classes = ($active ?? false)
|
$classes = $active
|
||||||
? 'inline-flex items-center gap-1.5 rounded-xl bg-gradient-to-r from-rose-600 to-pink-600 px-3.5 py-2 text-sm font-semibold text-white shadow-md shadow-rose-600/25'
|
? 'inline-flex h-9 min-w-0 items-center justify-center gap-1.5 rounded-full bg-gradient-to-r from-rose-600 to-pink-600 text-white shadow-md shadow-rose-600/25 max-lg:w-9 lg:px-3.5 [&>i]:shrink-0'
|
||||||
: 'inline-flex items-center gap-1.5 rounded-xl px-3.5 py-2 text-sm font-medium text-gray-600 dark:text-gray-300 hover:bg-rose-50 dark:hover:bg-rose-950/30 hover:text-rose-700 dark:hover:text-rose-300 transition-colors';
|
: 'inline-flex h-9 w-9 shrink-0 items-center justify-center rounded-full text-gray-600 ring-1 ring-gray-200 transition-colors hover:bg-rose-50 hover:text-rose-700 dark:text-gray-300 dark:ring-neutral-700 dark:hover:bg-rose-950/30 dark:hover:text-rose-300';
|
||||||
@endphp
|
@endphp
|
||||||
|
|
||||||
<a {{ $attributes->merge(['class' => $classes]) }}>
|
<a {{ $attributes->merge(['class' => $classes]) }} @if ($label && ! $active) title="{{ $label }}" @endif>
|
||||||
{{ $slot }}
|
{{ $slot }}
|
||||||
|
|
||||||
|
@if ($active && $label)
|
||||||
|
<span class="hidden truncate text-sm font-semibold lg:inline-flex">{{ $label }}</span>
|
||||||
|
@endif
|
||||||
</a>
|
</a>
|
||||||
|
|||||||
@@ -2,45 +2,44 @@
|
|||||||
@php $notAvailable = auth()->check() ? auth()->user()->unreadNotifications()->count() > 0 : false; @endphp
|
@php $notAvailable = auth()->check() ? auth()->user()->unreadNotifications()->count() > 0 : false; @endphp
|
||||||
|
|
||||||
<div class="mx-auto max-w-[100%] px-3 pt-3 sm:px-5 xl:max-w-[95%] 2xl:max-w-[84%]">
|
<div class="mx-auto max-w-[100%] px-3 pt-3 sm:px-5 xl:max-w-[95%] 2xl:max-w-[84%]">
|
||||||
<div class="flex h-16 items-center justify-between gap-3 rounded-2xl border border-gray-200/60 bg-white/70 px-3 backdrop-blur-xl shadow-lg shadow-black/5 dark:border-white/10 dark:bg-neutral-950/60 dark:shadow-black/40 sm:px-5">
|
<div class="grid h-16 grid-cols-[1fr_auto_1fr] items-center gap-2 rounded-2xl border border-gray-200/60 bg-white/70 px-3 backdrop-blur-xl shadow-lg shadow-black/5 dark:border-white/10 dark:bg-neutral-950/60 dark:shadow-black/40 sm:gap-3 sm:px-5">
|
||||||
{{-- Brand --}}
|
{{-- Left column: brand + inline links --}}
|
||||||
<div class="flex shrink-0 items-center">
|
<div class="flex min-w-0 items-center justify-self-start gap-1">
|
||||||
<a href="{{ route('home.index') }}" class="flex items-center gap-2.5">
|
<a href="{{ route('home.index') }}" class="flex shrink-0 items-center gap-2.5">
|
||||||
<span class="relative">
|
<span class="relative">
|
||||||
<img src="/images/cropped-HS-1-192x192.webp" class="h-9 w-9 rounded-xl " alt="hstream.moe Logo" />
|
<img src="/images/cropped-HS-1-192x192.webp" class="h-9 w-9 rounded-xl " alt="hstream.moe Logo" />
|
||||||
</span>
|
</span>
|
||||||
<span class="hidden text-lg font-bold bg-gradient-to-r from-rose-600 to-pink-500 bg-clip-text text-transparent sm:block">hstream.moe</span>
|
<span class="text-lg font-bold bg-gradient-to-r from-rose-600 to-pink-500 bg-clip-text text-transparent md:hidden xl:block truncate">hstream.moe</span>
|
||||||
</a>
|
</a>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Center: inline links + live search --}}
|
<div class="hidden min-w-0 items-center gap-1 md:flex">
|
||||||
<div class="flex items-center gap-1">
|
<x-nav-link :href="route('home.index')" :active="request()->routeIs('home.index')" :label="__('nav.home')">
|
||||||
<div class="hidden items-center gap-1 lg:flex">
|
<i class="fa-solid fa-house"></i>
|
||||||
<x-nav-link :href="route('home.index')" :active="request()->routeIs('home.index')">
|
|
||||||
<i class="fa-solid fa-house"></i> {{ __('nav.home') }}
|
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
|
|
||||||
<x-nav-link :href="route('hentai.search')" :active="request()->routeIs('hentai.search', 'hentai.searchredirect')">
|
<x-nav-link :href="route('hentai.search')" :active="request()->routeIs('hentai.search', 'hentai.searchredirect')" :label="__('nav.browse')">
|
||||||
<i class="fa-solid fa-compass"></i> {{ __('nav.browse') }}
|
<i class="fa-solid fa-compass"></i>
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
|
|
||||||
<x-nav-link :href="route('playlist.index')" :active="request()->routeIs('playlist.*')">
|
<x-nav-link :href="route('playlist.index')" :active="request()->routeIs('playlist.*')" :label="__('nav.public-playlists')">
|
||||||
<i class="fa-solid fa-rectangle-list"></i> {{ __('nav.public-playlists') }}
|
<i class="fa-solid fa-rectangle-list"></i>
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
|
|
||||||
@auth
|
@auth
|
||||||
<x-nav-link :href="route('download.search')" :active="request()->routeIs('download.search')">
|
<x-nav-link :href="route('download.search')" :active="request()->routeIs('download.search')" :label="__('nav.downloads')">
|
||||||
<i class="fa-solid fa-download"></i> {{ __('nav.downloads') }}
|
<i class="fa-solid fa-download"></i>
|
||||||
</x-nav-link>
|
</x-nav-link>
|
||||||
@endauth
|
@endauth
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
<div class="hidden items-center md:flex">
|
{{-- Center column: live search --}}
|
||||||
|
<div class="hidden items-center justify-self-center md:flex">
|
||||||
@livewire('nav-live-search')
|
@livewire('nav-live-search')
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
|
|
||||||
{{-- Right cluster --}}
|
{{-- Right column: right cluster + hamburger --}}
|
||||||
|
<div class="flex min-w-0 items-center justify-self-end col-start-3 gap-1.5">
|
||||||
<div class="hidden items-center gap-1.5 md:flex">
|
<div class="hidden items-center gap-1.5 md:flex">
|
||||||
{{-- Community dropdown --}}
|
{{-- Community dropdown --}}
|
||||||
<x-dropdown align="right" width="56">
|
<x-dropdown align="right" width="56">
|
||||||
@@ -219,6 +218,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
{{-- Drawer overlay --}}
|
{{-- Drawer overlay --}}
|
||||||
<div x-show="open" @click="open = false"
|
<div x-show="open" @click="open = false"
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
<div class="py-10">
|
<div class="py-10">
|
||||||
<div class="mx-auto sm:px-6 lg:px-8 space-y-6 max-w-[100%] xl:max-w-[95%] 2xl:max-w-[90%]">
|
<div class="mx-auto px-3 sm:px-5 space-y-6 max-w-[100%] xl:max-w-[95%] 2xl:max-w-[84%]">
|
||||||
@include('livewire.partials.search-filter')
|
@include('livewire.partials.search-filter')
|
||||||
</div>
|
</div>
|
||||||
<input type="hidden" id="ts_reference" value="{{ Carbon\Carbon::now()->timestamp }}" />
|
<input type="hidden" id="ts_reference" value="{{ Carbon\Carbon::now()->timestamp }}" />
|
||||||
<div class="relative pt-5 mx-auto sm:px-6 lg:px-8 space-y-6 text-gray-900 dark:text-white xl:max-w-[95%] 2xl:max-w-[90%]" wire:keydown.right.window="nextPage" wire:keydown.left.window="previousPage">
|
<div class="relative pt-5 mx-auto px-3 sm:px-5 space-y-6 text-gray-900 dark:text-white xl:max-w-[95%] 2xl:max-w-[84%]" wire:keydown.right.window="nextPage" wire:keydown.left.window="previousPage">
|
||||||
{{ $episodes->appends(['tags' => $selectedtags])->links('pagination::tailwind') }}
|
{{ $episodes->appends(['tags' => $selectedtags])->links('pagination::tailwind') }}
|
||||||
<div class="flex items-center justify-center">
|
<div class="flex items-center justify-center">
|
||||||
<div class="flex justify-center">
|
<div class="flex justify-center">
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
@csrf
|
@csrf
|
||||||
<div class="relative group">
|
<div class="relative group">
|
||||||
<label for="live-search" class="sr-only">Search</label>
|
<label for="live-search" class="sr-only">Search</label>
|
||||||
<div class="relative w-full sm:min-w-[200px] md:min-w-[200px] lg:min-w-[240px] xl:min-w-[300px]">
|
<div class="relative w-full md:min-w-[220px] lg:min-w-[280px] xl:min-w-[360px]">
|
||||||
{{-- Search Icon --}}
|
{{-- Search Icon --}}
|
||||||
<div class="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
|
<div class="pointer-events-none absolute inset-y-0 left-0 pl-3 flex items-center">
|
||||||
<svg class="w-4 h-4 text-gray-400 dark:text-gray-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
<svg class="w-4 h-4 text-gray-400 dark:text-gray-300" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 20 20">
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
@endif
|
@endif
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-1 flex-grow w-full">
|
<div class="mt-1 flex-grow w-full">
|
||||||
<div class="text-gray-700 dark:text-gray-200">{!! $comment->presenter()->markdownBody() !!}</div>
|
<div class="text-gray-700 dark:text-gray-200">{!! $comment->presenter()->markdownBody($limit ?? 250) !!}</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 space-x-2">
|
<div class="mt-2 space-x-2">
|
||||||
<span class="text-gray-500 dark:text-gray-300 font-medium">
|
<span class="text-gray-500 dark:text-gray-300 font-medium">
|
||||||
|
|||||||
@@ -0,0 +1,40 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
namespace Tests\Unit;
|
||||||
|
|
||||||
|
use App\Models\Comment;
|
||||||
|
use Tests\TestCase;
|
||||||
|
|
||||||
|
class CommentPresenterTest extends TestCase
|
||||||
|
{
|
||||||
|
public function test_markdown_body_renders_full_comment_without_limit(): void
|
||||||
|
{
|
||||||
|
$comment = new Comment(['body' => 'Hello **world**']);
|
||||||
|
|
||||||
|
$result = (string) $comment->presenter()->markdownBody();
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Hello', $result);
|
||||||
|
$this->assertStringContainsString('world', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_markdown_body_is_truncated_when_limit_is_provided(): void
|
||||||
|
{
|
||||||
|
$body = str_repeat('a very long comment. ', 50);
|
||||||
|
$comment = new Comment(['body' => $body]);
|
||||||
|
|
||||||
|
$result = (string) $comment->presenter()->markdownBody(40);
|
||||||
|
|
||||||
|
$this->assertLessThan(strlen($body), strlen($result));
|
||||||
|
$this->assertStringContainsString('...', $result);
|
||||||
|
}
|
||||||
|
|
||||||
|
public function test_markdown_body_is_not_truncated_when_body_is_shorter_than_limit(): void
|
||||||
|
{
|
||||||
|
$comment = new Comment(['body' => 'Short']);
|
||||||
|
|
||||||
|
$result = (string) $comment->presenter()->markdownBody(100);
|
||||||
|
|
||||||
|
$this->assertStringContainsString('Short', $result);
|
||||||
|
$this->assertStringNotContainsString('...', $result);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user