From c6890514724758ca05579b7ee2d5598a5d710e3d Mon Sep 17 00:00:00 2001 From: Eugene Burmakin Date: Thu, 28 Nov 2024 10:40:08 +0100 Subject: [PATCH] Show some photos from the trip --- app/controllers/trips_controller.rb | 4 ++ .../controllers/trips_controller.js | 32 +++++++--- app/models/trip.rb | 20 ++++++ app/services/immich/request_photos.rb | 3 +- app/views/trips/show.html.erb | 21 ++++--- spec/services/immich/request_photos_spec.rb | 62 ++++++++++++++++++- 6 files changed, 121 insertions(+), 21 deletions(-) diff --git a/app/controllers/trips_controller.rb b/app/controllers/trips_controller.rb index 417dcebd..30ff3de9 100644 --- a/app/controllers/trips_controller.rb +++ b/app/controllers/trips_controller.rb @@ -13,6 +13,10 @@ class TripsController < ApplicationController :latitude, :longitude, :battery, :altitude, :timestamp, :velocity, :id, :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 + end end def new diff --git a/app/javascript/controllers/trips_controller.js b/app/javascript/controllers/trips_controller.js index 9763d37c..fdbdca69 100644 --- a/app/javascript/controllers/trips_controller.js +++ b/app/javascript/controllers/trips_controller.js @@ -10,7 +10,7 @@ import { esriWorldStreetMapLayer } from "../maps/layers" import { esriWorldTopoMapLayer } from "../maps/layers" import { esriWorldImageryMapLayer } from "../maps/layers" import { esriWorldGrayCanvasMapLayer } from "../maps/layers" -// import { fetchAndDisplayPhotos } from "../helpers/photoFetcher"; +import { fetchAndDisplayPhotos } from '../maps/helpers'; export default class extends Controller { static targets = ["container"] @@ -52,7 +52,28 @@ export default class extends Controller { // Add layer control L.control.layers(this.baseMaps(), overlayMaps).addTo(this.map) - // Add markers for each coordinate + // Add event listener for layer changes + this.map.on('overlayadd', (e) => { + if (e.name === 'Photos' && this.coordinates?.length > 0) { + const firstCoord = this.coordinates[0]; + const lastCoord = this.coordinates[this.coordinates.length - 1]; + + // Convert Unix timestamp to a Date object + const startDate = new Date(firstCoord[4] * 1000).toISOString().split('T')[0]; + const endDate = new Date(lastCoord[4] * 1000).toISOString().split('T')[0]; + + fetchAndDisplayPhotos({ + map: this.map, + photoMarkers: this.photoMarkers, + apiKey: this.apiKey, + startDate: startDate, + endDate: endDate, + userSettings: this.userSettings + }); + } + }); + + // Add markers and route if (this.coordinates?.length > 0) { this.addMarkers() this.addPolyline() @@ -129,11 +150,4 @@ export default class extends Controller { esriWorldGrayCanvas: esriWorldGrayCanvasMapLayer(this.map, selectedLayerName) }; } - - someMethod() { - // Example usage - const startDate = '2023-01-01'; - const endDate = '2023-12-31'; - fetchAndDisplayPhotos(this.map, this.apiKey, this.photoMarkers, startDate, endDate); - } } diff --git a/app/models/trip.rb b/app/models/trip.rb index cae1b1f6..5c3851bd 100644 --- a/app/models/trip.rb +++ b/app/models/trip.rb @@ -12,4 +12,24 @@ class Trip < ApplicationRecord def countries points.pluck(:country).uniq.compact end + + def photos + immich_photos = Immich::RequestPhotos.new( + user, + start_date: started_at.to_date.to_s, + end_date: ended_at.to_date.to_s + ).call + + # 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).map do |asset| + { url: "/api/v1/photos/#{asset['id']}/thumbnail.jpg?api_key=#{user.api_key}" } + end + end end diff --git a/app/services/immich/request_photos.rb b/app/services/immich/request_photos.rb index e67c5c31..3ab8a246 100644 --- a/app/services/immich/request_photos.rb +++ b/app/services/immich/request_photos.rb @@ -27,6 +27,7 @@ class Immich::RequestPhotos data = [] max_pages = 10_000 # Prevent infinite loop + # TODO: Handle pagination using nextPage while page <= max_pages response = JSON.parse( HTTParty.post( @@ -49,7 +50,7 @@ class Immich::RequestPhotos page += 1 end - data.flatten + data.flatten.reject { |asset| asset['type'].downcase == 'video' } end def headers diff --git a/app/views/trips/show.html.erb b/app/views/trips/show.html.erb index 9db616d7..07f2f1e4 100644 --- a/app/views/trips/show.html.erb +++ b/app/views/trips/show.html.erb @@ -48,15 +48,20 @@ - <% (1..12).each_slice(4) do |slice| %> -
- <% slice.each do %> -
- Photo Placeholder -
+ <% if @photos.any? %> + <% @photos.each_slice(4) do |slice| %> +
+ <% slice.each do |photo| %> +
+ +
+ <% end %> +
<% end %> -
<% end %>
diff --git a/spec/services/immich/request_photos_spec.rb b/spec/services/immich/request_photos_spec.rb index e36b6449..1abfe566 100644 --- a/spec/services/immich/request_photos_spec.rb +++ b/spec/services/immich/request_photos_spec.rb @@ -18,8 +18,8 @@ RSpec.describe Immich::RequestPhotos do "facets": [] }, "assets": { - "total": 1000, - "count": 1000, + "total": 2, + "count": 2, "items": [ { "id": '7fe486e3-c3ba-4b54-bbf9-1281b39ed15c', @@ -71,8 +71,60 @@ RSpec.describe Immich::RequestPhotos do "hasMetadata": true, "duplicateId": '88a34bee-783d-46e4-aa52-33b75ffda375', "resized": true + }, + { + "id": '7fe486e3-c3ba-4b54-bbf9-1281b39ed15c2', + "deviceAssetId": 'IMG_9913.jpeg-1168914', + "ownerId": 'f579f328-c355-438c-a82c-fe3390bd5f08', + "deviceId": 'CLI', + "libraryId": nil, + "type": 'VIDEO', + "originalPath": 'upload/library/admin/2023/2023-06-08/IMG_9913.jpeg', + "originalFileName": 'IMG_9913.jpeg', + "originalMimeType": 'image/jpeg', + "thumbhash": '4RgONQaZqYaH93g3h3p3d6RfPPrG', + "fileCreatedAt": '2023-06-08T07:58:45.637Z', + "fileModifiedAt": '2023-06-08T09:58:45.000Z', + "localDateTime": '2023-06-08T09:58:45.637Z', + "updatedAt": '2024-08-24T18:20:47.965Z', + "isFavorite": false, + "isArchived": false, + "isTrashed": false, + "duration": '0:00:00.00000', + "exifInfo": { + "make": 'Apple', + "model": 'iPhone 12 Pro', + "exifImageWidth": 4032, + "exifImageHeight": 3024, + "fileSizeInByte": 1_168_914, + "orientation": '6', + "dateTimeOriginal": '2023-06-08T07:58:45.637Z', + "modifyDate": '2023-06-08T07:58:45.000Z', + "timeZone": 'Europe/Berlin', + "lensModel": 'iPhone 12 Pro back triple camera 4.2mm f/1.6', + "fNumber": 1.6, + "focalLength": 4.2, + "iso": 320, + "exposureTime": '1/60', + "latitude": 52.11, + "longitude": 13.22, + "city": 'Johannisthal', + "state": 'Berlin', + "country": 'Germany', + "description": '', + "projectionType": nil, + "rating": nil + }, + "livePhotoVideoId": nil, + "people": [], + "checksum": 'aL1edPVg4ZpEnS6xCRWNUY0pUS8=', + "isOffline": false, + "hasMetadata": true, + "duplicateId": '88a34bee-783d-46e4-aa52-33b75ffda375', + "resized": true } - ] + ], + nextPage: nil } }.to_json end @@ -84,6 +136,10 @@ RSpec.describe Immich::RequestPhotos do 'http://immich.app/api/search/metadata' ).to_return(status: 200, body: immich_data, headers: {}) end + + it 'returns only images' do + expect(service.map { _1['type'] }.uniq).to eq(['IMAGE']) + end end context 'when user has no immich_url' do