Compare commits
4 Commits
v1.28.1_39
...
v1.28.2_40
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
31739aca02 | ||
|
|
8f2e7b6f65 | ||
|
|
4ed647c43d | ||
|
|
f88ff4fb5c |
25
install.sh
25
install.sh
@@ -6,10 +6,6 @@ RED='\033[0;31m'
|
|||||||
GREEN='\032[0;31m'
|
GREEN='\032[0;31m'
|
||||||
NC='\033[0m' # No Color
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
machine_has() {
|
|
||||||
type "$1" >/dev/null 2>&1
|
|
||||||
}
|
|
||||||
|
|
||||||
create_immich_directory() {
|
create_immich_directory() {
|
||||||
echo "Creating Immich directory..."
|
echo "Creating Immich directory..."
|
||||||
mkdir -p ./immich-app/immich-data
|
mkdir -p ./immich-app/immich-data
|
||||||
@@ -45,18 +41,21 @@ populate_upload_location() {
|
|||||||
start_docker_compose() {
|
start_docker_compose() {
|
||||||
echo "Starting Immich's docker containers"
|
echo "Starting Immich's docker containers"
|
||||||
|
|
||||||
if machine_has "docker compose"; then {
|
if docker compose &> /dev/null; then
|
||||||
docker compose up --remove-orphans -d
|
docker_bin="docker compose"
|
||||||
|
elif docker-compose &> /dev/null; then
|
||||||
show_friendly_message
|
docker_bin="docker-compose"
|
||||||
exit 0
|
else
|
||||||
}; fi
|
echo 'Cannot find `docker compose` or `docker-compose`.'
|
||||||
|
exit 1
|
||||||
if machine_has "docker-compose"; then
|
fi
|
||||||
docker-compose up --remove-orphans -d
|
|
||||||
|
|
||||||
|
if $docker_bin up --remove-orphans -d; then
|
||||||
show_friendly_message
|
show_friendly_message
|
||||||
exit 0
|
exit 0
|
||||||
|
else
|
||||||
|
echo "Could not start. Check for errors above."
|
||||||
|
exit 1
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -30,8 +30,8 @@ platform :android do
|
|||||||
task: 'bundle',
|
task: 'bundle',
|
||||||
build_type: 'Release',
|
build_type: 'Release',
|
||||||
properties: {
|
properties: {
|
||||||
"android.injected.version.code" => 39,
|
"android.injected.version.code" => 40,
|
||||||
"android.injected.version.name" => "1.28.1",
|
"android.injected.version.name" => "1.28.2",
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
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')
|
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')
|
||||||
|
|||||||
@@ -0,0 +1 @@
|
|||||||
|
* Fix background service cannot run in release build
|
||||||
@@ -19,7 +19,7 @@ platform :ios do
|
|||||||
desc "iOS Beta"
|
desc "iOS Beta"
|
||||||
lane :beta do
|
lane :beta do
|
||||||
increment_version_number(
|
increment_version_number(
|
||||||
version_number: "1.28.1"
|
version_number: "1.28.2"
|
||||||
)
|
)
|
||||||
increment_build_number(
|
increment_build_number(
|
||||||
build_number: latest_testflight_build_number + 1,
|
build_number: latest_testflight_build_number + 1,
|
||||||
|
|||||||
@@ -173,7 +173,8 @@ class BackgroundService {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
debugPrint(
|
debugPrint(
|
||||||
"[_clearErrorNotifications] failed to communicate with plugin");
|
"[_clearErrorNotifications] failed to communicate with plugin",
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -344,7 +345,9 @@ class BackgroundService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<bool> _runBackup(
|
Future<bool> _runBackup(
|
||||||
BackupService backupService, HiveBackupAlbums backupAlbumInfo) async {
|
BackupService backupService,
|
||||||
|
HiveBackupAlbums backupAlbumInfo,
|
||||||
|
) async {
|
||||||
_errorGracePeriodExceeded = _isErrorGracePeriodExceeded();
|
_errorGracePeriodExceeded = _isErrorGracePeriodExceeded();
|
||||||
|
|
||||||
if (_canceledBySystem) {
|
if (_canceledBySystem) {
|
||||||
@@ -445,6 +448,7 @@ class BackgroundService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// entry point called by Kotlin/Java code; needs to be a top-level function
|
/// entry point called by Kotlin/Java code; needs to be a top-level function
|
||||||
|
@pragma('vm:entry-point')
|
||||||
void _nativeEntry() {
|
void _nativeEntry() {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
WidgetsFlutterBinding.ensureInitialized();
|
||||||
BackgroundService backgroundService = BackgroundService();
|
BackgroundService backgroundService = BackgroundService();
|
||||||
|
|||||||
@@ -173,19 +173,19 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||||||
).tr(),
|
).tr(),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
OutlinedButton(
|
||||||
onPressed: () => launchUrl(
|
onPressed: () => launchUrl(
|
||||||
Uri.parse('https://dontkillmyapp.com'),
|
Uri.parse('https://dontkillmyapp.com'),
|
||||||
mode: LaunchMode.externalApplication),
|
mode: LaunchMode.externalApplication,
|
||||||
child: Text(
|
),
|
||||||
|
child: const Text(
|
||||||
"backup_controller_page_background_battery_info_link",
|
"backup_controller_page_background_battery_info_link",
|
||||||
style: TextStyle(color: buttonTextColor),
|
|
||||||
).tr(),
|
).tr(),
|
||||||
),
|
),
|
||||||
TextButton(
|
ElevatedButton(
|
||||||
child: Text(
|
child: const Text(
|
||||||
'backup_controller_page_background_battery_info_ok',
|
'backup_controller_page_background_battery_info_ok',
|
||||||
style: TextStyle(color: buttonTextColor),
|
style: TextStyle(fontWeight: FontWeight.bold, fontSize: 12),
|
||||||
).tr(),
|
).tr(),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
@@ -636,8 +636,8 @@ class BackupControllerPage extends HookConsumerWidget {
|
|||||||
backupState.backupProgress == BackUpProgressEnum.inProgress
|
backupState.backupProgress == BackUpProgressEnum.inProgress
|
||||||
? ElevatedButton(
|
? ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
primary: Colors.red[300],
|
foregroundColor: Colors.grey[50],
|
||||||
onPrimary: Colors.grey[50],
|
backgroundColor: Colors.red[300],
|
||||||
// padding: const EdgeInsets.all(14),
|
// padding: const EdgeInsets.all(14),
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ name: immich_mobile
|
|||||||
description: Immich - selfhosted backup media file on mobile phone
|
description: Immich - selfhosted backup media file on mobile phone
|
||||||
|
|
||||||
publish_to: "none"
|
publish_to: "none"
|
||||||
version: 1.28.1+39
|
version: 1.28.2+40
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ">=2.17.0 <3.0.0"
|
sdk: ">=2.17.0 <3.0.0"
|
||||||
|
|||||||
@@ -11,6 +11,6 @@ export interface IServerVersion {
|
|||||||
export const serverVersion: IServerVersion = {
|
export const serverVersion: IServerVersion = {
|
||||||
major: 1,
|
major: 1,
|
||||||
minor: 28,
|
minor: 28,
|
||||||
patch: 1,
|
patch: 2,
|
||||||
build: 39,
|
build: 40,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import cookieParser from 'cookie-parser';
|
|||||||
import { writeFileSync } from 'fs';
|
import { writeFileSync } from 'fs';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { AppModule } from './app.module';
|
import { AppModule } from './app.module';
|
||||||
|
import { serverVersion } from './constants/server_version.constant';
|
||||||
import { RedisIoAdapter } from './middlewares/redis-io.adapter.middleware';
|
import { RedisIoAdapter } from './middlewares/redis-io.adapter.middleware';
|
||||||
|
|
||||||
async function bootstrap() {
|
async function bootstrap() {
|
||||||
@@ -52,11 +53,17 @@ async function bootstrap() {
|
|||||||
// Generate API Documentation only in development mode
|
// Generate API Documentation only in development mode
|
||||||
const outputPath = path.resolve(process.cwd(), 'immich-openapi-specs.json');
|
const outputPath = path.resolve(process.cwd(), 'immich-openapi-specs.json');
|
||||||
writeFileSync(outputPath, JSON.stringify(apiDocument), { encoding: 'utf8' });
|
writeFileSync(outputPath, JSON.stringify(apiDocument), { encoding: 'utf8' });
|
||||||
Logger.log('Running Immich Server in DEVELOPMENT environment', 'ImmichServer');
|
Logger.log(
|
||||||
|
`Running Immich Server in DEVELOPMENT environment - version ${serverVersion.major}.${serverVersion.minor}.${serverVersion.patch}`,
|
||||||
|
'ImmichServer',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV == 'production') {
|
if (process.env.NODE_ENV == 'production') {
|
||||||
Logger.log('Running Immich Server in PRODUCTION environment', 'ImmichServer');
|
Logger.log(
|
||||||
|
`Running Immich Server in PRODUCTION environment - version ${serverVersion.major}.${serverVersion.minor}.${serverVersion.patch}`,
|
||||||
|
'ImmichServer',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { NestFactory } from '@nestjs/core';
|
import { NestFactory } from '@nestjs/core';
|
||||||
|
import { serverVersion } from 'apps/immich/src/constants/server_version.constant';
|
||||||
import { RedisIoAdapter } from '../../immich/src/middlewares/redis-io.adapter.middleware';
|
import { RedisIoAdapter } from '../../immich/src/middlewares/redis-io.adapter.middleware';
|
||||||
import { MicroservicesModule } from './microservices.module';
|
import { MicroservicesModule } from './microservices.module';
|
||||||
|
|
||||||
@@ -10,11 +11,17 @@ async function bootstrap() {
|
|||||||
|
|
||||||
await app.listen(3002, () => {
|
await app.listen(3002, () => {
|
||||||
if (process.env.NODE_ENV == 'development') {
|
if (process.env.NODE_ENV == 'development') {
|
||||||
Logger.log('Running Immich Microservices in DEVELOPMENT environment', 'ImmichMicroservice');
|
Logger.log(
|
||||||
|
`Running Immich Microservices in DEVELOPMENT environment - version ${serverVersion.major}.${serverVersion.minor}.${serverVersion.patch}`,
|
||||||
|
'ImmichMicroservice',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (process.env.NODE_ENV == 'production') {
|
if (process.env.NODE_ENV == 'production') {
|
||||||
Logger.log('Running Immich Microservices in PRODUCTION environment', 'ImmichMicroservice');
|
Logger.log(
|
||||||
|
`Running Immich Microservices in PRODUCTION environment - version ${serverVersion.major}.${serverVersion.minor}.${serverVersion.patch}`,
|
||||||
|
'ImmichMicroservice',
|
||||||
|
);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { Logger } from '@nestjs/common';
|
|||||||
import { InjectRepository } from '@nestjs/typeorm';
|
import { InjectRepository } from '@nestjs/typeorm';
|
||||||
import { createHash } from 'node:crypto';
|
import { createHash } from 'node:crypto';
|
||||||
import fs from 'node:fs';
|
import fs from 'node:fs';
|
||||||
import { IsNull, Repository } from 'typeorm';
|
import { FindOptionsWhere, IsNull, MoreThan, QueryFailedError, Repository } from 'typeorm';
|
||||||
|
|
||||||
// TODO: just temporary task to generate previous uploaded assets.
|
// TODO: just temporary task to generate previous uploaded assets.
|
||||||
@Processor(generateChecksumQueueName)
|
@Processor(generateChecksumQueueName)
|
||||||
@@ -17,15 +17,23 @@ export class GenerateChecksumProcessor {
|
|||||||
|
|
||||||
@Process()
|
@Process()
|
||||||
async generateChecksum() {
|
async generateChecksum() {
|
||||||
let hasNext = true;
|
|
||||||
const pageSize = 200;
|
const pageSize = 200;
|
||||||
|
let hasNext = true;
|
||||||
|
let lastErrAssetId: string | undefined = undefined;
|
||||||
|
|
||||||
while (hasNext) {
|
while (hasNext) {
|
||||||
|
const whereStat: FindOptionsWhere<AssetEntity> = {
|
||||||
|
checksum: IsNull(),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (lastErrAssetId) {
|
||||||
|
whereStat.id = MoreThan(lastErrAssetId);
|
||||||
|
}
|
||||||
|
|
||||||
const assets = await this.assetRepository.find({
|
const assets = await this.assetRepository.find({
|
||||||
where: {
|
where: whereStat,
|
||||||
checksum: IsNull()
|
|
||||||
},
|
|
||||||
take: pageSize,
|
take: pageSize,
|
||||||
|
order: { id: 'ASC' }
|
||||||
});
|
});
|
||||||
|
|
||||||
if (!assets?.length) {
|
if (!assets?.length) {
|
||||||
@@ -35,15 +43,24 @@ export class GenerateChecksumProcessor {
|
|||||||
try {
|
try {
|
||||||
await this.generateAssetChecksum(asset);
|
await this.generateAssetChecksum(asset);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
Logger.error(`Error generate checksum ${err}`);
|
lastErrAssetId = asset.id;
|
||||||
|
|
||||||
|
if (err instanceof QueryFailedError && (err as any).constraint === 'UQ_userid_checksum') {
|
||||||
|
Logger.error(`${asset.originalPath} duplicated`);
|
||||||
|
} else {
|
||||||
|
Logger.error(`checksum generation ${err}`);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// break when reach to the last page
|
||||||
if (assets.length < pageSize) {
|
if (assets.length < pageSize) {
|
||||||
hasNext = false;
|
hasNext = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Logger.log(`checksum generation done!`);
|
||||||
}
|
}
|
||||||
|
|
||||||
private async generateAssetChecksum(asset: AssetEntity) {
|
private async generateAssetChecksum(asset: AssetEntity) {
|
||||||
|
|||||||
Reference in New Issue
Block a user