From 58b055e9cd92741ee3e9bb5e93cb6d034e90de43 Mon Sep 17 00:00:00 2001 From: Andy Heathershaw Date: Wed, 5 Oct 2016 11:49:39 +0100 Subject: [PATCH] refs #3: implemented multiple independent views for an album and created a slideshow view --- app/Helpers/MiscHelper.php | 13 +++ .../Controllers/Gallery/AlbumController.php | 25 +++++- .../Controllers/Gallery/PhotoController.php | 13 ++- public/themes/base/css/app.css | 13 +++ public/themes/base/js/app.js | 61 ++++++++++++++ resources/lang/en/forms.php | 1 + resources/lang/en/gallery.php | 5 ++ ...lbum.blade.php => album_default.blade.php} | 4 + .../base/gallery/album_slideshow.blade.php | 81 +++++++++++++++++++ .../views/themes/base/gallery/photo.blade.php | 8 +- .../partials/album_view_selector.blade.php | 19 +++++ resources/views/themes/bootstrap3/theme.json | 5 ++ 12 files changed, 241 insertions(+), 7 deletions(-) rename resources/views/themes/base/gallery/{album.blade.php => album_default.blade.php} (90%) create mode 100644 resources/views/themes/base/gallery/album_slideshow.blade.php create mode 100644 resources/views/themes/base/partials/album_view_selector.blade.php diff --git a/app/Helpers/MiscHelper.php b/app/Helpers/MiscHelper.php index aa04da7..bf224b4 100644 --- a/app/Helpers/MiscHelper.php +++ b/app/Helpers/MiscHelper.php @@ -43,6 +43,19 @@ class MiscHelper return sprintf('https://www.gravatar.com/avatar/%s?s=%d&d=%s', $hash, $size, $default); } + /** + * Tests whether the provided URL belongs to the current application (i.e. both scheme and hostname match.) + * @param $url + * @return bool + */ + public static function isSafeUrl($url) + { + $parts = parse_url($url); + $validParts = parse_url(url('/')); + + return ($parts['scheme'] == $validParts['scheme'] && $parts['host'] == $validParts['host']); + } + public static function randomString($length = 10) { $seed = 'abcdefghijklmnopqrstuvwxyz01234567890'; diff --git a/app/Http/Controllers/Gallery/AlbumController.php b/app/Http/Controllers/Gallery/AlbumController.php index 5069553..481af28 100644 --- a/app/Http/Controllers/Gallery/AlbumController.php +++ b/app/Http/Controllers/Gallery/AlbumController.php @@ -14,7 +14,7 @@ use Illuminate\Support\Facades\DB; class AlbumController extends Controller { - public function index($albumUrlAlias) + public function index(Request $request, $albumUrlAlias) { $album = DbHelper::loadAlbumByUrlAlias($albumUrlAlias); if (is_null($album)) @@ -23,14 +23,31 @@ class AlbumController extends Controller return null; } + $validViews = ['default', 'slideshow']; + $requestedView = strtolower($request->get('view')); + if (!in_array($requestedView, $validViews)) + { + $requestedView = $validViews[0]; + } + $this->authorizeForUser($this->getUser(), 'album.view', $album); + // The slideshow view needs access to all photos, not paged $photos = $album->photos() - ->orderBy(DB::raw('COALESCE(taken_at, created_at)')) - ->paginate(UserConfig::get('items_per_page')); + ->orderBy(DB::raw('COALESCE(taken_at, created_at)')); - return Theme::render('gallery.album', [ + if ($requestedView != 'slideshow') + { + $photos = $photos->paginate(UserConfig::get('items_per_page')); + } + else + { + $photos = $photos->get(); + } + + return Theme::render(sprintf('gallery.album_%s', $requestedView), [ 'album' => $album, + 'current_view' => $requestedView, 'photos' => $photos ]); } diff --git a/app/Http/Controllers/Gallery/PhotoController.php b/app/Http/Controllers/Gallery/PhotoController.php index e4dbb22..69a3636 100644 --- a/app/Http/Controllers/Gallery/PhotoController.php +++ b/app/Http/Controllers/Gallery/PhotoController.php @@ -6,6 +6,7 @@ use App\Album; use App\Facade\Theme; use App\Facade\UserConfig; use App\Helpers\DbHelper; +use App\Helpers\MiscHelper; use app\Http\Controllers\Admin\AlbumController; use App\Http\Controllers\Controller; use App\Http\Middleware\VerifyCsrfToken; @@ -58,7 +59,7 @@ class PhotoController extends Controller return response()->file($album->getAlbumSource()->getPathToPhoto($photo, $thumbnail)); } - public function show($albumUrlAlias, $photoFilename) + public function show(Request $request, $albumUrlAlias, $photoFilename) { $album = DbHelper::loadAlbumByUrlAlias($albumUrlAlias); if (is_null($album)) @@ -73,10 +74,18 @@ class PhotoController extends Controller $isOriginalAllowed = Gate::forUser($this->getUser())->allows('photo.download_original', $photo); + $returnAlbumUrl = $album->url(); + $referer = $request->headers->get('Referer'); + if (strlen($referer) > 0 && MiscHelper::isSafeUrl($referer)) + { + $returnAlbumUrl = $referer; + } + return Theme::render('gallery.photo', [ 'album' => $album, 'is_original_allowed' => $isOriginalAllowed, - 'photo' => $photo + 'photo' => $photo, + 'return_album_url' => $returnAlbumUrl ]); } diff --git a/public/themes/base/css/app.css b/public/themes/base/css/app.css index 0660324..e48de88 100644 --- a/public/themes/base/css/app.css +++ b/public/themes/base/css/app.css @@ -1,3 +1,16 @@ +.album-slideshow-container .image-preview { + height: 600px; + max-width: 100%; + width: 800px; +} + +.album-slideshow-container .thumbnails { + overflow-x: scroll; + overflow-y: hidden; + white-space: nowrap; + width: auto; +} + .no-margin-bottom { margin-bottom: 0; } diff --git a/public/themes/base/js/app.js b/public/themes/base/js/app.js index 217c5d5..6c70656 100644 --- a/public/themes/base/js/app.js +++ b/public/themes/base/js/app.js @@ -364,6 +364,67 @@ function EditPhotosViewModel(album_id, language, urls) { }; } +function SlideShowViewModel(required_timeout_ms) { + var self = this; + + self.current = ko.observable(); + self.currentIndex = ko.observable(0); + self.images = ko.observableArray(); + self.interval = null; + + self.isRunning = ko.observable(false); + self.isPaused = ko.observable(false); + + self.changeCurrentImage = function(photo_id) + { + for (var i = 0; i < self.images().length; i++) + { + var this_image = self.images()[i]; + if (this_image.id == photo_id) + { + self.current(this_image); + self.currentIndex(i); + window.clearInterval(self.interval); + self.interval = window.setInterval(self.rotateNextImage, required_timeout_ms); + return; + } + } + }; + + self.continueSlideshow = function() { + self.isPaused(false); + self.interval = window.setInterval(self.rotateNextImage, required_timeout_ms); + }; + + self.pauseSlideshow = function() { + self.isPaused(true); + window.clearInterval(self.interval); + }; + + self.rotateNextImage = function() { + var next_index = self.currentIndex() + 1; + if (next_index >= self.images().length) + { + next_index = 0; + } + + self.current(self.images()[next_index]); + self.currentIndex(next_index); + }; + + self.startSlideshow = function() { + if (self.images().length <= 0) + { + return; + } + + self.interval = window.setInterval(self.rotateNextImage, required_timeout_ms); + + self.current(self.images()[0]); + self.isRunning(true); + }; +} + function StorageLocationsViewModel() { var self = this; diff --git a/resources/lang/en/forms.php b/resources/lang/en/forms.php index 19b18b0..52ef5f5 100644 --- a/resources/lang/en/forms.php +++ b/resources/lang/en/forms.php @@ -3,6 +3,7 @@ return [ 'activate_user_label' => 'Manually activate this account', 'admin_user_label' => 'User is an administrator', 'album_source_label' => 'Storage location:', + 'album_view_label' => 'View as:', 'apply_action' => 'Apply', 'bulk_edit_photos_label' => 'Bulk edit selected photos:', 'bulk_edit_photos_placeholder' => 'Select an action', diff --git a/resources/lang/en/gallery.php b/resources/lang/en/gallery.php index 18a8a6e..975089d 100644 --- a/resources/lang/en/gallery.php +++ b/resources/lang/en/gallery.php @@ -1,5 +1,10 @@ [ + 'default' => 'Default', + 'slideshow' => 'Slideshow' + ], + 'back_to_album' => 'Back to :name', 'index_no_results_heading' => 'This gallery is empty!', 'index_no_results_text' => 'If you are the owner of this gallery, you can create new albums and upload photos using the :admin_link.' ]; \ No newline at end of file diff --git a/resources/views/themes/base/gallery/album.blade.php b/resources/views/themes/base/gallery/album_default.blade.php similarity index 90% rename from resources/views/themes/base/gallery/album.blade.php rename to resources/views/themes/base/gallery/album_default.blade.php index 3f46ce2..7db37dd 100644 --- a/resources/views/themes/base/gallery/album.blade.php +++ b/resources/views/themes/base/gallery/album_default.blade.php @@ -16,6 +16,10 @@
+
+ @include(\App\Facade\Theme::viewName('partials.album_view_selector')) +
+

{{ $album->name }}

{{ $album->description }}


diff --git a/resources/views/themes/base/gallery/album_slideshow.blade.php b/resources/views/themes/base/gallery/album_slideshow.blade.php new file mode 100644 index 0000000..439f3b6 --- /dev/null +++ b/resources/views/themes/base/gallery/album_slideshow.blade.php @@ -0,0 +1,81 @@ +@extends('themes.base.layout') +@section('title', $album->name) + +@section('breadcrumb') + +@endsection + +@section('content') +
+
+
+
+ @include(\App\Facade\Theme::viewName('partials.album_view_selector')) +
+ +

{{ $album->name }}

+

{{ $album->description }}

+
+
+
+ +
+
+
+
+ + +
+
+ +
+ + + +
+
+
+ +
+
+
+ @foreach ($photos as $photo) + + {{ $photo->name }} + + @endforeach +
+
+
+
+@endsection + +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/themes/base/gallery/photo.blade.php b/resources/views/themes/base/gallery/photo.blade.php index 0a04cd3..d455c83 100644 --- a/resources/views/themes/base/gallery/photo.blade.php +++ b/resources/views/themes/base/gallery/photo.blade.php @@ -6,7 +6,7 @@ @@ -85,5 +85,11 @@
+ +
+ +
@endsection \ No newline at end of file diff --git a/resources/views/themes/base/partials/album_view_selector.blade.php b/resources/views/themes/base/partials/album_view_selector.blade.php new file mode 100644 index 0000000..0492e06 --- /dev/null +++ b/resources/views/themes/base/partials/album_view_selector.blade.php @@ -0,0 +1,19 @@ +
+
+ + +
+
+ +@push('scripts') + +@endpush \ No newline at end of file diff --git a/resources/views/themes/bootstrap3/theme.json b/resources/views/themes/bootstrap3/theme.json index 7904c4f..3b08eb8 100644 --- a/resources/views/themes/bootstrap3/theme.json +++ b/resources/views/themes/bootstrap3/theme.json @@ -19,6 +19,11 @@ "name": "admin-preview", "height": 112, "width": 150 + }, + { + "name": "slideshow-tiny", + "height": 75, + "width": 100 } ] } \ No newline at end of file