mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-01-22 08:46:18 +01:00
Cache server version for use when server is down
This commit is contained in:
parent
d363d544d6
commit
2374fe83df
9 changed files with 109 additions and 20 deletions
|
@ -63,6 +63,7 @@ class AccountController {
|
|||
ServerController get serverController =>
|
||||
_serverController ??= ServerController(
|
||||
account: _account!,
|
||||
accountPrefController: accountPrefController,
|
||||
);
|
||||
|
||||
AccountPrefController get accountPrefController =>
|
||||
|
|
|
@ -1,8 +1,12 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/entity/person.dart';
|
||||
import 'package:nc_photos/entity/pref.dart';
|
||||
import 'package:nc_photos/entity/server_status.dart';
|
||||
import 'package:np_codegen/np_codegen.dart';
|
||||
import 'package:np_common/object_util.dart';
|
||||
import 'package:rxdart/rxdart.dart';
|
||||
|
||||
part 'account_pref_controller.g.dart';
|
||||
|
@ -52,6 +56,13 @@ class AccountPrefController {
|
|||
value: value,
|
||||
);
|
||||
|
||||
Future<void> setServerStatus(ServerStatus value) => _set(
|
||||
controller: _serverStatusController,
|
||||
setter: (pref, value) =>
|
||||
pref.setServerStatus(jsonEncode(value!.toJson())),
|
||||
value: value,
|
||||
);
|
||||
|
||||
Future<void> _set<T>({
|
||||
required BehaviorSubject<T> controller,
|
||||
required Future<bool> Function(AccountPref pref, T value) setter,
|
||||
|
@ -89,4 +100,8 @@ class AccountPrefController {
|
|||
@npSubjectAccessor
|
||||
late final _hasNewSharedAlbumController =
|
||||
BehaviorSubject.seeded(_accountPref.hasNewSharedAlbum() ?? false);
|
||||
@npSubjectAccessor
|
||||
late final _serverStatusController = BehaviorSubject.seeded(_accountPref
|
||||
.getServerStatus()
|
||||
?.let((e) => ServerStatus.fromJson(jsonDecode(e))));
|
||||
}
|
||||
|
|
|
@ -50,4 +50,10 @@ extension $AccountPrefControllerNpSubjectAccessor on AccountPrefController {
|
|||
Stream<bool> get hasNewSharedAlbumChange =>
|
||||
hasNewSharedAlbum.distinct().skip(1);
|
||||
bool get hasNewSharedAlbumValue => _hasNewSharedAlbumController.value;
|
||||
// _serverStatusController
|
||||
ValueStream<ServerStatus?> get serverStatus => _serverStatusController.stream;
|
||||
Stream<ServerStatus?> get serverStatusNew => serverStatus.skip(1);
|
||||
Stream<ServerStatus?> get serverStatusChange =>
|
||||
serverStatus.distinct().skip(1);
|
||||
ServerStatus? get serverStatusValue => _serverStatusController.value;
|
||||
}
|
||||
|
|
|
@ -5,4 +5,13 @@ extension on AccountPref {
|
|||
provider.getBool(AccountPrefKey.hasNewSharedAlbum);
|
||||
// Future<bool> setNewSharedAlbum(bool value) =>
|
||||
// provider.setBool(AccountPrefKey.hasNewSharedAlbum, value);
|
||||
|
||||
String? getServerStatus() => provider.getString(AccountPrefKey.serverStatus);
|
||||
Future<bool> setServerStatus(String? value) {
|
||||
if (value == null) {
|
||||
return provider.remove(AccountPrefKey.serverStatus);
|
||||
} else {
|
||||
return provider.setString(AccountPrefKey.serverStatus, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ import 'dart:async';
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/api/entity_converter.dart';
|
||||
import 'package:nc_photos/controller/account_pref_controller.dart';
|
||||
import 'package:nc_photos/entity/server_status.dart';
|
||||
import 'package:nc_photos/np_api_util.dart';
|
||||
import 'package:np_api/np_api.dart' as api;
|
||||
|
@ -20,6 +21,7 @@ enum ServerFeature {
|
|||
class ServerController {
|
||||
ServerController({
|
||||
required this.account,
|
||||
required this.accountPrefController,
|
||||
});
|
||||
|
||||
void dispose() {
|
||||
|
@ -33,17 +35,6 @@ class ServerController {
|
|||
return _statusStreamContorller.stream;
|
||||
}
|
||||
|
||||
bool isSupported(ServerFeature feature) {
|
||||
switch (feature) {
|
||||
case ServerFeature.ncAlbum:
|
||||
return !_statusStreamContorller.hasValue ||
|
||||
_statusStreamContorller.value.majorVersion >= 25;
|
||||
case ServerFeature.ncMetadata:
|
||||
return !_statusStreamContorller.hasValue ||
|
||||
_statusStreamContorller.value.majorVersion >= 28;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _load() => _getStatus();
|
||||
|
||||
Future<void> _getStatus() async {
|
||||
|
@ -51,19 +42,49 @@ class ServerController {
|
|||
final response = await ApiUtil.fromAccount(account).status().get();
|
||||
if (!response.isGood) {
|
||||
_log.severe("[_getStatus] Failed requesting server: $response");
|
||||
_loadStatus();
|
||||
return;
|
||||
}
|
||||
final apiStatus = await api.StatusParser().parse(response.body);
|
||||
final status = ApiStatusConverter.fromApi(apiStatus);
|
||||
_log.info("[_getStatus] Server status: $status");
|
||||
_statusStreamContorller.add(status);
|
||||
_saveStatus(status);
|
||||
} catch (e, stackTrace) {
|
||||
_log.severe("[_getStatus] Failed while get", e, stackTrace);
|
||||
_loadStatus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void _loadStatus() {
|
||||
final cache = accountPrefController.serverStatusValue;
|
||||
if (cache != null) {
|
||||
_statusStreamContorller.add(cache);
|
||||
}
|
||||
}
|
||||
|
||||
void _saveStatus(ServerStatus status) {
|
||||
final cache = accountPrefController.serverStatusValue;
|
||||
if (cache != status) {
|
||||
accountPrefController.setServerStatus(status);
|
||||
}
|
||||
}
|
||||
|
||||
final Account account;
|
||||
final AccountPrefController accountPrefController;
|
||||
|
||||
final _statusStreamContorller = BehaviorSubject<ServerStatus>();
|
||||
}
|
||||
|
||||
extension ServerControllerExtension on ServerController {
|
||||
bool isSupported(ServerFeature feature) {
|
||||
final status = _statusStreamContorller.valueOrNull;
|
||||
switch (feature) {
|
||||
case ServerFeature.ncAlbum:
|
||||
return status == null || status.majorVersion >= 25;
|
||||
case ServerFeature.ncMetadata:
|
||||
return status != null && status.majorVersion >= 28;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -230,6 +230,7 @@ enum AccountPrefKey implements PrefKeyInterface {
|
|||
accountLabel,
|
||||
lastNewCollectionType,
|
||||
personProvider,
|
||||
serverStatus,
|
||||
;
|
||||
|
||||
@override
|
||||
|
@ -249,6 +250,8 @@ enum AccountPrefKey implements PrefKeyInterface {
|
|||
return "lastNewCollectionType";
|
||||
case AccountPrefKey.personProvider:
|
||||
return "personProvider";
|
||||
case AccountPrefKey.serverStatus:
|
||||
return "serverStatus";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import 'package:equatable/equatable.dart';
|
||||
import 'package:np_common/type.dart';
|
||||
import 'package:to_string/to_string.dart';
|
||||
|
||||
part 'server_status.g.dart';
|
||||
|
||||
@toString
|
||||
class ServerStatus {
|
||||
class ServerStatus with EquatableMixin {
|
||||
const ServerStatus({
|
||||
required this.versionRaw,
|
||||
required this.versionName,
|
||||
|
@ -13,6 +15,25 @@ class ServerStatus {
|
|||
@override
|
||||
String toString() => _$toString();
|
||||
|
||||
factory ServerStatus.fromJson(JsonObj json) {
|
||||
return ServerStatus(
|
||||
versionRaw: json["versionRaw"],
|
||||
versionName: json["versionName"],
|
||||
productName: json["productName"],
|
||||
);
|
||||
}
|
||||
|
||||
JsonObj toJson() {
|
||||
return {
|
||||
"versionRaw": versionRaw,
|
||||
"versionName": versionName,
|
||||
"productName": productName,
|
||||
};
|
||||
}
|
||||
|
||||
@override
|
||||
List<Object?> get props => [versionRaw, versionName, productName];
|
||||
|
||||
final String versionRaw;
|
||||
final String versionName;
|
||||
final String productName;
|
||||
|
|
|
@ -9,10 +9,10 @@ import 'package:kiwi/kiwi.dart';
|
|||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/app_init.dart' as app_init;
|
||||
import 'package:nc_photos/app_localizations.dart';
|
||||
import 'package:nc_photos/controller/account_pref_controller.dart';
|
||||
import 'package:nc_photos/controller/pref_controller.dart';
|
||||
import 'package:nc_photos/di_container.dart';
|
||||
import 'package:nc_photos/entity/file_descriptor.dart';
|
||||
import 'package:nc_photos/entity/pref.dart';
|
||||
import 'package:nc_photos/event/native_event.dart';
|
||||
import 'package:nc_photos/language_util.dart' as language_util;
|
||||
import 'package:nc_photos/use_case/battery_ensurer.dart';
|
||||
|
@ -95,13 +95,14 @@ class _Service {
|
|||
}
|
||||
|
||||
Future<void> _doWork() async {
|
||||
final prefController = PrefController(Pref());
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
final prefController = PrefController(c.pref);
|
||||
final account = prefController.currentAccountValue;
|
||||
if (account == null) {
|
||||
_log.shout("[_doWork] account == null");
|
||||
return;
|
||||
}
|
||||
final c = KiwiContainer().resolve<DiContainer>();
|
||||
final accountPrefController = AccountPrefController(account: account);
|
||||
|
||||
final wifiEnsurer = WifiEnsurer(
|
||||
interrupter: _shouldRun.stream,
|
||||
|
@ -143,7 +144,7 @@ class _Service {
|
|||
batteryEnsurer: batteryEnsurer,
|
||||
);
|
||||
final processedIds = <int>[];
|
||||
await for (final f in syncOp.syncAccount(account)) {
|
||||
await for (final f in syncOp.syncAccount(account, accountPrefController)) {
|
||||
processedIds.add(f.fdId);
|
||||
service.setNotificationInfo(
|
||||
title: _L10n.global().metadataTaskProcessingNotification,
|
||||
|
|
|
@ -2,6 +2,7 @@ import 'dart:async';
|
|||
|
||||
import 'package:logging/logging.dart';
|
||||
import 'package:nc_photos/account.dart';
|
||||
import 'package:nc_photos/controller/account_pref_controller.dart';
|
||||
import 'package:nc_photos/controller/server_controller.dart';
|
||||
import 'package:nc_photos/db/entity_converter.dart';
|
||||
import 'package:nc_photos/entity/exif_util.dart';
|
||||
|
@ -10,6 +11,7 @@ import 'package:nc_photos/entity/file/file_cache_manager.dart';
|
|||
import 'package:nc_photos/entity/file/repo.dart';
|
||||
import 'package:nc_photos/entity/file_util.dart' as file_util;
|
||||
import 'package:nc_photos/geocoder_util.dart';
|
||||
import 'package:nc_photos/service/service.dart';
|
||||
import 'package:nc_photos/use_case/battery_ensurer.dart';
|
||||
import 'package:nc_photos/use_case/get_file_binary.dart';
|
||||
import 'package:nc_photos/use_case/load_metadata.dart';
|
||||
|
@ -38,10 +40,14 @@ class SyncMetadata {
|
|||
required this.batteryEnsurer,
|
||||
});
|
||||
|
||||
Stream<File> syncAccount(Account account) async* {
|
||||
Stream<File> syncAccount(
|
||||
Account account,
|
||||
AccountPrefController accountPrefController,
|
||||
) async* {
|
||||
final bool isNcMetadataSupported;
|
||||
try {
|
||||
isNcMetadataSupported = await _isNcMetadataSupported(account);
|
||||
isNcMetadataSupported =
|
||||
(await _isNcMetadataSupported(account, accountPrefController))!;
|
||||
} catch (e) {
|
||||
_log.severe("[syncAccount] Failed to get server version", e);
|
||||
return;
|
||||
|
@ -111,8 +117,14 @@ class SyncMetadata {
|
|||
yield* stream;
|
||||
}
|
||||
|
||||
Future<bool> _isNcMetadataSupported(Account account) async {
|
||||
final serverController = ServerController(account: account);
|
||||
Future<bool?> _isNcMetadataSupported(
|
||||
Account account,
|
||||
AccountPrefController accountPrefController,
|
||||
) async {
|
||||
final serverController = ServerController(
|
||||
account: account,
|
||||
accountPrefController: accountPrefController,
|
||||
);
|
||||
await serverController.status.first.timeout(const Duration(seconds: 15));
|
||||
return serverController.isSupported(ServerFeature.ncMetadata);
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue