Skip to content

Commit

Permalink
merge main
Browse files Browse the repository at this point in the history
  • Loading branch information
alextran1502 committed Apr 1, 2024
2 parents 1fd6371 + 27be813 commit 12c5b5f
Show file tree
Hide file tree
Showing 43 changed files with 2,662 additions and 1,060 deletions.
4 changes: 2 additions & 2 deletions docs/docs/administration/postgres-standalone.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Preparing a pre-existing Postgres server
# Pre-existing Postgres

While not officially recommended, it is possible to run Immich using a pre-existing Postgres server. To use this setup, you should have a baseline level of familiarity with Postgres and the Linux command line. If you do not have these, we recommend using the default setup with a dedicated Postgres container.

Expand Down Expand Up @@ -45,7 +45,7 @@ CREATE EXTENSION vectors;
CREATE EXTENSION earthdistance CASCADE;
ALTER DATABASE <immichdatabasename> SET search_path TO "$user", public, vectors;
GRANT USAGE ON SCHEMA vectors TO <immichdbusername>;
GRANT SELECT ON TABLE pg_vector_index_stat to <immichdbusername>;
ALTER DEFAULT PRIVILEGES IN SCHEMA vectors GRANT SELECT ON TABLES TO <immichdbusername>;
COMMIT;
```

Expand Down
4 changes: 2 additions & 2 deletions docs/docs/features/monitoring.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,8 @@ The metrics in immich are grouped into API (endpoint calls and response times),

Immich will not expose an endpoint for metrics by default. To enable this endpoint, you can add the `IMMICH_METRICS=true` environmental variable to your `.env` file. Note that only the server and microservices containers currently use this variable.

:::note
`IMMICH_METRICS` is equivalent to enabling the following three environmental variables: `IMMICH_API_METRICS`, `IMMICH_HOST_METRICS`, and `IMMICH_IO_METRICS`. If you would like to only expose certain kinds of metrics, you can set only those environmental variables to `true`. Explicitly setting the environmental variable for a metric group overrides `IMMICH_METRICS` for that group.
:::tip
`IMMICH_METRICS` enables all metrics, but there are also [environmental variables](/docs/install/environment-variables.md#prometheus) to toggle specific metric groups. If you'd like to only expose certain kinds of metrics, you can set only those environmental variables to `true`. Explicitly setting the environmental variable for a metric group overrides `IMMICH_METRICS` for that group. For example, setting `IMMICH_METRICS=true` and `IMMICH_API_METRICS=false` will enable all metrics except API metrics.
:::

The next step is to configure a new or existing Prometheus instance to scrape this endpoint. The following steps assume that you do not have an existing Prometheus instance, but the steps will be similar either way.
Expand Down
18 changes: 14 additions & 4 deletions docs/docs/install/environment-variables.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,9 @@ These environment variables are used by the `docker-compose.yml` file and do **N
| `IMMICH_REVERSE_GEOCODING_ROOT` | Path of reverse geocoding dump directory | `/usr/src/resources` | microservices |

:::tip
`TZ` should be set to a `TZ identifier` from [this list](https://en.wikipedia.org/wiki/List_of_tz_database_time_zones#List). For example, `TZ="Etc/UTC"`.

`TZ` is only used by the `exiftool` as a fallback in case the timezone cannot be determined from the image metadata.

`exiftool` is only present in the microservices container.

`TZ` is only used by `exiftool`, which is present in the microservices container, as a fallback in case the timezone cannot be determined from the image metadata.
:::

## Ports
Expand Down Expand Up @@ -147,6 +145,18 @@ Other machine learning parameters can be tuned from the admin UI.

:::

## Prometheus

| Variable | Description | Default | Services |
| :----------------------------- | :-------------------------------------------------------------------------------------------- | :-----: | :-------------------- |
| `IMMICH_METRICS`<sup>\*1</sup> | Toggle all metrics (one of [`true`, `false`]) | | server, microservices |
| `IMMICH_API_METRICS` | Toggle metrics for endpoints and response times (one of [`true`, `false`]) | | server, microservices |
| `IMMICH_HOST_METRICS` | Toggle metrics for CPU and memory utilization for host and process (one of [`true`, `false`]) | | server, microservices |
| `IMMICH_IO_METRICS` | Toggle metrics for database queries, image processing, etc. (one of [`true`, `false`]) | | server, microservices |
| `IMMICH_JOB_METRICS` | Toggle metrics for jobs and queues (one of [`true`, `false`]) | | server, microservices |

\*1: Overridden for a metric group when its corresponding environmental variable is set.

## Docker Secrets

The following variables support the use of [Docker secrets](https://docs.docker.com/engine/swarm/secrets/) for additional security.
Expand Down
27 changes: 16 additions & 11 deletions mobile/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,9 @@ PODS:
- fluttertoast (0.0.2):
- Flutter
- Toast
- FMDB (2.7.5):
- FMDB/standard (= 2.7.5)
- FMDB/standard (2.7.5)
- geolocator_apple (1.2.0):
- Flutter
- image_picker_ios (0.0.1):
Expand All @@ -36,7 +39,7 @@ PODS:
- FlutterMacOS
- path_provider_ios (0.0.1):
- Flutter
- permission_handler_apple (9.3.0):
- permission_handler_apple (9.1.1):
- Flutter
- photo_manager (2.0.0):
- Flutter
Expand All @@ -50,7 +53,7 @@ PODS:
- FlutterMacOS
- sqflite (0.0.3):
- Flutter
- FlutterMacOS
- FMDB (>= 2.7.5)
- Toast (4.0.0)
- url_launcher_ios (0.0.1):
- Flutter
Expand Down Expand Up @@ -81,13 +84,14 @@ DEPENDENCIES:
- photo_manager (from `.symlinks/plugins/photo_manager/ios`)
- share_plus (from `.symlinks/plugins/share_plus/ios`)
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/darwin`)
- sqflite (from `.symlinks/plugins/sqflite/ios`)
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/darwin`)
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)

SPEC REPOS:
trunk:
- FMDB
- MapLibre
- ReachabilitySwift
- SAMKeychain
Expand Down Expand Up @@ -135,7 +139,7 @@ EXTERNAL SOURCES:
shared_preferences_foundation:
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
sqflite:
:path: ".symlinks/plugins/sqflite/darwin"
:path: ".symlinks/plugins/sqflite/ios"
url_launcher_ios:
:path: ".symlinks/plugins/url_launcher_ios/ios"
video_player_avfoundation:
Expand All @@ -151,28 +155,29 @@ SPEC CHECKSUMS:
flutter_native_splash: 52501b97d1c0a5f898d687f1646226c1f93c56ef
flutter_udid: a2482c67a61b9c806ef59dd82ed8d007f1b7ac04
flutter_web_auth: c25208760459cec375a3c39f6a8759165ca0fa4d
fluttertoast: fafc4fa4d01a6a9e4f772ecd190ffa525e9e2d9c
fluttertoast: 31b00dabfa7fb7bacd9e7dbee580d7a2ff4bf265
FMDB: 2ce00b547f966261cd18927a3ddb07cb6f3db82a
geolocator_apple: 9157311f654584b9bb72686c55fc02a97b73f461
image_picker_ios: 99dfe1854b4fa34d0364e74a78448a0151025425
image_picker_ios: 4a8aadfbb6dc30ad5141a2ce3832af9214a705b5
integration_test: 13825b8a9334a850581300559b8839134b124670
isar_flutter_libs: b69f437aeab9c521821c3f376198c4371fa21073
MapLibre: 620fc933c1d6029b33738c905c1490d024e5d4ef
maplibre_gl: a2efec727dd340e4c65e26d2b03b584f14881fd9
package_info_plus: 115f4ad11e0698c8c1c5d8a689390df880f47e85
path_provider_foundation: 3784922295ac71e43754bd15e0653ccfd36a147c
path_provider_foundation: 29f094ae23ebbca9d3d0cec13889cd9060c0e943
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
permission_handler_apple: 036b856153a2b1f61f21030ff725f3e6fece2b78
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
photo_manager: 4f6810b7dfc4feb03b461ac1a70dacf91fba7604
ReachabilitySwift: 985039c6f7b23a1da463388634119492ff86c825
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
share_plus: c3fef564749587fc939ef86ffb283ceac0baf9f5
shared_preferences_foundation: b4c3b4cddf1c21f02770737f147a3f5da9d39695
sqflite: 673a0e54cc04b7d6dba8d24fb8095b31c3a99eec
shared_preferences_foundation: 5b919d13b803cadd15ed2dc053125c68730e5126
sqflite: 31f7eba61e3074736dff8807a9b41581e4f7f15a
Toast: 91b396c56ee72a5790816f40d3a94dd357abc196
url_launcher_ios: bbd758c6e7f9fd7b5b1d4cde34d2b95fcce5e812
video_player_avfoundation: 02011213dab73ae3687df27ce441fbbcc82b5579
wakelock_plus: 8b09852c8876491e4b6d179e17dfe2a0b5f60d47

PODFILE CHECKSUM: 64c9b5291666c0ca3caabdfe9865c141ac40321d

COCOAPODS: 1.12.1
COCOAPODS: 1.15.2
53 changes: 33 additions & 20 deletions mobile/lib/modules/album/services/album.service.dart
Original file line number Diff line number Diff line change
Expand Up @@ -243,12 +243,7 @@ class AlbumService {
}
}

await _db.writeTxn(() async {
await album.assets.update(link: successAssets);
final a = await _db.albums.get(album.id);
// trigger watcher
await _db.albums.put(a!);
});
await _updateAssets(album.id, add: successAssets);

return AddAssetsResponse(
alreadyInAlbum: duplicatedAssets,
Expand All @@ -257,11 +252,28 @@ class AlbumService {
}
} catch (e) {
debugPrint("Error addAdditionalAssetToAlbum ${e.toString()}");
return null;
}
return null;
}

Future<void> _updateAssets(
int albumId, {
Iterable<Asset> add = const [],
Iterable<Asset> remove = const [],
}) {
return _db.writeTxn(() async {
final album = await _db.albums.get(albumId);
if (album == null) return;
await album.assets.update(link: add, unlink: remove);
album.startDate =
await album.assets.filter().fileCreatedAtProperty().min();
album.endDate = await album.assets.filter().fileCreatedAtProperty().max();
album.lastModifiedAssetTimestamp =
await album.assets.filter().updatedAtProperty().max();
await _db.albums.put(album);
});
}

Future<bool> addAdditionalUserToAlbum(
List<String> sharedUserIds,
Album album,
Expand Down Expand Up @@ -342,7 +354,7 @@ class AlbumService {
await _apiService.albumApi.removeUserFromAlbum(album.remoteId!, "me");
return true;
} catch (e) {
debugPrint("Error deleteAlbum ${e.toString()}");
debugPrint("Error leaveAlbum ${e.toString()}");
return false;
}
}
Expand All @@ -352,24 +364,25 @@ class AlbumService {
Iterable<Asset> assets,
) async {
try {
await _apiService.albumApi.removeAssetFromAlbum(
final response = await _apiService.albumApi.removeAssetFromAlbum(
album.remoteId!,
BulkIdsDto(
ids: assets.map((asset) => asset.remoteId!).toList(),
),
);
await _db.writeTxn(() async {
await album.assets.update(unlink: assets);
final a = await _db.albums.get(album.id);
// trigger watcher
await _db.albums.put(a!);
});

return true;
if (response != null) {
final toRemove = response.every((e) => e.success)
? assets
: response
.where((e) => e.success)
.map((e) => assets.firstWhere((a) => a.remoteId == e.id));
await _updateAssets(album.id, remove: toRemove);
return true;
}
} catch (e) {
debugPrint("Error deleteAlbum ${e.toString()}");
return false;
debugPrint("Error removeAssetFromAlbum ${e.toString()}");
}
return false;
}

Future<bool> removeUserFromAlbum(
Expand Down Expand Up @@ -413,7 +426,7 @@ class AlbumService {

return true;
} catch (e) {
debugPrint("Error deleteAlbum ${e.toString()}");
debugPrint("Error changeTitleAlbum ${e.toString()}");
return false;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ class ImmichAssetGrid extends HookConsumerWidget {
this.assetsPerRow,
this.showStorageIndicator,
this.listener,
this.margin = 5.0,
this.margin = 2.0,
this.selectionActive = false,
this.preselectedAssets,
this.canDeselect = true,
Expand Down
75 changes: 60 additions & 15 deletions mobile/lib/modules/search/models/curated_content.dart
Original file line number Diff line number Diff line change
@@ -1,15 +1,60 @@
/// A wrapper for [CuratedLocationsResponseDto] objects
/// and [CuratedObjectsResponseDto] to be displayed in
/// a view
class CuratedContent {
/// The label to show associated with this curated object
final String label;

/// The id to lookup the asset from the server
final String id;

CuratedContent({
required this.id,
required this.label,
});
}
// ignore_for_file: public_member_api_docs, sort_constructors_first
import 'dart:convert';

/// A wrapper for [CuratedLocationsResponseDto] objects
/// and [CuratedObjectsResponseDto] to be displayed in
/// a view
class CuratedContent {
/// The label to show associated with this curated object
final String label;

/// The id to lookup the asset from the server
final String id;

CuratedContent({
required this.label,
required this.id,
});

CuratedContent copyWith({
String? label,
String? id,
}) {
return CuratedContent(
label: label ?? this.label,
id: id ?? this.id,
);
}

Map<String, dynamic> toMap() {
return <String, dynamic>{
'label': label,
'id': id,
};
}

factory CuratedContent.fromMap(Map<String, dynamic> map) {
return CuratedContent(
label: map['label'] as String,
id: map['id'] as String,
);
}

String toJson() => json.encode(toMap());

factory CuratedContent.fromJson(String source) =>
CuratedContent.fromMap(json.decode(source) as Map<String, dynamic>);

@override
String toString() => 'CuratedContent(label: $label, id: $id)';

@override
bool operator ==(covariant CuratedContent other) {
if (identical(this, other)) return true;

return other.label == label && other.id == id;
}

@override
int get hashCode => label.hashCode ^ id.hashCode;
}

0 comments on commit 12c5b5f

Please sign in to comment.