Show photoprism photos on a trip page

This commit is contained in:
Eugene Burmakin 2024-12-10 18:49:37 +01:00
parent e5b7cc1619
commit b336172b31
5 changed files with 68 additions and 22 deletions

View file

@ -120,4 +120,17 @@ module ApplicationHelper
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

View file

@ -18,8 +18,9 @@ class Import < ApplicationRecord
end
def years_and_months_tracked
points.order(:timestamp).map do |point|
[Time.zone.at(point.timestamp).year, Time.zone.at(point.timestamp).month]
points.order(:timestamp).pluck(:timestamp).map do |timestamp|
time = Time.zone.at(timestamp)
[time.year, time.month]
end.uniq
end
end

View file

@ -18,25 +18,15 @@ class Trip < ApplicationRecord
end
def photos
return [] if user.settings['immich_url'].blank? || user.settings['immich_api_key'].blank?
return [] unless can_fetch_photos?
immich_photos = Immich::RequestPhotos.new(
user,
start_date: started_at.to_date.to_s,
end_date: ended_at.to_date.to_s
).call.reject { |asset| asset['type'].downcase == 'video' }
filtered_photos.sample(12)
.sort_by { |photo| photo['localDateTime'] }
.map { |asset| photo_thumbnail(asset) }
end
# let's count what photos are more: vertical or horizontal and select the ones that are more
vertical_photos = immich_photos.select { _1['exifInfo']['orientation'] == '6' }
horizontal_photos = immich_photos.select { _1['exifInfo']['orientation'] == '3' }
# this is ridiculous, but I couldn't find my way around frontend
# to show all photos in the same height
photos = vertical_photos.count > horizontal_photos.count ? vertical_photos : horizontal_photos
photos.sample(12).sort_by { _1['localDateTime'] }.map do |asset|
{ url: "/api/v1/photos/#{asset['id']}/thumbnail.jpg?api_key=#{user.api_key}" }
end
def photos_sources
filtered_photos.map { _1[:source] }.uniq
end
private
@ -54,4 +44,32 @@ 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

View file

@ -17,6 +17,7 @@ class Api::PhotoSerializer
state: state,
country: country,
type: type,
orientation: orientation,
source: source
}
end
@ -60,4 +61,13 @@ class Api::PhotoSerializer
def type
(photo['type'] || photo['Type']).downcase
end
def orientation
case source
when 'immich'
photo.dig('exifInfo', 'orientation') == '6' ? 'portrait' : 'landscape'
when 'photoprism'
photo['Portrait'] ? 'portrait' : 'landscape'
end
end
end

View file

@ -52,9 +52,13 @@
<% end %>
<% end %>
<div class="text-center mt-6">
<%= link_to "More photos on Immich", immich_search_url(current_user.settings['immich_url'], @trip.started_at, @trip.ended_at), class: "btn btn-primary", target: '_blank' %>
</div>
<% if @trip.photos_sources.any? %>
<div class="text-center mt-6">
<% @trip.photos_sources.each do |source| %>
<%= link_to "More photos on #{source}", photo_search_url(source, current_user.settings, @trip.started_at, @trip.ended_at), class: "btn btn-primary mt-2", target: '_blank' %>
<% end %>
</div>
<% end %>
</div>
</div>
</div>