Compare commits

...

5 Commits
v2.4.0 ... main

Author SHA1 Message Date
Timon c9b58f5893
fix(web): auto-start slideshow when confirming settings modal (#24629)
feat(web): auto-start slideshow when confirming settings modal
2025-12-18 21:58:22 +00:00
Timon 640fd7308b
fix(mobile): infinite loading screen when hiding UI in map viewer on iOS (#24563)
* fix with logging

* remove logging

* analyze
2025-12-18 21:07:58 +00:00
shenlong 557a79f747
chore(mobile): log failures from share upload intent (#24680)
chore: log failures from share intent upload

Co-authored-by: shenlong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
2025-12-18 14:30:55 -06:00
Yaros 5ade152bc5
fix(web): shared link expiry does not save (#24569)
* fix(web): shared link expiry does not save

* chore: fix lint errors

---------

Co-authored-by: Alex <alex.tran1502@gmail.com>
2025-12-18 06:19:31 +00:00
bo0tzz 827bf1ef18
fix: pass bumped version through outputs (#24649) 2025-12-17 17:06:54 -06:00
5 changed files with 39 additions and 8 deletions

View File

@ -45,6 +45,7 @@ jobs:
needs: [merge_translations]
outputs:
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
version: ${{ steps.output.outputs.version }}
permissions: {} # No job-level permissions are needed because it uses the app-token
steps:
- name: Generate a token
@ -80,13 +81,16 @@ jobs:
MOBILE_BUMP: ${{ inputs.mobileBump }}
run: misc/release/pump-version.sh -s "${SERVER_BUMP}" -m "${MOBILE_BUMP}"
- id: output
run: echo "version=$IMMICH_VERSION" >> $GITHUB_OUTPUT
- name: Commit and tag
id: push-tag
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
with:
default_author: github_actions
message: 'chore: version ${{ env.IMMICH_VERSION }}'
tag: ${{ env.IMMICH_VERSION }}
message: 'chore: version ${{ steps.output.outputs.version }}'
tag: ${{ steps.output.outputs.version }}
push: true
build_mobile:
@ -119,7 +123,7 @@ jobs:
prepare_release:
runs-on: ubuntu-latest
needs: build_mobile
needs: [build_mobile, bump_version]
permissions:
actions: read # To download the app artifact
# No content permissions are needed because it uses the app-token
@ -147,7 +151,7 @@ jobs:
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
with:
draft: true
tag_name: ${{ env.IMMICH_VERSION }}
tag_name: ${{ needs.bump_version.outputs.version }}
token: ${{ steps.generate-token.outputs.token }}
generate_release_notes: true
body_path: misc/release/notes.tmpl

View File

@ -12,6 +12,8 @@ import 'package:immich_mobile/extensions/translate_extensions.dart';
import 'package:immich_mobile/presentation/widgets/bottom_sheet/map_bottom_sheet.widget.dart';
import 'package:immich_mobile/presentation/widgets/map/map.state.dart';
import 'package:immich_mobile/presentation/widgets/map/map_utils.dart';
import 'package:immich_mobile/providers/routes.provider.dart';
import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/utils/async_mutex.dart';
import 'package:immich_mobile/utils/debounce.dart';
import 'package:immich_mobile/widgets/common/immich_toast.dart';
@ -114,6 +116,14 @@ class _DriftMapState extends ConsumerState<DriftMap> {
return;
}
// When the AssetViewer is open, the DriftMap route stays alive in the background.
// If we continue to update bounds, the map-scoped timeline service gets recreated and the previous one disposed,
// which can invalidate the TimelineService instance that was passed into AssetViewerRoute (causing "loading forever").
final currentRoute = ref.read(currentRouteNameProvider);
if (currentRoute == AssetViewerRoute.name || currentRoute == GalleryViewerRoute.name) {
return;
}
final bounds = await controller.getVisibleRegion();
unawaited(
_reloadMutex.run(() async {

View File

@ -11,6 +11,7 @@ import 'package:immich_mobile/routing/router.dart';
import 'package:immich_mobile/services/api.service.dart';
import 'package:immich_mobile/services/share_intent_service.dart';
import 'package:immich_mobile/services/upload.service.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart';
final shareIntentUploadProvider = StateNotifierProvider<ShareIntentUploadStateNotifier, List<ShareIntentAttachment>>(
@ -25,6 +26,7 @@ class ShareIntentUploadStateNotifier extends StateNotifier<List<ShareIntentAttac
final AppRouter router;
final UploadService _uploadService;
final ShareIntentService _shareIntentService;
final Logger _logger = Logger('ShareIntentUploadStateNotifier');
ShareIntentUploadStateNotifier(this.router, this._uploadService, this._shareIntentService) : super([]) {
_uploadService.taskStatusStream.listen(_updateUploadStatus);
@ -86,6 +88,21 @@ class ShareIntentUploadStateNotifier extends StateNotifier<List<ShareIntentAttac
for (final attachment in state)
if (attachment.id == taskId.toInt()) attachment.copyWith(status: uploadStatus) else attachment,
];
if (task.status == TaskStatus.failed) {
String? error;
final exception = task.exception;
if (exception != null && exception is TaskHttpException) {
final message = tryJsonDecode(exception.description)?['message'] as String?;
if (message != null) {
final responseCode = exception.httpResponseCode;
error = "${exception.exceptionType}, response code $responseCode: $message";
}
}
error ??= task.exception?.toString();
_logger.warning("Upload failed for asset: ${task.task.filename}, error: $error");
}
}
void _taskProgressCallback(TaskProgressUpdate update) {

View File

@ -4,7 +4,6 @@
import { SharedLinkType } from '@immich/sdk';
import { Button, Field, HStack, Input, Modal, ModalBody, ModalFooter, PasswordInput, Switch, Text } from '@immich/ui';
import { mdiLink } from '@mdi/js';
import { DateTime } from 'luxon';
import { t } from 'svelte-i18n';
interface Props {
@ -19,7 +18,6 @@
let allowDownload = $state(true);
let allowUpload = $state(false);
let showMetadata = $state(true);
let expirationOption: number = $state(0);
let password = $state('');
let slug = $state('');
let expiresAt = $state<string | null>(null);
@ -37,7 +35,7 @@
type: shareType,
albumId,
assetIds,
expiresAt: expirationOption > 0 ? DateTime.now().plus(expirationOption).toISO() : undefined,
expiresAt,
allowUpload,
description,
password,

View File

@ -14,7 +14,7 @@
} from '@mdi/js';
import { t } from 'svelte-i18n';
import SettingDropdown from '../components/shared-components/settings/setting-dropdown.svelte';
import { SlideshowLook, SlideshowNavigation, slideshowStore } from '../stores/slideshow.store';
import { SlideshowLook, SlideshowNavigation, SlideshowState, slideshowStore } from '../stores/slideshow.store';
const {
slideshowDelay,
@ -23,6 +23,7 @@
slideshowLook,
slideshowTransition,
slideshowAutoplay,
slideshowState,
} = slideshowStore;
interface Props {
@ -69,6 +70,7 @@
$slideshowLook = tempSlideshowLook;
$slideshowTransition = tempSlideshowTransition;
$slideshowAutoplay = tempSlideshowAutoplay;
$slideshowState = SlideshowState.PlaySlideshow;
onClose();
};
</script>