mirror of
https://github.com/immich-app/immich.git
synced 2026-01-29 08:14:47 -08:00
Compare commits
13 Commits
fix/save-c
...
fix/flippe
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
da7554c92b | ||
|
|
55622b9db0 | ||
|
|
e462c144df | ||
|
|
cbac907807 | ||
|
|
c46f723631 | ||
|
|
a69baa5f6a | ||
|
|
082a82c48a | ||
|
|
41e2ed3754 | ||
|
|
1319ad373f | ||
|
|
97df9fd53f | ||
|
|
4707821451 | ||
|
|
20c4d375b1 | ||
|
|
46d2238431 |
2
.github/workflows/build-mobile.yml
vendored
2
.github/workflows/build-mobile.yml
vendored
@@ -269,6 +269,8 @@ jobs:
|
||||
ENVIRONMENT: ${{ inputs.environment || 'development' }}
|
||||
BUNDLE_ID_SUFFIX: ${{ inputs.environment == 'production' && '' || 'development' }}
|
||||
GITHUB_REF: ${{ github.ref }}
|
||||
FASTLANE_XCODEBUILD_SETTINGS_TIMEOUT: 120
|
||||
FASTLANE_XCODEBUILD_SETTINGS_RETRIES: 6
|
||||
working-directory: ./mobile/ios
|
||||
run: |
|
||||
# Only upload to TestFlight on main branch
|
||||
|
||||
2
.github/workflows/weblate-lock.yml
vendored
2
.github/workflows/weblate-lock.yml
vendored
@@ -36,7 +36,7 @@ jobs:
|
||||
github-token: ${{ steps.token.outputs.token }}
|
||||
filters: |
|
||||
i18n:
|
||||
- modified: 'i18n/!(en)**\.json'
|
||||
- modified: 'i18n/!(en|package)**\.json'
|
||||
skip-force-logic: 'true'
|
||||
|
||||
enforce-lock:
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/cli",
|
||||
"version": "2.2.106",
|
||||
"version": "2.5.1",
|
||||
"description": "Command Line Interface (CLI) for Immich",
|
||||
"type": "module",
|
||||
"exports": "./dist/index.js",
|
||||
|
||||
32
docs/static/archived-versions.json
vendored
32
docs/static/archived-versions.json
vendored
@@ -1,40 +1,20 @@
|
||||
[
|
||||
{
|
||||
"label": "v2.5.0",
|
||||
"url": "https://docs.v2.5.0.archive.immich.app"
|
||||
"label": "v2.5.1",
|
||||
"url": "https://docs.v2.5.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.4.1",
|
||||
"url": "https://docs.v2.4.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.4.0",
|
||||
"url": "https://docs.v2.4.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.3.1",
|
||||
"url": "https://docs.v2.3.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.3.0",
|
||||
"url": "https://docs.v2.3.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.2.3",
|
||||
"url": "https://docs.v2.2.3.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.2.2",
|
||||
"url": "https://docs.v2.2.2.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.2.1",
|
||||
"url": "https://docs.v2.2.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.2.0",
|
||||
"url": "https://docs.v2.2.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.1.0",
|
||||
"url": "https://docs.v2.1.0.archive.immich.app"
|
||||
@@ -43,18 +23,10 @@
|
||||
"label": "v2.0.1",
|
||||
"url": "https://docs.v2.0.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v2.0.0",
|
||||
"url": "https://docs.v2.0.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.144.1",
|
||||
"url": "https://docs.v1.144.1.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.144.0",
|
||||
"url": "https://docs.v1.144.0.archive.immich.app"
|
||||
},
|
||||
{
|
||||
"label": "v1.143.1",
|
||||
"url": "https://docs.v1.143.1.archive.immich.app"
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-e2e",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"description": "",
|
||||
"main": "index.js",
|
||||
"type": "module",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-i18n",
|
||||
"version": "1.0.0",
|
||||
"version": "2.5.1",
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"format": "prettier --check .",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "immich-ml"
|
||||
version = "2.5.0"
|
||||
version = "2.5.1"
|
||||
description = ""
|
||||
authors = [{ name = "Hau Tran", email = "alex.tran1502@gmail.com" }]
|
||||
requires-python = ">=3.11,<4.0"
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
#! /usr/bin/env node
|
||||
const { readFileSync, writeFileSync } = require('node:fs');
|
||||
|
||||
const asVersion = (item) => {
|
||||
const { label, url } = item;
|
||||
const [major, minor, patch] = label.substring(1).split('.').map(Number);
|
||||
return { major, minor, patch, label, url };
|
||||
};
|
||||
|
||||
const nextVersion = process.argv[2];
|
||||
if (!nextVersion) {
|
||||
console.log('Usage: archive-version.js <version>');
|
||||
@@ -8,10 +14,32 @@ if (!nextVersion) {
|
||||
}
|
||||
|
||||
const filename = './docs/static/archived-versions.json';
|
||||
const oldVersions = JSON.parse(readFileSync(filename));
|
||||
const newVersions = [
|
||||
{ label: `v${nextVersion}`, url: `https://docs.v${nextVersion}.archive.immich.app` },
|
||||
...oldVersions,
|
||||
];
|
||||
let versions = JSON.parse(readFileSync(filename));
|
||||
const newVersion = {
|
||||
label: `v${nextVersion}`,
|
||||
url: `https://docs.v${nextVersion}.archive.immich.app`,
|
||||
};
|
||||
|
||||
writeFileSync(filename, JSON.stringify(newVersions, null, 2) + '\n');
|
||||
let lastVersion = asVersion(newVersion);
|
||||
for (const item of versions) {
|
||||
const version = asVersion(item);
|
||||
// only keep the latest patch version for each minor release
|
||||
if (
|
||||
lastVersion.major === version.major &&
|
||||
lastVersion.minor === version.minor &&
|
||||
lastVersion.patch >= version.patch
|
||||
) {
|
||||
versions = versions.filter((item) => item.label !== version.label);
|
||||
console.log(
|
||||
`Removed ${version.label} (replaced with ${lastVersion.label})`
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
lastVersion = version;
|
||||
}
|
||||
|
||||
writeFileSync(
|
||||
filename,
|
||||
JSON.stringify([newVersion, ...versions], null, 2) + '\n'
|
||||
);
|
||||
|
||||
@@ -61,26 +61,23 @@ fi
|
||||
|
||||
if [ "$CURRENT_SERVER" != "$NEXT_SERVER" ]; then
|
||||
echo "Pumping Server: $CURRENT_SERVER => $NEXT_SERVER"
|
||||
jq --arg version "$NEXT_SERVER" '.version = $version' server/package.json > server/package.json.tmp && mv server/package.json.tmp server/package.json
|
||||
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix server
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix i18n
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix cli
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix web
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix e2e
|
||||
pnpm version "$NEXT_SERVER" --no-git-tag-version --prefix open-api/typescript-sdk
|
||||
|
||||
# copy version to open-api spec
|
||||
pnpm install --frozen-lockfile --prefix server
|
||||
pnpm --prefix server run build
|
||||
|
||||
( cd ./open-api && bash ./bin/generate-open-api.sh )
|
||||
|
||||
jq --arg version "$NEXT_SERVER" '.version = $version' open-api/typescript-sdk/package.json > open-api/typescript-sdk/package.json.tmp && mv open-api/typescript-sdk/package.json.tmp open-api/typescript-sdk/package.json
|
||||
|
||||
# TODO use $SERVER_PUMP once we pass 2.2.x
|
||||
CURRENT_CLI_VERSION=$(jq -r '.version' cli/package.json)
|
||||
CLI_PATCH_VERSION=$(echo "$CURRENT_CLI_VERSION" | awk -F. '{print $1"."$2"."($3+1)}')
|
||||
jq --arg version "$CLI_PATCH_VERSION" '.version = $version' cli/package.json > cli/package.json.tmp && mv cli/package.json.tmp cli/package.json
|
||||
pnpm install --frozen-lockfile --prefix cli
|
||||
|
||||
jq --arg version "$NEXT_SERVER" '.version = $version' web/package.json > web/package.json.tmp && mv web/package.json.tmp web/package.json
|
||||
pnpm install --frozen-lockfile --prefix web
|
||||
|
||||
jq --arg version "$NEXT_SERVER" '.version = $version' e2e/package.json > e2e/package.json.tmp && mv e2e/package.json.tmp e2e/package.json
|
||||
pnpm install --frozen-lockfile --prefix e2e
|
||||
uvx --from=toml-cli toml set --toml-path=machine-learning/pyproject.toml project.version "$NEXT_SERVER"
|
||||
|
||||
./misc/release/archive-version.js "$NEXT_SERVER"
|
||||
fi
|
||||
|
||||
if [ "$CURRENT_MOBILE" != "$NEXT_MOBILE" ]; then
|
||||
@@ -92,6 +89,5 @@ sed -i "s/\"android\.injected\.version\.code\" => $CURRENT_MOBILE,/\"android\.in
|
||||
sed -i "s/^version: $CURRENT_SERVER+$CURRENT_MOBILE$/version: $NEXT_SERVER+$NEXT_MOBILE/" mobile/pubspec.yaml
|
||||
perl -i -p0e "s/(<key>CFBundleShortVersionString<\/key>\s*<string>)$CURRENT_SERVER(<\/string>)/\${1}$NEXT_SERVER\${2}/s" mobile/ios/Runner/Info.plist
|
||||
|
||||
./misc/release/archive-version.js "$NEXT_SERVER"
|
||||
|
||||
echo "IMMICH_VERSION=v$NEXT_SERVER" >>"$GITHUB_ENV"
|
||||
|
||||
@@ -35,8 +35,8 @@ platform :android do
|
||||
task: 'bundle',
|
||||
build_type: 'Release',
|
||||
properties: {
|
||||
"android.injected.version.code" => 3031,
|
||||
"android.injected.version.name" => "2.5.0",
|
||||
"android.injected.version.code" => 3032,
|
||||
"android.injected.version.name" => "2.5.1",
|
||||
}
|
||||
)
|
||||
upload_to_play_store(skip_upload_apk: true, skip_upload_images: true, skip_upload_screenshots: true, aab: '../build/app/outputs/bundle/release/app-release.aab')
|
||||
|
||||
@@ -80,7 +80,7 @@
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>2.5.0</string>
|
||||
<string>2.5.1</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
|
||||
@@ -193,7 +193,13 @@ class Drift extends $Drift implements IDatabaseRepository {
|
||||
await m.addColumn(v14.localAssetEntity, v14.localAssetEntity.longitude);
|
||||
},
|
||||
from14To15: (m, v15) async {
|
||||
await m.addColumn(v15.trashedLocalAssetEntity, v15.trashedLocalAssetEntity.source);
|
||||
await m.alterTable(
|
||||
TableMigration(
|
||||
v15.trashedLocalAssetEntity,
|
||||
columnTransformer: {v15.trashedLocalAssetEntity.source: Constant(TrashOrigin.localSync.index)},
|
||||
newColumns: [v15.trashedLocalAssetEntity.source],
|
||||
),
|
||||
);
|
||||
},
|
||||
from15To16: (m, v16) async {
|
||||
// Add i_cloud_id to local and remote asset tables
|
||||
|
||||
@@ -36,6 +36,9 @@ class SyncApiRepository {
|
||||
headers.addAll(headerParams);
|
||||
|
||||
final shouldReset = Store.get(StoreKey.shouldResetSync, false);
|
||||
if (shouldReset) {
|
||||
_logger.info("Resetting sync state by client");
|
||||
}
|
||||
final request = http.Request('POST', Uri.parse(endpoint));
|
||||
request.headers.addAll(headers);
|
||||
request.body = jsonEncode(
|
||||
|
||||
@@ -268,7 +268,7 @@ class SyncStreamRepository extends DriftDatabaseRepository {
|
||||
batch.update(
|
||||
_db.remoteAssetEntity,
|
||||
RemoteAssetEntityCompanion(width: Value(width), height: Value(height)),
|
||||
where: (row) => row.id.equals(exif.assetId) & row.width.isNull() & row.height.isNull(),
|
||||
where: (row) => row.id.equals(exif.assetId) & row.isEdited.equals(false),
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -31,7 +31,7 @@ import 'package:isar/isar.dart';
|
||||
// ignore: import_rule_photo_manager
|
||||
import 'package:photo_manager/photo_manager.dart';
|
||||
|
||||
const int targetVersion = 20;
|
||||
const int targetVersion = 21;
|
||||
|
||||
Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
|
||||
final hasVersion = Store.tryGet(StoreKey.version) != null;
|
||||
@@ -88,7 +88,10 @@ Future<void> migrateDatabaseIfNeeded(Isar db, Drift drift) async {
|
||||
|
||||
if (version < 20 && Store.isBetaTimelineEnabled) {
|
||||
await _syncLocalAlbumIsIosSharedAlbum(drift);
|
||||
await _backfillAssetExifWidthHeight(drift);
|
||||
}
|
||||
|
||||
if (version < 21) {
|
||||
await Store.put(StoreKey.shouldResetSync, true);
|
||||
}
|
||||
|
||||
if (targetVersion >= 12) {
|
||||
@@ -282,22 +285,6 @@ Future<void> _syncLocalAlbumIsIosSharedAlbum(Drift db) async {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _backfillAssetExifWidthHeight(Drift db) async {
|
||||
try {
|
||||
await db.customStatement('''
|
||||
UPDATE remote_exif_entity AS remote_exif
|
||||
SET width = asset.width,
|
||||
height = asset.height
|
||||
FROM remote_asset_entity AS asset
|
||||
WHERE remote_exif.asset_id = asset.id;
|
||||
''');
|
||||
|
||||
dPrint(() => "[MIGRATION] Successfully backfilled asset exif width and height");
|
||||
} catch (error) {
|
||||
dPrint(() => "[MIGRATION] Error while backfilling asset exif width and height: $error");
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> migrateDeviceAssetToSqlite(Isar db, Drift drift) async {
|
||||
try {
|
||||
final isarDeviceAssets = await db.deviceAssetEntitys.where().findAll();
|
||||
|
||||
@@ -13,6 +13,7 @@ import 'package:immich_mobile/providers/haptic_feedback.provider.dart';
|
||||
import 'package:immich_mobile/providers/infrastructure/album.provider.dart';
|
||||
import 'package:immich_mobile/routing/router.dart';
|
||||
import 'package:immich_mobile/utils/bytes_units.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
class FreeUpSpaceSettings extends ConsumerStatefulWidget {
|
||||
const FreeUpSpaceSettings({super.key});
|
||||
@@ -29,6 +30,7 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
WakelockPlus.enable();
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
_initializeAlbumDefaults();
|
||||
});
|
||||
@@ -168,6 +170,12 @@ class _FreeUpSpaceSettingsState extends ConsumerState<FreeUpSpaceSettings> {
|
||||
context.pushRoute(CleanupPreviewRoute(assets: assets));
|
||||
}
|
||||
|
||||
@override
|
||||
dispose() {
|
||||
super.dispose();
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final state = ref.watch(cleanupProvider);
|
||||
|
||||
2
mobile/openapi/README.md
generated
2
mobile/openapi/README.md
generated
@@ -3,7 +3,7 @@ Immich API
|
||||
|
||||
This Dart package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:
|
||||
|
||||
- API version: 2.5.0
|
||||
- API version: 2.5.1
|
||||
- Generator version: 7.8.0
|
||||
- Build package: org.openapitools.codegen.languages.DartClientCodegen
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
||||
description: Immich - selfhosted backup media file on mobile phone
|
||||
|
||||
publish_to: 'none'
|
||||
version: 2.5.0+3031
|
||||
version: 2.5.1+3032
|
||||
|
||||
environment:
|
||||
sdk: '>=3.8.0 <4.0.0'
|
||||
|
||||
@@ -24,6 +24,7 @@ SyncAssetV1 _createAsset({
|
||||
String ownerId = 'user-1',
|
||||
int? width,
|
||||
int? height,
|
||||
bool isEdited = false,
|
||||
}) {
|
||||
return SyncAssetV1(
|
||||
id: id,
|
||||
@@ -44,7 +45,7 @@ SyncAssetV1 _createAsset({
|
||||
livePhotoVideoId: null,
|
||||
stackId: null,
|
||||
thumbhash: null,
|
||||
isEdited: false,
|
||||
isEdited: isEdited,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -154,7 +155,7 @@ void main() {
|
||||
}
|
||||
});
|
||||
|
||||
test('does not update dimensions if asset already has width and height', () async {
|
||||
test('does not update dimensions if asset is edited', () async {
|
||||
const assetId = 'asset-with-dimensions';
|
||||
const existingWidth = 1920;
|
||||
const existingHeight = 1080;
|
||||
@@ -169,6 +170,7 @@ void main() {
|
||||
fileName: 'with_dimensions.jpg',
|
||||
width: existingWidth,
|
||||
height: existingHeight,
|
||||
isEdited: true,
|
||||
);
|
||||
await sut.updateAssetsV1([asset]);
|
||||
|
||||
|
||||
@@ -14951,7 +14951,7 @@
|
||||
"info": {
|
||||
"title": "Immich",
|
||||
"description": "Immich API",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"contact": {}
|
||||
},
|
||||
"tags": [
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@immich/sdk",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"description": "Auto-generated TypeScript SDK for the Immich API",
|
||||
"type": "module",
|
||||
"main": "./build/index.js",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/**
|
||||
* Immich
|
||||
* 2.5.0
|
||||
* 2.5.1
|
||||
* DO NOT MODIFY - This file has been generated using oazapfts.
|
||||
* See https://www.npmjs.com/package/oazapfts
|
||||
*/
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-monorepo",
|
||||
"version": "0.0.1",
|
||||
"version": "2.5.1",
|
||||
"description": "Monorepo for Immich",
|
||||
"private": true,
|
||||
"packageManager": "pnpm@10.28.0+sha512.05df71d1421f21399e053fde567cea34d446fa02c76571441bfc1c7956e98e363088982d940465fd34480d4d90a0668bc12362f8aa88000a64e83d0b0e47be48",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"description": "",
|
||||
"author": "",
|
||||
"private": true,
|
||||
|
||||
8
server/src/schema/migrations/1769598833536-ResetSync.ts
Normal file
8
server/src/schema/migrations/1769598833536-ResetSync.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
import { Kysely, sql } from 'kysely';
|
||||
|
||||
export async function up(db: Kysely<any>): Promise<void> {
|
||||
await sql`UPDATE "session" SET "isPendingSyncReset" = false`.execute(db);
|
||||
await sql`TRUNCATE TABLE "session_sync_checkpoint"`.execute(db);
|
||||
}
|
||||
|
||||
export async function down(): Promise<void> {}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "immich-web",
|
||||
"version": "2.5.0",
|
||||
"version": "2.5.1",
|
||||
"license": "GNU Affero General Public License version 3",
|
||||
"type": "module",
|
||||
"scripts": {
|
||||
|
||||
Reference in New Issue
Block a user