diff --git a/.github/workflows/dart.yml b/.github/workflows/dart.yml
index 08b11ef143a..4df1fc8aa14 100644
--- a/.github/workflows/dart.yml
+++ b/.github/workflows/dart.yml
@@ -35,16 +35,16 @@ jobs:
- name: mono_repo self validate
run: dart pub global run mono_repo generate --validate
job_002:
- name: "analyze; PKGS: packages/file_icons, packages/harbour, packages/nextcloud, packages/settings, packages/sort_box, packages/spec_templates; `dart format --output=none --set-exit-if-changed --line-length 120 .`"
+ name: "analyze; PKGS: packages/file_icons, packages/harbour, packages/nextcloud, packages/nextcloud_push_proxy, packages/settings, packages/sort_box, packages/spec_templates; `dart format --output=none --set-exit-if-changed --line-length 120 .`"
runs-on: ubuntu-latest
steps:
- name: Cache Pub hosted dependencies
uses: actions/cache@4504faf7e9bcf8f3ed0bc863c4e1d21499ab8ef8
with:
path: "~/.pub-cache/hosted"
- key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/settings-packages/sort_box-packages/spec_templates;commands:format"
+ key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/nextcloud_push_proxy-packages/settings-packages/sort_box-packages/spec_templates;commands:format"
restore-keys: |
- os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/settings-packages/sort_box-packages/spec_templates
+ os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/file_icons-packages/harbour-packages/nextcloud-packages/nextcloud_push_proxy-packages/settings-packages/sort_box-packages/spec_templates
os:ubuntu-latest;pub-cache-hosted;sdk:stable
os:ubuntu-latest;pub-cache-hosted
os:ubuntu-latest
@@ -80,6 +80,15 @@ jobs:
if: "always() && steps.packages_nextcloud_pub_upgrade.conclusion == 'success'"
working-directory: packages/nextcloud
run: "dart format --output=none --set-exit-if-changed --line-length 120 ."
+ - id: packages_nextcloud_push_proxy_pub_upgrade
+ name: packages/nextcloud_push_proxy; flutter pub pub upgrade
+ if: "always() && steps.checkout.conclusion == 'success'"
+ working-directory: packages/nextcloud_push_proxy
+ run: flutter pub pub upgrade
+ - name: "packages/nextcloud_push_proxy; dart format --output=none --set-exit-if-changed --line-length 120 ."
+ if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'"
+ working-directory: packages/nextcloud_push_proxy
+ run: "dart format --output=none --set-exit-if-changed --line-length 120 ."
- id: packages_settings_pub_upgrade
name: packages/settings; flutter pub pub upgrade
if: "always() && steps.checkout.conclusion == 'success'"
@@ -158,16 +167,16 @@ jobs:
needs:
- job_001
job_004:
- name: "analyze; PKGS: packages/nextcloud, packages/sort_box, packages/spec_templates; `dart analyze`"
+ name: "analyze; PKGS: packages/nextcloud, packages/nextcloud_push_proxy, packages/sort_box, packages/spec_templates; `dart analyze`"
runs-on: ubuntu-latest
steps:
- name: Cache Pub hosted dependencies
uses: actions/cache@4504faf7e9bcf8f3ed0bc863c4e1d21499ab8ef8
with:
path: "~/.pub-cache/hosted"
- key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/sort_box-packages/spec_templates;commands:analyze_1"
+ key: "os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/nextcloud_push_proxy-packages/sort_box-packages/spec_templates;commands:analyze_1"
restore-keys: |
- os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/sort_box-packages/spec_templates
+ os:ubuntu-latest;pub-cache-hosted;sdk:stable;packages:packages/nextcloud-packages/nextcloud_push_proxy-packages/sort_box-packages/spec_templates
os:ubuntu-latest;pub-cache-hosted;sdk:stable
os:ubuntu-latest;pub-cache-hosted
os:ubuntu-latest
@@ -185,6 +194,15 @@ jobs:
if: "always() && steps.packages_nextcloud_pub_upgrade.conclusion == 'success'"
working-directory: packages/nextcloud
run: dart analyze
+ - id: packages_nextcloud_push_proxy_pub_upgrade
+ name: packages/nextcloud_push_proxy; dart pub upgrade
+ if: "always() && steps.checkout.conclusion == 'success'"
+ working-directory: packages/nextcloud_push_proxy
+ run: dart pub upgrade
+ - name: packages/nextcloud_push_proxy; dart analyze
+ if: "always() && steps.packages_nextcloud_push_proxy_pub_upgrade.conclusion == 'success'"
+ working-directory: packages/nextcloud_push_proxy
+ run: dart analyze
- id: packages_sort_box_pub_upgrade
name: packages/sort_box; dart pub upgrade
if: "always() && steps.checkout.conclusion == 'success'"
diff --git a/.gitmodules b/.gitmodules
index 787dc6729d3..117f9b69075 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -13,3 +13,6 @@
[submodule "external/nextcloud-notes"]
path = external/nextcloud-notes
url = https://github.com/nextcloud/notes
+[submodule "external/nextcloud-notifications"]
+ path = external/nextcloud-notifications
+ url = https://github.com/nextcloud/notifications
diff --git a/.idea/nextcloud-harbour.iml b/.idea/nextcloud-harbour.iml
index 4db18808617..1078fb02a35 100644
--- a/.idea/nextcloud-harbour.iml
+++ b/.idea/nextcloud-harbour.iml
@@ -44,6 +44,11 @@
+
+
+
+
+
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
index 611fc781df6..6b5ae81c302 100644
--- a/.idea/vcs.xml
+++ b/.idea/vcs.xml
@@ -4,6 +4,7 @@
+
diff --git a/external/nextcloud-notifications b/external/nextcloud-notifications
new file mode 160000
index 00000000000..62c670f2cf9
--- /dev/null
+++ b/external/nextcloud-notifications
@@ -0,0 +1 @@
+Subproject commit 62c670f2cf9674b95e2f7b94f7bf0cd3887f3418
diff --git a/packages/nextcloud/doc/notifications/AdminNotification.md b/packages/nextcloud/doc/notifications/AdminNotification.md
new file mode 100644
index 00000000000..6fafeb7bb5b
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/AdminNotification.md
@@ -0,0 +1,16 @@
+# openapi.model.AdminNotification
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**shortMessage** | **String** | | [optional]
+**longMessage** | **String** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/DefaultApi.md b/packages/nextcloud/doc/notifications/DefaultApi.md
new file mode 100644
index 00000000000..58ddd9ab4aa
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/DefaultApi.md
@@ -0,0 +1,318 @@
+# openapi.api.DefaultApi
+
+## Load the API package
+```dart
+import 'package:openapi/api.dart';
+```
+
+All URIs are relative to *https://localhost:8080/ocs/v1.php/apps/notifications*
+
+Method | HTTP request | Description
+------------- | ------------- | -------------
+[**deleteAllNotifications**](DefaultApi.md#deleteallnotifications) | **DELETE** /api/v2/notifications |
+[**deleteNotification**](DefaultApi.md#deletenotification) | **DELETE** /api/v2/notifications/{id} |
+[**getNotification**](DefaultApi.md#getnotification) | **GET** /api/v2/notifications/{id} |
+[**listNotifications**](DefaultApi.md#listnotifications) | **GET** /api/v2/notifications |
+[**registerDevice**](DefaultApi.md#registerdevice) | **POST** /api/v2/push |
+[**removeDevice**](DefaultApi.md#removedevice) | **DELETE** /api/v2/push |
+[**sendAdminNotification**](DefaultApi.md#sendadminnotification) | **POST** /api/v2/admin_notifications/{userId} |
+
+
+# **deleteAllNotifications**
+> String deleteAllNotifications()
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+
+try {
+ final result = api_instance.deleteAllNotifications();
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->deleteAllNotifications: $e\n');
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+**String**
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **deleteNotification**
+> EmptyResponse deleteNotification(id)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+final id = 56; // int |
+
+try {
+ final result = api_instance.deleteNotification(id);
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->deleteNotification: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **id** | **int**| |
+
+### Return type
+
+[**EmptyResponse**](EmptyResponse.md)
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **getNotification**
+> GetNotificationResponse getNotification(id)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+final id = 56; // int |
+
+try {
+ final result = api_instance.getNotification(id);
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->getNotification: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **id** | **int**| |
+
+### Return type
+
+[**GetNotificationResponse**](GetNotificationResponse.md)
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **listNotifications**
+> String listNotifications()
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+
+try {
+ final result = api_instance.listNotifications();
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->listNotifications: $e\n');
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+**String**
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **registerDevice**
+> PushServerRegistrationResponse registerDevice(pushServerDevice)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+final pushServerDevice = PushServerDevice(); // PushServerDevice |
+
+try {
+ final result = api_instance.registerDevice(pushServerDevice);
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->registerDevice: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **pushServerDevice** | [**PushServerDevice**](PushServerDevice.md)| |
+
+### Return type
+
+[**PushServerRegistrationResponse**](PushServerRegistrationResponse.md)
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **removeDevice**
+> String removeDevice()
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+
+try {
+ final result = api_instance.removeDevice();
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->removeDevice: $e\n');
+}
+```
+
+### Parameters
+This endpoint does not need any parameter.
+
+### Return type
+
+**String**
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: Not defined
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
+# **sendAdminNotification**
+> EmptyResponse sendAdminNotification(userId, adminNotification)
+
+
+
+### Example
+```dart
+import 'package:openapi/api.dart';
+// TODO Configure HTTP basic authorization: basic_auth
+//defaultApiClient.getAuthentication('basic_auth').username = 'YOUR_USERNAME'
+//defaultApiClient.getAuthentication('basic_auth').password = 'YOUR_PASSWORD';
+
+final api_instance = DefaultApi();
+final userId = userId_example; // String |
+final adminNotification = AdminNotification(); // AdminNotification |
+
+try {
+ final result = api_instance.sendAdminNotification(userId, adminNotification);
+ print(result);
+} catch (e) {
+ print('Exception when calling DefaultApi->sendAdminNotification: $e\n');
+}
+```
+
+### Parameters
+
+Name | Type | Description | Notes
+------------- | ------------- | ------------- | -------------
+ **userId** | **String**| |
+ **adminNotification** | [**AdminNotification**](AdminNotification.md)| |
+
+### Return type
+
+[**EmptyResponse**](EmptyResponse.md)
+
+### Authorization
+
+[basic_auth](../README.md#basic_auth)
+
+### HTTP request headers
+
+ - **Content-Type**: application/json
+ - **Accept**: application/json
+
+[[Back to top]](#) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to Model list]](../README.md#documentation-for-models) [[Back to README]](../README.md)
+
diff --git a/packages/nextcloud/doc/notifications/EmptyResponse.md b/packages/nextcloud/doc/notifications/EmptyResponse.md
new file mode 100644
index 00000000000..c983d5488fc
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/EmptyResponse.md
@@ -0,0 +1,15 @@
+# openapi.model.EmptyResponse
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**ocs** | [**EmptyResponseOcs**](EmptyResponseOcs.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/EmptyResponseOcs.md b/packages/nextcloud/doc/notifications/EmptyResponseOcs.md
new file mode 100644
index 00000000000..2cd835c7e7f
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/EmptyResponseOcs.md
@@ -0,0 +1,16 @@
+# openapi.model.EmptyResponseOcs
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**meta** | [**Object**](.md) | Stub | [optional]
+**data** | **List** | | [optional] [default to const []]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/GetNotificationResponse.md b/packages/nextcloud/doc/notifications/GetNotificationResponse.md
new file mode 100644
index 00000000000..45319629e2b
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/GetNotificationResponse.md
@@ -0,0 +1,15 @@
+# openapi.model.GetNotificationResponse
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**ocs** | [**GetNotificationResponseOcs**](GetNotificationResponseOcs.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md b/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md
new file mode 100644
index 00000000000..48f88537c51
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/GetNotificationResponseOcs.md
@@ -0,0 +1,16 @@
+# openapi.model.GetNotificationResponseOcs
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**meta** | [**Object**](.md) | Stub | [optional]
+**data** | [**Notification**](Notification.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/ListNotificationsResponse.md b/packages/nextcloud/doc/notifications/ListNotificationsResponse.md
new file mode 100644
index 00000000000..53f4e3d644e
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/ListNotificationsResponse.md
@@ -0,0 +1,15 @@
+# openapi.model.ListNotificationsResponse
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**ocs** | [**ListNotificationsResponseOcs**](ListNotificationsResponseOcs.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md b/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md
new file mode 100644
index 00000000000..57fc6d59d39
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/ListNotificationsResponseOcs.md
@@ -0,0 +1,16 @@
+# openapi.model.ListNotificationsResponseOcs
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**meta** | [**Object**](.md) | Stub | [optional]
+**data** | [**List**](Notification.md) | | [optional] [default to const []]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/Notification.md b/packages/nextcloud/doc/notifications/Notification.md
new file mode 100644
index 00000000000..c9f80d1c13c
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/Notification.md
@@ -0,0 +1,29 @@
+# openapi.model.Notification
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**notificationId** | **int** | | [optional]
+**app** | **String** | | [optional]
+**user** | **String** | | [optional]
+**datetime** | **String** | | [optional]
+**objectType** | **String** | | [optional]
+**objectId** | **String** | | [optional]
+**subject** | **String** | | [optional]
+**message** | **String** | | [optional]
+**link** | **String** | | [optional]
+**subjectRich** | **String** | | [optional]
+**subjectRichParameters** | **List** | | [optional] [default to const []]
+**messageRich** | **String** | | [optional]
+**messageRichParameters** | **List** | | [optional] [default to const []]
+**icon** | **String** | | [optional]
+**actions** | **List** | | [optional] [default to const []]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md b/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md
new file mode 100644
index 00000000000..a32f0de9aa6
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/PushNotificationDecryptedSubject.md
@@ -0,0 +1,19 @@
+# openapi.model.PushNotificationDecryptedSubject
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**nid** | **int** | | [optional]
+**app** | **String** | | [optional]
+**subject** | **String** | | [optional]
+**type** | **String** | | [optional]
+**id** | **String** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/PushServerDevice.md b/packages/nextcloud/doc/notifications/PushServerDevice.md
new file mode 100644
index 00000000000..b2091f59ea5
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/PushServerDevice.md
@@ -0,0 +1,17 @@
+# openapi.model.PushServerDevice
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**pushTokenHash** | **String** | | [optional]
+**devicePublicKey** | **String** | | [optional]
+**proxyServer** | **String** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md b/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md
new file mode 100644
index 00000000000..64f5dd69a7b
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/PushServerRegistrationResponse.md
@@ -0,0 +1,15 @@
+# openapi.model.PushServerRegistrationResponse
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**ocs** | [**PushServerRegistrationResponseOcs**](PushServerRegistrationResponseOcs.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md b/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md
new file mode 100644
index 00000000000..f28ad4195de
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/PushServerRegistrationResponseOcs.md
@@ -0,0 +1,16 @@
+# openapi.model.PushServerRegistrationResponseOcs
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**meta** | [**Object**](.md) | Stub | [optional]
+**data** | [**PushServerSubscription**](PushServerSubscription.md) | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/doc/notifications/PushServerSubscription.md b/packages/nextcloud/doc/notifications/PushServerSubscription.md
new file mode 100644
index 00000000000..35581a35a7f
--- /dev/null
+++ b/packages/nextcloud/doc/notifications/PushServerSubscription.md
@@ -0,0 +1,17 @@
+# openapi.model.PushServerSubscription
+
+## Load the model package
+```dart
+import 'package:openapi/api.dart';
+```
+
+## Properties
+Name | Type | Description | Notes
+------------ | ------------- | ------------- | -------------
+**publicKey** | **String** | | [optional]
+**deviceIdentifier** | **String** | | [optional]
+**signature** | **String** | | [optional]
+
+[[Back to Model list]](../README.md#documentation-for-models) [[Back to API list]](../README.md#documentation-for-api-endpoints) [[Back to README]](../README.md)
+
+
diff --git a/packages/nextcloud/lib/nextcloud.dart b/packages/nextcloud/lib/nextcloud.dart
index 11772ab42e7..c240ef2b88d 100644
--- a/packages/nextcloud/lib/nextcloud.dart
+++ b/packages/nextcloud/lib/nextcloud.dart
@@ -1,5 +1,7 @@
library nextcloud;
+export 'package:crypton/crypton.dart' show RSAKeypair, RSAPublicKey, RSAPrivateKey;
+
export 'src/app_type.dart';
export 'src/client.dart';
export 'src/clients/common/api.dart';
@@ -11,12 +13,15 @@ export 'src/clients/generated/news/api.dart'
hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi;
export 'src/clients/generated/notes/api.dart'
hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi;
+export 'src/clients/generated/notifications/api.dart'
+ hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi;
export 'src/clients/generated/provisioning_api/api.dart'
hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi;
export 'src/clients/generated/user_status/api.dart'
hide ApiClient, serializeAsync, deserializeAsync, DeserializationMessage, DefaultApi;
export 'src/clients/news.dart';
export 'src/clients/notes.dart';
+export 'src/clients/notifications.dart';
export 'src/clients/provisioning_api.dart';
export 'src/clients/user_status.dart';
export 'src/clients/webdav.dart';
diff --git a/packages/nextcloud/lib/src/client.dart b/packages/nextcloud/lib/src/client.dart
index 085db14beae..97656ec4589 100644
--- a/packages/nextcloud/lib/src/client.dart
+++ b/packages/nextcloud/lib/src/client.dart
@@ -29,6 +29,11 @@ class NextcloudClient {
authentication,
_addCommonSettings,
);
+ _notifications = NextcloudNotificationsClient(
+ baseURL,
+ authentication,
+ _addCommonSettings,
+ );
_provisioningApi = NextcloudProvisioningApiClient(
baseURL,
authentication,
@@ -103,6 +108,7 @@ class NextcloudClient {
late NextcloudCoreClient _core;
late NextcloudNewsClient _news;
late NextcloudNotesClient _notes;
+ late NextcloudNotificationsClient _notifications;
late NextcloudProvisioningApiClient _provisioningApi;
late NextcloudUserStatusClient _userStatus;
@@ -118,6 +124,9 @@ class NextcloudClient {
/// Client for Nextcloud Notes app
NextcloudNotesClient get notes => _notes;
+ /// Client for Nextcloud Notifications API
+ NextcloudNotificationsClient get notifications => _notifications;
+
/// Client for Provisioning APIs
NextcloudProvisioningApiClient get provisioningApi => _provisioningApi;
diff --git a/packages/nextcloud/lib/src/clients/custom/webdav/client.dart b/packages/nextcloud/lib/src/clients/custom/webdav/client.dart
index 35ead488408..00331144ea1 100644
--- a/packages/nextcloud/lib/src/clients/custom/webdav/client.dart
+++ b/packages/nextcloud/lib/src/clients/custom/webdav/client.dart
@@ -30,12 +30,6 @@ class WebDavClient {
'http://sabredav.org/ns': 's', // mostly used in error responses
};
- Future _responseToBodyBytes(final HttpClientResponse response) async =>
- Uint8List.fromList((await response.toList()).reduce((final value, final element) => [...value, ...element]));
-
- Future _responseToBodyString(final HttpClientResponse response) async =>
- utf8.decode(await _responseToBodyBytes(response));
-
Future _send(
final String method,
final String url,
@@ -66,7 +60,7 @@ class WebDavClient {
if (!expectedCodes.contains(response.statusCode)) {
throw ApiException(
response.statusCode,
- await _responseToBodyString(response),
+ await response.body,
);
}
@@ -233,7 +227,7 @@ class WebDavClient {
return treeFromWebDavXml(
basePath,
namespaces,
- await _responseToBodyString(response),
+ await response.body,
)..removeAt(0);
}
@@ -284,7 +278,7 @@ class WebDavClient {
return treeFromWebDavXml(
basePath,
namespaces,
- await _responseToBodyString(response),
+ await response.body,
);
}
@@ -306,7 +300,7 @@ class WebDavClient {
return fileFromWebDavXml(
basePath,
namespaces,
- await _responseToBodyString(response),
+ await response.body,
);
}
@@ -350,7 +344,7 @@ class WebDavClient {
[200, 207],
data: Stream.value(Uint8List.fromList(utf8.encode(builder.buildDocument().toString()))),
);
- return checkUpdateFromWebDavXml(await _responseToBodyString(response));
+ return checkUpdateFromWebDavXml(await response.body);
}
/// Move a file from [sourcePath] to [destinationPath]
diff --git a/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart b/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart
index 5d7e664cb38..c0653380272 100644
--- a/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart
+++ b/packages/nextcloud/lib/src/clients/custom/webdav/webdav.dart
@@ -6,6 +6,7 @@ import 'dart:typed_data';
import 'package:intl/intl.dart';
import 'package:nextcloud/src/clients/common/api.dart';
+import 'package:nextcloud/src/http_client_response_extension.dart';
import 'package:xml/xml.dart';
import 'package:xml/xml.dart' as xml;
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api.dart
new file mode 100644
index 00000000000..60138dc8d3e
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/api.dart
@@ -0,0 +1,39 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+library openapi.api;
+
+import 'package:nextcloud/src/clients/common/api.dart';
+
+import 'dart:async';
+import 'dart:convert';
+import 'dart:io';
+
+import 'package:http/http.dart';
+import 'package:intl/intl.dart';
+import 'package:meta/meta.dart';
+
+part 'api_client.dart';
+
+part 'api/default_api.dart';
+
+part 'model/admin_notification.dart';
+part 'model/empty_response.dart';
+part 'model/empty_response_ocs.dart';
+part 'model/get_notification_response.dart';
+part 'model/get_notification_response_ocs.dart';
+part 'model/list_notifications_response.dart';
+part 'model/list_notifications_response_ocs.dart';
+part 'model/notification.dart';
+part 'model/push_notification_decrypted_subject.dart';
+part 'model/push_server_device.dart';
+part 'model/push_server_registration_response.dart';
+part 'model/push_server_registration_response_ocs.dart';
+part 'model/push_server_subscription.dart';
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart
new file mode 100644
index 00000000000..7a6bbe0ecc5
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/api/default_api.dart
@@ -0,0 +1,364 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+class DefaultApi extends ApiInstance {
+ DefaultApi(ApiClient apiClient) : super(apiClient);
+
+ /// Performs an HTTP 'DELETE /api/v2/notifications' operation and returns the [Response].
+ Future deleteAllNotificationsWithHttpInfo() async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/notifications';
+
+ // ignore: prefer_final_locals
+ Object? postBody;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = [];
+
+ return apiClient.invokeAPI(
+ path,
+ 'DELETE',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ Future deleteAllNotifications() async {
+ final response = await deleteAllNotificationsWithHttpInfo();
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'String',
+ ) as String;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'DELETE /api/v2/notifications/{id}' operation and returns the [Response].
+ /// Parameters:
+ ///
+ /// * [int] id (required):
+ Future deleteNotificationWithHttpInfo(
+ int id,
+ ) async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/notifications/{id}'.replaceAll('{id}', id.toString());
+
+ // ignore: prefer_final_locals
+ Object? postBody;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = [];
+
+ return apiClient.invokeAPI(
+ path,
+ 'DELETE',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ /// Parameters:
+ ///
+ /// * [int] id (required):
+ Future deleteNotification(
+ int id,
+ ) async {
+ final response = await deleteNotificationWithHttpInfo(
+ id,
+ );
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'EmptyResponse',
+ ) as EmptyResponse;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'GET /api/v2/notifications/{id}' operation and returns the [Response].
+ /// Parameters:
+ ///
+ /// * [int] id (required):
+ Future getNotificationWithHttpInfo(
+ int id,
+ ) async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/notifications/{id}'.replaceAll('{id}', id.toString());
+
+ // ignore: prefer_final_locals
+ Object? postBody;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = [];
+
+ return apiClient.invokeAPI(
+ path,
+ 'GET',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ /// Parameters:
+ ///
+ /// * [int] id (required):
+ Future getNotification(
+ int id,
+ ) async {
+ final response = await getNotificationWithHttpInfo(
+ id,
+ );
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'GetNotificationResponse',
+ ) as GetNotificationResponse;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'GET /api/v2/notifications' operation and returns the [Response].
+ Future listNotificationsWithHttpInfo() async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/notifications';
+
+ // ignore: prefer_final_locals
+ Object? postBody;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = [];
+
+ return apiClient.invokeAPI(
+ path,
+ 'GET',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ Future listNotifications() async {
+ final response = await listNotificationsWithHttpInfo();
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'String',
+ ) as String;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'POST /api/v2/push' operation and returns the [Response].
+ /// Parameters:
+ ///
+ /// * [PushServerDevice] pushServerDevice (required):
+ Future registerDeviceWithHttpInfo(
+ PushServerDevice pushServerDevice,
+ ) async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/push';
+
+ // ignore: prefer_final_locals
+ Object? postBody = pushServerDevice;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = ['application/json'];
+
+ return apiClient.invokeAPI(
+ path,
+ 'POST',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ /// Parameters:
+ ///
+ /// * [PushServerDevice] pushServerDevice (required):
+ Future registerDevice(
+ PushServerDevice pushServerDevice,
+ ) async {
+ final response = await registerDeviceWithHttpInfo(
+ pushServerDevice,
+ );
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'PushServerRegistrationResponse',
+ ) as PushServerRegistrationResponse;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'DELETE /api/v2/push' operation and returns the [Response].
+ Future removeDeviceWithHttpInfo() async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/push';
+
+ // ignore: prefer_final_locals
+ Object? postBody;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = [];
+
+ return apiClient.invokeAPI(
+ path,
+ 'DELETE',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ Future removeDevice() async {
+ final response = await removeDeviceWithHttpInfo();
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'String',
+ ) as String;
+ }
+ return null;
+ }
+
+ /// Performs an HTTP 'POST /api/v2/admin_notifications/{userId}' operation and returns the [Response].
+ /// Parameters:
+ ///
+ /// * [String] userId (required):
+ ///
+ /// * [AdminNotification] adminNotification (required):
+ Future sendAdminNotificationWithHttpInfo(
+ String userId,
+ AdminNotification adminNotification,
+ ) async {
+ // ignore: prefer_const_declarations
+ final path = r'/api/v2/admin_notifications/{userId}'.replaceAll('{userId}', userId);
+
+ // ignore: prefer_final_locals
+ Object? postBody = adminNotification;
+
+ final queryParams = [];
+ final headerParams = {};
+ final formParams = {};
+
+ const contentTypes = ['application/json'];
+
+ return apiClient.invokeAPI(
+ path,
+ 'POST',
+ queryParams,
+ postBody,
+ headerParams,
+ formParams,
+ contentTypes.isEmpty ? null : contentTypes.first,
+ );
+ }
+
+ /// Parameters:
+ ///
+ /// * [String] userId (required):
+ ///
+ /// * [AdminNotification] adminNotification (required):
+ Future sendAdminNotification(
+ String userId,
+ AdminNotification adminNotification,
+ ) async {
+ final response = await sendAdminNotificationWithHttpInfo(
+ userId,
+ adminNotification,
+ );
+ if (response.statusCode >= HttpStatus.badRequest) {
+ throw ApiException(response.statusCode, await decodeBodyBytes(response));
+ }
+ // When a remote server returns no body with a status of 204, we shall not decode it.
+ // At the time of writing this, `dart:convert` will throw an "Unexpected end of input"
+ // FormatException when trying to decode an empty string.
+ if (response.body.isNotEmpty && response.statusCode != HttpStatus.noContent) {
+ return await apiClient.deserializeAsync(
+ await decodeBodyBytes(response),
+ 'EmptyResponse',
+ ) as EmptyResponse;
+ }
+ return null;
+ }
+}
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart b/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart
new file mode 100644
index 00000000000..69aca6f01b8
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/api_client.dart
@@ -0,0 +1,329 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+class ApiClient extends BaseApiClient {
+ ApiClient({this.basePath = 'https://localhost:8080/ocs/v1.php/apps/notifications', this.authentication});
+
+ final String basePath;
+
+ var _client = Client();
+
+ /// Returns the current HTTP [Client] instance to use in this class.
+ ///
+ /// The return value is guaranteed to never be null.
+ Client get client => _client;
+
+ /// Requests to use a new HTTP [Client] in this class.
+ set client(Client newClient) {
+ _client = newClient;
+ }
+
+ final _defaultHeaderMap = {};
+ final Authentication? authentication;
+
+ void addDefaultHeader(String key, String value) {
+ _defaultHeaderMap[key] = value;
+ }
+
+ Map get defaultHeaderMap => _defaultHeaderMap;
+
+ // We don't use a Map for queryParams.
+ // If collectionFormat is 'multi', a key might appear multiple times.
+ Future invokeAPI(
+ String path,
+ String method,
+ List queryParams,
+ Object? body,
+ Map headerParams,
+ Map formParams,
+ String? contentType,
+ ) async {
+ _updateParamsForAuth(queryParams, headerParams);
+
+ headerParams.addAll(_defaultHeaderMap);
+ if (contentType != null) {
+ headerParams['Content-Type'] = contentType;
+ }
+
+ final urlEncodedQueryParams = queryParams.map((param) => '$param');
+ final queryString = urlEncodedQueryParams.isNotEmpty ? '?${urlEncodedQueryParams.join('&')}' : '';
+ final uri = Uri.parse('$basePath$path$queryString');
+
+ try {
+ // Special case for uploading a single file which isn't a 'multipart/form-data'.
+ if (body is MultipartFile &&
+ (contentType == null || !contentType.toLowerCase().startsWith('multipart/form-data'))) {
+ final request = StreamedRequest(method, uri);
+ request.headers.addAll(headerParams);
+ request.contentLength = body.length;
+ body.finalize().listen(
+ request.sink.add,
+ onDone: request.sink.close,
+ // ignore: avoid_types_on_closure_parameters
+ onError: (Object error, StackTrace trace) => request.sink.close(),
+ cancelOnError: true,
+ );
+ final response = await _client.send(request);
+ return Response.fromStream(response);
+ }
+
+ if (body is MultipartRequest) {
+ final request = MultipartRequest(method, uri);
+ request.fields.addAll(body.fields);
+ request.files.addAll(body.files);
+ request.headers.addAll(body.headers);
+ request.headers.addAll(headerParams);
+ final response = await _client.send(request);
+ return Response.fromStream(response);
+ }
+
+ final msgBody = contentType == 'application/x-www-form-urlencoded' ? formParams : await serializeAsync(body);
+ final nullableHeaderParams = headerParams.isEmpty ? null : headerParams;
+
+ switch (method) {
+ case 'POST':
+ return await _client.post(
+ uri,
+ headers: nullableHeaderParams,
+ body: msgBody,
+ );
+ case 'PUT':
+ return await _client.put(
+ uri,
+ headers: nullableHeaderParams,
+ body: msgBody,
+ );
+ case 'DELETE':
+ return await _client.delete(
+ uri,
+ headers: nullableHeaderParams,
+ body: msgBody,
+ );
+ case 'PATCH':
+ return await _client.patch(
+ uri,
+ headers: nullableHeaderParams,
+ body: msgBody,
+ );
+ case 'HEAD':
+ return await _client.head(
+ uri,
+ headers: nullableHeaderParams,
+ );
+ case 'GET':
+ return await _client.get(
+ uri,
+ headers: nullableHeaderParams,
+ );
+ }
+ } on SocketException catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.badRequest,
+ 'Socket operation failed: $method $path',
+ error,
+ trace,
+ );
+ } on TlsException catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.badRequest,
+ 'TLS/SSL communication failed: $method $path',
+ error,
+ trace,
+ );
+ } on IOException catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.badRequest,
+ 'I/O operation failed: $method $path',
+ error,
+ trace,
+ );
+ } on ClientException catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.badRequest,
+ 'HTTP connection failed: $method $path',
+ error,
+ trace,
+ );
+ } on Exception catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.badRequest,
+ 'Exception occurred: $method $path',
+ error,
+ trace,
+ );
+ }
+
+ throw ApiException(
+ HttpStatus.badRequest,
+ 'Invalid HTTP operation: $method $path',
+ );
+ }
+
+ Future deserializeAsync(
+ String json,
+ String targetType, {
+ bool growable = false,
+ }) async =>
+ // ignore: deprecated_member_use_from_same_package
+ deserialize(json, targetType, growable: growable);
+
+ @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use deserializeAsync() instead.')
+ dynamic deserialize(
+ String json,
+ String targetType, {
+ bool growable = false,
+ }) {
+ // Remove all spaces. Necessary for regular expressions as well.
+ targetType = targetType.replaceAll(' ', ''); // ignore: parameter_assignments
+
+ // If the expected target type is String, nothing to do...
+ return targetType == 'String' ? json : _deserialize(jsonDecode(json), targetType, growable: growable);
+ }
+
+ // ignore: deprecated_member_use_from_same_package
+ Future serializeAsync(Object? value) async => serialize(value);
+
+ @Deprecated('Scheduled for removal in OpenAPI Generator 6.x. Use serializeAsync() instead.')
+ String serialize(Object? value) => value == null ? '' : json.encode(value);
+
+ /// Update query and header parameters based on authentication settings.
+ void _updateParamsForAuth(
+ List queryParams,
+ Map headerParams,
+ ) {
+ if (authentication != null) {
+ authentication!.applyToParams(queryParams, headerParams);
+ }
+ }
+
+ static dynamic _deserialize(dynamic value, String targetType, {bool growable = false}) {
+ try {
+ switch (targetType) {
+ case 'String':
+ return value is String ? value : value.toString();
+ case 'int':
+ return value is int ? value : int.parse('$value');
+ case 'double':
+ return value is double ? value : double.parse('$value');
+ case 'bool':
+ if (value is bool) {
+ return value;
+ }
+ final valueString = '$value'.toLowerCase();
+ return valueString == 'true' || valueString == '1';
+ case 'AdminNotification':
+ return AdminNotification.fromJson(value);
+ case 'EmptyResponse':
+ return EmptyResponse.fromJson(value);
+ case 'EmptyResponseOcs':
+ return EmptyResponseOcs.fromJson(value);
+ case 'GetNotificationResponse':
+ return GetNotificationResponse.fromJson(value);
+ case 'GetNotificationResponseOcs':
+ return GetNotificationResponseOcs.fromJson(value);
+ case 'ListNotificationsResponse':
+ return ListNotificationsResponse.fromJson(value);
+ case 'ListNotificationsResponseOcs':
+ return ListNotificationsResponseOcs.fromJson(value);
+ case 'Notification':
+ return Notification.fromJson(value);
+ case 'PushNotificationDecryptedSubject':
+ return PushNotificationDecryptedSubject.fromJson(value);
+ case 'PushServerDevice':
+ return PushServerDevice.fromJson(value);
+ case 'PushServerRegistrationResponse':
+ return PushServerRegistrationResponse.fromJson(value);
+ case 'PushServerRegistrationResponseOcs':
+ return PushServerRegistrationResponseOcs.fromJson(value);
+ case 'PushServerSubscription':
+ return PushServerSubscription.fromJson(value);
+ default:
+ dynamic match;
+ if (value is List && (match = apiRegList.firstMatch(targetType)?.group(1)) != null) {
+ return value
+ .map((dynamic v) => _deserialize(
+ v,
+ match,
+ growable: growable,
+ ))
+ .toList(growable: growable);
+ }
+ if (value is Set && (match = apiRegSet.firstMatch(targetType)?.group(1)) != null) {
+ return value
+ .map((dynamic v) => _deserialize(
+ v,
+ match,
+ growable: growable,
+ ))
+ .toSet();
+ }
+ if (value is Map && (match = apiRegMap.firstMatch(targetType)?.group(1)) != null) {
+ return Map.fromIterables(
+ value.keys.cast(),
+ value.values.map((dynamic v) => _deserialize(
+ v,
+ match,
+ growable: growable,
+ )),
+ );
+ }
+ }
+ } on Exception catch (error, trace) {
+ throw ApiException.withInner(
+ HttpStatus.internalServerError,
+ 'Exception during deserialization.',
+ error,
+ trace,
+ );
+ }
+ throw ApiException(
+ HttpStatus.internalServerError,
+ 'Could not find a suitable class for deserialization',
+ );
+ }
+}
+
+/// Primarily intended for use in an isolate.
+class DeserializationMessage {
+ const DeserializationMessage({
+ required this.json,
+ required this.targetType,
+ this.growable = false,
+ });
+
+ /// The JSON value to deserialize.
+ final String json;
+
+ /// Target type to deserialize to.
+ final String targetType;
+
+ /// Whether to make deserialized lists or maps growable.
+ final bool growable;
+}
+
+/// Primarily intended for use in an isolate.
+Future deserializeAsync(DeserializationMessage message) async {
+ // Remove all spaces. Necessary for regular expressions as well.
+ final targetType = message.targetType.replaceAll(' ', '');
+
+ // If the expected target type is String, nothing to do...
+ return targetType == 'String'
+ ? message.json
+ : ApiClient._deserialize(
+ jsonDecode(message.json),
+ targetType,
+ growable: message.growable,
+ );
+}
+
+/// Primarily intended for use in an isolate.
+Future serializeAsync(Object? value) async => value == null ? '' : json.encode(value);
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart
new file mode 100644
index 00000000000..6b7ccd2205c
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/admin_notification.dart
@@ -0,0 +1,139 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+class AdminNotification {
+ /// Returns a new [AdminNotification] instance.
+ AdminNotification({
+ this.shortMessage,
+ this.longMessage,
+ });
+
+ ///
+ /// Please note: This property should have been non-nullable! Since the specification file
+ /// does not include a default value (using the "default:" property), however, the generated
+ /// source code must fall back to having a nullable type.
+ /// Consider adding a "default:" property in the specification file to hide this note.
+ ///
+ String? shortMessage;
+
+ ///
+ /// Please note: This property should have been non-nullable! Since the specification file
+ /// does not include a default value (using the "default:" property), however, the generated
+ /// source code must fall back to having a nullable type.
+ /// Consider adding a "default:" property in the specification file to hide this note.
+ ///
+ String? longMessage;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) ||
+ other is AdminNotification && other.shortMessage == shortMessage && other.longMessage == longMessage;
+
+ @override
+ int get hashCode =>
+ // ignore: unnecessary_parenthesis
+ (shortMessage == null ? 0 : shortMessage!.hashCode) + (longMessage == null ? 0 : longMessage!.hashCode);
+
+ @override
+ String toString() => 'AdminNotification[shortMessage=$shortMessage, longMessage=$longMessage]';
+
+ Map toJson() {
+ final _json = {};
+ if (shortMessage != null) {
+ _json[r'shortMessage'] = shortMessage;
+ }
+ if (longMessage != null) {
+ _json[r'longMessage'] = longMessage;
+ }
+ return _json;
+ }
+
+ /// Returns a new [AdminNotification] instance and imports its values from
+ /// [value] if it's a [Map], null otherwise.
+ // ignore: prefer_constructors_over_static_methods
+ static AdminNotification? fromJson(dynamic value) {
+ if (value is Map) {
+ final json = value.cast();
+
+ // Ensure that the map contains the required keys.
+ // Note 1: the values aren't checked for validity beyond being non-null.
+ // Note 2: this code is stripped in release mode!
+ assert(() {
+ requiredKeys.forEach((key) {
+ assert(json.containsKey(key), 'Required key "AdminNotification[$key]" is missing from JSON.');
+ assert(json[key] != null, 'Required key "AdminNotification[$key]" has a null value in JSON.');
+ });
+ return true;
+ }());
+
+ return AdminNotification(
+ shortMessage: mapValueOfType(json, r'shortMessage'),
+ longMessage: mapValueOfType(json, r'longMessage'),
+ );
+ }
+ return null;
+ }
+
+ static List? listFromJson(
+ dynamic json, {
+ bool growable = false,
+ }) {
+ final result = [];
+ if (json is List && json.isNotEmpty) {
+ for (final row in json) {
+ final value = AdminNotification.fromJson(row);
+ if (value != null) {
+ result.add(value);
+ }
+ }
+ }
+ return result.toList(growable: growable);
+ }
+
+ static Map mapFromJson(dynamic json) {
+ final map = {};
+ if (json is Map && json.isNotEmpty) {
+ json = json.cast(); // ignore: parameter_assignments
+ for (final entry in json.entries) {
+ final value = AdminNotification.fromJson(entry.value);
+ if (value != null) {
+ map[entry.key] = value;
+ }
+ }
+ }
+ return map;
+ }
+
+ // maps a json object with a list of AdminNotification-objects as value to a dart map
+ static Map> mapListFromJson(
+ dynamic json, {
+ bool growable = false,
+ }) {
+ final map = >{};
+ if (json is Map && json.isNotEmpty) {
+ json = json.cast(); // ignore: parameter_assignments
+ for (final entry in json.entries) {
+ final value = AdminNotification.listFromJson(
+ entry.value,
+ growable: growable,
+ );
+ if (value != null) {
+ map[entry.key] = value;
+ }
+ }
+ }
+ return map;
+ }
+
+ /// The list of required keys that must be present in a JSON.
+ static const requiredKeys = {};
+}
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart
new file mode 100644
index 00000000000..f8190763ce1
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response.dart
@@ -0,0 +1,124 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+class EmptyResponse {
+ /// Returns a new [EmptyResponse] instance.
+ EmptyResponse({
+ this.ocs,
+ });
+
+ ///
+ /// Please note: This property should have been non-nullable! Since the specification file
+ /// does not include a default value (using the "default:" property), however, the generated
+ /// source code must fall back to having a nullable type.
+ /// Consider adding a "default:" property in the specification file to hide this note.
+ ///
+ EmptyResponseOcs? ocs;
+
+ @override
+ bool operator ==(Object other) => identical(this, other) || other is EmptyResponse && other.ocs == ocs;
+
+ @override
+ int get hashCode =>
+ // ignore: unnecessary_parenthesis
+ (ocs == null ? 0 : ocs!.hashCode);
+
+ @override
+ String toString() => 'EmptyResponse[ocs=$ocs]';
+
+ Map toJson() {
+ final _json = {};
+ if (ocs != null) {
+ _json[r'ocs'] = ocs;
+ }
+ return _json;
+ }
+
+ /// Returns a new [EmptyResponse] instance and imports its values from
+ /// [value] if it's a [Map], null otherwise.
+ // ignore: prefer_constructors_over_static_methods
+ static EmptyResponse? fromJson(dynamic value) {
+ if (value is Map) {
+ final json = value.cast();
+
+ // Ensure that the map contains the required keys.
+ // Note 1: the values aren't checked for validity beyond being non-null.
+ // Note 2: this code is stripped in release mode!
+ assert(() {
+ requiredKeys.forEach((key) {
+ assert(json.containsKey(key), 'Required key "EmptyResponse[$key]" is missing from JSON.');
+ assert(json[key] != null, 'Required key "EmptyResponse[$key]" has a null value in JSON.');
+ });
+ return true;
+ }());
+
+ return EmptyResponse(
+ ocs: EmptyResponseOcs.fromJson(json[r'ocs']),
+ );
+ }
+ return null;
+ }
+
+ static List? listFromJson(
+ dynamic json, {
+ bool growable = false,
+ }) {
+ final result = [];
+ if (json is List && json.isNotEmpty) {
+ for (final row in json) {
+ final value = EmptyResponse.fromJson(row);
+ if (value != null) {
+ result.add(value);
+ }
+ }
+ }
+ return result.toList(growable: growable);
+ }
+
+ static Map mapFromJson(dynamic json) {
+ final map = {};
+ if (json is Map && json.isNotEmpty) {
+ json = json.cast(); // ignore: parameter_assignments
+ for (final entry in json.entries) {
+ final value = EmptyResponse.fromJson(entry.value);
+ if (value != null) {
+ map[entry.key] = value;
+ }
+ }
+ }
+ return map;
+ }
+
+ // maps a json object with a list of EmptyResponse-objects as value to a dart map
+ static Map> mapListFromJson(
+ dynamic json, {
+ bool growable = false,
+ }) {
+ final map = >{};
+ if (json is Map && json.isNotEmpty) {
+ json = json.cast(); // ignore: parameter_assignments
+ for (final entry in json.entries) {
+ final value = EmptyResponse.listFromJson(
+ entry.value,
+ growable: growable,
+ );
+ if (value != null) {
+ map[entry.key] = value;
+ }
+ }
+ }
+ return map;
+ }
+
+ /// The list of required keys that must be present in a JSON.
+ static const requiredKeys = {};
+}
diff --git a/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart
new file mode 100644
index 00000000000..e5f3157b5fc
--- /dev/null
+++ b/packages/nextcloud/lib/src/clients/generated/notifications/model/empty_response_ocs.dart
@@ -0,0 +1,125 @@
+//
+// AUTO-GENERATED FILE, DO NOT MODIFY!
+//
+// @dart=2.12
+
+// ignore_for_file: unused_element, unused_import
+// ignore_for_file: always_put_required_named_parameters_first
+// ignore_for_file: constant_identifier_names
+// ignore_for_file: lines_longer_than_80_chars
+
+part of openapi.api;
+
+class EmptyResponseOcs {
+ /// Returns a new [EmptyResponseOcs] instance.
+ EmptyResponseOcs({
+ this.meta,
+ this.data = const [],
+ });
+
+ /// Stub
+ Object? meta;
+
+ List data;
+
+ @override
+ bool operator ==(Object other) =>
+ identical(this, other) || other is EmptyResponseOcs && other.meta == meta && other.data == data;
+
+ @override
+ int get hashCode =>
+ // ignore: unnecessary_parenthesis
+ (meta == null ? 0 : meta!.hashCode) + (data.hashCode);
+
+ @override
+ String toString() => 'EmptyResponseOcs[meta=$meta, data=$data]';
+
+ Map toJson() {
+ final _json = {};
+ if (meta != null) {
+ _json[r'meta'] = meta;
+ }
+ _json[r'data'] = data;
+ return _json;
+ }
+
+ /// Returns a new [EmptyResponseOcs] instance and imports its values from
+ /// [value] if it's a [Map], null otherwise.
+ // ignore: prefer_constructors_over_static_methods
+ static EmptyResponseOcs? fromJson(dynamic value) {
+ if (value is Map) {
+ final json = value.cast();
+
+ // Ensure that the map contains the required keys.
+ // Note 1: the values aren't checked for validity beyond being non-null.
+ // Note 2: this code is stripped in release mode!
+ assert(() {
+ requiredKeys.forEach((key) {
+ assert(json.containsKey(key), 'Required key "EmptyResponseOcs[$key]" is missing from JSON.');
+ assert(json[key] != null, 'Required key "EmptyResponseOcs[$key]" has a null value in JSON.');
+ });
+ return true;
+ }());
+
+ return EmptyResponseOcs(
+ meta: mapValueOfType