diff --git a/app/Domain/Online/FakeSessionRepository.php b/app/Domain/Online/FakeSessionRepository.php index d94b4feeb..13751fe6a 100644 --- a/app/Domain/Online/FakeSessionRepository.php +++ b/app/Domain/Online/FakeSessionRepository.php @@ -20,7 +20,7 @@ public function sessionsIn(string $prefixPath): SessionsSnapshot return new SessionsSnapshot( users:[ ...$this->id(User::query()->whereNotNull('group_name')->limit(1)), - ...$this->id(User::query()->inRandomOrder()->limit(\rand(5, 7))), + ...$this->id(User::query()->inRandomOrder()->limit(\rand(3, 20))), ], guestsCount:\rand(5, 90), ); diff --git a/app/Domain/Online/Viewers.php b/app/Domain/Online/Viewers.php index d52658f1d..03860b9d7 100644 --- a/app/Domain/Online/Viewers.php +++ b/app/Domain/Online/Viewers.php @@ -1,6 +1,8 @@ usersWithoutGroup(), 0, $limit); + } + + public function usersSuperfluous(int $limit): int + { + return \max(0, \count($this->usersWithoutGroup()) - $limit); + } + + public function totalCount(): int + { + return count($this->users) + $this->guestsCount; + } + + /** + * @return ViewerUser[] + */ + public function usersWithGroup(): array + { + return $this->usersFiltered(fn(ViewerUser $user) => $user->groupName); + } + + private function usersWithoutGroup(): array + { + return $this->usersFiltered(fn(ViewerUser $user) => !$user->groupName); + } + + private function usersFiltered(callable $predicate): array + { + return \array_values(\array_filter($this->users, $predicate)); + } } diff --git a/app/Services/Session/Renderer.php b/app/Services/Session/Renderer.php index 21a951c70..216c3ec77 100644 --- a/app/Services/Session/Renderer.php +++ b/app/Services/Session/Renderer.php @@ -2,6 +2,7 @@ namespace Coyote\Services\Session; use Coyote\Domain\Online\FakeSessionRepository; +use Coyote\Domain\Online\Viewers; use Coyote\Domain\Online\ViewersStore; use Illuminate\Http\Request; use Illuminate\View\View; @@ -17,6 +18,23 @@ public function __construct( } public function render(string $requestUri, bool $local): View + { + $viewers = $this->sessionViewers($requestUri); + $limit = 8; + return view('components.viewers', [ + 'local' => $local, + 'guestsCount' => $viewers->guestsCount, + 'usersCount' => \count($viewers->users), + 'title' => $local + ? 'Aktualnie na tej stronie' + : "{$viewers->totalCount()} użytkowników online", + 'usersWithGroup' => $viewers->usersWithGroup(), + 'usersWithoutGroup' => $viewers->usersLeading($limit), + 'superfluousCount' => $viewers->usersSuperfluous($limit), + ]); + } + + private function sessionViewers(string $requestUri): Viewers { $sessions = $this->session->sessionsIn($requestUri); if ($this->isUserLogged()) { @@ -24,19 +42,7 @@ public function render(string $requestUri, bool $local): View } else { $sessions = $sessions->coalesceGuest(); } - $viewers = $this->store->viewers($sessions); - - $viewersCount = $viewers->guestsCount + \count($viewers->users); - return view('components.viewers', [ - 'local' => $local, - 'showAvatars' => $local, - 'guestsCount' => $viewers->guestsCount, - 'usersCount' => \count($viewers->users), - 'title' => $local - ? 'Aktualnie na tej stronie' - : "$viewersCount użytkowników online", - 'users' => $viewers->users, - ]); + return $this->store->viewers($sessions); } private function isUserLogged(): bool diff --git a/resources/feature/viewersOnline/viewers-online.scss b/resources/feature/viewersOnline/viewers-online.scss index 86a9333ba..074192303 100644 --- a/resources/feature/viewersOnline/viewers-online.scss +++ b/resources/feature/viewersOnline/viewers-online.scss @@ -49,11 +49,22 @@ border-radius: 32px; overflow: hidden; margin-right: -12px; - @include dark { - border: 1px solid #444; + width: 32px; + + &.viewers-superfluous { + height: 32px; + text-align: center; + line-height: 32px; + font-size: 0.8em; } + @include light { border: 1px solid #dedede; + background: white; + } + @include dark { + border: 1px solid #444; + background: #2e2e2e; } } } diff --git a/resources/views/components/viewers.twig b/resources/views/components/viewers.twig index 997ce81bc..58a2ac9a3 100644 --- a/resources/views/components/viewers.twig +++ b/resources/views/components/viewers.twig @@ -16,30 +16,29 @@

- {% for user in users %} - {% if user.groupName %} -
-
- {{ user_avatar(user.avatarUrl, user.name) }} -
- - {{ user.name }} -
- {{ user.groupName }} -
+ {% for user in usersWithGroup %} +
+
+ {{ user_avatar(user.avatarUrl, user.name) }}
- {% endif %} + + {{ user.name }} +
+ {{ user.groupName }} +
+
{% endfor %}
- {% if showAvatars %} -
- {% for user in users %} - {% if not user.groupName %} -
- {{ user_avatar(user.avatarUrl, user.name) }} -
- {% endif %} - {% endfor %} -
- {% endif %} +
+ {% for user in usersWithoutGroup %} +
+ {{ user_avatar(user.avatarUrl, user.name) }} +
+ {% endfor %} + {% if superfluousCount > 0 %} +
+ +{{ superfluousCount }} +
+ {% endif %} +
diff --git a/tests/Unit/OnlineUsers/ViewersTest.php b/tests/Unit/OnlineUsers/ViewersTest.php new file mode 100644 index 000000000..62ffffacf --- /dev/null +++ b/tests/Unit/OnlineUsers/ViewersTest.php @@ -0,0 +1,91 @@ +usersOfSize(2), 3); + $this->assertSame(5, $viewers->totalCount()); + } + + #[Test] + public function leadingUsers(): void + { + $viewers = new Viewers([$this->user('Mark')], 0); + [$leading] = $viewers->usersLeading(2); + $this->assertSame('Mark', $leading->name); + } + + #[Test] + public function leadingUsersUpToLimit(): void + { + $viewers = new Viewers($this->usersOfSize(5), 0); + $this->assertCount(2, $viewers->usersLeading(2)); + } + + #[Test] + public function countSuperfluousUsers(): void + { + $viewers = new Viewers($this->usersOfSize(5), 0); + $this->assertSame(3, $viewers->usersSuperfluous(2)); + } + + #[Test] + public function withLimitBiggerThanUsers_returnEmptySuperfluous(): void + { + $viewers = new Viewers($this->usersOfSize(3), 0); + $this->assertSame(0, $viewers->usersSuperfluous(5)); + } + + #[Test] + public function usersWithGroup(): void + { + $viewers = new Viewers([ + $this->user(name:'Tom'), + $this->user(name:'Mark', group:'Blue'), + ], 0); + $users = $viewers->usersWithGroup(); + $this->assertCount(1, $users); + $this->assertSame('Mark', $users[0]->name); + } + + #[Test] + public function leadingUsers_areWithoutGroups(): void + { + $viewers = new Viewers([ + $this->user(name:'Mark', group:'Blue'), + $this->user(name:'Tom'), + ], 0); + $leading = $viewers->usersLeading(2); + $this->assertCount(1, $leading); + $this->assertSame('Tom', $leading[0]->name); + } + + #[Test] + public function superfluousUsers_areWithoutGroups(): void + { + $viewers = new Viewers([ + $this->user(name:'Mark', group:'Blue'), + $this->user(name:'Mark', group:'Blue'), + $this->user(name:'Tom'), + ], 0); + $this->assertSame(1, $viewers->usersSuperfluous(0)); + } + + private function usersOfSize(int $size): array + { + return \array_fill(0, $size, $this->user()); + } + + private function user(string $name = null, string $group = null): ViewerUser + { + return new ViewerUser($name ?? '', $group, null); + } +}