diff --git a/ImmichFrame.Core/Interfaces/IClientSettings.cs b/ImmichFrame.Core/Interfaces/IClientSettings.cs index 576c13eb..410423f7 100644 --- a/ImmichFrame.Core/Interfaces/IClientSettings.cs +++ b/ImmichFrame.Core/Interfaces/IClientSettings.cs @@ -13,6 +13,8 @@ public interface IClientSettings public bool ShowProgressBar { get; } public string? PhotoDateFormat { get; } public bool ShowImageDesc { get; } + public bool ShowImageCamera { get; } + public bool ShowImageExif { get; } public bool ShowPeopleDesc { get; } public bool ShowTagsDesc { get; } public bool ShowAlbumName { get; } diff --git a/ImmichFrame.WebApi.Tests/Controllers/ConfigControllerTests.cs b/ImmichFrame.WebApi.Tests/Controllers/ConfigControllerTests.cs index de31232a..ad9e32bd 100644 --- a/ImmichFrame.WebApi.Tests/Controllers/ConfigControllerTests.cs +++ b/ImmichFrame.WebApi.Tests/Controllers/ConfigControllerTests.cs @@ -34,6 +34,8 @@ public void Setup() ShowProgressBar = false, PhotoDateFormat = "dd.MM.yyyy", ShowImageDesc = false, + ShowImageCamera = true, + ShowImageExif = true, ShowPeopleDesc = false, ShowTagsDesc = false, ShowAlbumName = false, diff --git a/ImmichFrame.WebApi.Tests/Resources/TestV1.json b/ImmichFrame.WebApi.Tests/Resources/TestV1.json index e6c49102..506b98a0 100644 --- a/ImmichFrame.WebApi.Tests/Resources/TestV1.json +++ b/ImmichFrame.WebApi.Tests/Resources/TestV1.json @@ -42,6 +42,8 @@ "ShowPhotoDate": true, "PhotoDateFormat": "PhotoDateFormat_TEST", "ShowImageDesc": true, + "ShowImageCamera": true, + "ShowImageExif": true, "ShowPeopleDesc": true, "ShowImageLocation": true, "ImageLocationFormat": "ImageLocationFormat_TEST", diff --git a/ImmichFrame.WebApi.Tests/Resources/TestV2.json b/ImmichFrame.WebApi.Tests/Resources/TestV2.json index 4d603dc9..444ae82a 100644 --- a/ImmichFrame.WebApi.Tests/Resources/TestV2.json +++ b/ImmichFrame.WebApi.Tests/Resources/TestV2.json @@ -22,6 +22,8 @@ "ShowProgressBar": true, "ShowPhotoDate": true, "ShowImageDesc": true, + "ShowImageCamera": true, + "ShowImageExif": true, "ShowPeopleDesc": true, "ShowAlbumName": true, "ShowImageLocation": true, diff --git a/ImmichFrame.WebApi.Tests/Resources/TestV2.yml b/ImmichFrame.WebApi.Tests/Resources/TestV2.yml index 47f45947..a61228e1 100644 --- a/ImmichFrame.WebApi.Tests/Resources/TestV2.yml +++ b/ImmichFrame.WebApi.Tests/Resources/TestV2.yml @@ -21,6 +21,8 @@ General: ShowProgressBar: true ShowPhotoDate: true ShowImageDesc: true + ShowImageCamera: true + ShowImageExif: true ShowPeopleDesc: true ShowAlbumName: true ShowImageLocation: true diff --git a/ImmichFrame.WebApi/Helpers/Config/ServerSettingsV1.cs b/ImmichFrame.WebApi/Helpers/Config/ServerSettingsV1.cs index 076f36da..e1f77e8a 100644 --- a/ImmichFrame.WebApi/Helpers/Config/ServerSettingsV1.cs +++ b/ImmichFrame.WebApi/Helpers/Config/ServerSettingsV1.cs @@ -40,6 +40,8 @@ public class ServerSettingsV1 : IConfigSettable public bool ShowPhotoDate { get; set; } = true; public string? PhotoDateFormat { get; set; } = "MM/dd/yyyy"; public bool ShowImageDesc { get; set; } = true; + public bool ShowImageCamera { get; set; } = false; + public bool ShowImageExif { get; set; } = false; public bool ShowPeopleDesc { get; set; } = true; public bool ShowTagsDesc { get; set; } = true; public bool ShowAlbumName { get; set; } = true; @@ -118,6 +120,8 @@ class GeneralSettingsV1Adapter(ServerSettingsV1 _delegate) : IGeneralSettings public bool ShowPhotoDate => _delegate.ShowPhotoDate; public string? PhotoDateFormat => _delegate.PhotoDateFormat; public bool ShowImageDesc => _delegate.ShowImageDesc; + public bool ShowImageCamera => _delegate.ShowImageCamera; + public bool ShowImageExif => _delegate.ShowImageExif; public bool ShowPeopleDesc => _delegate.ShowPeopleDesc; public bool ShowTagsDesc => _delegate.ShowTagsDesc; public bool ShowAlbumName => _delegate.ShowAlbumName; diff --git a/ImmichFrame.WebApi/Models/ClientSettingsDto.cs b/ImmichFrame.WebApi/Models/ClientSettingsDto.cs index 5e408fe9..075d1f86 100644 --- a/ImmichFrame.WebApi/Models/ClientSettingsDto.cs +++ b/ImmichFrame.WebApi/Models/ClientSettingsDto.cs @@ -15,6 +15,8 @@ public class ClientSettingsDto(IClientSettings settings) : IClientSettings public bool ShowProgressBar => settings.ShowProgressBar; public string? PhotoDateFormat => settings.PhotoDateFormat; public bool ShowImageDesc => settings.ShowImageDesc; + public bool ShowImageCamera => settings.ShowImageCamera; + public bool ShowImageExif => settings.ShowImageExif; public bool ShowPeopleDesc => settings.ShowPeopleDesc; public bool ShowTagsDesc => settings.ShowTagsDesc; public bool ShowAlbumName => settings.ShowAlbumName; diff --git a/ImmichFrame.WebApi/Models/ServerSettings.cs b/ImmichFrame.WebApi/Models/ServerSettings.cs index 74d0fb8e..c529ee13 100644 --- a/ImmichFrame.WebApi/Models/ServerSettings.cs +++ b/ImmichFrame.WebApi/Models/ServerSettings.cs @@ -49,6 +49,8 @@ public class GeneralSettings : IGeneralSettings, IConfigSettable public bool ShowProgressBar { get; set; } = true; public bool ShowPhotoDate { get; set; } = true; public bool ShowImageDesc { get; set; } = true; + public bool ShowImageCamera { get; set; } = false; + public bool ShowImageExif { get; set; } = false; public bool ShowPeopleDesc { get; set; } = true; public bool ShowTagsDesc { get; set; } = true; public bool ShowAlbumName { get; set; } = true; diff --git a/Install_Web.md b/Install_Web.md index 5cf3f94c..7cfe0da6 100644 --- a/Install_Web.md +++ b/Install_Web.md @@ -66,6 +66,8 @@ services: # ShowPhotoDate: "true" # PhotoDateFormat: "yyyy-MM-dd" # ShowImageDesc: "true" + # ShowImageCamera: "false" + # ShowImageExif: "false" # ShowPeopleDesc: "true" # ShowAlbumName: "true" # ShowImageLocation: "true" diff --git a/docker/Settings.example.json b/docker/Settings.example.json index a86a4d00..940baad8 100644 --- a/docker/Settings.example.json +++ b/docker/Settings.example.json @@ -22,6 +22,8 @@ "ShowProgressBar": true, "ShowPhotoDate": true, "ShowImageDesc": true, + "ShowImageCamera": false, + "ShowImageExif": false, "ShowPeopleDesc": true, "ShowAlbumName": true, "ShowImageLocation": true, diff --git a/docker/Settings.example.yml b/docker/Settings.example.yml index 173b31a5..5a53e201 100644 --- a/docker/Settings.example.yml +++ b/docker/Settings.example.yml @@ -20,6 +20,8 @@ General: ShowProgressBar: true ShowPhotoDate: true ShowImageDesc: true + ShowImageCamera: false + ShowImageExif: false ShowPeopleDesc: true ShowAlbumName: true ShowImageLocation: true diff --git a/docker/example.env b/docker/example.env index 51d80ed5..38169c8d 100644 --- a/docker/example.env +++ b/docker/example.env @@ -33,6 +33,8 @@ ApiKey=KEY # ShowPhotoDate=true # PhotoDateFormat=yyyy-MM-dd # ShowImageDesc=true +# ShowImageCamera=false +# ShowImageExif=false # ShowPeopleDesc=true # ShowAlbumName=true # ShowImageLocation=true diff --git a/docs/docs/getting-started/configuration.md b/docs/docs/getting-started/configuration.md index 7378c7d1..e9c788a6 100644 --- a/docs/docs/getting-started/configuration.md +++ b/docs/docs/getting-started/configuration.md @@ -74,6 +74,10 @@ General: ShowPhotoDate: true # boolean # Displays the description of the current image. ShowImageDesc: true # boolean + # Displays camera make and model for the current image. + ShowImageCamera: false # boolean + # Displays image EXIF details: f-number, shutter speed, focal length, and ISO. + ShowImageExif: false # boolean # Displays a comma separated list of names of all the people that are assigned in immich. ShowPeopleDesc: true # boolean # Displays a comma separated list of names of all the tags that are assigned in immich. diff --git a/docs/docs/getting-started/configurationV1.md b/docs/docs/getting-started/configurationV1.md index bf9ca932..1ab32d10 100644 --- a/docs/docs/getting-started/configurationV1.md +++ b/docs/docs/getting-started/configurationV1.md @@ -40,6 +40,8 @@ sidebar_position: 4 | Clock | ClockDateFormat | string | eee, MMM d | Date format for the clock. | | [Calendar](#calendar) | Webcalendars | string[] | [] | A list of webcalendar URIs in the .ics format. e.g. https://calendar.google.com/calendar/ical/XXXXXX/public/basic.ics | | [Metadata](#metadata) | ShowImageDesc | boolean | true | Displays the description of the current image. | +| [Metadata](#metadata) | ShowImageCamera | boolean | false | Displays camera make and model for the current image. | +| [Metadata](#metadata) | ShowImageExif | boolean | false | Displays image EXIF details: f-number, shutter speed, focal length, and ISO. | | [Metadata](#metadata) | ShowPeopleDesc | boolean | true | Displays a comma separated list of names of all the people that are assigned in immich. | | [Metadata](#metadata) | ShowAlbumName | boolean | true | Displays a comma separated list of names of all the albums for an image. | | [Metadata](#metadata) | ShowImageLocation | boolean | true | Displays the location of the current image. | @@ -111,4 +113,4 @@ volumes: ``` [openweathermap-url]: https://openweathermap.org/appid -[immich-api-url]: https://immich.app/docs/features/command-line-interface#obtain-the-api-key \ No newline at end of file +[immich-api-url]: https://immich.app/docs/features/command-line-interface#obtain-the-api-key diff --git a/immichFrame.Web/src/lib/components/elements/asset-component.svelte b/immichFrame.Web/src/lib/components/elements/asset-component.svelte index 13ed3901..092eb4c4 100644 --- a/immichFrame.Web/src/lib/components/elements/asset-component.svelte +++ b/immichFrame.Web/src/lib/components/elements/asset-component.svelte @@ -22,6 +22,8 @@ showLocation?: boolean; showPhotoDate?: boolean; showImageDesc?: boolean; + showImageCamera?: boolean; + showImageExif?: boolean; showPeopleDesc?: boolean; showTagsDesc?: boolean; showAlbumName?: boolean; @@ -45,6 +47,8 @@ showLocation = true, showPhotoDate = true, showImageDesc = true, + showImageCamera = false, + showImageExif = false, showPeopleDesc = true, showTagsDesc = true, showAlbumName = true, @@ -111,6 +115,8 @@ {showLocation} {showPhotoDate} {showImageDesc} + {showImageCamera} + {showImageExif} {showPeopleDesc} {showTagsDesc} {showAlbumName} @@ -133,6 +139,8 @@ {showLocation} {showPhotoDate} {showImageDesc} + {showImageCamera} + {showImageExif} {showPeopleDesc} {showTagsDesc} {showAlbumName} @@ -157,6 +165,8 @@ {showLocation} {showPhotoDate} {showImageDesc} + {showImageCamera} + {showImageExif} {showPeopleDesc} {showTagsDesc} {showAlbumName} diff --git a/immichFrame.Web/src/lib/components/elements/asset-info.svelte b/immichFrame.Web/src/lib/components/elements/asset-info.svelte index a3aa3885..54b790c8 100644 --- a/immichFrame.Web/src/lib/components/elements/asset-info.svelte +++ b/immichFrame.Web/src/lib/components/elements/asset-info.svelte @@ -4,7 +4,16 @@ import * as locale from 'date-fns/locale'; import { configStore } from '$lib/stores/config.store'; import Icon from './icon.svelte'; - import { mdiCalendar, mdiMapMarker, mdiAccount, mdiText, mdiImageAlbum, mdiTag } from '@mdi/js'; + import { + mdiCalendar, + mdiMapMarker, + mdiAccount, + mdiText, + mdiImageAlbum, + mdiTag, + mdiCamera, + mdiCameraIris + } from '@mdi/js'; interface Props { asset: AssetResponseDto; @@ -12,6 +21,8 @@ showLocation: boolean; showPhotoDate: boolean; showImageDesc: boolean; + showImageCamera: boolean; + showImageExif: boolean; showPeopleDesc: boolean; showTagsDesc: boolean; showAlbumName: boolean; @@ -24,10 +35,12 @@ showLocation, showPhotoDate, showImageDesc, + showImageCamera, + showImageExif, showPeopleDesc, showTagsDesc, showAlbumName, - split, + split }: Props = $props(); function formatLocation(format: string, city?: string, state?: string, country?: string) { @@ -46,6 +59,28 @@ return Array.from(locationParts).join(', '); } + + function trimFloat(value: number) { + return value.toFixed(2).replace(/\.?0+$/, ''); + } + + function containsWholeWord(value: string, word: string) { + if (!word) return false; + const escaped = word.replace(/[.*+?^${}()|[\]\\]/g, '\\$&'); + return new RegExp(`(^|\\s)${escaped}(?=\\s|$)`, 'i').test(value); + } + + function formatCamera(make?: string | null, model?: string | null) { + const trimmedMake = make?.trim() ?? ''; + const trimmedModel = model?.trim() ?? ''; + + if (containsWholeWord(trimmedModel, trimmedMake)) { + return trimmedModel; + } + + return `${trimmedMake} ${trimmedModel}`.trim(); + } + let assetDate = $derived(asset.exifInfo?.dateTimeOriginal); let desc = $derived(asset.exifInfo?.description ?? ''); let time = $derived(assetDate ? new Date(assetDate) : null); @@ -66,11 +101,20 @@ asset.exifInfo?.country ?? '' ) ); + let imageCamera = $derived(formatCamera(asset.exifInfo?.make, asset.exifInfo?.model)); + let imageExif = $derived( + [ + asset.exifInfo?.fNumber ? `ƒ/${asset.exifInfo.fNumber.toFixed(1)}` : null, + asset.exifInfo?.exposureTime ? `${asset.exifInfo.exposureTime}s` : null, + asset.exifInfo?.focalLength ? `${trimFloat(asset.exifInfo.focalLength)}mm` : null, + asset.exifInfo?.iso ? `ISO ${asset.exifInfo.iso}` : null + ].filter((item): item is string => item !== null) + ); let availablePeople = $derived(asset.people?.filter((x) => x.name)); let availableTags = $derived(asset.tags?.filter((x) => x.name)); -{#if showPhotoDate || showLocation || showImageDesc || showPeopleDesc || showTagsDesc || showAlbumName} +{#if showPhotoDate || showLocation || showImageDesc || showImageCamera || showImageExif || showPeopleDesc || showTagsDesc || showAlbumName}
{desc}

{/if} + {#if showImageCamera && imageCamera} +

+ + {imageCamera} +

+ {/if} + {#if showImageExif && imageExif.length > 0} +

+ + {imageExif.join(' | ')} +

+ {/if} {#if showAlbumName && albums && albums.length > 0}

- {albums.map((x) => x.albumName).join(', ')} + {albums.map((x) => x.albumName).join(', ')}

{/if} {#if showPeopleDesc && availablePeople && availablePeople.length > 0}

- {availablePeople.map((x) => x.name).join(', ')} + {availablePeople.map((x) => x.name).join(', ')}

{/if} {#if showTagsDesc && availableTags && availableTags.length > 0}

- {availableTags.map((x) => x.name).join(', ')} + {availableTags.map((x) => x.name).join(', ')}

{/if} {#if showLocation && location} diff --git a/immichFrame.Web/src/lib/components/elements/asset.svelte b/immichFrame.Web/src/lib/components/elements/asset.svelte index 7df465b8..8d9220cc 100644 --- a/immichFrame.Web/src/lib/components/elements/asset.svelte +++ b/immichFrame.Web/src/lib/components/elements/asset.svelte @@ -21,6 +21,8 @@ showLocation: boolean; showPhotoDate: boolean; showImageDesc: boolean; + showImageCamera: boolean; + showImageExif: boolean; showPeopleDesc: boolean; showTagsDesc: boolean; showAlbumName: boolean; @@ -41,6 +43,8 @@ showLocation, showPhotoDate, showImageDesc, + showImageCamera, + showImageExif, showPeopleDesc, showTagsDesc, showAlbumName, @@ -288,6 +292,8 @@ {showLocation} {showPhotoDate} {showImageDesc} + {showImageCamera} + {showImageExif} {showPeopleDesc} {showTagsDesc} {showAlbumName} diff --git a/immichFrame.Web/src/lib/components/home-page/home-page.svelte b/immichFrame.Web/src/lib/components/home-page/home-page.svelte index fa91b97e..b8cf0d4d 100644 --- a/immichFrame.Web/src/lib/components/home-page/home-page.svelte +++ b/immichFrame.Web/src/lib/components/home-page/home-page.svelte @@ -504,6 +504,8 @@ interval={currentDuration} showPhotoDate={$configStore.showPhotoDate} showImageDesc={$configStore.showImageDesc} + showImageCamera={$configStore.showImageCamera} + showImageExif={$configStore.showImageExif} showPeopleDesc={$configStore.showPeopleDesc} showTagsDesc={$configStore.showTagsDesc} showAlbumName={$configStore.showAlbumName} diff --git a/immichFrame.Web/src/lib/immichFrameApi.ts b/immichFrame.Web/src/lib/immichFrameApi.ts index 85fa762b..e4064c1c 100644 --- a/immichFrame.Web/src/lib/immichFrameApi.ts +++ b/immichFrame.Web/src/lib/immichFrameApi.ts @@ -211,6 +211,8 @@ export type ClientSettingsDto = { showProgressBar?: boolean; photoDateFormat?: string | null; showImageDesc?: boolean; + showImageCamera?: boolean; + showImageExif?: boolean; showPeopleDesc?: boolean; showTagsDesc?: boolean; showAlbumName?: boolean; diff --git a/openApi/swagger.json b/openApi/swagger.json index 9569c297..eb08dba6 100644 --- a/openApi/swagger.json +++ b/openApi/swagger.json @@ -1034,6 +1034,12 @@ "showImageDesc": { "type": "boolean" }, + "showImageCamera": { + "type": "boolean" + }, + "showImageExif": { + "type": "boolean" + }, "showPeopleDesc": { "type": "boolean" }, @@ -1527,4 +1533,4 @@ } } } -} \ No newline at end of file +}