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