diff --git a/.app_version b/.app_version index b72b05ed..c0b8d590 100644 --- a/.app_version +++ b/.app_version @@ -1 +1 @@ -0.19.3 +0.19.4 diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b6f86d..19dcf086 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +# 0.19.4 - 2024-12-10 + +### Fixed + +- Fixed a bug where the Photoprism photos were not being shown on the trip page. +- Fixed a bug where the Immich photos were not being shown on the trip page. + +### Added + +- A link to the Photoprism photos on the trip page if there are any. +- A `orientation` field in the Api::PhotoSerializer, hence the `GET /api/v1/photos` endpoint now includes the orientation of the photo. Valid values are `portrait` and `landscape`. + # 0.19.3 - 2024-12-06 ### Changed diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 97492e74..2a9a26d2 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -15,9 +15,10 @@ class TripsController < ApplicationController :country ).map { [_1.to_f, _2.to_f, _3.to_s, _4.to_s, _5.to_s, _6.to_s, _7.to_s, _8.to_s] } - @photos = Rails.cache.fetch("trip_photos_#{@trip.id}", expires_in: 1.day) do - @trip.photos + @photo_previews = Rails.cache.fetch("trip_photos_#{@trip.id}", expires_in: 1.day) do + @trip.photo_previews end + @photo_sources = @trip.photo_sources end def new diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 8cc09c1c..3fe89204 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -110,27 +110,4 @@ module ApplicationHelper def human_date(date) date.strftime('%e %B %Y') end - - def immich_search_url(base_url, start_date, end_date) - query = { - takenAfter: "#{start_date.to_date}T00:00:00.000Z", - takenBefore: "#{end_date.to_date}T23:59:59.999Z" - } - - encoded_query = URI.encode_www_form_component(query.to_json) - "#{base_url}/search?query=#{encoded_query}" - end - - def photoprism_search_url(base_url, start_date, _end_date) - "#{base_url}/library/browse?view=cards&year=#{start_date.year}&month=#{start_date.month}&order=newest&public=true&quality=3" - end - - def photo_search_url(source, settings, start_date, end_date) - case source - when 'immich' - immich_search_url(settings['immich_url'], start_date, end_date) - when 'photoprism' - photoprism_search_url(settings['photoprism_url'], start_date, end_date) - end - end end diff --git a/app/helpers/trips_helper.rb b/app/helpers/trips_helper.rb new file mode 100644 index 00000000..fa0b77ae --- /dev/null +++ b/app/helpers/trips_helper.rb @@ -0,0 +1,26 @@ +# frozen_string_literal: true + +module TripsHelper + def immich_search_url(base_url, start_date, end_date) + query = { + takenAfter: "#{start_date.to_date}T00:00:00.000Z", + takenBefore: "#{end_date.to_date}T23:59:59.999Z" + } + + encoded_query = URI.encode_www_form_component(query.to_json) + "#{base_url}/search?query=#{encoded_query}" + end + + def photoprism_search_url(base_url, start_date, _end_date) + "#{base_url}/library/browse?view=cards&year=#{start_date.year}&month=#{start_date.month}&order=newest&public=true&quality=3" + end + + def photo_search_url(source, settings, start_date, end_date) + case source + when 'immich' + immich_search_url(settings['immich_url'], start_date, end_date) + when 'photoprism' + photoprism_search_url(settings['photoprism_url'], start_date, end_date) + end + end +end diff --git a/app/models/trip.rb b/app/models/trip.rb index 7a0fdaba..e75103c2 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -17,20 +17,27 @@ class Trip < ApplicationRecord points.pluck(:country).uniq.compact end - def photos - return [] unless can_fetch_photos? - - filtered_photos.sample(12) - .sort_by { |photo| photo['localDateTime'] } - .map { |asset| photo_thumbnail(asset) } + def photo_previews + @photo_previews ||= select_dominant_orientation(photos).sample(12) end - def photos_sources - filtered_photos.map { _1[:source] }.uniq + def photo_sources + @photo_sources ||= photos.map { _1[:source] }.uniq end private + def photos + @photos ||= Trips::Photos.new(self, user).call + end + + def select_dominant_orientation(photos) + vertical_photos = photos.select { |photo| photo[:orientation] == 'portrait' } + horizontal_photos = photos.select { |photo| photo[:orientation] == 'landscape' } + + vertical_photos.count > horizontal_photos.count ? vertical_photos : horizontal_photos + end + def calculate_distance distance = 0 @@ -44,32 +51,4 @@ class Trip < ApplicationRecord self.distance = distance.round end - - def can_fetch_photos? - user.immich_integration_configured? || user.photoprism_integration_configured? - end - - def filtered_photos - return @filtered_photos if defined?(@filtered_photos) - - photos = Photos::Search.new( - user, - start_date: started_at.to_date.to_s, - end_date: ended_at.to_date.to_s - ).call - - @filtered_photos = select_dominant_orientation(photos) - end - - def select_dominant_orientation(photos) - vertical_photos = photos.select { |photo| photo[:orientation] == 'portrait' } - horizontal_photos = photos.select { |photo| photo[:orientation] == 'landscape' } - - vertical_photos.count > horizontal_photos.count ? vertical_photos : horizontal_photos - end - - def photo_thumbnail(asset) - { url: "/api/v1/photos/#{asset[:id]}/thumbnail.jpg?api_key=#{user.api_key}&source=#{asset[:source]}" } - end end - diff --git a/app/services/immich/request_photos.rb b/app/services/immich/request_photos.rb index 034a6452..59baa496 100644 --- a/app/services/immich/request_photos.rb +++ b/app/services/immich/request_photos.rb @@ -37,15 +37,7 @@ class Immich::RequestPhotos items = response.dig('assets', 'items') - if items.blank? - Rails.logger.debug('==== IMMICH RESPONSE WITH NO ITEMS ====') - Rails.logger.debug("START_DATE: #{start_date}") - Rails.logger.debug("END_DATE: #{end_date}") - Rails.logger.debug(response) - Rails.logger.debug('==== IMMICH RESPONSE WITH NO ITEMS ====') - - break - end + break if items.blank? data << items diff --git a/app/services/trips/photos.rb b/app/services/trips/photos.rb new file mode 100644 index 00000000..33442833 --- /dev/null +++ b/app/services/trips/photos.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +class Trips::Photos + def initialize(trip, user) + @trip = trip + @user = user + end + + def call + return [] unless can_fetch_photos? + + photos + end + + private + + attr_reader :trip, :user + + def can_fetch_photos? + user.immich_integration_configured? || user.photoprism_integration_configured? + end + + def photos + return @photos if defined?(@photos) + + photos = Photos::Search.new( + user, + start_date: trip.started_at.to_date.to_s, + end_date: trip.ended_at.to_date.to_s + ).call + + @photos = photos.map { |photo| photo_thumbnail(photo) } + end + + def photo_thumbnail(asset) + { + id: asset[:id], + url: "/api/v1/photos/#{asset[:id]}/thumbnail.jpg?api_key=#{user.api_key}&source=#{asset[:source]}", + source: asset[:source], + orientation: asset[:orientation] + } + end +end diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb index d0b265fc..f399eb3f 100644 --- a/app/views/trips/show.html.erb +++ b/app/views/trips/show.html.erb @@ -36,8 +36,8 @@ - <% if @photos.any? %> - <% @photos.each_slice(4) do |slice| %> + <% if @photo_previews.any? %> + <% @photo_previews.each_slice(4) do |slice| %>