Compare commits
5 Commits
| Author | SHA1 | Date |
|---|---|---|
|
|
c9b58f5893 | |
|
|
640fd7308b | |
|
|
557a79f747 | |
|
|
5ade152bc5 | |
|
|
827bf1ef18 |
|
|
@ -45,6 +45,7 @@ jobs:
|
||||||
needs: [merge_translations]
|
needs: [merge_translations]
|
||||||
outputs:
|
outputs:
|
||||||
ref: ${{ steps.push-tag.outputs.commit_long_sha }}
|
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
|
permissions: {} # No job-level permissions are needed because it uses the app-token
|
||||||
steps:
|
steps:
|
||||||
- name: Generate a token
|
- name: Generate a token
|
||||||
|
|
@ -80,13 +81,16 @@ jobs:
|
||||||
MOBILE_BUMP: ${{ inputs.mobileBump }}
|
MOBILE_BUMP: ${{ inputs.mobileBump }}
|
||||||
run: misc/release/pump-version.sh -s "${SERVER_BUMP}" -m "${MOBILE_BUMP}"
|
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
|
- name: Commit and tag
|
||||||
id: push-tag
|
id: push-tag
|
||||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
||||||
with:
|
with:
|
||||||
default_author: github_actions
|
default_author: github_actions
|
||||||
message: 'chore: version ${{ env.IMMICH_VERSION }}'
|
message: 'chore: version ${{ steps.output.outputs.version }}'
|
||||||
tag: ${{ env.IMMICH_VERSION }}
|
tag: ${{ steps.output.outputs.version }}
|
||||||
push: true
|
push: true
|
||||||
|
|
||||||
build_mobile:
|
build_mobile:
|
||||||
|
|
@ -119,7 +123,7 @@ jobs:
|
||||||
|
|
||||||
prepare_release:
|
prepare_release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
needs: build_mobile
|
needs: [build_mobile, bump_version]
|
||||||
permissions:
|
permissions:
|
||||||
actions: read # To download the app artifact
|
actions: read # To download the app artifact
|
||||||
# No content permissions are needed because it uses the app-token
|
# 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
|
uses: softprops/action-gh-release@a06a81a03ee405af7f2048a818ed3f03bbf83c7b # v2.5.0
|
||||||
with:
|
with:
|
||||||
draft: true
|
draft: true
|
||||||
tag_name: ${{ env.IMMICH_VERSION }}
|
tag_name: ${{ needs.bump_version.outputs.version }}
|
||||||
token: ${{ steps.generate-token.outputs.token }}
|
token: ${{ steps.generate-token.outputs.token }}
|
||||||
generate_release_notes: true
|
generate_release_notes: true
|
||||||
body_path: misc/release/notes.tmpl
|
body_path: misc/release/notes.tmpl
|
||||||
|
|
|
||||||
|
|
@ -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/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.state.dart';
|
||||||
import 'package:immich_mobile/presentation/widgets/map/map_utils.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/async_mutex.dart';
|
||||||
import 'package:immich_mobile/utils/debounce.dart';
|
import 'package:immich_mobile/utils/debounce.dart';
|
||||||
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
import 'package:immich_mobile/widgets/common/immich_toast.dart';
|
||||||
|
|
@ -114,6 +116,14 @@ class _DriftMapState extends ConsumerState<DriftMap> {
|
||||||
return;
|
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();
|
final bounds = await controller.getVisibleRegion();
|
||||||
unawaited(
|
unawaited(
|
||||||
_reloadMutex.run(() async {
|
_reloadMutex.run(() async {
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,7 @@ import 'package:immich_mobile/routing/router.dart';
|
||||||
import 'package:immich_mobile/services/api.service.dart';
|
import 'package:immich_mobile/services/api.service.dart';
|
||||||
import 'package:immich_mobile/services/share_intent_service.dart';
|
import 'package:immich_mobile/services/share_intent_service.dart';
|
||||||
import 'package:immich_mobile/services/upload.service.dart';
|
import 'package:immich_mobile/services/upload.service.dart';
|
||||||
|
import 'package:logging/logging.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
|
||||||
final shareIntentUploadProvider = StateNotifierProvider<ShareIntentUploadStateNotifier, List<ShareIntentAttachment>>(
|
final shareIntentUploadProvider = StateNotifierProvider<ShareIntentUploadStateNotifier, List<ShareIntentAttachment>>(
|
||||||
|
|
@ -25,6 +26,7 @@ class ShareIntentUploadStateNotifier extends StateNotifier<List<ShareIntentAttac
|
||||||
final AppRouter router;
|
final AppRouter router;
|
||||||
final UploadService _uploadService;
|
final UploadService _uploadService;
|
||||||
final ShareIntentService _shareIntentService;
|
final ShareIntentService _shareIntentService;
|
||||||
|
final Logger _logger = Logger('ShareIntentUploadStateNotifier');
|
||||||
|
|
||||||
ShareIntentUploadStateNotifier(this.router, this._uploadService, this._shareIntentService) : super([]) {
|
ShareIntentUploadStateNotifier(this.router, this._uploadService, this._shareIntentService) : super([]) {
|
||||||
_uploadService.taskStatusStream.listen(_updateUploadStatus);
|
_uploadService.taskStatusStream.listen(_updateUploadStatus);
|
||||||
|
|
@ -86,6 +88,21 @@ class ShareIntentUploadStateNotifier extends StateNotifier<List<ShareIntentAttac
|
||||||
for (final attachment in state)
|
for (final attachment in state)
|
||||||
if (attachment.id == taskId.toInt()) attachment.copyWith(status: uploadStatus) else attachment,
|
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) {
|
void _taskProgressCallback(TaskProgressUpdate update) {
|
||||||
|
|
|
||||||
|
|
@ -4,7 +4,6 @@
|
||||||
import { SharedLinkType } from '@immich/sdk';
|
import { SharedLinkType } from '@immich/sdk';
|
||||||
import { Button, Field, HStack, Input, Modal, ModalBody, ModalFooter, PasswordInput, Switch, Text } from '@immich/ui';
|
import { Button, Field, HStack, Input, Modal, ModalBody, ModalFooter, PasswordInput, Switch, Text } from '@immich/ui';
|
||||||
import { mdiLink } from '@mdi/js';
|
import { mdiLink } from '@mdi/js';
|
||||||
import { DateTime } from 'luxon';
|
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -19,7 +18,6 @@
|
||||||
let allowDownload = $state(true);
|
let allowDownload = $state(true);
|
||||||
let allowUpload = $state(false);
|
let allowUpload = $state(false);
|
||||||
let showMetadata = $state(true);
|
let showMetadata = $state(true);
|
||||||
let expirationOption: number = $state(0);
|
|
||||||
let password = $state('');
|
let password = $state('');
|
||||||
let slug = $state('');
|
let slug = $state('');
|
||||||
let expiresAt = $state<string | null>(null);
|
let expiresAt = $state<string | null>(null);
|
||||||
|
|
@ -37,7 +35,7 @@
|
||||||
type: shareType,
|
type: shareType,
|
||||||
albumId,
|
albumId,
|
||||||
assetIds,
|
assetIds,
|
||||||
expiresAt: expirationOption > 0 ? DateTime.now().plus(expirationOption).toISO() : undefined,
|
expiresAt,
|
||||||
allowUpload,
|
allowUpload,
|
||||||
description,
|
description,
|
||||||
password,
|
password,
|
||||||
|
|
|
||||||
|
|
@ -14,7 +14,7 @@
|
||||||
} from '@mdi/js';
|
} from '@mdi/js';
|
||||||
import { t } from 'svelte-i18n';
|
import { t } from 'svelte-i18n';
|
||||||
import SettingDropdown from '../components/shared-components/settings/setting-dropdown.svelte';
|
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 {
|
const {
|
||||||
slideshowDelay,
|
slideshowDelay,
|
||||||
|
|
@ -23,6 +23,7 @@
|
||||||
slideshowLook,
|
slideshowLook,
|
||||||
slideshowTransition,
|
slideshowTransition,
|
||||||
slideshowAutoplay,
|
slideshowAutoplay,
|
||||||
|
slideshowState,
|
||||||
} = slideshowStore;
|
} = slideshowStore;
|
||||||
|
|
||||||
interface Props {
|
interface Props {
|
||||||
|
|
@ -69,6 +70,7 @@
|
||||||
$slideshowLook = tempSlideshowLook;
|
$slideshowLook = tempSlideshowLook;
|
||||||
$slideshowTransition = tempSlideshowTransition;
|
$slideshowTransition = tempSlideshowTransition;
|
||||||
$slideshowAutoplay = tempSlideshowAutoplay;
|
$slideshowAutoplay = tempSlideshowAutoplay;
|
||||||
|
$slideshowState = SlideshowState.PlaySlideshow;
|
||||||
onClose();
|
onClose();
|
||||||
};
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue