102 lines
3.4 KiB
PHP
102 lines
3.4 KiB
PHP
<?php
|
|
|
|
namespace App\Http\Controllers;
|
|
|
|
use App\Models\Story;
|
|
use Illuminate\Http\JsonResponse;
|
|
|
|
class StoryController extends Controller
|
|
{
|
|
public function index(): JsonResponse
|
|
{
|
|
$activeStories = Story::active()->get();
|
|
|
|
$grouped = $activeStories->groupBy('user_id')->map(function ($items) {
|
|
$first = $items->first();
|
|
return [
|
|
'username' => $first->username,
|
|
'profile_pic_url' => $first->profile_pic_url,
|
|
'is_unread' => $items->contains(fn ($item) => $item->viewed_at === null),
|
|
'muted' => $first->muted,
|
|
'soonest_expiring_at' => $items->min('expiring_at'),
|
|
];
|
|
});
|
|
|
|
$sorted = $grouped
|
|
->sortBy(fn ($s) => [$s['muted'] ? 1 : 0, $s['is_unread'] ? 0 : 1, $s['soonest_expiring_at']])
|
|
->values()
|
|
->map(fn ($s) => [
|
|
'username' => $s['username'],
|
|
'profile_pic_url' => $s['profile_pic_url'],
|
|
'is_unread' => $s['is_unread'],
|
|
'muted' => $s['muted'],
|
|
]);
|
|
return response()->json($sorted);
|
|
}
|
|
|
|
public function show(string $username): JsonResponse
|
|
{
|
|
$items = Story::where('username', $username)->active()->orderBy('taken_at')->get();
|
|
|
|
if ($items->isEmpty()) {
|
|
return response()->json(['message' => 'No active story found.'], 404);
|
|
}
|
|
|
|
$firstUnread = $items->first(fn ($item) => $item->viewed_at === null);
|
|
|
|
$startIndex = $firstUnread
|
|
? $items->search(fn ($item) => $item->id === $firstUnread->id)
|
|
: 0;
|
|
|
|
return response()->json([
|
|
'username' => $username,
|
|
'profile_pic_url' => $items->first()->profile_pic_url,
|
|
'start_index' => $startIndex,
|
|
'items' => $items->map(fn (Story $item) => [
|
|
'id' => $item->id,
|
|
'code' => $item->code,
|
|
'is_video' => $item->is_video,
|
|
'image_url' => $item->image_url,
|
|
'video_url' => $item->video_url,
|
|
'accessibility_caption' => $item->accessibility_caption,
|
|
'taken_at' => $item->taken_at,
|
|
]),
|
|
]);
|
|
}
|
|
|
|
public function markViewed(string $id): JsonResponse
|
|
{
|
|
Story::where('id', $id)->update(['viewed_at' => now()]);
|
|
return response()->json(['ok' => true]);
|
|
}
|
|
|
|
/**
|
|
* Fetch a single story item by its own id, regardless of whether it's
|
|
* still active — used for opening a story someone shared in a DM long
|
|
* after it expired from the live tray.
|
|
*/
|
|
public function showItem(string $id): JsonResponse
|
|
{
|
|
$item = Story::find($id);
|
|
|
|
if (! $item) {
|
|
return response()->json(['message' => 'Story not found.'], 404);
|
|
}
|
|
|
|
return response()->json([
|
|
'username' => $item->username,
|
|
'profile_pic_url' => $item->profile_pic_url,
|
|
'start_index' => 0,
|
|
'items' => [[
|
|
'id' => $item->id,
|
|
'code' => $item->code,
|
|
'is_video' => $item->is_video,
|
|
'image_url' => $item->image_url,
|
|
'video_url' => $item->video_url,
|
|
'accessibility_caption' => $item->accessibility_caption,
|
|
'taken_at' => $item->taken_at,
|
|
]],
|
|
]);
|
|
}
|
|
}
|