mirror of
https://gitlab.com/nkming2/nc-photos.git
synced 2025-03-22 23:19:21 +01:00
Don't try to query ncalbum when Nextcloud <25
This commit is contained in:
parent
499583d76f
commit
2b177d7679
16 changed files with 215 additions and 19 deletions
|
@ -7,6 +7,7 @@ import 'package:nc_photos/entity/file.dart';
|
||||||
import 'package:nc_photos/entity/nc_album.dart';
|
import 'package:nc_photos/entity/nc_album.dart';
|
||||||
import 'package:nc_photos/entity/nc_album_item.dart';
|
import 'package:nc_photos/entity/nc_album_item.dart';
|
||||||
import 'package:nc_photos/entity/person.dart';
|
import 'package:nc_photos/entity/person.dart';
|
||||||
|
import 'package:nc_photos/entity/server_status.dart';
|
||||||
import 'package:nc_photos/entity/share.dart';
|
import 'package:nc_photos/entity/share.dart';
|
||||||
import 'package:nc_photos/entity/sharee.dart';
|
import 'package:nc_photos/entity/sharee.dart';
|
||||||
import 'package:nc_photos/entity/tag.dart';
|
import 'package:nc_photos/entity/tag.dart';
|
||||||
|
@ -179,6 +180,16 @@ class ApiShareeConverter {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ApiStatusConverter {
|
||||||
|
static ServerStatus fromApi(api.Status status) {
|
||||||
|
return ServerStatus(
|
||||||
|
versionRaw: status.version,
|
||||||
|
versionName: status.versionString,
|
||||||
|
productName: status.productName,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class ApiTagConverter {
|
class ApiTagConverter {
|
||||||
static Tag fromApi(api.Tag tag) {
|
static Tag fromApi(api.Tag tag) {
|
||||||
return Tag(
|
return Tag(
|
||||||
|
|
|
@ -5,6 +5,7 @@ import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/controller/collections_controller.dart';
|
import 'package:nc_photos/controller/collections_controller.dart';
|
||||||
|
import 'package:nc_photos/controller/server_controller.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/collection.dart';
|
import 'package:nc_photos/entity/collection.dart';
|
||||||
import 'package:nc_photos/entity/person.dart';
|
import 'package:nc_photos/entity/person.dart';
|
||||||
|
@ -126,7 +127,8 @@ class HomeSearchSuggestionBlocFailure extends HomeSearchSuggestionBlocState {
|
||||||
@npLog
|
@npLog
|
||||||
class HomeSearchSuggestionBloc
|
class HomeSearchSuggestionBloc
|
||||||
extends Bloc<HomeSearchSuggestionBlocEvent, HomeSearchSuggestionBlocState> {
|
extends Bloc<HomeSearchSuggestionBlocEvent, HomeSearchSuggestionBlocState> {
|
||||||
HomeSearchSuggestionBloc(this.account, this.collectionsController)
|
HomeSearchSuggestionBloc(
|
||||||
|
this.account, this.collectionsController, this.serverController)
|
||||||
: super(const HomeSearchSuggestionBlocInit()) {
|
: super(const HomeSearchSuggestionBlocInit()) {
|
||||||
final c = KiwiContainer().resolve<DiContainer>();
|
final c = KiwiContainer().resolve<DiContainer>();
|
||||||
assert(require(c));
|
assert(require(c));
|
||||||
|
@ -194,7 +196,9 @@ class HomeSearchSuggestionBloc
|
||||||
.map((e) => e.collection)
|
.map((e) => e.collection)
|
||||||
.toList();
|
.toList();
|
||||||
if (collections.isEmpty) {
|
if (collections.isEmpty) {
|
||||||
collections = await ListCollection(_c)(account).last;
|
collections = await ListCollection(_c,
|
||||||
|
serverController: serverController)(account)
|
||||||
|
.last;
|
||||||
}
|
}
|
||||||
product.addAll(collections.map(_CollectionSearcheable.new));
|
product.addAll(collections.map(_CollectionSearcheable.new));
|
||||||
_log.info(
|
_log.info(
|
||||||
|
@ -247,6 +251,7 @@ class HomeSearchSuggestionBloc
|
||||||
|
|
||||||
final Account account;
|
final Account account;
|
||||||
final CollectionsController collectionsController;
|
final CollectionsController collectionsController;
|
||||||
|
final ServerController serverController;
|
||||||
late final DiContainer _c;
|
late final DiContainer _c;
|
||||||
|
|
||||||
final _search = Woozy<_Searcheable>(limit: 10);
|
final _search = Woozy<_Searcheable>(limit: 10);
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/controller/collections_controller.dart';
|
import 'package:nc_photos/controller/collections_controller.dart';
|
||||||
|
import 'package:nc_photos/controller/server_controller.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
|
|
||||||
class AccountController {
|
class AccountController {
|
||||||
|
@ -8,6 +9,7 @@ class AccountController {
|
||||||
_account = account;
|
_account = account;
|
||||||
_collectionsController?.dispose();
|
_collectionsController?.dispose();
|
||||||
_collectionsController = null;
|
_collectionsController = null;
|
||||||
|
_serverController = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
Account get account => _account!;
|
Account get account => _account!;
|
||||||
|
@ -16,8 +18,15 @@ class AccountController {
|
||||||
_collectionsController ??= CollectionsController(
|
_collectionsController ??= CollectionsController(
|
||||||
KiwiContainer().resolve<DiContainer>(),
|
KiwiContainer().resolve<DiContainer>(),
|
||||||
account: _account!,
|
account: _account!,
|
||||||
|
serverController: serverController,
|
||||||
|
);
|
||||||
|
|
||||||
|
ServerController get serverController =>
|
||||||
|
_serverController ??= ServerController(
|
||||||
|
account: _account!,
|
||||||
);
|
);
|
||||||
|
|
||||||
Account? _account;
|
Account? _account;
|
||||||
CollectionsController? _collectionsController;
|
CollectionsController? _collectionsController;
|
||||||
|
ServerController? _serverController;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,7 @@ import 'package:logging/logging.dart';
|
||||||
import 'package:mutex/mutex.dart';
|
import 'package:mutex/mutex.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/controller/collection_items_controller.dart';
|
import 'package:nc_photos/controller/collection_items_controller.dart';
|
||||||
|
import 'package:nc_photos/controller/server_controller.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/collection.dart';
|
import 'package:nc_photos/entity/collection.dart';
|
||||||
import 'package:nc_photos/entity/collection/util.dart';
|
import 'package:nc_photos/entity/collection/util.dart';
|
||||||
|
@ -64,6 +65,7 @@ class CollectionsController {
|
||||||
CollectionsController(
|
CollectionsController(
|
||||||
this._c, {
|
this._c, {
|
||||||
required this.account,
|
required this.account,
|
||||||
|
required this.serverController,
|
||||||
});
|
});
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
|
@ -264,7 +266,7 @@ class CollectionsController {
|
||||||
hasNext: false,
|
hasNext: false,
|
||||||
);
|
);
|
||||||
final completer = Completer();
|
final completer = Completer();
|
||||||
ListCollection(_c)(account).listen(
|
ListCollection(_c, serverController: serverController)(account).listen(
|
||||||
(c) {
|
(c) {
|
||||||
lastData = CollectionStreamEvent(
|
lastData = CollectionStreamEvent(
|
||||||
data: _prepareDataFor(c),
|
data: _prepareDataFor(c),
|
||||||
|
@ -325,6 +327,7 @@ class CollectionsController {
|
||||||
|
|
||||||
final DiContainer _c;
|
final DiContainer _c;
|
||||||
final Account account;
|
final Account account;
|
||||||
|
final ServerController serverController;
|
||||||
|
|
||||||
var _isDataStreamInited = false;
|
var _isDataStreamInited = false;
|
||||||
final _dataStreamController = BehaviorSubject.seeded(
|
final _dataStreamController = BehaviorSubject.seeded(
|
||||||
|
|
49
app/lib/controller/server_controller.dart
Normal file
49
app/lib/controller/server_controller.dart
Normal file
|
@ -0,0 +1,49 @@
|
||||||
|
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/entity/server_status.dart';
|
||||||
|
import 'package:nc_photos/np_api_util.dart';
|
||||||
|
import 'package:np_api/np_api.dart' as api;
|
||||||
|
import 'package:np_codegen/np_codegen.dart';
|
||||||
|
import 'package:rxdart/rxdart.dart';
|
||||||
|
|
||||||
|
part 'server_controller.g.dart';
|
||||||
|
|
||||||
|
@npLog
|
||||||
|
class ServerController {
|
||||||
|
ServerController({
|
||||||
|
required this.account,
|
||||||
|
});
|
||||||
|
|
||||||
|
ValueStream<ServerStatus> get status {
|
||||||
|
if (!_statusStreamContorller.hasValue) {
|
||||||
|
unawaited(_load());
|
||||||
|
}
|
||||||
|
return _statusStreamContorller.stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _load() => _getStatus();
|
||||||
|
|
||||||
|
Future<void> _getStatus() async {
|
||||||
|
try {
|
||||||
|
final response = await ApiUtil.fromAccount(account).status().get();
|
||||||
|
if (!response.isGood) {
|
||||||
|
_log.severe("[_getStatus] Failed requesting server: $response");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final apiStatus = await api.StatusParser().parse(response.body);
|
||||||
|
final status = ApiStatusConverter.fromApi(apiStatus);
|
||||||
|
_log.info("[_getStatus] Server status: $status");
|
||||||
|
_statusStreamContorller.add(status);
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
_log.severe("[_getStatus] Failed while get", e, stackTrace);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
final Account account;
|
||||||
|
|
||||||
|
final _statusStreamContorller = BehaviorSubject<ServerStatus>();
|
||||||
|
}
|
14
app/lib/controller/server_controller.g.dart
Normal file
14
app/lib/controller/server_controller.g.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'server_controller.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// NpLogGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
extension _$ServerControllerNpLog on ServerController {
|
||||||
|
// ignore: unused_element
|
||||||
|
Logger get _log => log;
|
||||||
|
|
||||||
|
static final log = Logger("controller.server_controller.ServerController");
|
||||||
|
}
|
24
app/lib/entity/server_status.dart
Normal file
24
app/lib/entity/server_status.dart
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
import 'package:to_string/to_string.dart';
|
||||||
|
|
||||||
|
part 'server_status.g.dart';
|
||||||
|
|
||||||
|
@toString
|
||||||
|
class ServerStatus {
|
||||||
|
const ServerStatus({
|
||||||
|
required this.versionRaw,
|
||||||
|
required this.versionName,
|
||||||
|
required this.productName,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() => _$toString();
|
||||||
|
|
||||||
|
final String versionRaw;
|
||||||
|
final String versionName;
|
||||||
|
final String productName;
|
||||||
|
}
|
||||||
|
|
||||||
|
extension ServerStatusExtension on ServerStatus {
|
||||||
|
List<int> get versionNumber => versionRaw.split(".").map(int.parse).toList();
|
||||||
|
int get majorVersion => versionNumber[0];
|
||||||
|
}
|
14
app/lib/entity/server_status.g.dart
Normal file
14
app/lib/entity/server_status.g.dart
Normal file
|
@ -0,0 +1,14 @@
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'server_status.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// ToStringGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
extension _$ServerStatusToString on ServerStatus {
|
||||||
|
String _$toString() {
|
||||||
|
// ignore: unnecessary_string_interpolations
|
||||||
|
return "ServerStatus {versionRaw: $versionRaw, versionName: $versionName, productName: $productName}";
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,16 +1,21 @@
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
|
import 'package:nc_photos/controller/server_controller.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/collection.dart';
|
import 'package:nc_photos/entity/collection.dart';
|
||||||
import 'package:nc_photos/entity/collection/builder.dart';
|
import 'package:nc_photos/entity/collection/builder.dart';
|
||||||
import 'package:nc_photos/entity/nc_album.dart';
|
import 'package:nc_photos/entity/nc_album.dart';
|
||||||
|
import 'package:nc_photos/entity/server_status.dart';
|
||||||
import 'package:nc_photos/use_case/album/list_album2.dart';
|
import 'package:nc_photos/use_case/album/list_album2.dart';
|
||||||
import 'package:nc_photos/use_case/nc_album/list_nc_album.dart';
|
import 'package:nc_photos/use_case/nc_album/list_nc_album.dart';
|
||||||
|
|
||||||
class ListCollection {
|
class ListCollection {
|
||||||
ListCollection(this._c) : assert(require(_c));
|
ListCollection(
|
||||||
|
this._c, {
|
||||||
|
required this.serverController,
|
||||||
|
}) : assert(require(_c));
|
||||||
|
|
||||||
static bool require(DiContainer c) =>
|
static bool require(DiContainer c) =>
|
||||||
DiContainer.has(c, DiType.albumRepo2) &&
|
DiContainer.has(c, DiType.albumRepo2) &&
|
||||||
|
@ -51,6 +56,10 @@ class ListCollection {
|
||||||
onDone();
|
onDone();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
if (serverController.status.hasValue &&
|
||||||
|
serverController.status.value.majorVersion < 25) {
|
||||||
|
isNcAlbumDone = true;
|
||||||
|
} else {
|
||||||
ListNcAlbum(_c)(account).listen(
|
ListNcAlbum(_c)(account).listen(
|
||||||
(event) {
|
(event) {
|
||||||
ncAlbums = event;
|
ncAlbums = event;
|
||||||
|
@ -66,8 +75,10 @@ class ListCollection {
|
||||||
onDone();
|
onDone();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
}
|
||||||
return controller.stream;
|
return controller.stream;
|
||||||
}
|
}
|
||||||
|
|
||||||
final DiContainer _c;
|
final DiContainer _c;
|
||||||
|
final ServerController serverController;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,9 +1,13 @@
|
||||||
|
import 'dart:async';
|
||||||
|
|
||||||
import 'package:event_bus/event_bus.dart';
|
import 'package:event_bus/event_bus.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
||||||
import 'package:kiwi/kiwi.dart';
|
import 'package:kiwi/kiwi.dart';
|
||||||
import 'package:logging/logging.dart';
|
import 'package:logging/logging.dart';
|
||||||
import 'package:nc_photos/account.dart';
|
import 'package:nc_photos/account.dart';
|
||||||
import 'package:nc_photos/app_localizations.dart';
|
import 'package:nc_photos/app_localizations.dart';
|
||||||
|
import 'package:nc_photos/controller/account_controller.dart';
|
||||||
import 'package:nc_photos/di_container.dart';
|
import 'package:nc_photos/di_container.dart';
|
||||||
import 'package:nc_photos/entity/album.dart';
|
import 'package:nc_photos/entity/album.dart';
|
||||||
import 'package:nc_photos/entity/album/data_source.dart';
|
import 'package:nc_photos/entity/album/data_source.dart';
|
||||||
|
@ -64,6 +68,16 @@ class _HomeState extends State<Home> with TickerProviderStateMixin {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
_animationController.value = 1;
|
_animationController.value = 1;
|
||||||
|
|
||||||
|
// call once to pre-cache the value
|
||||||
|
unawaited(context
|
||||||
|
.read<AccountController>()
|
||||||
|
.serverController
|
||||||
|
.status
|
||||||
|
.first
|
||||||
|
.then((value) {
|
||||||
|
_log.info("Server status: $value");
|
||||||
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
|
@ -79,6 +79,7 @@ class _HomeSearchSuggestionState extends State<HomeSearchSuggestion>
|
||||||
_bloc = (widget.controller._bloc ??= HomeSearchSuggestionBloc(
|
_bloc = (widget.controller._bloc ??= HomeSearchSuggestionBloc(
|
||||||
widget.account,
|
widget.account,
|
||||||
context.read<AccountController>().collectionsController,
|
context.read<AccountController>().collectionsController,
|
||||||
|
context.read<AccountController>().serverController,
|
||||||
));
|
));
|
||||||
if (_bloc.state is! HomeSearchSuggestionBlocInit) {
|
if (_bloc.state is! HomeSearchSuggestionBlocInit) {
|
||||||
// process the current state
|
// process the current state
|
||||||
|
|
|
@ -8,6 +8,7 @@ export 'src/entity/nc_album_parser.dart';
|
||||||
export 'src/entity/person_parser.dart';
|
export 'src/entity/person_parser.dart';
|
||||||
export 'src/entity/share_parser.dart';
|
export 'src/entity/share_parser.dart';
|
||||||
export 'src/entity/sharee_parser.dart';
|
export 'src/entity/sharee_parser.dart';
|
||||||
|
export 'src/entity/status_parser.dart';
|
||||||
export 'src/entity/tag_parser.dart';
|
export 'src/entity/tag_parser.dart';
|
||||||
export 'src/entity/tagged_file_parser.dart';
|
export 'src/entity/tagged_file_parser.dart';
|
||||||
export 'src/type.dart';
|
export 'src/type.dart';
|
||||||
|
|
|
@ -27,6 +27,8 @@ class Api {
|
||||||
|
|
||||||
ApiPhotos photos(String userId) => ApiPhotos(this, userId);
|
ApiPhotos photos(String userId) => ApiPhotos(this, userId);
|
||||||
|
|
||||||
|
ApiStatus status() => ApiStatus(this);
|
||||||
|
|
||||||
ApiSystemtags systemtags() => ApiSystemtags(this);
|
ApiSystemtags systemtags() => ApiSystemtags(this);
|
||||||
|
|
||||||
ApiSystemtagsRelations systemtagsRelations() => ApiSystemtagsRelations(this);
|
ApiSystemtagsRelations systemtagsRelations() => ApiSystemtagsRelations(this);
|
||||||
|
|
|
@ -299,6 +299,7 @@ class Status with EquatableMixin {
|
||||||
const Status({
|
const Status({
|
||||||
required this.version,
|
required this.version,
|
||||||
required this.versionString,
|
required this.versionString,
|
||||||
|
required this.productName,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -308,10 +309,12 @@ class Status with EquatableMixin {
|
||||||
List<Object?> get props => [
|
List<Object?> get props => [
|
||||||
version,
|
version,
|
||||||
versionString,
|
versionString,
|
||||||
|
productName,
|
||||||
];
|
];
|
||||||
|
|
||||||
final String version;
|
final String version;
|
||||||
final String versionString;
|
final String versionString;
|
||||||
|
final String productName;
|
||||||
}
|
}
|
||||||
|
|
||||||
@toString
|
@toString
|
||||||
|
|
|
@ -13,6 +13,7 @@ class StatusParser {
|
||||||
return Status(
|
return Status(
|
||||||
version: json["version"],
|
version: json["version"],
|
||||||
versionString: json["versionstring"],
|
versionString: json["versionstring"],
|
||||||
|
productName: json["productname"],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
34
np_api/test/entity/status_parser_test.dart
Normal file
34
np_api/test/entity/status_parser_test.dart
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
import 'package:np_api/np_api.dart';
|
||||||
|
import 'package:test/test.dart';
|
||||||
|
|
||||||
|
void main() {
|
||||||
|
group("StatusParser", () {
|
||||||
|
group("parse", () {
|
||||||
|
test("Nextcloud 25", _nextcloud25);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _nextcloud25() async {
|
||||||
|
const json = """
|
||||||
|
{
|
||||||
|
"installed": true,
|
||||||
|
"maintenance": false,
|
||||||
|
"needsDbUpgrade": false,
|
||||||
|
"version": "25.0.2.3",
|
||||||
|
"versionstring": "25.0.2",
|
||||||
|
"edition": "",
|
||||||
|
"productname": "Nextcloud",
|
||||||
|
"extendedSupport": false
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
final results = await StatusParser().parse(json);
|
||||||
|
expect(
|
||||||
|
results,
|
||||||
|
const Status(
|
||||||
|
version: "25.0.2.3",
|
||||||
|
versionString: "25.0.2",
|
||||||
|
productName: "Nextcloud",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
Loading…
Reference in a new issue