diff --git a/lib/philomena_web/controllers/gallery_controller.ex b/lib/philomena_web/controllers/gallery_controller.ex index 6d919b6a..52e40d32 100644 --- a/lib/philomena_web/controllers/gallery_controller.ex +++ b/lib/philomena_web/controllers/gallery_controller.ex @@ -57,22 +57,32 @@ defmodule PhilomenaWeb.GalleryController do {:ok, {images, _tags}} = ImageLoader.search_string(conn, query, queries: sort.queries, sorts: sort.sorts) - interactions = Interactions.user_interactions(images, user) + {gallery_prev, gallery_next} = prev_next_page_images(conn, query, sort) + + interactions = Interactions.user_interactions([images, gallery_prev, gallery_next], user) watching = Galleries.subscribed?(gallery, user) - gallery_images = Jason.encode!(Enum.map(images, & &1.id)) + + prev_image = if gallery_prev, do: [gallery_prev], else: [] + next_image = if gallery_next, do: [gallery_next], else: [] + + gallery_images = prev_image ++ Enum.to_list(images) ++ next_image + gallery_json = Jason.encode!(Enum.map(gallery_images, & &1.id)) Galleries.clear_notification(gallery, user) conn |> NotificationCountPlug.call([]) |> Map.put(:params, params) - |> assign(:clientside_data, gallery_images: gallery_images) + |> assign(:clientside_data, gallery_images: gallery_json) |> render("show.html", title: "Showing Gallery", layout_class: "layout--wide", watching: watching, gallery: gallery, + gallery_prev: gallery_prev, + gallery_next: gallery_next, + gallery_images: gallery_images, images: images, interactions: interactions ) @@ -135,6 +145,39 @@ defmodule PhilomenaWeb.GalleryController do |> redirect(to: Routes.gallery_path(conn, :index)) end + defp prev_next_page_images(conn, query, sort) do + limit = conn.assigns.image_pagination.page_size + offset = (conn.assigns.image_pagination.page_number - 1) * limit + + # Inconsistency: Elasticsearch doesn't allow requesting offsets which are less than 0, + # but it does allow requesting offsets which are beyond the total number of results. + + prev_image = gallery_image(offset - 1, conn, query, sort) + next_image = gallery_image(offset + limit, conn, query, sort) + + {prev_image, next_image} + end + + defp gallery_image(offset, _conn, _query, _sorts) when offset < 0, do: nil + + defp gallery_image(offset, conn, query, sort) do + pagination_params = %{page_number: offset + 1, page_size: 1} + + {:ok, {image, _tags}} = + ImageLoader.search_string( + conn, + query, + pagination: pagination_params, + queries: sort.queries, + sorts: sort.sorts + ) + + case Enum.to_list(image) do + [image] -> image + [] -> nil + end + end + defp parse_search(%{"gallery" => gallery_params}) do parse_title(gallery_params) ++ parse_creator(gallery_params) ++ diff --git a/lib/philomena_web/templates/gallery/show.html.slime b/lib/philomena_web/templates/gallery/show.html.slime index 2f3a13e8..97abf78d 100644 --- a/lib/philomena_web/templates/gallery/show.html.slime +++ b/lib/philomena_web/templates/gallery/show.html.slime @@ -5,7 +5,7 @@ elixir: pagination = render PhilomenaWeb.PaginationView, "_pagination.html", page: @images, route: route, params: scope info = render PhilomenaWeb.PaginationView, "_pagination_info.html", page: @images -#sortable +#sortable class=sortable_classes(@conn) .block#imagelist-container section.block__header.flex span.block__header__title.hide-mobile @@ -72,7 +72,7 @@ elixir: strong Note that you may have to wait a couple of seconds before the order is applied. .block__content.js-resizable-media-container - = for image <- @images do + = for image <- @gallery_images do = render PhilomenaWeb.ImageView, "_image_box.html", image: image, link: image_url.(image), size: :thumb, conn: @conn .block__header.block__header--light.flex diff --git a/lib/philomena_web/views/gallery_view.ex b/lib/philomena_web/views/gallery_view.ex index 231cbdc9..2f0ae2d0 100644 --- a/lib/philomena_web/views/gallery_view.ex +++ b/lib/philomena_web/views/gallery_view.ex @@ -5,6 +5,19 @@ defmodule PhilomenaWeb.GalleryView do def scope(conn), do: ImageScope.scope(conn) + def sortable_classes(%{assigns: %{gallery_prev: prev, gallery_next: next}}) do + [] + |> sortable_prev(prev) + |> sortable_next(next) + |> Enum.join(" ") + end + + def sortable_prev(list, nil), do: list + def sortable_prev(list, _), do: ["js-sortable-has-prev" | list] + + def sortable_next(list, nil), do: list + def sortable_next(list, _), do: ["js-sortable-has-next" | list] + def show_subscription_link?(%{id: id}, %{id: id}), do: false def show_subscription_link?(_user1, _user2), do: true end