diff --git a/packages/neon/integration_test/screenshot_test.dart b/packages/neon/integration_test/screenshot_test.dart index 0b2f8776..d5050324 100644 --- a/packages/neon/integration_test/screenshot_test.dart +++ b/packages/neon/integration_test/screenshot_test.dart @@ -307,10 +307,10 @@ Future main() async { const wikipediaFeedURL = 'https://en.wikipedia.org/w/api.php?action=featuredfeed&feed=featured&feedformat=atom'; const nasaFeedURL = 'https://www.nasa.gov/rss/dyn/breaking_news.rss'; - final folder = await account.client.news.createFolder('test'); + final folder = await account.client.news.createFolder(name: 'test'); await account.client.news.addFeed( - nasaFeedURL, - folderId: folder!.folders.single.id, + url: nasaFeedURL, + folderId: folder.folders!.single.id, ); await pumpAppPage( @@ -449,8 +449,8 @@ Future main() async { testWidgets('notifications', (final tester) async { await account.client.notifications.sendAdminNotification( - account.username, - 'Notifications demo', + userId: account.username, + shortMessage: 'Notifications demo', longMessage: 'This is a notifications demo of the Neon app', ); diff --git a/packages/neon/lib/app.dart b/packages/neon/lib/app.dart index 1546d2be..4e2fcdca 100644 --- a/packages/neon/lib/app.dart +++ b/packages/neon/lib/app.dart @@ -4,8 +4,8 @@ import 'package:flutter/material.dart'; import 'package:flutter_native_splash/flutter_native_splash.dart'; import 'package:neon/l10n/localizations.dart'; import 'package:neon/src/blocs/accounts.dart'; -import 'package:neon/src/blocs/capabilities.dart'; import 'package:neon/src/neon.dart'; +import 'package:nextcloud/nextcloud.dart'; import 'package:rxdart/rxdart.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -32,7 +32,7 @@ class NeonApp extends StatefulWidget { // ignore: prefer_mixin class _NeonAppState extends State with WidgetsBindingObserver { final _navigatorKey = GlobalKey(); - NextcloudTheme? _userTheme; + CoreServerCapabilitiesOcsDataCapabilitiesTheming? _userTheme; final _platformBrightness = BehaviorSubject.seeded( WidgetsBinding.instance.window.platformBrightness, ); diff --git a/packages/neon/lib/src/apps/files/widgets/file_preview.dart b/packages/neon/lib/src/apps/files/widgets/file_preview.dart index f3712073..be74267a 100644 --- a/packages/neon/lib/src/apps/files/widgets/file_preview.dart +++ b/packages/neon/lib/src/apps/files/widgets/file_preview.dart @@ -46,11 +46,11 @@ class FilePreview extends StatelessWidget { final stream = Provider.of(context).wrapBytes( account.client.id, 'files-preview-${details.etag}-$width-$height', - () async => (await account.client.core.getPreviewBytes( - details.path.join('/'), - width: width, - height: height, - ))!, + () async => account.client.core.getPreview( + file: details.path.join('/'), + x: width, + y: height, + ), preferCache: true, ); diff --git a/packages/neon/lib/src/apps/news/blocs/articles.dart b/packages/neon/lib/src/apps/news/blocs/articles.dart index 3fbde7d5..02953555 100644 --- a/packages/neon/lib/src/apps/news/blocs/articles.dart +++ b/packages/neon/lib/src/apps/news/blocs/articles.dart @@ -70,29 +70,39 @@ class NewsArticlesBloc extends $NewsArticlesBloc { _$markArticleAsReadEvent.listen((final article) { _wrapArticleAction((final client) async { - await client.news.markArticleAsRead(article.id!); - _articleUpdateController.add(article..unread = false); + await client.news.markArticleAsRead(itemId: article.id!); + // TODO + //_articleUpdateController.add(article..unread = false); }); }); _$markArticleAsUnreadEvent.listen((final article) { _wrapArticleAction((final client) async { - await client.news.markArticleAsUnread(article.id!); - _articleUpdateController.add(article..unread = true); + await client.news.markArticleAsUnread(itemId: article.id!); + // TODO + //_articleUpdateController.add(article..unread = true); }); }); _$starArticleEvent.listen((final article) { _wrapArticleAction((final client) async { - await client.news.starArticle(article.feedId!, article.guidHash!); - _articleUpdateController.add(article..starred = true); + await client.news.starArticle( + feedId: article.feedId!, + guidHash: article.guidHash!, + ); + // TODO + //_articleUpdateController.add(article..starred = true); }); }); _$unstarArticleEvent.listen((final article) { _wrapArticleAction((final client) async { - await client.news.unstarArticle(article.feedId!, article.guidHash!); - _articleUpdateController.add(article..starred = false); + await client.news.unstarArticle( + feedId: article.feedId!, + guidHash: article.guidHash!, + ); + // TODO + //_articleUpdateController.add(article..starred = false); }); }); @@ -149,16 +159,15 @@ class NewsArticlesBloc extends $NewsArticlesBloc { } newsBloc.requestManager - .wrapNextcloud, NewsListArticles, void, NextcloudNewsClient>( + .wrapNextcloud, NewsListArticles>( newsBloc.client.id, - newsBloc.client.news, 'news-articles-$type-$id-$getRead', - () async => (await newsBloc.client.news.listArticles( + () async => newsBloc.client.news.listArticles( type: type, - id: id, - getRead: getRead, - ))!, - (final response) => response.items, + id: id ?? 0, + getRead: getRead ?? true ? 1 : 0, + ), + (final response) => response.items!, previousData: _articlesSubject.valueOrNull?.data, ) .listen(_articlesSubject.add); diff --git a/packages/neon/lib/src/apps/news/blocs/news.dart b/packages/neon/lib/src/apps/news/blocs/news.dart index b7784a89..65ff0a9b 100644 --- a/packages/neon/lib/src/apps/news/blocs/news.dart +++ b/packages/neon/lib/src/apps/news/blocs/news.dart @@ -13,23 +13,23 @@ part 'news.rxb.g.dart'; abstract class NewsBlocEvents { void refresh({required final bool mainArticlesToo}); - void addFeed(final String url, final int? folderID); + void addFeed(final String url, final int? folderId); - void removeFeed(final int feedID); + void removeFeed(final int feedId); - void renameFeed(final int feedID, final String name); + void renameFeed(final int feedId, final String feedTitle); - void moveFeed(final int feedID, final int? folderID); + void moveFeed(final int feedId, final int? folderId); - void markFeedAsRead(final int feedID); + void markFeedAsRead(final int feedId); void createFolder(final String name); - void deleteFolder(final int folderID); + void deleteFolder(final int folderId); - void renameFolder(final int folderID, final String name); + void renameFolder(final int folderId, final String name); - void markFolderAsRead(final int folderID); + void markFolderAsRead(final int folderId); } abstract class NewsBlocStates { @@ -54,21 +54,21 @@ class NewsBloc extends $NewsBloc { _$addFeedEvent.listen((final event) { _wrapFeedAction( (final client) async => client.news.addFeed( - event.url, - folderId: event.folderID, + url: event.url, + folderId: event.folderId, ), ); }); - _$removeFeedEvent.listen((final feedID) { - _wrapFeedAction((final client) async => client.news.deleteFeed(feedID)); + _$removeFeedEvent.listen((final feedId) { + _wrapFeedAction((final client) async => client.news.deleteFeed(feedId: feedId)); }); _$renameFeedEvent.listen((final event) { _wrapFeedAction( (final client) async => client.news.renameFeed( - event.feedID, - event.name, + feedId: event.feedId, + feedTitle: event.feedTitle, ), ); }); @@ -77,8 +77,8 @@ class NewsBloc extends $NewsBloc { final stream = requestManager .wrapWithoutCache( () async => client.news.moveFeed( - event.feedID, - folderId: event.folderID, + feedId: event.feedId, + folderId: event.folderId, ), ) .asBroadcastStream(); @@ -89,12 +89,12 @@ class NewsBloc extends $NewsBloc { }); }); - _$markFeedAsReadEvent.listen((final feedID) { + _$markFeedAsReadEvent.listen((final feedId) { final stream = requestManager .wrapWithoutCache( () async => client.news.markFeedAsRead( - feedID, - _newestItemId, + feedId: feedId, + newestItemId: _newestItemId, ), ) .asBroadcastStream(); @@ -105,28 +105,28 @@ class NewsBloc extends $NewsBloc { }); _$createFolderEvent.listen((final name) { - _wrapFolderAction((final client) async => client.news.createFolder(name)); + _wrapFolderAction((final client) async => client.news.createFolder(name: name)); }); - _$deleteFolderEvent.listen((final folderID) { - _wrapFolderAction((final client) async => client.news.deleteFolder(folderID)); + _$deleteFolderEvent.listen((final folderId) { + _wrapFolderAction((final client) async => client.news.deleteFolder(folderId: folderId)); }); _$renameFolderEvent.listen((final event) { _wrapFolderAction( (final client) async => client.news.renameFolder( - event.folderID, - event.name, + folderId: event.folderId, + name: event.name, ), ); }); - _$markFolderAsReadEvent.listen((final folderID) { + _$markFolderAsReadEvent.listen((final folderId) { final stream = requestManager .wrapWithoutCache( () async => client.news.markFolderAsRead( - folderID, - _newestItemId, + folderId: folderId, + newestItemId: _newestItemId, ), ) .asBroadcastStream(); @@ -182,29 +182,27 @@ class NewsBloc extends $NewsBloc { void _loadFolders() { requestManager - .wrapNextcloud, NewsListFolders, void, NextcloudNewsClient>( + .wrapNextcloud, NewsListFolders>( client.id, - client.news, 'news-folders', - () async => (await client.news.listFolders())!, - (final response) => response.folders, + () async => client.news.listFolders(), + (final response) => response.folders!, previousData: _foldersSubject.valueOrNull?.data, ) .listen(_foldersSubject.add); } void _loadFeeds() { - requestManager.wrapNextcloud, NewsListFeeds, void, NextcloudNewsClient>( + requestManager.wrapNextcloud, NewsListFeeds>( client.id, - client.news, 'news-feeds', - () async => (await client.news.listFeeds())!, + () async => client.news.listFeeds(), (final response) { // This is a bit ugly, but IDGAF right now if (response.newestItemId != null) { _newestItemId = response.newestItemId!; } - return response.feeds; + return response.feeds!; }, previousData: _feedsSubject.valueOrNull?.data, ).listen(_feedsSubject.add); diff --git a/packages/neon/lib/src/apps/news/blocs/news.rxb.g.dart b/packages/neon/lib/src/apps/news/blocs/news.rxb.g.dart index e9b3694a..f7ef4769 100644 --- a/packages/neon/lib/src/apps/news/blocs/news.rxb.g.dart +++ b/packages/neon/lib/src/apps/news/blocs/news.rxb.g.dart @@ -64,31 +64,31 @@ abstract class $NewsBloc extends RxBlocBase implements NewsBlocEvents, NewsBlocS void refresh({required bool mainArticlesToo}) => _$refreshEvent.add(mainArticlesToo); @override - void addFeed(String url, int? folderID) => _$addFeedEvent.add(_AddFeedEventArgs(url, folderID)); + void addFeed(String url, int? folderId) => _$addFeedEvent.add(_AddFeedEventArgs(url, folderId)); @override - void removeFeed(int feedID) => _$removeFeedEvent.add(feedID); + void removeFeed(int feedId) => _$removeFeedEvent.add(feedId); @override - void renameFeed(int feedID, String name) => _$renameFeedEvent.add(_RenameFeedEventArgs(feedID, name)); + void renameFeed(int feedId, String feedTitle) => _$renameFeedEvent.add(_RenameFeedEventArgs(feedId, feedTitle)); @override - void moveFeed(int feedID, int? folderID) => _$moveFeedEvent.add(_MoveFeedEventArgs(feedID, folderID)); + void moveFeed(int feedId, int? folderId) => _$moveFeedEvent.add(_MoveFeedEventArgs(feedId, folderId)); @override - void markFeedAsRead(int feedID) => _$markFeedAsReadEvent.add(feedID); + void markFeedAsRead(int feedId) => _$markFeedAsReadEvent.add(feedId); @override void createFolder(String name) => _$createFolderEvent.add(name); @override - void deleteFolder(int folderID) => _$deleteFolderEvent.add(folderID); + void deleteFolder(int folderId) => _$deleteFolderEvent.add(folderId); @override - void renameFolder(int folderID, String name) => _$renameFolderEvent.add(_RenameFolderEventArgs(folderID, name)); + void renameFolder(int folderId, String name) => _$renameFolderEvent.add(_RenameFolderEventArgs(folderId, name)); @override - void markFolderAsRead(int folderID) => _$markFolderAsReadEvent.add(folderID); + void markFolderAsRead(int folderId) => _$markFolderAsReadEvent.add(folderId); @override BehaviorSubject>> get folders => _foldersState; @@ -136,39 +136,39 @@ abstract class $NewsBloc extends RxBlocBase implements NewsBlocEvents, NewsBlocS /// Helps providing the arguments in the [Subject.add] for /// [NewsBlocEvents.addFeed] event class _AddFeedEventArgs { - const _AddFeedEventArgs(this.url, this.folderID); + const _AddFeedEventArgs(this.url, this.folderId); final String url; - final int? folderID; + final int? folderId; } /// Helps providing the arguments in the [Subject.add] for /// [NewsBlocEvents.renameFeed] event class _RenameFeedEventArgs { - const _RenameFeedEventArgs(this.feedID, this.name); + const _RenameFeedEventArgs(this.feedId, this.feedTitle); - final int feedID; + final int feedId; - final String name; + final String feedTitle; } /// Helps providing the arguments in the [Subject.add] for /// [NewsBlocEvents.moveFeed] event class _MoveFeedEventArgs { - const _MoveFeedEventArgs(this.feedID, this.folderID); + const _MoveFeedEventArgs(this.feedId, this.folderId); - final int feedID; + final int feedId; - final int? folderID; + final int? folderId; } /// Helps providing the arguments in the [Subject.add] for /// [NewsBlocEvents.renameFolder] event class _RenameFolderEventArgs { - const _RenameFolderEventArgs(this.folderID, this.name); + const _RenameFolderEventArgs(this.folderId, this.name); - final int folderID; + final int folderId; final String name; } diff --git a/packages/neon/lib/src/apps/notes/blocs/notes.dart b/packages/neon/lib/src/apps/notes/blocs/notes.dart index 1822a562..d12071bc 100644 --- a/packages/neon/lib/src/apps/notes/blocs/notes.dart +++ b/packages/neon/lib/src/apps/notes/blocs/notes.dart @@ -13,8 +13,8 @@ abstract class NotesBlocEvents { void refresh(); void createNote({ - final String? title, - final String? category, + final String title = '', + final String category = '', }); void updateNote( @@ -58,20 +58,20 @@ class NotesBloc extends $NotesBloc { _$updateNoteEvent.listen((final event) { _wrapAction( () async => _noteUpdateController.add( - (await client.notes.updateNote( - event.id, + await client.notes.updateNote( + id: event.id, title: event.title, category: event.category, content: event.content, - favorite: event.favorite, + favorite: event.favorite ?? false ? 1 : 0, ifMatch: '"${event.etag}"', - ))!, + ), ), ); }); _$deleteNoteEvent.listen((final id) { - _wrapAction(() async => client.notes.deleteNote(id)); + _wrapAction(() async => client.notes.deleteNote(id: id)); }); _loadNotes(); @@ -87,11 +87,10 @@ class NotesBloc extends $NotesBloc { void _loadNotes() { requestManager - .wrapNextcloud, List, NotesNote, NextcloudNotesClient>( + .wrapNextcloud, List>( client.id, - client.notes, 'notes-notes', - () async => (await client.notes.getNotes())!, + () async => client.notes.getNotes(), (final response) => response, previousData: _notesSubject.valueOrNull?.data, ) diff --git a/packages/neon/lib/src/apps/notes/blocs/notes.rxb.g.dart b/packages/neon/lib/src/apps/notes/blocs/notes.rxb.g.dart index 41575414..83e8a5f4 100644 --- a/packages/neon/lib/src/apps/notes/blocs/notes.rxb.g.dart +++ b/packages/neon/lib/src/apps/notes/blocs/notes.rxb.g.dart @@ -43,7 +43,7 @@ abstract class $NotesBloc extends RxBlocBase implements NotesBlocEvents, NotesBl void refresh() => _$refreshEvent.add(null); @override - void createNote({String? title, String? category}) => + void createNote({String title = '', String category = ''}) => _$createNoteEvent.add(_CreateNoteEventArgs(title: title, category: category)); @override @@ -89,11 +89,11 @@ abstract class $NotesBloc extends RxBlocBase implements NotesBlocEvents, NotesBl /// Helps providing the arguments in the [Subject.add] for /// [NotesBlocEvents.createNote] event class _CreateNoteEventArgs { - const _CreateNoteEventArgs({this.title, this.category}); + const _CreateNoteEventArgs({this.title = '', this.category = ''}); - final String? title; + final String title; - final String? category; + final String category; } /// Helps providing the arguments in the [Subject.add] for diff --git a/packages/neon/lib/src/apps/notes/utils/exception_handler.dart b/packages/neon/lib/src/apps/notes/utils/exception_handler.dart index b0103844..f9faf7b1 100644 --- a/packages/neon/lib/src/apps/notes/utils/exception_handler.dart +++ b/packages/neon/lib/src/apps/notes/utils/exception_handler.dart @@ -1,7 +1,7 @@ part of '../app.dart'; void handleNotesException(final BuildContext context, final Exception error) { - if (error is ApiException && error.code == 412) { + if (error is ApiException && error.statusCode == 412) { ExceptionWidget.showSnackbar(context, AppLocalizations.of(context).notesNoteChangedOnServer); } else { ExceptionWidget.showSnackbar(context, error); diff --git a/packages/neon/lib/src/apps/notes/widgets/notes_view.dart b/packages/neon/lib/src/apps/notes/widgets/notes_view.dart index 83c37554..46640ed3 100644 --- a/packages/neon/lib/src/apps/notes/widgets/notes_view.dart +++ b/packages/neon/lib/src/apps/notes/widgets/notes_view.dart @@ -35,7 +35,7 @@ class NotesView extends StatelessWidget { if (result != null) { bloc.createNote( title: result[0] as String, - category: result[1] as String?, + category: result[1] as String? ?? '', ); } }, diff --git a/packages/neon/lib/src/apps/notifications/blocs/notifications.dart b/packages/neon/lib/src/apps/notifications/blocs/notifications.dart index 74b78465..12c19d34 100644 --- a/packages/neon/lib/src/apps/notifications/blocs/notifications.dart +++ b/packages/neon/lib/src/apps/notifications/blocs/notifications.dart @@ -12,7 +12,7 @@ part 'notifications.rxb.g.dart'; abstract class NotificationsBlocEvents { void refresh(); - void deleteNotification(final NotificationsNotification notification); + void deleteNotification(final int id); void deleteAllNotifications(); } @@ -34,8 +34,8 @@ class NotificationsBloc extends $NotificationsBloc { ) { _$refreshEvent.listen((final _) => _loadNotifications()); - _$deleteNotificationEvent.listen((final notification) { - _wrapAction(() async => client.notifications.deleteNotification(notification.notificationId!)); + _$deleteNotificationEvent.listen((final id) { + _wrapAction(() async => client.notifications.deleteNotification(id: id)); }); _$deleteAllNotificationsEvent.listen((final notification) { @@ -61,13 +61,11 @@ class NotificationsBloc extends $NotificationsBloc { void _loadNotifications() { requestManager - .wrapNextcloud, NotificationsListNotifications, NotificationsNotification, - NextcloudNotificationsClient>( + .wrapNextcloud, NotificationsListNotifications>( client.id, - client.notifications, 'notifications-notifications', - () async => (await client.notifications.listNotifications())!, - (final response) => response.ocs!.data, + () async => client.notifications.listNotifications(), + (final response) => response.ocs!.data!, previousData: _notificationsSubject.valueOrNull?.data, ) .listen(_notificationsSubject.add); diff --git a/packages/neon/lib/src/apps/notifications/blocs/notifications.rxb.g.dart b/packages/neon/lib/src/apps/notifications/blocs/notifications.rxb.g.dart index b8750028..7956ea22 100644 --- a/packages/neon/lib/src/apps/notifications/blocs/notifications.rxb.g.dart +++ b/packages/neon/lib/src/apps/notifications/blocs/notifications.rxb.g.dart @@ -23,7 +23,7 @@ abstract class $NotificationsBloc extends RxBlocBase final _$refreshEvent = PublishSubject(); /// Тhe [Subject] where events sink to by calling [deleteNotification] - final _$deleteNotificationEvent = PublishSubject(); + final _$deleteNotificationEvent = PublishSubject(); /// Тhe [Subject] where events sink to by calling [deleteAllNotifications] final _$deleteAllNotificationsEvent = PublishSubject(); @@ -41,7 +41,7 @@ abstract class $NotificationsBloc extends RxBlocBase void refresh() => _$refreshEvent.add(null); @override - void deleteNotification(NotificationsNotification notification) => _$deleteNotificationEvent.add(notification); + void deleteNotification(int id) => _$deleteNotificationEvent.add(id); @override void deleteAllNotifications() => _$deleteAllNotificationsEvent.add(null); diff --git a/packages/neon/lib/src/apps/notifications/pages/main.dart b/packages/neon/lib/src/apps/notifications/pages/main.dart index 9c94278a..a83ca729 100644 --- a/packages/neon/lib/src/apps/notifications/pages/main.dart +++ b/packages/neon/lib/src/apps/notifications/pages/main.dart @@ -144,7 +144,7 @@ class _NotificationsMainPageState extends State { } }, onLongPress: () { - widget.bloc.deleteNotification(notification); + widget.bloc.deleteNotification(notification.notificationId!); }, ); } diff --git a/packages/neon/lib/src/blocs/apps.dart b/packages/neon/lib/src/blocs/apps.dart index 612adfd9..d5f0173d 100644 --- a/packages/neon/lib/src/blocs/apps.dart +++ b/packages/neon/lib/src/blocs/apps.dart @@ -10,7 +10,7 @@ import 'package:rxdart/rxdart.dart'; part 'apps.rxb.g.dart'; -typedef NextcloudApp = CoreNavigationAppsOcsDataInner; +typedef NextcloudApp = CoreNavigationAppsOcsData; abstract class AppsBlocEvents { void refresh(); @@ -99,12 +99,11 @@ class AppsBloc extends $AppsBloc { void _loadApps() { _requestManager - .wrapNextcloud, CoreNavigationApps, void, NextcloudCoreClient>( + .wrapNextcloud, CoreNavigationApps>( _account.client.id, - _account.client.core, 'apps-apps', - () async => (await _account.client.core.getNavigationApps())!, - (final response) => response.ocs!.data, + () async => _account.client.core.getNavigationApps(), + (final response) => response.ocs!.data!, preloadCache: true, ) .listen(_appsSubject.add); diff --git a/packages/neon/lib/src/blocs/apps.rxb.g.dart b/packages/neon/lib/src/blocs/apps.rxb.g.dart index f269ec91..7a50d934 100644 --- a/packages/neon/lib/src/blocs/apps.rxb.g.dart +++ b/packages/neon/lib/src/blocs/apps.rxb.g.dart @@ -25,7 +25,7 @@ abstract class $AppsBloc extends RxBlocBase implements AppsBlocEvents, AppsBlocS final _$setActiveAppEvent = PublishSubject(); /// The state of [apps] implemented in [_mapToAppsState] - late final BehaviorSubject>> _appsState = _mapToAppsState(); + late final BehaviorSubject>> _appsState = _mapToAppsState(); /// The state of [appImplementations] implemented in /// [_mapToAppImplementationsState] @@ -42,7 +42,7 @@ abstract class $AppsBloc extends RxBlocBase implements AppsBlocEvents, AppsBlocS void setActiveApp(String? appID) => _$setActiveAppEvent.add(appID); @override - BehaviorSubject>> get apps => _appsState; + BehaviorSubject>> get apps => _appsState; @override BehaviorSubject>>> get appImplementations => @@ -51,7 +51,7 @@ abstract class $AppsBloc extends RxBlocBase implements AppsBlocEvents, AppsBlocS @override BehaviorSubject get activeAppID => _activeAppIDState; - BehaviorSubject>> _mapToAppsState(); + BehaviorSubject>> _mapToAppsState(); BehaviorSubject>>> _mapToAppImplementationsState(); diff --git a/packages/neon/lib/src/blocs/capabilities.dart b/packages/neon/lib/src/blocs/capabilities.dart index e67da2e5..e65ff7bc 100644 --- a/packages/neon/lib/src/blocs/capabilities.dart +++ b/packages/neon/lib/src/blocs/capabilities.dart @@ -32,11 +32,10 @@ class CapabilitiesBloc extends $CapabilitiesBloc { void _loadCapabilities() { _requestManager - .wrapNextcloud( + .wrapNextcloud( _client.id, - _client.core, 'capabilities', - () async => (await _client.core.getCapabilities())!, + () async => _client.core.getCapabilities(), (final response) => response.ocs!.data!, preloadCache: true, ) diff --git a/packages/neon/lib/src/blocs/login.dart b/packages/neon/lib/src/blocs/login.dart index 0a96440b..fcd7e320 100644 --- a/packages/neon/lib/src/blocs/login.dart +++ b/packages/neon/lib/src/blocs/login.dart @@ -39,7 +39,7 @@ class LoginBloc extends $LoginBloc { userAgentOverride: userAgent(_packageInfo), ); - final status = (await client.core.getStatus())!; + final status = await client.core.getStatus(); if (status.maintenance!) { _serverConnectionStateSubject.add(ServerConnectionState.maintenanceMode); return; @@ -53,7 +53,7 @@ class LoginBloc extends $LoginBloc { _cancelPollTimer(); _pollTimer = Timer.periodic(const Duration(seconds: 2), (final _) async { try { - final result = await client.core.getLoginFlowResult(init!.poll!.token!); + final result = await client.core.getLoginFlowResult(token: init.poll!.token!); _cancelPollTimer(); _loginFlowResultSubject.add(result); } catch (e) { diff --git a/packages/neon/lib/src/blocs/push_notifications.dart b/packages/neon/lib/src/blocs/push_notifications.dart index d023e048..95595ed1 100644 --- a/packages/neon/lib/src/blocs/push_notifications.dart +++ b/packages/neon/lib/src/blocs/push_notifications.dart @@ -72,11 +72,11 @@ class PushNotificationsBloc extends $PushNotificationsBloc { proxyServerForClient = 'http://${_env!.testHost}:8080/'; } - final subscription = (await account.client.notifications.registerDeviceAtServer( - endpoint, - _keypair!.publicKey, - proxyServerForNextcloud, - ))!; + final subscription = await account.client.notifications.registerDevice( + pushTokenHash: account.client.notifications.generatePushTokenHash(endpoint), + devicePublicKey: _keypair!.publicKey.toFormattedPEM(), + proxyServer: proxyServerForNextcloud, + ); await account.client.notifications.registerDeviceAtPushProxy( endpoint, diff --git a/packages/neon/lib/src/blocs/user_details.dart b/packages/neon/lib/src/blocs/user_details.dart index 2d07d19d..19f08c1b 100644 --- a/packages/neon/lib/src/blocs/user_details.dart +++ b/packages/neon/lib/src/blocs/user_details.dart @@ -29,11 +29,10 @@ class UserDetailsBloc extends $UserDetailsBloc { void _loadUserDetails() { _requestManager - .wrapNextcloud( + .wrapNextcloud( _client.id, - _client.provisioningApi, 'user-details', - () async => (await _client.provisioningApi.getCurrentUser())!, + () async => _client.provisioningApi.getCurrentUser(), (final response) => response.ocs!.data!, preloadCache: true, ) diff --git a/packages/neon/lib/src/blocs/user_status.dart b/packages/neon/lib/src/blocs/user_status.dart index ee8b7504..378b5794 100644 --- a/packages/neon/lib/src/blocs/user_status.dart +++ b/packages/neon/lib/src/blocs/user_status.dart @@ -38,13 +38,13 @@ class UserStatusBloc extends $UserStatusBloc { } void _loadUserStatus() { + // TODO: Fix for no user status _requestManager - .wrapNextcloud( + .wrapNextcloud( _account.client.id, - _account.client.userStatus, 'user-status', - () async => (await _account.client.userStatus.getStatus())!, - (final response) => response.ocs?.data, + () async => _account.client.userStatus.getStatus(), + (final response) => response.ocs?.data?.userStatus, preloadCache: true, ) .listen(_userStatusSubject.add); @@ -56,7 +56,7 @@ class UserStatusBloc extends $UserStatusBloc { // TODO: https://github.com/jld3103/nextcloud-neon/issues/10 // ignore: dead_code try { - await _account.client.userStatus.heartbeat(UserStatusTypeEnum.online); + await _account.client.userStatus.heartbeat(status: UserStatusType.online); } catch (e) { debugPrint(e.toString()); } diff --git a/packages/neon/lib/src/models/nextcloud_notification.dart b/packages/neon/lib/src/models/nextcloud_notification.dart deleted file mode 100644 index 31df58c4..00000000 --- a/packages/neon/lib/src/models/nextcloud_notification.dart +++ /dev/null @@ -1,32 +0,0 @@ -import 'package:json_annotation/json_annotation.dart'; -import 'package:nextcloud/nextcloud.dart'; - -part 'nextcloud_notification.g.dart'; - -@JsonSerializable() -class NextcloudNotification { - NextcloudNotification({ - required this.accountID, - required this.priority, - required this.type, - required this.subject, - }); - - factory NextcloudNotification.fromJson(final Map json) => _$NextcloudNotificationFromJson(json); - Map toJson() => _$NextcloudNotificationToJson(this); - - final String accountID; - final String priority; - final String type; - - @JsonKey( - fromJson: _fromJsonSubject, - toJson: _toJsonSubject, - ) - final NotificationsPushNotificationDecryptedSubject subject; -} - -NotificationsPushNotificationDecryptedSubject _fromJsonSubject(final Map data) => - NotificationsPushNotificationDecryptedSubject.fromJson(data)!; - -Map? _toJsonSubject(final NotificationsPushNotificationDecryptedSubject subject) => subject.toJson(); diff --git a/packages/neon/lib/src/models/nextcloud_notification.g.dart b/packages/neon/lib/src/models/nextcloud_notification.g.dart deleted file mode 100644 index 16a8f602..00000000 --- a/packages/neon/lib/src/models/nextcloud_notification.g.dart +++ /dev/null @@ -1,21 +0,0 @@ -// GENERATED CODE - DO NOT MODIFY BY HAND - -part of 'nextcloud_notification.dart'; - -// ************************************************************************** -// JsonSerializableGenerator -// ************************************************************************** - -NextcloudNotification _$NextcloudNotificationFromJson(Map json) => NextcloudNotification( - accountID: json['accountID'] as String, - priority: json['priority'] as String, - type: json['type'] as String, - subject: _fromJsonSubject(json['subject'] as Map), - ); - -Map _$NextcloudNotificationToJson(NextcloudNotification instance) => { - 'accountID': instance.accountID, - 'priority': instance.priority, - 'type': instance.type, - 'subject': _toJsonSubject(instance.subject), - }; diff --git a/packages/neon/lib/src/neon.dart b/packages/neon/lib/src/neon.dart index 14300e31..d6ba2e6a 100644 --- a/packages/neon/lib/src/neon.dart +++ b/packages/neon/lib/src/neon.dart @@ -32,7 +32,6 @@ import 'package:neon/src/blocs/login.dart'; import 'package:neon/src/blocs/user_details.dart'; import 'package:neon/src/blocs/user_status.dart'; import 'package:neon/src/models/account.dart'; -import 'package:neon/src/models/nextcloud_notification.dart'; import 'package:nextcloud/nextcloud.dart'; import 'package:package_info_plus/package_info_plus.dart'; import 'package:path/path.dart' as p; diff --git a/packages/neon/lib/src/pages/home/home.dart b/packages/neon/lib/src/pages/home/home.dart index 5a6a7b2a..6c51ec3a 100644 --- a/packages/neon/lib/src/pages/home/home.dart +++ b/packages/neon/lib/src/pages/home/home.dart @@ -165,13 +165,13 @@ class _HomePageState extends State with tray.TrayListener, WindowListe }; Global.onPushNotificationClicked = (final payload) async { if (payload != null) { - final notification = NextcloudNotification.fromJson(json.decode(payload) as Map); + final notification = NotificationsPushNotification.fromJson(json.decode(payload) as Map); debugPrint('onNotificationClicked: ${notification.subject}'); final allAppImplementations = Provider.of>(context, listen: false); final matchingAppImplementations = - allAppImplementations.where((final a) => a.id == notification.subject.app); + allAppImplementations.where((final a) => a.id == notification.subject!.app); late AppImplementation appImplementation; if (matchingAppImplementations.isNotEmpty) { @@ -181,11 +181,7 @@ class _HomePageState extends State with tray.TrayListener, WindowListe } if (appImplementation.id != 'notifications') { - _appsBloc.getAppBloc(appImplementation).deleteNotification( - NotificationsNotification( - notificationId: notification.subject.nid, - ), - ); + _appsBloc.getAppBloc(appImplementation).deleteNotification(notification.subject!.nid!); } await _openAppFromExternal(appImplementation.id); } diff --git a/packages/neon/lib/src/pages/home/widgets/server_status.dart b/packages/neon/lib/src/pages/home/widgets/server_status.dart index 8d5aa9b6..1baa3f1d 100644 --- a/packages/neon/lib/src/pages/home/widgets/server_status.dart +++ b/packages/neon/lib/src/pages/home/widgets/server_status.dart @@ -19,7 +19,7 @@ class _ServerStatusState extends State { WidgetsBinding.instance.addPostFrameCallback((final _) async { try { - final status = (await widget.account.client.core.getStatus())!; + final status = await widget.account.client.core.getStatus(); if (status.maintenance! && mounted) { ExceptionWidget.showSnackbar(context, AppLocalizations.of(context).errorServerInMaintenanceMode); } diff --git a/packages/neon/lib/src/utils/push_utils.dart b/packages/neon/lib/src/utils/push_utils.dart index c9f9307a..b187023a 100644 --- a/packages/neon/lib/src/utils/push_utils.dart +++ b/packages/neon/lib/src/utils/push_utils.dart @@ -49,18 +49,18 @@ class PushUtils { final keypair = await loadRSAKeypair(Storage('notifications', sharedPreferences)); final data = json.decode(utf8.decode(message)) as Map; - final notification = NextcloudNotification( + final notification = NotificationsPushNotification( accountID: instance, priority: data['priority']! as String, type: data['type']! as String, subject: decryptPushNotificationSubject(keypair.privateKey, data['subject']! as String), ); - if (notification.subject.delete ?? false) { + if (notification.subject!.delete ?? false) { await localNotificationsPlugin.cancel(_getNotificationID(instance, notification)); return; } - if (notification.subject.deleteAll ?? false) { + if (notification.subject!.deleteAll ?? false) { await localNotificationsPlugin.cancelAll(); return; } @@ -80,7 +80,7 @@ class PushUtils { final allAppImplementations = getAppImplementations(sharedPreferences, requestManager, platform); final matchingAppImplementations = - allAppImplementations.where((final a) => a.id == notification.subject.app!).toList(); + allAppImplementations.where((final a) => a.id == notification.subject!.app!).toList(); late AppImplementation app; if (matchingAppImplementations.isNotEmpty) { app = matchingAppImplementations.single; @@ -93,7 +93,7 @@ class PushUtils { await localNotificationsPlugin.show( _getNotificationID(instance, notification), appName, - notification.subject.subject!, + notification.subject!.subject!, NotificationDetails( android: AndroidNotificationDetails( app.id, @@ -120,7 +120,7 @@ class PushUtils { static int _getNotificationID( final String instance, - final NextcloudNotification notification, + final NotificationsPushNotification notification, ) => - sha256.convert(utf8.encode('$instance${notification.subject.nid!}')).bytes.reduce((final a, final b) => a + b); + sha256.convert(utf8.encode('$instance${notification.subject!.nid!}')).bytes.reduce((final a, final b) => a + b); } diff --git a/packages/neon/lib/src/utils/request_manager.dart b/packages/neon/lib/src/utils/request_manager.dart index 889db050..7cb392cd 100644 --- a/packages/neon/lib/src/utils/request_manager.dart +++ b/packages/neon/lib/src/utils/request_manager.dart @@ -28,9 +28,8 @@ class RequestManager { } } - Stream> wrapNextcloud( + Stream> wrapNextcloud( final String clientID, - final S apiInstance, final String k, final Future Function() call, final T Function(R) unwrap, { @@ -39,30 +38,11 @@ class RequestManager { final bool disableTimeout = false, final T? previousData, }) async* { - if (R.toString().endsWith('?')) { - final e = Exception('You can not request a nullable type ${R.toString()}'); - debugPrint(e.toString()); - yield Result.error(e); - return; - } - if (R is List && R != List) { - final e = Exception('$R is not List<$U> as expected'); - debugPrint(e.toString()); - yield Result.error(e); - return; - } - yield* _wrap( clientID, k, - apiInstance.apiClient.serializeAsync, - (final d) async { - var a = await apiInstance.apiClient.deserializeAsync(d, R.toString()); - if (a is List) { - a = a.map((final b) => b as U).toList(); - } - return a as R; - }, + (final s) => json.encode(serialize(s)), + (final d) => deserialize(json.decode(d)), call, unwrap: unwrap, preloadCache: preloadCache, @@ -84,8 +64,8 @@ class RequestManager { _wrap( clientID, k, - (final s) async => base64.encode(s), - (final d) async => base64.decode(d), + (final s) => base64.encode(s), + (final d) => base64.decode(d), call, preloadCache: preloadCache, preferCache: preferCache, @@ -105,20 +85,19 @@ class RequestManager { _wrap( clientID, k, - (final s) async => s, - (final d) async => d, + (final s) => s, + (final d) => d, call, preloadCache: preloadCache, preferCache: preferCache, previousData: previousData, disableTimeout: disableTimeout, ); - Stream> _wrap( final String clientID, final String k, - final Future Function(R) serialize, - final Future Function(String) deserialize, + final String Function(R) serialize, + final R Function(String) deserialize, final Future Function() call, { final bool preloadCache = false, final bool preferCache = false, @@ -140,7 +119,7 @@ class RequestManager { if ((preferCache || preloadCache) && cache != null && await cache!.has(key)) { _print('[Cache]: $k'); - final s = unwrap(await deserialize((await cache!.get(key))!)); + final s = unwrap(deserialize((await cache!.get(key))!)); if (preloadCache) { yield ResultCached(s, loading: true); } else { @@ -152,7 +131,7 @@ class RequestManager { try { final response = await _timeout(disableTimeout, call); - final s = await serialize(response); + final s = serialize(response); _print('[Response]: $k'); await cache?.set(key, s); @@ -161,7 +140,7 @@ class RequestManager { if (cache != null && await cache!.has(key)) { _print('[Cache]: $k'); debugPrint(e.toString()); - yield ResultCached(unwrap(await deserialize((await cache!.get(key))!)), error: e); + yield ResultCached(unwrap(deserialize((await cache!.get(key))!)), error: e); return; } _print('[Failure]: $k'); @@ -282,7 +261,3 @@ extension ResultDataError on Result { return null; } } - -extension ListAs on List { - List as>() => map((final e) => e as V).toList(); -} diff --git a/packages/neon/lib/src/utils/theme.dart b/packages/neon/lib/src/utils/theme.dart index 9022e96e..a78f1221 100644 --- a/packages/neon/lib/src/utils/theme.dart +++ b/packages/neon/lib/src/utils/theme.dart @@ -4,7 +4,7 @@ const themePrimaryColor = Color(0xFFF37736); const themeOnPrimaryColor = Color(0xFFFFFFFF); ThemeData getThemeFromNextcloudTheme( - final NextcloudTheme? nextcloudTheme, + final CoreServerCapabilitiesOcsDataCapabilitiesTheming? nextcloudTheme, final ThemeMode themeMode, final Brightness platformBrightness, { required final bool oledAsDark, diff --git a/packages/neon/lib/src/widgets/account_avatar.dart b/packages/neon/lib/src/widgets/account_avatar.dart index cce38b10..ab0d3b85 100644 --- a/packages/neon/lib/src/widgets/account_avatar.dart +++ b/packages/neon/lib/src/widgets/account_avatar.dart @@ -20,10 +20,10 @@ class AccountAvatar extends StatelessWidget { stream: requestManager.wrapBytes( account.client.id, 'accounts-avatar-${account.id}', - () async => (await account.client.core.getAvatarBytes( - account.username, - (kAvatarSize * MediaQuery.of(context).devicePixelRatio).toInt(), - ))!, + () async => account.client.core.getAvatar( + userId: account.username, + size: (kAvatarSize * MediaQuery.of(context).devicePixelRatio).toInt(), + ), preferCache: true, ), builder: ( @@ -78,8 +78,8 @@ class AccountAvatar extends StatelessWidget { : BoxDecoration( shape: BoxShape.circle, color: _userStatusToColor(userStatusData), - border: userStatusData.status != UserStatusTypeEnum.offline && - userStatusData.status != UserStatusTypeEnum.invisible + border: userStatusData.status != UserStatusType.offline && + userStatusData.status != UserStatusType.invisible ? Border.all( color: Theme.of(context).colorScheme.onPrimary, ) @@ -90,7 +90,8 @@ class AccountAvatar extends StatelessWidget { strokeWidth: 1.5, color: Theme.of(context).colorScheme.onPrimary, ) - : userStatusError != null && (userStatusError is! ApiException || userStatusError.code != 404) + : userStatusError != null && + (userStatusError is! ApiException || userStatusError.statusCode != 404) ? const Icon( Icons.error_outline, size: kAvatarSize / 3, @@ -106,17 +107,14 @@ class AccountAvatar extends StatelessWidget { Color _userStatusToColor(final UserStatus userStatus) { switch (userStatus.status) { - case UserStatusTypeEnum.online: + case UserStatusType.online: return const Color(0xFF49B382); - case UserStatusTypeEnum.away: + case UserStatusType.away: return const Color(0xFFF4A331); - case UserStatusTypeEnum.dnd: + case UserStatusType.dnd: return const Color(0xFFED484C); - case UserStatusTypeEnum.invisible: - case UserStatusTypeEnum.offline: + default: return Colors.transparent; } - - return Colors.transparent; } } diff --git a/packages/neon/lib/src/widgets/cached_url_image.dart b/packages/neon/lib/src/widgets/cached_url_image.dart index 68fa3f98..ff4af1e8 100644 --- a/packages/neon/lib/src/widgets/cached_url_image.dart +++ b/packages/neon/lib/src/widgets/cached_url_image.dart @@ -35,7 +35,7 @@ class CachedURLImage extends StatelessWidget { 'image-${base64.encode(url.codeUnits)}', () async => (await http.get( Uri.parse(url), - headers: client.commonHeaders, + headers: client.baseHeaders, )) .bodyBytes, preferCache: true, diff --git a/packages/neon/lib/src/widgets/exception.dart b/packages/neon/lib/src/widgets/exception.dart index 5114ee25..e3e9fc6a 100644 --- a/packages/neon/lib/src/widgets/exception.dart +++ b/packages/neon/lib/src/widgets/exception.dart @@ -89,43 +89,40 @@ class ExceptionWidget extends StatelessWidget { } if (exception is ApiException) { - if (exception.code == 401) { + if (exception.statusCode == 401) { return _ExceptionDetails( text: AppLocalizations.of(context).errorCredentialsForAccountNoLongerMatch, isUnauthorized: true, ); } - if (exception.code >= 500 && exception.code <= 599) { + if (exception.statusCode >= 500 && exception.statusCode <= 599) { return _ExceptionDetails( text: AppLocalizations.of(context).errorServerHadAProblemProcessingYourRequest, ); } } - final socketException = _getSpecificExceptionForException(exception); - if (socketException != null) { + if (exception is SocketException) { return _ExceptionDetails( - text: socketException.address != null - ? AppLocalizations.of(context).errorUnableToReachServerAt(socketException.address!.host) + text: exception.address != null + ? AppLocalizations.of(context).errorUnableToReachServerAt(exception.address!.host) : AppLocalizations.of(context).errorUnableToReachServer, ); } - final clientException = _getSpecificExceptionForException(exception); - if (clientException != null) { + if (exception is ClientException) { return _ExceptionDetails( - text: clientException.uri != null - ? AppLocalizations.of(context).errorUnableToReachServerAt(clientException.uri!.host) + text: exception.uri != null + ? AppLocalizations.of(context).errorUnableToReachServerAt(exception.uri!.host) : AppLocalizations.of(context).errorUnableToReachServer, ); } - final httpException = _getSpecificExceptionForException(exception); - if (httpException != null) { + if (exception is HttpException) { return _ExceptionDetails( - text: httpException.uri != null - ? AppLocalizations.of(context).errorUnableToReachServerAt(httpException.uri!.host) + text: exception.uri != null + ? AppLocalizations.of(context).errorUnableToReachServerAt(exception.uri!.host) : AppLocalizations.of(context).errorUnableToReachServer, ); } @@ -141,17 +138,6 @@ class ExceptionWidget extends StatelessWidget { ); } - static T? _getSpecificExceptionForException(final dynamic exception) { - if (exception is T) { - return exception; - } - if (exception is ApiException && exception.innerException != null && exception.innerException is T) { - return exception.innerException! as T; - } - - return null; - } - static Future _openLoginPage(final BuildContext context) async { await Navigator.of(context).push( MaterialPageRoute(