1
0
mirror of https://github.com/immich-app/immich.git synced 2024-12-26 10:50:29 +02:00

fix(mobile): shows asset datetime with original timezone (#4774)

This commit is contained in:
waclaw66 2023-11-03 15:04:41 +01:00 committed by GitHub
parent 81792a5342
commit 33ce2b7bba
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 49 additions and 6 deletions

View File

@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
import 'package:flutter/services.dart'; import 'package:flutter/services.dart';
import 'package:flutter_displaymode/flutter_displaymode.dart'; import 'package:flutter_displaymode/flutter_displaymode.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:timezone/data/latest.dart';
import 'package:immich_mobile/constants/locales.dart'; import 'package:immich_mobile/constants/locales.dart';
import 'package:immich_mobile/modules/backup/background_service/background.service.dart'; import 'package:immich_mobile/modules/backup/background_service/background.service.dart';
import 'package:immich_mobile/modules/backup/models/backup_album.model.dart'; import 'package:immich_mobile/modules/backup/models/backup_album.model.dart';
@ -77,6 +78,8 @@ Future<void> initApp() async {
log.severe('Catch all error: ${error.toString()} - $error', error, stack); log.severe('Catch all error: ${error.toString()} - $error', error, stack);
return true; return true;
}; };
initializeTimeZones();
} }
Future<Isar> loadDb() async { Future<Isar> loadDb() async {

View File

@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart'; import 'package:flutter_map/flutter_map.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:timezone/timezone.dart';
import 'package:immich_mobile/modules/asset_viewer/ui/description_input.dart'; import 'package:immich_mobile/modules/asset_viewer/ui/description_input.dart';
import 'package:immich_mobile/modules/map/ui/map_thumbnail.dart'; import 'package:immich_mobile/modules/map/ui/map_thumbnail.dart';
import 'package:immich_mobile/shared/models/asset.dart'; import 'package:immich_mobile/shared/models/asset.dart';
@ -26,12 +27,36 @@ class ExifBottomSheet extends HookConsumerWidget {
exifInfo.latitude != 0 && exifInfo.latitude != 0 &&
exifInfo.longitude != 0; exifInfo.longitude != 0;
String get formattedDateTime { String formatTimeZone(Duration d) =>
final fileCreatedAt = asset.fileCreatedAt.toLocal(); "GMT${d.isNegative ? '-': '+'}${d.inHours.abs().toString().padLeft(2, '0')}:${d.inMinutes.abs().remainder(60).toString().padLeft(2, '0')}";
final date = DateFormat.yMMMEd().format(fileCreatedAt);
final time = DateFormat.jm().format(fileCreatedAt);
return '$date$time'; String get formattedDateTime {
DateTime dt = asset.fileCreatedAt.toLocal();
String? timeZone;
if (asset.exifInfo?.dateTimeOriginal != null) {
dt = asset.exifInfo!.dateTimeOriginal!;
if (asset.exifInfo?.timeZone != null) {
dt = dt.toUtc();
try {
final location = getLocation(asset.exifInfo!.timeZone!);
dt = TZDateTime.from(dt, location);
} on LocationNotFoundException {
RegExp re = RegExp(r'^utc(?:([+-]\d{1,2})(?::(\d{2}))?)?$', caseSensitive: false);
final m = re.firstMatch(asset.exifInfo!.timeZone!);
if (m != null) {
final duration = Duration(hours: int.parse(m.group(1) ?? '0'), minutes: int.parse(m.group(2) ?? '0'));
dt = dt.add(duration);
timeZone = formatTimeZone(duration);
}
}
}
}
final date = DateFormat.yMMMEd().format(dt);
final time = DateFormat.jm().format(dt);
timeZone ??= formatTimeZone(dt.timeZoneOffset);
return '$date$time $timeZone';
} }
Future<Uri?> _createCoordinatesUri(ExifInfo? exifInfo) async { Future<Uri?> _createCoordinatesUri(ExifInfo? exifInfo) async {

View File

@ -8,6 +8,8 @@ part 'exif_info.g.dart';
class ExifInfo { class ExifInfo {
Id? id; Id? id;
int? fileSize; int? fileSize;
DateTime? dateTimeOriginal;
String? timeZone;
String? make; String? make;
String? model; String? model;
String? lens; String? lens;
@ -47,6 +49,8 @@ class ExifInfo {
ExifInfo.fromDto(ExifResponseDto dto) ExifInfo.fromDto(ExifResponseDto dto)
: fileSize = dto.fileSizeInByte, : fileSize = dto.fileSizeInByte,
dateTimeOriginal = dto.dateTimeOriginal,
timeZone = dto.timeZone,
make = dto.make, make = dto.make,
model = dto.model, model = dto.model,
lens = dto.lensModel, lens = dto.lensModel,
@ -64,6 +68,8 @@ class ExifInfo {
ExifInfo({ ExifInfo({
this.id, this.id,
this.fileSize, this.fileSize,
this.dateTimeOriginal,
this.timeZone,
this.make, this.make,
this.model, this.model,
this.lens, this.lens,
@ -82,6 +88,8 @@ class ExifInfo {
ExifInfo copyWith({ ExifInfo copyWith({
Id? id, Id? id,
int? fileSize, int? fileSize,
DateTime? dateTimeOriginal,
String? timeZone,
String? make, String? make,
String? model, String? model,
String? lens, String? lens,
@ -99,6 +107,8 @@ class ExifInfo {
ExifInfo( ExifInfo(
id: id ?? this.id, id: id ?? this.id,
fileSize: fileSize ?? this.fileSize, fileSize: fileSize ?? this.fileSize,
dateTimeOriginal: dateTimeOriginal ?? this.dateTimeOriginal,
timeZone: timeZone ?? this.timeZone,
make: make ?? this.make, make: make ?? this.make,
model: model ?? this.model, model: model ?? this.model,
lens: lens ?? this.lens, lens: lens ?? this.lens,
@ -119,6 +129,8 @@ class ExifInfo {
if (other is! ExifInfo) return false; if (other is! ExifInfo) return false;
return id == other.id && return id == other.id &&
fileSize == other.fileSize && fileSize == other.fileSize &&
dateTimeOriginal == other.dateTimeOriginal &&
timeZone == other.timeZone &&
make == other.make && make == other.make &&
model == other.model && model == other.model &&
lens == other.lens && lens == other.lens &&
@ -139,6 +151,8 @@ class ExifInfo {
int get hashCode => int get hashCode =>
id.hashCode ^ id.hashCode ^
fileSize.hashCode ^ fileSize.hashCode ^
dateTimeOriginal.hashCode ^
timeZone.hashCode ^
make.hashCode ^ make.hashCode ^
model.hashCode ^ model.hashCode ^
lens.hashCode ^ lens.hashCode ^

View File

@ -1401,7 +1401,7 @@ packages:
source: hosted source: hosted
version: "2.1.3" version: "2.1.3"
timezone: timezone:
dependency: transitive dependency: "direct main"
description: description:
name: timezone name: timezone
sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0" sha256: "1cfd8ddc2d1cfd836bc93e67b9be88c3adaeca6f40a00ca999104c30693cdca0"

View File

@ -52,6 +52,7 @@ dependencies:
crypto: ^3.0.3 # TODO remove once native crypto is used on iOS crypto: ^3.0.3 # TODO remove once native crypto is used on iOS
wakelock_plus: ^1.1.1 wakelock_plus: ^1.1.1
flutter_local_notifications: ^15.1.0+1 flutter_local_notifications: ^15.1.0+1
timezone: ^0.9.2
openapi: openapi:
path: openapi path: openapi