mirror of
https://github.com/immich-app/immich.git
synced 2024-12-26 10:50:29 +02:00
feat(mobile): remove announcement overlay and show in app bar dialog (#5104)
Co-authored-by: shalong-tanwen <139912620+shalong-tanwen@users.noreply.github.com>
This commit is contained in:
parent
63a745c7ad
commit
4daf2478aa
@ -292,6 +292,7 @@
|
|||||||
"server_info_box_app_version": "App Version",
|
"server_info_box_app_version": "App Version",
|
||||||
"server_info_box_server_url": "Server URL",
|
"server_info_box_server_url": "Server URL",
|
||||||
"server_info_box_server_version": "Server Version",
|
"server_info_box_server_version": "Server Version",
|
||||||
|
"server_info_box_latest_release":"Latest Version",
|
||||||
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
"setting_image_viewer_help": "The detail viewer loads the small thumbnail first, then loads the medium-size preview (if enabled), finally loads the original (if enabled).",
|
||||||
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
"setting_image_viewer_original_subtitle": "Enable to load the original full-resolution image (large!). Disable to reduce data usage (both network and on device cache).",
|
||||||
"setting_image_viewer_original_title": "Load original image",
|
"setting_image_viewer_original_title": "Load original image",
|
||||||
|
@ -26,11 +26,9 @@ import 'package:immich_mobile/shared/models/store.dart';
|
|||||||
import 'package:immich_mobile/shared/models/user.dart';
|
import 'package:immich_mobile/shared/models/user.dart';
|
||||||
import 'package:immich_mobile/shared/providers/app_state.provider.dart';
|
import 'package:immich_mobile/shared/providers/app_state.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
import 'package:immich_mobile/shared/providers/db.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/release_info.provider.dart';
|
|
||||||
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
import 'package:immich_mobile/shared/services/immich_logger.service.dart';
|
||||||
import 'package:immich_mobile/shared/services/local_notification.service.dart';
|
import 'package:immich_mobile/shared/services/local_notification.service.dart';
|
||||||
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
import 'package:immich_mobile/shared/views/immich_loading_overlay.dart';
|
||||||
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
|
|
||||||
import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
|
import 'package:immich_mobile/utils/http_ssl_cert_override.dart';
|
||||||
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
import 'package:immich_mobile/utils/immich_app_theme.dart';
|
||||||
import 'package:immich_mobile/utils/migration.dart';
|
import 'package:immich_mobile/utils/migration.dart';
|
||||||
@ -196,7 +194,6 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var router = ref.watch(appRouterProvider);
|
var router = ref.watch(appRouterProvider);
|
||||||
ref.watch(releaseInfoProvider.notifier).checkGithubReleaseInfo();
|
|
||||||
|
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
localizationsDelegates: context.localizationDelegates,
|
localizationsDelegates: context.localizationDelegates,
|
||||||
@ -217,7 +214,6 @@ class ImmichAppState extends ConsumerState<ImmichApp>
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const ImmichLoadingOverlay(),
|
const ImmichLoadingOverlay(),
|
||||||
const VersionAnnouncementOverlay(),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -5,43 +5,52 @@ import 'package:immich_mobile/shared/models/server_info/server_version.model.dar
|
|||||||
|
|
||||||
class ServerInfo {
|
class ServerInfo {
|
||||||
final ServerVersion serverVersion;
|
final ServerVersion serverVersion;
|
||||||
|
final ServerVersion latestVersion;
|
||||||
final ServerFeatures serverFeatures;
|
final ServerFeatures serverFeatures;
|
||||||
final ServerConfig serverConfig;
|
final ServerConfig serverConfig;
|
||||||
final ServerDiskInfo serverDiskInfo;
|
final ServerDiskInfo serverDiskInfo;
|
||||||
final bool isVersionMismatch;
|
final bool isVersionMismatch;
|
||||||
|
final bool isNewReleaseAvailable;
|
||||||
final String versionMismatchErrorMessage;
|
final String versionMismatchErrorMessage;
|
||||||
|
|
||||||
ServerInfo({
|
ServerInfo({
|
||||||
required this.serverVersion,
|
required this.serverVersion,
|
||||||
|
required this.latestVersion,
|
||||||
required this.serverFeatures,
|
required this.serverFeatures,
|
||||||
required this.serverConfig,
|
required this.serverConfig,
|
||||||
required this.isVersionMismatch,
|
|
||||||
required this.serverDiskInfo,
|
required this.serverDiskInfo,
|
||||||
|
required this.isVersionMismatch,
|
||||||
|
required this.isNewReleaseAvailable,
|
||||||
required this.versionMismatchErrorMessage,
|
required this.versionMismatchErrorMessage,
|
||||||
});
|
});
|
||||||
|
|
||||||
ServerInfo copyWith({
|
ServerInfo copyWith({
|
||||||
ServerVersion? serverVersion,
|
ServerVersion? serverVersion,
|
||||||
|
ServerVersion? latestVersion,
|
||||||
ServerFeatures? serverFeatures,
|
ServerFeatures? serverFeatures,
|
||||||
ServerConfig? serverConfig,
|
ServerConfig? serverConfig,
|
||||||
ServerDiskInfo? serverDiskInfo,
|
ServerDiskInfo? serverDiskInfo,
|
||||||
bool? isVersionMismatch,
|
bool? isVersionMismatch,
|
||||||
|
bool? isNewReleaseAvailable,
|
||||||
String? versionMismatchErrorMessage,
|
String? versionMismatchErrorMessage,
|
||||||
}) {
|
}) {
|
||||||
return ServerInfo(
|
return ServerInfo(
|
||||||
serverVersion: serverVersion ?? this.serverVersion,
|
serverVersion: serverVersion ?? this.serverVersion,
|
||||||
|
latestVersion: latestVersion ?? this.latestVersion,
|
||||||
serverFeatures: serverFeatures ?? this.serverFeatures,
|
serverFeatures: serverFeatures ?? this.serverFeatures,
|
||||||
serverConfig: serverConfig ?? this.serverConfig,
|
serverConfig: serverConfig ?? this.serverConfig,
|
||||||
|
serverDiskInfo: serverDiskInfo ?? this.serverDiskInfo,
|
||||||
isVersionMismatch: isVersionMismatch ?? this.isVersionMismatch,
|
isVersionMismatch: isVersionMismatch ?? this.isVersionMismatch,
|
||||||
|
isNewReleaseAvailable:
|
||||||
|
isNewReleaseAvailable ?? this.isNewReleaseAvailable,
|
||||||
versionMismatchErrorMessage:
|
versionMismatchErrorMessage:
|
||||||
versionMismatchErrorMessage ?? this.versionMismatchErrorMessage,
|
versionMismatchErrorMessage ?? this.versionMismatchErrorMessage,
|
||||||
serverDiskInfo: serverDiskInfo ?? this.serverDiskInfo,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ServerInfo(serverVersion: $serverVersion, serverFeatures: $serverFeatures, serverConfig: $serverConfig, isVersionMismatch: $isVersionMismatch, versionMismatchErrorMessage: $versionMismatchErrorMessage, serverDiskInfo: $serverDiskInfo)';
|
return 'ServerInfo(serverVersion: $serverVersion, latestVersion: $latestVersion, serverFeatures: $serverFeatures, serverConfig: $serverConfig, serverDiskInfo: $serverDiskInfo, isVersionMismatch: $isVersionMismatch, isNewReleaseAvailable: $isNewReleaseAvailable, versionMismatchErrorMessage: $versionMismatchErrorMessage)';
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@ -50,20 +59,24 @@ class ServerInfo {
|
|||||||
|
|
||||||
return other is ServerInfo &&
|
return other is ServerInfo &&
|
||||||
other.serverVersion == serverVersion &&
|
other.serverVersion == serverVersion &&
|
||||||
|
other.latestVersion == latestVersion &&
|
||||||
other.serverFeatures == serverFeatures &&
|
other.serverFeatures == serverFeatures &&
|
||||||
other.serverConfig == serverConfig &&
|
other.serverConfig == serverConfig &&
|
||||||
other.serverDiskInfo == serverDiskInfo &&
|
other.serverDiskInfo == serverDiskInfo &&
|
||||||
other.isVersionMismatch == isVersionMismatch &&
|
other.isVersionMismatch == isVersionMismatch &&
|
||||||
|
other.isNewReleaseAvailable == isNewReleaseAvailable &&
|
||||||
other.versionMismatchErrorMessage == versionMismatchErrorMessage;
|
other.versionMismatchErrorMessage == versionMismatchErrorMessage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode {
|
int get hashCode {
|
||||||
return serverVersion.hashCode ^
|
return serverVersion.hashCode ^
|
||||||
|
latestVersion.hashCode ^
|
||||||
serverFeatures.hashCode ^
|
serverFeatures.hashCode ^
|
||||||
serverConfig.hashCode ^
|
serverConfig.hashCode ^
|
||||||
|
serverDiskInfo.hashCode ^
|
||||||
isVersionMismatch.hashCode ^
|
isVersionMismatch.hashCode ^
|
||||||
versionMismatchErrorMessage.hashCode ^
|
isNewReleaseAvailable.hashCode ^
|
||||||
serverDiskInfo.hashCode;
|
versionMismatchErrorMessage.hashCode;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,6 @@ enum StoreKey<T> {
|
|||||||
backupRequireWifi<bool>(6, type: bool),
|
backupRequireWifi<bool>(6, type: bool),
|
||||||
backupRequireCharging<bool>(7, type: bool),
|
backupRequireCharging<bool>(7, type: bool),
|
||||||
backupTriggerDelay<int>(8, type: int),
|
backupTriggerDelay<int>(8, type: int),
|
||||||
githubReleaseInfo<String>(9, type: String),
|
|
||||||
serverUrl<String>(10, type: String),
|
serverUrl<String>(10, type: String),
|
||||||
accessToken<String>(11, type: String),
|
accessToken<String>(11, type: String),
|
||||||
serverEndpoint<String>(12, type: String),
|
serverEndpoint<String>(12, type: String),
|
||||||
|
@ -11,7 +11,6 @@ import 'package:immich_mobile/modules/memories/providers/memory.provider.dart';
|
|||||||
import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart';
|
import 'package:immich_mobile/modules/onboarding/providers/gallery_permission.provider.dart';
|
||||||
import 'package:immich_mobile/modules/settings/providers/notification_permission.provider.dart';
|
import 'package:immich_mobile/modules/settings/providers/notification_permission.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/release_info.provider.dart';
|
|
||||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/tab.provider.dart';
|
import 'package:immich_mobile/shared/providers/tab.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
import 'package:immich_mobile/shared/providers/websocket.provider.dart';
|
||||||
@ -70,8 +69,6 @@ class AppStateNotiifer extends StateNotifier<AppStateEnum> {
|
|||||||
|
|
||||||
_ref.read(websocketProvider.notifier).connect();
|
_ref.read(websocketProvider.notifier).connect();
|
||||||
|
|
||||||
_ref.read(releaseInfoProvider.notifier).checkGithubReleaseInfo();
|
|
||||||
|
|
||||||
_ref
|
_ref
|
||||||
.read(notificationPermissionProvider.notifier)
|
.read(notificationPermissionProvider.notifier)
|
||||||
.getNotificationPermission();
|
.getNotificationPermission();
|
||||||
|
@ -1,57 +0,0 @@
|
|||||||
import 'dart:convert';
|
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:http/http.dart';
|
|
||||||
import 'package:immich_mobile/shared/models/store.dart';
|
|
||||||
import 'package:immich_mobile/shared/views/version_announcement_overlay.dart';
|
|
||||||
import 'package:logging/logging.dart';
|
|
||||||
|
|
||||||
class ReleaseInfoNotifier extends StateNotifier<String> {
|
|
||||||
ReleaseInfoNotifier() : super("");
|
|
||||||
final log = Logger('ReleaseInfoNotifier');
|
|
||||||
void checkGithubReleaseInfo() async {
|
|
||||||
final Client client = Client();
|
|
||||||
|
|
||||||
try {
|
|
||||||
final String? localReleaseVersion =
|
|
||||||
Store.tryGet(StoreKey.githubReleaseInfo);
|
|
||||||
final res = await client.get(
|
|
||||||
Uri.parse(
|
|
||||||
"https://api.github.com/repos/immich-app/immich/releases/latest",
|
|
||||||
),
|
|
||||||
headers: {"Accept": "application/vnd.github.v3+json"},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (res.statusCode == 200) {
|
|
||||||
final data = jsonDecode(res.body);
|
|
||||||
String latestTagVersion = data["tag_name"];
|
|
||||||
state = latestTagVersion;
|
|
||||||
|
|
||||||
if (localReleaseVersion == null && latestTagVersion.isNotEmpty) {
|
|
||||||
VersionAnnouncementOverlayController.appLoader.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (latestTagVersion.isNotEmpty &&
|
|
||||||
localReleaseVersion != latestTagVersion) {
|
|
||||||
VersionAnnouncementOverlayController.appLoader.show();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
debugPrint("Error gettting latest release version");
|
|
||||||
|
|
||||||
state = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void acknowledgeNewVersion() {
|
|
||||||
Store.put(StoreKey.githubReleaseInfo, state);
|
|
||||||
VersionAnnouncementOverlayController.appLoader.hide();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final releaseInfoProvider = StateNotifierProvider<ReleaseInfoNotifier, String>(
|
|
||||||
(ref) => ReleaseInfoNotifier(),
|
|
||||||
);
|
|
@ -18,6 +18,11 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
minor: 0,
|
minor: 0,
|
||||||
patch: 0,
|
patch: 0,
|
||||||
),
|
),
|
||||||
|
latestVersion: const ServerVersion(
|
||||||
|
major: 0,
|
||||||
|
minor: 0,
|
||||||
|
patch: 0,
|
||||||
|
),
|
||||||
serverFeatures: const ServerFeatures(
|
serverFeatures: const ServerFeatures(
|
||||||
map: true,
|
map: true,
|
||||||
trash: true,
|
trash: true,
|
||||||
@ -32,6 +37,7 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
diskUsagePercentage: 0,
|
diskUsagePercentage: 0,
|
||||||
),
|
),
|
||||||
isVersionMismatch: false,
|
isVersionMismatch: false,
|
||||||
|
isNewReleaseAvailable: false,
|
||||||
versionMismatchErrorMessage: "",
|
versionMismatchErrorMessage: "",
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@ -55,6 +61,10 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
await _checkServerVersionMismatch(serverVersion);
|
||||||
|
}
|
||||||
|
|
||||||
|
_checkServerVersionMismatch(ServerVersion serverVersion) async {
|
||||||
state = state.copyWith(serverVersion: serverVersion);
|
state = state.copyWith(serverVersion: serverVersion);
|
||||||
|
|
||||||
var packageInfo = await PackageInfo.fromPlatform();
|
var packageInfo = await PackageInfo.fromPlatform();
|
||||||
@ -67,7 +77,15 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
versionMismatchErrorMessage:
|
versionMismatchErrorMessage:
|
||||||
"Server is out of date. Please update to the latest major version.",
|
"Server is out of date. Please update to the latest major version.",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appVersion["major"]! < serverVersion.major) {
|
||||||
|
state = state.copyWith(
|
||||||
|
isVersionMismatch: true,
|
||||||
|
versionMismatchErrorMessage:
|
||||||
|
"Mobile App is out of date. Please update to the latest major version.",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -75,9 +93,17 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
isVersionMismatch: true,
|
isVersionMismatch: true,
|
||||||
versionMismatchErrorMessage:
|
versionMismatchErrorMessage:
|
||||||
"Server is out of date. Consider updating to the latest minor version.",
|
"Server is out of date. Please update to the latest minor version.",
|
||||||
);
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (appVersion["minor"]! < serverVersion.minor) {
|
||||||
|
state = state.copyWith(
|
||||||
|
isVersionMismatch: true,
|
||||||
|
versionMismatchErrorMessage:
|
||||||
|
"Mobile App is out of date. Please update to the latest minor version.",
|
||||||
|
);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -87,6 +113,25 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
handleNewRelease(
|
||||||
|
ServerVersion serverVersion,
|
||||||
|
ServerVersion latestVersion,
|
||||||
|
) {
|
||||||
|
// Update local server version
|
||||||
|
_checkServerVersionMismatch(serverVersion);
|
||||||
|
|
||||||
|
final majorEqual = latestVersion.major == serverVersion.major;
|
||||||
|
final minorEqual = majorEqual && latestVersion.minor == serverVersion.minor;
|
||||||
|
final newVersionAvailable = latestVersion.major > serverVersion.major ||
|
||||||
|
(majorEqual && latestVersion.minor > serverVersion.minor) ||
|
||||||
|
(minorEqual && latestVersion.patch > serverVersion.patch);
|
||||||
|
|
||||||
|
state = state.copyWith(
|
||||||
|
latestVersion: latestVersion,
|
||||||
|
isNewReleaseAvailable: newVersionAvailable,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
getServerFeatures() async {
|
getServerFeatures() async {
|
||||||
final serverFeatures = await _serverInfoService.getServerFeatures();
|
final serverFeatures = await _serverInfoService.getServerFeatures();
|
||||||
if (serverFeatures == null) {
|
if (serverFeatures == null) {
|
||||||
@ -120,5 +165,5 @@ class ServerInfoNotifier extends StateNotifier<ServerInfo> {
|
|||||||
|
|
||||||
final serverInfoProvider =
|
final serverInfoProvider =
|
||||||
StateNotifierProvider<ServerInfoNotifier, ServerInfo>((ref) {
|
StateNotifierProvider<ServerInfoNotifier, ServerInfo>((ref) {
|
||||||
return ServerInfoNotifier(ref.watch(serverInfoServiceProvider));
|
return ServerInfoNotifier(ref.read(serverInfoServiceProvider));
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,7 @@ import 'package:flutter/foundation.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
import 'package:immich_mobile/modules/login/providers/authentication.provider.dart';
|
||||||
import 'package:immich_mobile/shared/models/asset.dart';
|
import 'package:immich_mobile/shared/models/asset.dart';
|
||||||
|
import 'package:immich_mobile/shared/models/server_info/server_version.model.dart';
|
||||||
import 'package:immich_mobile/shared/models/store.dart';
|
import 'package:immich_mobile/shared/models/store.dart';
|
||||||
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
import 'package:immich_mobile/shared/providers/asset.provider.dart';
|
||||||
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
import 'package:immich_mobile/shared/providers/server_info.provider.dart';
|
||||||
@ -130,6 +131,7 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
socket.on('on_asset_trash', _handleServerUpdates);
|
socket.on('on_asset_trash', _handleServerUpdates);
|
||||||
socket.on('on_asset_restore', _handleServerUpdates);
|
socket.on('on_asset_restore', _handleServerUpdates);
|
||||||
socket.on('on_asset_update', _handleServerUpdates);
|
socket.on('on_asset_update', _handleServerUpdates);
|
||||||
|
socket.on('on_new_release', _handleReleaseUpdates);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}");
|
debugPrint("[WEBSOCKET] Catch Websocket Error - ${e.toString()}");
|
||||||
}
|
}
|
||||||
@ -204,6 +206,36 @@ class WebsocketNotifier extends StateNotifier<WebsocketState> {
|
|||||||
addPendingChange(PendingAction.assetDelete, data);
|
addPendingChange(PendingAction.assetDelete, data);
|
||||||
_debounce(handlePendingChanges);
|
_debounce(handlePendingChanges);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_handleReleaseUpdates(dynamic data) {
|
||||||
|
// Json guard
|
||||||
|
if (data is! Map) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final json = data.cast<String, dynamic>();
|
||||||
|
final serverVersionJson =
|
||||||
|
json.containsKey('serverVersion') ? json['serverVersion'] : null;
|
||||||
|
final releaseVersionJson =
|
||||||
|
json.containsKey('releaseVersion') ? json['releaseVersion'] : null;
|
||||||
|
if (serverVersionJson == null || releaseVersionJson == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final serverVersionDto =
|
||||||
|
ServerVersionResponseDto.fromJson(serverVersionJson);
|
||||||
|
final releaseVersionDto =
|
||||||
|
ServerVersionResponseDto.fromJson(releaseVersionJson);
|
||||||
|
if (serverVersionDto == null || releaseVersionDto == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final serverVersion = ServerVersion.fromDto(serverVersionDto);
|
||||||
|
final releaseVersion = ServerVersion.fromDto(releaseVersionDto);
|
||||||
|
_ref
|
||||||
|
.read(serverInfoProvider.notifier)
|
||||||
|
.handleNewRelease(serverVersion, releaseVersion);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final websocketProvider =
|
final websocketProvider =
|
||||||
|
@ -137,7 +137,7 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||||||
child: Text(
|
child: Text(
|
||||||
serverInfoState.serverVersion.major > 0
|
serverInfoState.serverVersion.major > 0
|
||||||
? "${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch}"
|
? "${serverInfoState.serverVersion.major}.${serverInfoState.serverVersion.minor}.${serverInfoState.serverVersion.patch}"
|
||||||
: "?",
|
: "--",
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: 11,
|
fontSize: 11,
|
||||||
color: context.textTheme.labelSmall?.color
|
color: context.textTheme.labelSmall?.color
|
||||||
@ -207,6 +207,61 @@ class AppBarServerInfo extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 10),
|
||||||
|
child: Divider(
|
||||||
|
color: Color.fromARGB(101, 201, 201, 201),
|
||||||
|
thickness: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(left: 10.0),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
if (serverInfoState.isNewReleaseAvailable)
|
||||||
|
const Padding(
|
||||||
|
padding: EdgeInsets.only(right: 5.0),
|
||||||
|
child: Icon(
|
||||||
|
Icons.info,
|
||||||
|
color: Color.fromARGB(255, 243, 188, 106),
|
||||||
|
size: 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
"server_info_box_latest_release".tr(),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: context.textTheme.labelSmall?.color,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
flex: 0,
|
||||||
|
child: Padding(
|
||||||
|
padding: const EdgeInsets.only(right: 10.0),
|
||||||
|
child: Text(
|
||||||
|
serverInfoState.latestVersion.major > 0
|
||||||
|
? "${serverInfoState.latestVersion.major}.${serverInfoState.latestVersion.minor}.${serverInfoState.latestVersion.patch}"
|
||||||
|
: "--",
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: context.textTheme.labelSmall?.color
|
||||||
|
?.withOpacity(0.5),
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@ -50,7 +50,9 @@ class ImmichAppBar extends ConsumerWidget implements PreferredSizeWidget {
|
|||||||
),
|
),
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
alignment: Alignment.bottomRight,
|
alignment: Alignment.bottomRight,
|
||||||
isLabelVisible: serverInfoState.isVersionMismatch,
|
isLabelVisible: serverInfoState.isVersionMismatch ||
|
||||||
|
((user?.isAdmin ?? false) &&
|
||||||
|
serverInfoState.isNewReleaseAvailable),
|
||||||
offset: const Offset(2, 2),
|
offset: const Offset(2, 2),
|
||||||
child: user == null
|
child: user == null
|
||||||
? const Icon(
|
? const Icon(
|
||||||
|
@ -1,160 +0,0 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/gestures.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:immich_mobile/shared/providers/release_info.provider.dart';
|
|
||||||
import 'package:immich_mobile/shared/providers/admin_provider.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
|
||||||
|
|
||||||
class VersionAnnouncementOverlay extends HookConsumerWidget {
|
|
||||||
const VersionAnnouncementOverlay({
|
|
||||||
Key? key,
|
|
||||||
}) : super(key: key);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final bool isAdmin = ref.watch(isAdminProvider);
|
|
||||||
|
|
||||||
if (!isAdmin) {
|
|
||||||
return const SizedBox.shrink(); // Don't show anything for non-admins
|
|
||||||
}
|
|
||||||
|
|
||||||
void goToReleaseNote() async {
|
|
||||||
final Uri url =
|
|
||||||
Uri.parse('https://github.com/immich-app/immich/releases/latest');
|
|
||||||
await launchUrl(url);
|
|
||||||
}
|
|
||||||
|
|
||||||
void onAcknowledgeTapped() {
|
|
||||||
ref.watch(releaseInfoProvider.notifier).acknowledgeNewVersion();
|
|
||||||
}
|
|
||||||
|
|
||||||
return ValueListenableBuilder<bool>(
|
|
||||||
valueListenable:
|
|
||||||
VersionAnnouncementOverlayController.appLoader.loaderShowingNotifier,
|
|
||||||
builder: (context, shouldShow, child) {
|
|
||||||
if (shouldShow) {
|
|
||||||
return Scaffold(
|
|
||||||
backgroundColor: Colors.black38,
|
|
||||||
body: Center(
|
|
||||||
child: ConstrainedBox(
|
|
||||||
constraints: const BoxConstraints(maxWidth: 307),
|
|
||||||
child: Wrap(
|
|
||||||
children: [
|
|
||||||
Card(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(30.0),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
const Text(
|
|
||||||
"version_announcement_overlay_title",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 16,
|
|
||||||
fontFamily: 'WorkSans',
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
color: Colors.indigo,
|
|
||||||
),
|
|
||||||
).tr(),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 16.0),
|
|
||||||
child: RichText(
|
|
||||||
text: TextSpan(
|
|
||||||
style: const TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
fontFamily: 'WorkSans',
|
|
||||||
color: Colors.black87,
|
|
||||||
height: 1.2,
|
|
||||||
),
|
|
||||||
children: <TextSpan>[
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
'version_announcement_overlay_text_1'
|
|
||||||
.tr(),
|
|
||||||
),
|
|
||||||
const TextSpan(
|
|
||||||
text: ' Immich ',
|
|
||||||
style: TextStyle(
|
|
||||||
fontFamily: "SnowBurstOne",
|
|
||||||
color: Colors.indigo,
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
"version_announcement_overlay_text_2"
|
|
||||||
.tr(),
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
"version_announcement_overlay_release_notes"
|
|
||||||
.tr(),
|
|
||||||
style: const TextStyle(
|
|
||||||
decoration: TextDecoration.underline,
|
|
||||||
),
|
|
||||||
recognizer: TapGestureRecognizer()
|
|
||||||
..onTap = goToReleaseNote,
|
|
||||||
),
|
|
||||||
TextSpan(
|
|
||||||
text:
|
|
||||||
"version_announcement_overlay_text_3"
|
|
||||||
.tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.only(top: 16.0),
|
|
||||||
child: ElevatedButton(
|
|
||||||
style: ElevatedButton.styleFrom(
|
|
||||||
shape: const StadiumBorder(),
|
|
||||||
visualDensity: VisualDensity.standard,
|
|
||||||
backgroundColor: Colors.indigo,
|
|
||||||
foregroundColor: Colors.grey[50],
|
|
||||||
elevation: 2,
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
vertical: 10,
|
|
||||||
horizontal: 25,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onPressed: onAcknowledgeTapped,
|
|
||||||
child: const Text(
|
|
||||||
"version_announcement_overlay_ack",
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 14,
|
|
||||||
),
|
|
||||||
).tr(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
return const SizedBox();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class VersionAnnouncementOverlayController {
|
|
||||||
static final VersionAnnouncementOverlayController appLoader =
|
|
||||||
VersionAnnouncementOverlayController();
|
|
||||||
ValueNotifier<bool> loaderShowingNotifier = ValueNotifier(false);
|
|
||||||
ValueNotifier<String> loaderTextNotifier = ValueNotifier('error message');
|
|
||||||
|
|
||||||
void show() {
|
|
||||||
loaderShowingNotifier.value = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void hide() {
|
|
||||||
loaderShowingNotifier.value = false;
|
|
||||||
}
|
|
||||||
}
|
|
@ -346,7 +346,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "0.0.2"
|
version: "0.0.2"
|
||||||
executor_lib:
|
executor_lib:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: executor_lib
|
name: executor_lib
|
||||||
sha256: "544889daa5726462657dab6410b75f2f8e3a77479d85b307a25c346e243bc38e"
|
sha256: "544889daa5726462657dab6410b75f2f8e3a77479d85b307a25c346e243bc38e"
|
||||||
@ -1562,7 +1562,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
vector_tile_renderer:
|
vector_tile_renderer:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_tile_renderer
|
name: vector_tile_renderer
|
||||||
sha256: de212da0f5e48107d3b763a940a428eb1f49d8a4664d41ac0b654f77209a2d0b
|
sha256: de212da0f5e48107d3b763a940a428eb1f49d8a4664d41ac0b654f77209a2d0b
|
||||||
|
@ -32,9 +32,6 @@ dependencies:
|
|||||||
git:
|
git:
|
||||||
url: https://github.com/shenlong-tanwen/flutter-vector-map-tiles.git
|
url: https://github.com/shenlong-tanwen/flutter-vector-map-tiles.git
|
||||||
ref: immich_above_4
|
ref: immich_above_4
|
||||||
# Adding the following as direct dependency since flutter cannot detect them as transitive dep
|
|
||||||
vector_tile_renderer: ^4.0.0
|
|
||||||
executor_lib: 1.1.1
|
|
||||||
flutter_udid: ^2.0.0
|
flutter_udid: ^2.0.0
|
||||||
package_info_plus: ^4.1.0
|
package_info_plus: ^4.1.0
|
||||||
url_launcher: ^6.1.3
|
url_launcher: ^6.1.3
|
||||||
|
Loading…
Reference in New Issue
Block a user