mirror of
https://github.com/immich-app/immich.git
synced 2026-05-18 03:10:24 +03:00
feat: album map markers endpoint (#27830)
This commit is contained in:
Generated
+1
@@ -89,6 +89,7 @@ Class | Method | HTTP request | Description
|
|||||||
*AlbumsApi* | [**createAlbum**](doc//AlbumsApi.md#createalbum) | **POST** /albums | Create an album
|
*AlbumsApi* | [**createAlbum**](doc//AlbumsApi.md#createalbum) | **POST** /albums | Create an album
|
||||||
*AlbumsApi* | [**deleteAlbum**](doc//AlbumsApi.md#deletealbum) | **DELETE** /albums/{id} | Delete an album
|
*AlbumsApi* | [**deleteAlbum**](doc//AlbumsApi.md#deletealbum) | **DELETE** /albums/{id} | Delete an album
|
||||||
*AlbumsApi* | [**getAlbumInfo**](doc//AlbumsApi.md#getalbuminfo) | **GET** /albums/{id} | Retrieve an album
|
*AlbumsApi* | [**getAlbumInfo**](doc//AlbumsApi.md#getalbuminfo) | **GET** /albums/{id} | Retrieve an album
|
||||||
|
*AlbumsApi* | [**getAlbumMapMarkers**](doc//AlbumsApi.md#getalbummapmarkers) | **GET** /albums/{id}/map-markers | Retrieve album map markers
|
||||||
*AlbumsApi* | [**getAlbumStatistics**](doc//AlbumsApi.md#getalbumstatistics) | **GET** /albums/statistics | Retrieve album statistics
|
*AlbumsApi* | [**getAlbumStatistics**](doc//AlbumsApi.md#getalbumstatistics) | **GET** /albums/statistics | Retrieve album statistics
|
||||||
*AlbumsApi* | [**getAllAlbums**](doc//AlbumsApi.md#getallalbums) | **GET** /albums | List all albums
|
*AlbumsApi* | [**getAllAlbums**](doc//AlbumsApi.md#getallalbums) | **GET** /albums | List all albums
|
||||||
*AlbumsApi* | [**removeAssetFromAlbum**](doc//AlbumsApi.md#removeassetfromalbum) | **DELETE** /albums/{id}/assets | Remove assets from an album
|
*AlbumsApi* | [**removeAssetFromAlbum**](doc//AlbumsApi.md#removeassetfromalbum) | **DELETE** /albums/{id}/assets | Remove assets from an album
|
||||||
|
|||||||
Generated
+75
@@ -383,6 +383,81 @@ class AlbumsApi {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieve album map markers
|
||||||
|
///
|
||||||
|
/// Retrieve map marker information for a specific album by its ID.
|
||||||
|
///
|
||||||
|
/// Note: This method returns the HTTP [Response].
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [String] key:
|
||||||
|
///
|
||||||
|
/// * [String] slug:
|
||||||
|
Future<Response> getAlbumMapMarkersWithHttpInfo(String id, { String? key, String? slug, }) async {
|
||||||
|
// ignore: prefer_const_declarations
|
||||||
|
final apiPath = r'/albums/{id}/map-markers'
|
||||||
|
.replaceAll('{id}', id);
|
||||||
|
|
||||||
|
// ignore: prefer_final_locals
|
||||||
|
Object? postBody;
|
||||||
|
|
||||||
|
final queryParams = <QueryParam>[];
|
||||||
|
final headerParams = <String, String>{};
|
||||||
|
final formParams = <String, String>{};
|
||||||
|
|
||||||
|
if (key != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'key', key));
|
||||||
|
}
|
||||||
|
if (slug != null) {
|
||||||
|
queryParams.addAll(_queryParams('', 'slug', slug));
|
||||||
|
}
|
||||||
|
|
||||||
|
const contentTypes = <String>[];
|
||||||
|
|
||||||
|
|
||||||
|
return apiClient.invokeAPI(
|
||||||
|
apiPath,
|
||||||
|
'GET',
|
||||||
|
queryParams,
|
||||||
|
postBody,
|
||||||
|
headerParams,
|
||||||
|
formParams,
|
||||||
|
contentTypes.isEmpty ? null : contentTypes.first,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieve album map markers
|
||||||
|
///
|
||||||
|
/// Retrieve map marker information for a specific album by its ID.
|
||||||
|
///
|
||||||
|
/// Parameters:
|
||||||
|
///
|
||||||
|
/// * [String] id (required):
|
||||||
|
///
|
||||||
|
/// * [String] key:
|
||||||
|
///
|
||||||
|
/// * [String] slug:
|
||||||
|
Future<List<MapMarkerResponseDto>?> getAlbumMapMarkers(String id, { String? key, String? slug, }) async {
|
||||||
|
final response = await getAlbumMapMarkersWithHttpInfo(id, key: key, slug: slug, );
|
||||||
|
if (response.statusCode >= HttpStatus.badRequest) {
|
||||||
|
throw ApiException(response.statusCode, await _decodeBodyBytes(response));
|
||||||
|
}
|
||||||
|
// When a remote server returns no body with a status of 204, we shall not decode it.
|
||||||
|
// At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
|
||||||
|
// FormatException when trying to decode an empty string.
|
||||||
|
if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
|
||||||
|
final responseBody = await _decodeBodyBytes(response);
|
||||||
|
return (await apiClient.deserializeAsync(responseBody, 'List<MapMarkerResponseDto>') as List)
|
||||||
|
.cast<MapMarkerResponseDto>()
|
||||||
|
.toList(growable: false);
|
||||||
|
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Retrieve album statistics
|
/// Retrieve album statistics
|
||||||
///
|
///
|
||||||
/// Returns statistics about the albums available to the authenticated user.
|
/// Returns statistics about the albums available to the authenticated user.
|
||||||
|
|||||||
@@ -2227,6 +2227,77 @@
|
|||||||
"x-immich-state": "Stable"
|
"x-immich-state": "Stable"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"/albums/{id}/map-markers": {
|
||||||
|
"get": {
|
||||||
|
"description": "Retrieve map marker information for a specific album by its ID.",
|
||||||
|
"operationId": "getAlbumMapMarkers",
|
||||||
|
"parameters": [
|
||||||
|
{
|
||||||
|
"name": "id",
|
||||||
|
"required": true,
|
||||||
|
"in": "path",
|
||||||
|
"schema": {
|
||||||
|
"format": "uuid",
|
||||||
|
"pattern": "^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-4[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$",
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "key",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "slug",
|
||||||
|
"required": false,
|
||||||
|
"in": "query",
|
||||||
|
"schema": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"responses": {
|
||||||
|
"200": {
|
||||||
|
"content": {
|
||||||
|
"application/json": {
|
||||||
|
"schema": {
|
||||||
|
"items": {
|
||||||
|
"$ref": "#/components/schemas/MapMarkerResponseDto"
|
||||||
|
},
|
||||||
|
"type": "array"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"description": ""
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"security": [
|
||||||
|
{
|
||||||
|
"bearer": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"cookie": []
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"api_key": []
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"summary": "Retrieve album map markers",
|
||||||
|
"tags": [
|
||||||
|
"Albums"
|
||||||
|
],
|
||||||
|
"x-immich-history": [
|
||||||
|
{
|
||||||
|
"version": "v3",
|
||||||
|
"state": "Added"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"x-immich-permission": "album.read"
|
||||||
|
}
|
||||||
|
},
|
||||||
"/albums/{id}/user/{userId}": {
|
"/albums/{id}/user/{userId}": {
|
||||||
"delete": {
|
"delete": {
|
||||||
"description": "Remove a user from an album. Use an ID of \"me\" to leave a shared album.",
|
"description": "Remove a user from an album. Use an ID of \"me\" to leave a shared album.",
|
||||||
|
|||||||
@@ -710,6 +710,20 @@ export type BulkIdResponseDto = {
|
|||||||
/** Whether operation succeeded */
|
/** Whether operation succeeded */
|
||||||
success: boolean;
|
success: boolean;
|
||||||
};
|
};
|
||||||
|
export type MapMarkerResponseDto = {
|
||||||
|
/** City name */
|
||||||
|
city: string | null;
|
||||||
|
/** Country name */
|
||||||
|
country: string | null;
|
||||||
|
/** Asset ID */
|
||||||
|
id: string;
|
||||||
|
/** Latitude */
|
||||||
|
lat: number;
|
||||||
|
/** Longitude */
|
||||||
|
lon: number;
|
||||||
|
/** State/Province name */
|
||||||
|
state: string | null;
|
||||||
|
};
|
||||||
export type UpdateAlbumUserDto = {
|
export type UpdateAlbumUserDto = {
|
||||||
role: AlbumUserRole;
|
role: AlbumUserRole;
|
||||||
};
|
};
|
||||||
@@ -1305,20 +1319,6 @@ export type ValidateLibraryResponseDto = {
|
|||||||
/** Validation results for import paths */
|
/** Validation results for import paths */
|
||||||
importPaths?: ValidateLibraryImportPathResponseDto[];
|
importPaths?: ValidateLibraryImportPathResponseDto[];
|
||||||
};
|
};
|
||||||
export type MapMarkerResponseDto = {
|
|
||||||
/** City name */
|
|
||||||
city: string | null;
|
|
||||||
/** Country name */
|
|
||||||
country: string | null;
|
|
||||||
/** Asset ID */
|
|
||||||
id: string;
|
|
||||||
/** Latitude */
|
|
||||||
lat: number;
|
|
||||||
/** Longitude */
|
|
||||||
lon: number;
|
|
||||||
/** State/Province name */
|
|
||||||
state: string | null;
|
|
||||||
};
|
|
||||||
export type MapReverseGeocodeResponseDto = {
|
export type MapReverseGeocodeResponseDto = {
|
||||||
/** City name */
|
/** City name */
|
||||||
city: string | null;
|
city: string | null;
|
||||||
@@ -3733,6 +3733,24 @@ export function addAssetsToAlbum({ id, bulkIdsDto }: {
|
|||||||
body: bulkIdsDto
|
body: bulkIdsDto
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* Retrieve album map markers
|
||||||
|
*/
|
||||||
|
export function getAlbumMapMarkers({ id, key, slug }: {
|
||||||
|
id: string;
|
||||||
|
key?: string;
|
||||||
|
slug?: string;
|
||||||
|
}, opts?: Oazapfts.RequestOpts) {
|
||||||
|
return oazapfts.ok(oazapfts.fetchJson<{
|
||||||
|
status: 200;
|
||||||
|
data: MapMarkerResponseDto[];
|
||||||
|
}>(`/albums/${encodeURIComponent(id)}/map-markers${QS.query(QS.explode({
|
||||||
|
key,
|
||||||
|
slug
|
||||||
|
}))}`, {
|
||||||
|
...opts
|
||||||
|
}));
|
||||||
|
}
|
||||||
/**
|
/**
|
||||||
* Remove user from album
|
* Remove user from album
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import {
|
|||||||
} from 'src/dtos/album.dto';
|
} from 'src/dtos/album.dto';
|
||||||
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
|
import { MapMarkerResponseDto } from 'src/dtos/map.dto';
|
||||||
import { ApiTag, Permission } from 'src/enum';
|
import { ApiTag, Permission } from 'src/enum';
|
||||||
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
import { Auth, Authenticated } from 'src/middleware/auth.guard';
|
||||||
import { AlbumService } from 'src/services/album.service';
|
import { AlbumService } from 'src/services/album.service';
|
||||||
@@ -102,6 +103,17 @@ export class AlbumController {
|
|||||||
return this.service.delete(auth, id);
|
return this.service.delete(auth, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Authenticated({ permission: Permission.AlbumRead, sharedLink: true })
|
||||||
|
@Get(':id/map-markers')
|
||||||
|
@Endpoint({
|
||||||
|
summary: 'Retrieve album map markers',
|
||||||
|
description: 'Retrieve map marker information for a specific album by its ID.',
|
||||||
|
history: new HistoryBuilder().added('v3'),
|
||||||
|
})
|
||||||
|
getAlbumMapMarkers(@Auth() auth: AuthDto, @Param() { id }: UUIDParamDto): Promise<MapMarkerResponseDto[]> {
|
||||||
|
return this.service.getMapMarkers(auth, id);
|
||||||
|
}
|
||||||
|
|
||||||
@Put(':id/assets')
|
@Put(':id/assets')
|
||||||
@Authenticated({ permission: Permission.AlbumAssetCreate })
|
@Authenticated({ permission: Permission.AlbumAssetCreate })
|
||||||
@Endpoint({
|
@Endpoint({
|
||||||
|
|||||||
@@ -1,5 +1,25 @@
|
|||||||
-- NOTE: This file is auto generated by ./sql-generator
|
-- NOTE: This file is auto generated by ./sql-generator
|
||||||
|
|
||||||
|
-- MapRepository.getAlbumMapMarkers
|
||||||
|
select
|
||||||
|
"id",
|
||||||
|
"asset_exif"."latitude" as "lat",
|
||||||
|
"asset_exif"."longitude" as "lon",
|
||||||
|
"asset_exif"."city",
|
||||||
|
"asset_exif"."state",
|
||||||
|
"asset_exif"."country"
|
||||||
|
from
|
||||||
|
"asset"
|
||||||
|
inner join "asset_exif" on "asset"."id" = "asset_exif"."assetId"
|
||||||
|
and "asset_exif"."latitude" is not null
|
||||||
|
and "asset_exif"."longitude" is not null
|
||||||
|
inner join "album_asset" on "asset"."id" = "album_asset"."assetId"
|
||||||
|
where
|
||||||
|
"asset"."deletedAt" is null
|
||||||
|
and "album_asset"."albumId" = $1
|
||||||
|
order by
|
||||||
|
"fileCreatedAt" desc
|
||||||
|
|
||||||
-- MapRepository.getMapMarkers
|
-- MapRepository.getMapMarkers
|
||||||
select
|
select
|
||||||
"id",
|
"id",
|
||||||
@@ -14,8 +34,8 @@ from
|
|||||||
and "asset_exif"."latitude" is not null
|
and "asset_exif"."latitude" is not null
|
||||||
and "asset_exif"."longitude" is not null
|
and "asset_exif"."longitude" is not null
|
||||||
where
|
where
|
||||||
"asset"."visibility" = $1
|
"asset"."deletedAt" is null
|
||||||
and "deletedAt" is null
|
and "asset"."visibility" = $1
|
||||||
and (
|
and (
|
||||||
"ownerId" in ($2)
|
"ownerId" in ($2)
|
||||||
or exists (
|
or exists (
|
||||||
|
|||||||
@@ -76,29 +76,21 @@ export class MapRepository {
|
|||||||
this.logger.log('Geodata import completed');
|
this.logger.log('Geodata import completed');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@GenerateSql({ params: [DummyValue.UUID] })
|
||||||
|
getAlbumMapMarkers(albumId: string) {
|
||||||
|
return this.mapMarkersQuery()
|
||||||
|
.innerJoin('album_asset', 'asset.id', 'album_asset.assetId')
|
||||||
|
.where('album_asset.albumId', '=', albumId)
|
||||||
|
.execute();
|
||||||
|
}
|
||||||
|
|
||||||
@GenerateSql({ params: [[DummyValue.UUID], [DummyValue.UUID]] })
|
@GenerateSql({ params: [[DummyValue.UUID], [DummyValue.UUID]] })
|
||||||
getMapMarkers(
|
getMapMarkers(
|
||||||
ownerIds: string[],
|
ownerIds: string[],
|
||||||
albumIds: string[],
|
albumIds: string[],
|
||||||
{ isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore }: MapMarkerSearchOptions = {},
|
{ isArchived, isFavorite, fileCreatedAfter, fileCreatedBefore }: MapMarkerSearchOptions = {},
|
||||||
) {
|
) {
|
||||||
return this.db
|
return this.mapMarkersQuery()
|
||||||
.selectFrom('asset')
|
|
||||||
.innerJoin('asset_exif', (builder) =>
|
|
||||||
builder
|
|
||||||
.onRef('asset.id', '=', 'asset_exif.assetId')
|
|
||||||
.on('asset_exif.latitude', 'is not', null)
|
|
||||||
.on('asset_exif.longitude', 'is not', null),
|
|
||||||
)
|
|
||||||
.select([
|
|
||||||
'id',
|
|
||||||
'asset_exif.latitude as lat',
|
|
||||||
'asset_exif.longitude as lon',
|
|
||||||
'asset_exif.city',
|
|
||||||
'asset_exif.state',
|
|
||||||
'asset_exif.country',
|
|
||||||
])
|
|
||||||
.$narrowType<{ lat: NotNull; lon: NotNull }>()
|
|
||||||
.$if(isArchived === true, (qb) =>
|
.$if(isArchived === true, (qb) =>
|
||||||
qb.where((eb) =>
|
qb.where((eb) =>
|
||||||
eb.or([
|
eb.or([
|
||||||
@@ -113,7 +105,6 @@ export class MapRepository {
|
|||||||
.$if(isFavorite !== undefined, (q) => q.where('isFavorite', '=', isFavorite!))
|
.$if(isFavorite !== undefined, (q) => q.where('isFavorite', '=', isFavorite!))
|
||||||
.$if(fileCreatedAfter !== undefined, (q) => q.where('fileCreatedAt', '>=', fileCreatedAfter!))
|
.$if(fileCreatedAfter !== undefined, (q) => q.where('fileCreatedAt', '>=', fileCreatedAfter!))
|
||||||
.$if(fileCreatedBefore !== undefined, (q) => q.where('fileCreatedAt', '<=', fileCreatedBefore!))
|
.$if(fileCreatedBefore !== undefined, (q) => q.where('fileCreatedAt', '<=', fileCreatedBefore!))
|
||||||
.where('deletedAt', 'is', null)
|
|
||||||
.where((eb) => {
|
.where((eb) => {
|
||||||
const expression: Expression<SqlBool>[] = [];
|
const expression: Expression<SqlBool>[] = [];
|
||||||
|
|
||||||
@@ -134,10 +125,31 @@ export class MapRepository {
|
|||||||
|
|
||||||
return eb.or(expression);
|
return eb.or(expression);
|
||||||
})
|
})
|
||||||
.orderBy('fileCreatedAt', 'desc')
|
|
||||||
.execute();
|
.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private mapMarkersQuery() {
|
||||||
|
return this.db
|
||||||
|
.selectFrom('asset')
|
||||||
|
.innerJoin('asset_exif', (builder) =>
|
||||||
|
builder
|
||||||
|
.onRef('asset.id', '=', 'asset_exif.assetId')
|
||||||
|
.on('asset_exif.latitude', 'is not', null)
|
||||||
|
.on('asset_exif.longitude', 'is not', null),
|
||||||
|
)
|
||||||
|
.where('asset.deletedAt', 'is', null)
|
||||||
|
.orderBy('fileCreatedAt', 'desc')
|
||||||
|
.select([
|
||||||
|
'id',
|
||||||
|
'asset_exif.latitude as lat',
|
||||||
|
'asset_exif.longitude as lon',
|
||||||
|
'asset_exif.city',
|
||||||
|
'asset_exif.state',
|
||||||
|
'asset_exif.country',
|
||||||
|
])
|
||||||
|
.$narrowType<{ lat: NotNull; lon: NotNull }>();
|
||||||
|
}
|
||||||
|
|
||||||
async reverseGeocode(point: GeoPoint): Promise<ReverseGeocodeResult> {
|
async reverseGeocode(point: GeoPoint): Promise<ReverseGeocodeResult> {
|
||||||
this.logger.debug(`Request: ${point.latitude},${point.longitude}`);
|
this.logger.debug(`Request: ${point.latitude},${point.longitude}`);
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import {
|
|||||||
} from 'src/dtos/album.dto';
|
} from 'src/dtos/album.dto';
|
||||||
import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
import { BulkIdErrorReason, BulkIdResponseDto, BulkIdsDto } from 'src/dtos/asset-ids.response.dto';
|
||||||
import { AuthDto } from 'src/dtos/auth.dto';
|
import { AuthDto } from 'src/dtos/auth.dto';
|
||||||
|
import { MapMarkerResponseDto } from 'src/dtos/map.dto';
|
||||||
import { Permission } from 'src/enum';
|
import { Permission } from 'src/enum';
|
||||||
import { AlbumAssetCount, AlbumInfoOptions } from 'src/repositories/album.repository';
|
import { AlbumAssetCount, AlbumInfoOptions } from 'src/repositories/album.repository';
|
||||||
import { BaseService } from 'src/services/base.service';
|
import { BaseService } from 'src/services/base.service';
|
||||||
@@ -94,6 +95,16 @@ export class AlbumService extends BaseService {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getMapMarkers(auth: AuthDto, id: string): Promise<MapMarkerResponseDto[]> {
|
||||||
|
await this.requireAccess({ auth, permission: Permission.AlbumRead, ids: [id] });
|
||||||
|
|
||||||
|
if (auth.sharedLink && !auth.sharedLink.showExif) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
return this.mapRepository.getAlbumMapMarkers(id);
|
||||||
|
}
|
||||||
|
|
||||||
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
async create(auth: AuthDto, dto: CreateAlbumDto): Promise<AlbumResponseDto> {
|
||||||
const albumUsers = dto.albumUsers || [];
|
const albumUsers = dto.albumUsers || [];
|
||||||
|
|
||||||
|
|||||||
@@ -2,8 +2,9 @@
|
|||||||
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
import { assetViewerManager } from '$lib/managers/asset-viewer-manager.svelte';
|
||||||
import { authManager } from '$lib/managers/auth-manager.svelte';
|
import { authManager } from '$lib/managers/auth-manager.svelte';
|
||||||
import MapModal from '$lib/modals/MapModal.svelte';
|
import MapModal from '$lib/modals/MapModal.svelte';
|
||||||
|
import { handleError } from '$lib/utils/handle-error';
|
||||||
import { navigate } from '$lib/utils/navigation';
|
import { navigate } from '$lib/utils/navigation';
|
||||||
import { getAlbumInfo, type AlbumResponseDto, type MapMarkerResponseDto } from '@immich/sdk';
|
import { getAlbumMapMarkers, type AlbumResponseDto, type MapMarkerResponseDto } from '@immich/sdk';
|
||||||
import { IconButton, modalManager } from '@immich/ui';
|
import { IconButton, modalManager } from '@immich/ui';
|
||||||
import { mdiMapOutline } from '@mdi/js';
|
import { mdiMapOutline } from '@mdi/js';
|
||||||
import { onDestroy, onMount } from 'svelte';
|
import { onDestroy, onMount } from 'svelte';
|
||||||
@@ -14,7 +15,7 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
let { album }: Props = $props();
|
let { album }: Props = $props();
|
||||||
let abortController: AbortController;
|
let cancelable: AbortController;
|
||||||
|
|
||||||
let returnToMap = $state(false);
|
let returnToMap = $state(false);
|
||||||
let mapMarkers: MapMarkerResponseDto[] = $state([]);
|
let mapMarkers: MapMarkerResponseDto[] = $state([]);
|
||||||
@@ -24,7 +25,7 @@
|
|||||||
});
|
});
|
||||||
|
|
||||||
onDestroy(() => {
|
onDestroy(() => {
|
||||||
abortController?.abort();
|
cancelable?.abort();
|
||||||
assetViewerManager.showAssetViewer(false);
|
assetViewerManager.showAssetViewer(false);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -35,30 +36,17 @@
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
async function loadMapMarkers() {
|
const loadMapMarkers = async () => {
|
||||||
if (abortController) {
|
cancelable?.abort();
|
||||||
abortController.abort();
|
cancelable = new AbortController();
|
||||||
|
|
||||||
|
try {
|
||||||
|
return await getAlbumMapMarkers({ ...authManager.params, id: album.id }, { signal: cancelable.signal });
|
||||||
|
} catch (error) {
|
||||||
|
handleError(error, $t('errors.something_went_wrong'));
|
||||||
|
return [];
|
||||||
}
|
}
|
||||||
abortController = new AbortController();
|
};
|
||||||
|
|
||||||
let albumInfo: AlbumResponseDto = await getAlbumInfo({ id: album.id, withoutAssets: false, ...authManager.params });
|
|
||||||
|
|
||||||
let markers: MapMarkerResponseDto[] = [];
|
|
||||||
for (const asset of albumInfo.assets) {
|
|
||||||
if (asset.exifInfo?.latitude && asset.exifInfo?.longitude) {
|
|
||||||
markers.push({
|
|
||||||
id: asset.id,
|
|
||||||
lat: asset.exifInfo.latitude,
|
|
||||||
lon: asset.exifInfo.longitude,
|
|
||||||
city: asset.exifInfo?.city ?? null,
|
|
||||||
country: asset.exifInfo?.country ?? null,
|
|
||||||
state: asset.exifInfo?.state ?? null,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return markers;
|
|
||||||
}
|
|
||||||
|
|
||||||
const onClick = async () => {
|
const onClick = async () => {
|
||||||
const assetIds = await modalManager.show(MapModal, { mapMarkers });
|
const assetIds = await modalManager.show(MapModal, { mapMarkers });
|
||||||
|
|||||||
Reference in New Issue
Block a user