-
-
Notifications
You must be signed in to change notification settings - Fork 315
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
13 changed files
with
485 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
<?php | ||
|
||
namespace App\Actions\Photo; | ||
|
||
use App\Eloquent\FixedQueryBuilder; | ||
use App\Enum\ColumnSortingPhotoType; | ||
use App\Enum\OrderSortingType; | ||
use App\Models\Configs; | ||
use App\Models\Photo; | ||
use App\Policies\PhotoQueryPolicy; | ||
use Illuminate\Database\Eloquent\Builder; | ||
|
||
class Timeline | ||
{ | ||
protected PhotoQueryPolicy $photoQueryPolicy; | ||
|
||
public function __construct(PhotoQueryPolicy $photoQueryPolicy) | ||
{ | ||
$this->photoQueryPolicy = $photoQueryPolicy; | ||
} | ||
|
||
/** | ||
* Create the query manually. | ||
* | ||
* @return FixedQueryBuilder<Photo> | ||
*/ | ||
public function do(): Builder | ||
{ | ||
$order = Configs::getValueAsEnum('timeline_photos_order', ColumnSortingPhotoType::class); | ||
|
||
// Safe default (should not be needed). | ||
// @codeCoverageIgnoreStart | ||
if (!in_array($order, [ColumnSortingPhotoType::CREATED_AT, ColumnSortingPhotoType::TAKEN_AT], true)) { | ||
$order = ColumnSortingPhotoType::TAKEN_AT; | ||
} | ||
// @codeCoverageIgnoreEnd | ||
|
||
return $this->photoQueryPolicy->applySearchabilityFilter( | ||
query: Photo::query()->with(['album', 'size_variants', 'size_variants.sym_links']), | ||
origin: null, | ||
include_nsfw: !Configs::getValueAsBool('hide_nsfw_in_timeline') | ||
)->orderBy($order->value, OrderSortingType::DESC->value); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,40 @@ | ||
<?php | ||
|
||
namespace App\Http\Controllers\Gallery; | ||
|
||
use App\Actions\Photo\Timeline; | ||
use App\Http\Requests\Photo\GetTimelineRequest; | ||
use App\Http\Resources\Timeline\InitResource; | ||
use App\Http\Resources\Timeline\TimelineResource; | ||
use App\Models\Configs; | ||
use App\Models\Photo; | ||
use Illuminate\Contracts\Pagination\LengthAwarePaginator; | ||
use Illuminate\Routing\Controller; | ||
use Spatie\LaravelData\Data; | ||
|
||
/** | ||
* Controller responsible for the Timeline data. | ||
*/ | ||
class TimelineController extends Controller | ||
{ | ||
public function __invoke(GetTimelineRequest $request, Timeline $timeline): Data | ||
{ | ||
/** @var LengthAwarePaginator<Photo> $photoResults */ | ||
/** @disregard P1013 Undefined method withQueryString() (stupid intelephense) */ | ||
$photoResults = $timeline->do()->paginate(Configs::getValueAsInt('timeline_photos_pagination_limit')); | ||
|
||
return TimelineResource::fromData($photoResults); | ||
} | ||
|
||
/** | ||
* Return init Search. | ||
* | ||
* @param GetTimelineRequest $request | ||
* | ||
* @return InitResource | ||
*/ | ||
public function init(GetTimelineRequest $request): Data | ||
{ | ||
return new InitResource(); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace App\Http\Requests\Photo; | ||
|
||
use App\Http\Requests\AbstractEmptyRequest; | ||
use App\Models\Configs; | ||
use Illuminate\Support\Facades\Auth; | ||
|
||
class GetTimelineRequest extends AbstractEmptyRequest | ||
{ | ||
/** | ||
* {@inheritDoc} | ||
*/ | ||
public function authorize(): bool | ||
{ | ||
if (!Auth::check() && !Configs::getValueAsBool('timeline_photos_public')) { | ||
return false; | ||
} | ||
|
||
return Configs::getValueAsBool('timeline_photos_enabled'); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
<?php | ||
|
||
namespace App\Http\Resources\Timeline; | ||
|
||
use App\Enum\PhotoLayoutType; | ||
use App\Models\Configs; | ||
use Spatie\LaravelData\Data; | ||
use Spatie\TypeScriptTransformer\Attributes\TypeScript; | ||
|
||
/** | ||
* Initialization resource for the search. | ||
*/ | ||
#[TypeScript()] | ||
class InitResource extends Data | ||
{ | ||
public PhotoLayoutType $photo_layout; | ||
|
||
public function __construct() | ||
{ | ||
$this->photo_layout = Configs::getValueAsEnum('timeline_photos_layout', PhotoLayoutType::class); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
<?php | ||
|
||
namespace App\Http\Resources\Timeline; | ||
|
||
use App\Enum\TimelinePhotoGranularity; | ||
use App\Http\Resources\Models\PhotoResource; | ||
use App\Http\Resources\Models\Utils\TimelineData; | ||
use App\Http\Resources\Traits\HasPrepPhotoCollection; | ||
use App\Models\Configs; | ||
use App\Models\Photo; | ||
use Illuminate\Contracts\Pagination\LengthAwarePaginator; | ||
use Illuminate\Contracts\Pagination\Paginator; | ||
use Illuminate\Support\Collection; | ||
use Spatie\LaravelData\Data; | ||
use Spatie\TypeScriptTransformer\Attributes\LiteralTypeScriptType; | ||
use Spatie\TypeScriptTransformer\Attributes\TypeScript; | ||
|
||
/** | ||
* Result of a Search query. | ||
*/ | ||
#[TypeScript()] | ||
class TimelineResource extends Data | ||
{ | ||
use HasPrepPhotoCollection; | ||
|
||
/** @var Collection<int,PhotoResource> */ | ||
#[LiteralTypeScriptType('App.Http.Resources.Models.PhotoResource[]')] | ||
public Collection $photos; | ||
|
||
public int $current_page; | ||
public int $from; | ||
public int $last_page; | ||
public int $per_page; | ||
public int $to; | ||
public int $total; | ||
|
||
/** | ||
* @param LengthAwarePaginator<PhotoResource>&Paginator<PhotoResource> $photos | ||
* | ||
* @return void | ||
*/ | ||
public function __construct( | ||
LengthAwarePaginator $photos, | ||
) { | ||
$this->photos = collect($photos->items()); | ||
$this->current_page = $photos->currentPage(); | ||
$this->from = $photos->firstItem() ?? 0; | ||
$this->last_page = $photos->lastPage(); | ||
$this->per_page = $photos->perPage(); | ||
$this->to = $photos->lastItem() ?? 0; | ||
$this->total = $photos->total(); | ||
|
||
// We do it manually this time. | ||
$previous_photo = null; | ||
$this->photos->each(function (PhotoResource &$photo) use (&$previous_photo) { | ||
if ($previous_photo !== null) { | ||
$previous_photo->next_photo_id = $photo->id; | ||
} | ||
$photo->previous_photo_id = $previous_photo?->id; | ||
$previous_photo = $photo; | ||
}); | ||
$photo_granularity = Configs::getValueAsEnum('timeline_photos_granularity', TimelinePhotoGranularity::class); | ||
$this->photos = TimelineData::setTimeLineDataForPhotos($this->photos, $photo_granularity); | ||
} | ||
|
||
/** | ||
* @param LengthAwarePaginator<Photo> $photos | ||
* | ||
* @return TimelineResource | ||
*/ | ||
public static function fromData(LengthAwarePaginator $photos): self | ||
{ | ||
return new self( | ||
photos: PhotoResource::collect($photos), // @phpstan-ignore-line | ||
); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import axios, { type AxiosResponse } from "axios"; | ||
import Constants from "./constants"; | ||
|
||
const TimelineService = { | ||
timeline(page: number = 1): Promise<AxiosResponse<App.Http.Resources.Timeline.TimelineResource>> { | ||
return axios.get(`${Constants.getApiUrl()}Timeline`, { params: { page: page }, data: {} }); | ||
}, | ||
|
||
init(): Promise<AxiosResponse<App.Http.Resources.Timeline.InitResource>> { | ||
return axios.get(`${Constants.getApiUrl()}Timeline::init`, { data: {} }); | ||
}, | ||
}; | ||
|
||
export default TimelineService; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.