diff --git a/packages/app/aurora/rpm/su.markow.nextcloud-neon.spec b/packages/app/aurora/rpm/su.markow.nextcloud-neon.spec index 510c7210..35e85b3b 100644 --- a/packages/app/aurora/rpm/su.markow.nextcloud-neon.spec +++ b/packages/app/aurora/rpm/su.markow.nextcloud-neon.spec @@ -1,5 +1,5 @@ %global __provides_exclude_from ^%{_datadir}/%{name}/lib/.*$ -%global __requires_exclude ^lib(dconf|flutter-embedder|maliit-glib|.+_platform_plugin)\\.so.*$ +%global __requires_exclude ^lib(yuv|ZXing|jpeg|dconf|flutter-embedder|maliit-glib|.+_platform_plugin)\\.so.*$ Name: su.markow.nextcloud-neon Summary: A new Flutter project. @@ -11,6 +11,7 @@ Source0: %{name}-%{version}.tar.zst BuildRequires: cmake BuildRequires: pkgconfig(flutter-embedder) BuildRequires: pkgconfig(sqlite3) +BuildRequires: pkgconfig(streamcamera) %description %{summary}. @@ -19,7 +20,7 @@ BuildRequires: pkgconfig(sqlite3) %autosetup %build -%cmake -DCMAKE_BUILD_TYPE=%{_flutter_build_type} +%cmake -DCMAKE_BUILD_TYPE=%{_flutter_build_type} -DPSDK_VERSION=%{_flutter_psdk_version} -DPSDK_MAJOR=%{_flutter_psdk_major} %make_build %install diff --git a/packages/app/linux/flutter/generated_plugins.cmake b/packages/app/linux/flutter/generated_plugins.cmake index eb1257c1..92928726 100644 --- a/packages/app/linux/flutter/generated_plugins.cmake +++ b/packages/app/linux/flutter/generated_plugins.cmake @@ -12,6 +12,7 @@ list(APPEND FLUTTER_PLUGIN_LIST ) list(APPEND FLUTTER_FFI_PLUGIN_LIST + camera_linux flutter_zxing ) diff --git a/packages/app/pubspec.lock b/packages/app/pubspec.lock index 5f81a88f..962bdd0c 100644 --- a/packages/app/pubspec.lock +++ b/packages/app/pubspec.lock @@ -74,7 +74,7 @@ packages: source: hosted version: "8.8.0" camera: - dependency: transitive + dependency: "direct main" description: name: camera sha256: "1f9010f0689774380fbcd7d6b7820a5157e8e97685fa66d619e1d1f58b3fdf93" @@ -89,6 +89,15 @@ packages: url: "https://pub.dev" source: hosted version: "0.10.8+13" + camera_aurora: + dependency: "direct main" + description: + path: "packages/camera/camera_aurora" + ref: "camera_aurora-0.0.1" + resolved-ref: c60d7e18a052dcefaf790f41272949551c421a47 + url: "https://gitlab.com/omprussia/flutter/flutter-plugins.git" + source: git + version: "0.0.1" camera_avfoundation: dependency: transitive description: @@ -97,6 +106,14 @@ packages: url: "https://pub.dev" source: hosted version: "0.9.13+7" + camera_linux: + dependency: "direct main" + description: + name: camera_linux + sha256: "6ea08c23f643364e650e8fad73653747c049cbd00803a7c317132379ee3653ac" + url: "https://pub.dev" + source: hosted + version: "0.0.8" camera_platform_interface: dependency: transitive description: @@ -141,10 +158,10 @@ packages: dependency: transitive description: name: collection - sha256: f092b211a4319e98e5ff58223576de6c2803db36221657b46c82574721240687 + sha256: ee67cb0715911d28db6bf4af1026078bd6f0128b07a5f66fb2ed94ec6783c09a url: "https://pub.dev" source: hosted - version: "1.17.2" + version: "1.18.0" convert: dependency: transitive description: @@ -654,10 +671,10 @@ packages: dependency: transitive description: name: meta - sha256: "3c74dbf8763d36539f114c799d8a2d87343b5067e9d796ca22b5eb8437090ee3" + sha256: a6e590c838b18133bb482a2745ad77c5bb7715fb0451209e1a7567d416678b8e url: "https://pub.dev" source: hosted - version: "1.9.1" + version: "1.10.0" mime: dependency: transitive description: @@ -896,10 +913,10 @@ packages: dependency: transitive description: name: platform - sha256: "4a451831508d7d6ca779f7ac6e212b4023dd5a7d08a27a63da33756410e32b76" + sha256: ae68c7bfcd7383af3629daafb32fb4e8681c7154428da4febcff06200585f102 url: "https://pub.dev" source: hosted - version: "3.1.0" + version: "3.1.2" plugin_platform_interface: dependency: transitive description: @@ -1182,18 +1199,18 @@ packages: dependency: transitive description: name: stack_trace - sha256: c3c7d8edb15bee7f0f74debd4b9c5f3c2ea86766fe4178eb2a18eb30a0bdaed5 + sha256: "73713990125a6d93122541237550ee3352a2d84baad52d375a4cad2eb9b7ce0b" url: "https://pub.dev" source: hosted - version: "1.11.0" + version: "1.11.1" stream_channel: dependency: transitive description: name: stream_channel - sha256: "83615bee9045c1d322bbbd1ba209b7a749c2cbcdcb3fdd1df8eb488b3279c1c8" + sha256: ba2aa5d8cc609d96bbb2899c28934f9e1af5cddbd60a827822ea467161eb54e7 url: "https://pub.dev" source: hosted - version: "2.1.1" + version: "2.1.2" stream_transform: dependency: transitive description: @@ -1238,10 +1255,10 @@ packages: dependency: transitive description: name: test_api - sha256: "75760ffd7786fffdfb9597c35c5b27eaeec82be8edfb6d71d32651128ed7aab8" + sha256: "5c2f730018264d276c20e4f1503fd1308dfbbae39ec8ee63c5236311ac06954b" url: "https://pub.dev" source: hosted - version: "0.6.0" + version: "0.6.1" timezone: dependency: transitive description: @@ -1414,10 +1431,10 @@ packages: dependency: transitive description: name: vm_service - sha256: c620a6f783fa22436da68e42db7ebbf18b8c44b9a46ab911f666ff09ffd9153f + sha256: c538be99af830f478718b51630ec1b6bee5e74e52c8a802d328d9e71d35d2583 url: "https://pub.dev" source: hosted - version: "11.7.1" + version: "11.10.0" wakelock_plus: dependency: transitive description: @@ -1438,10 +1455,10 @@ packages: dependency: transitive description: name: web - sha256: dc8ccd225a2005c1be616fe02951e2e342092edf968cf0844220383757ef8f10 + sha256: afe077240a270dcfd2aafe77602b4113645af95d0ad31128cc02bce5ac5d5152 url: "https://pub.dev" source: hosted - version: "0.1.4-beta" + version: "0.3.0" webdriver: dependency: transitive description: @@ -1540,5 +1557,5 @@ packages: source: hosted version: "3.1.2" sdks: - dart: ">=3.1.0 <4.0.0" + dart: ">=3.2.0-194.0.dev <4.0.0" flutter: ">=3.13.0" diff --git a/packages/app/pubspec.yaml b/packages/app/pubspec.yaml index 7160e046..fe4f5b48 100644 --- a/packages/app/pubspec.yaml +++ b/packages/app/pubspec.yaml @@ -9,7 +9,13 @@ environment: dependencies: flutter: sdk: flutter - + camera: ^0.10.5+5 + camera_aurora: + git: + url: https://gitlab.com/omprussia/flutter/flutter-plugins.git + ref: camera_aurora-0.0.1 + path: packages/camera/camera_aurora + camera_linux: ^0.0.8 sqflite: ^2.3.0 sqflite_aurora: diff --git a/packages/neon/neon/lib/l10n/localizations.dart b/packages/neon/neon/lib/l10n/localizations.dart index b588aaf2..3374bac6 100644 --- a/packages/neon/neon/lib/l10n/localizations.dart +++ b/packages/neon/neon/lib/l10n/localizations.dart @@ -87,7 +87,9 @@ abstract class NeonLocalizations { ]; /// A list of this localizations delegate's supported locales. - static const List supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @nextcloud. /// @@ -706,14 +708,17 @@ class _NeonLocalizationsDelegate extends LocalizationsDelegate 'The credentials for this account no longer match'; @override - String get errorServerHadAProblemProcessingYourRequest => - 'The server had a problem while processing your request. You might want to try again'; + String get errorServerHadAProblemProcessingYourRequest => 'The server had a problem while processing your request. You might want to try again'; @override String get errorSomethingWentWrongTryAgainLater => 'Something went wrong. Please try again later'; @@ -95,12 +94,10 @@ class NeonLocalizationsEn extends NeonLocalizations { String get errorConnectionTimedOut => 'Connection has timed out'; @override - String get errorNoCompatibleNextcloudAppsFound => - 'No compatible Nextcloud apps could be found.\nWe are working hard to implement more and more apps!'; + String get errorNoCompatibleNextcloudAppsFound => 'No compatible Nextcloud apps could be found.\nWe are working hard to implement more and more apps!'; @override - String get errorServerInMaintenanceMode => - 'The server is in maintenance mode. Please try again later or contact the server admin.'; + String get errorServerInMaintenanceMode => 'The server is in maintenance mode. Please try again later or contact the server admin.'; @override String errorMissingPermission(String name) { @@ -154,8 +151,7 @@ class NeonLocalizationsEn extends NeonLocalizations { String get nextPushSupported => 'NextPush is supported!'; @override - String get nextPushSupportedText => - 'NextPush is a FOSS way of receiving push notifications using the UnifiedPush protocol via a Nextcloud instance.\nYou can install NextPush from the F-Droid app store.'; + String get nextPushSupportedText => 'NextPush is a FOSS way of receiving push notifications using the UnifiedPush protocol via a Nextcloud instance.\nYou can install NextPush from the F-Droid app store.'; @override String get nextPushSupportedInstall => 'Install NextPush'; @@ -258,8 +254,7 @@ class NeonLocalizationsEn extends NeonLocalizations { String get globalOptionsPushNotificationsEnabled => 'Enabled'; @override - String get globalOptionsPushNotificationsEnabledDisabledNotice => - 'No UnifiedPush distributor could be found or you denied the permission for showing notifications. Please go to the app settings and allow notifications and go to https://unifiedpush.org/users/distributors and setup any of the listed distributors. Then re-open this app and you should be able to enable notifications'; + String get globalOptionsPushNotificationsEnabledDisabledNotice => 'No UnifiedPush distributor could be found or you denied the permission for showing notifications. Please go to the app settings and allow notifications and go to https://unifiedpush.org/users/distributors and setup any of the listed distributors. Then re-open this app and you should be able to enable notifications'; @override String get globalOptionsPushNotificationsDistributor => 'UnifiedPush Distributor'; diff --git a/packages/neon/neon/lib/src/pages/aurora_login_qr_code.dart b/packages/neon/neon/lib/src/pages/aurora_login_qr_code.dart new file mode 100644 index 00000000..9c7ff1c2 --- /dev/null +++ b/packages/neon/neon/lib/src/pages/aurora_login_qr_code.dart @@ -0,0 +1,155 @@ +import 'dart:async'; +import 'dart:math'; +import 'dart:ui'; + +import 'package:camera/camera.dart'; +import 'package:camera_aurora/camera_aurora.dart'; +import 'package:flutter/material.dart'; +import 'package:neon/src/models/account.dart'; +import 'package:neon/src/pages/login_qr_code.dart'; +import 'package:neon/src/router.dart'; +import 'package:neon/widgets.dart'; + +class AuroraLoginQRcodePage extends StatefulWidget { + const AuroraLoginQRcodePage({super.key}); + + @override + State createState() => _AuroraLoginQRcodePageState(); +} + +class _AuroraLoginQRcodePageState extends State { + String? _lastErrorURL; + late Future _controller; + + StreamSubscription? _cameraSearchQrSubscription; + + String? code; + + Future _createController() async { + final cameras = await availableCameras(); + if (cameras.isEmpty) { + throw CameraException('not found', null); + } + + final camera = cameras.where((final element) => element.lensDirection == CameraLensDirection.back).first; + + final controller = CameraController( + camera, + ResolutionPreset.medium, + imageFormatGroup: ImageFormatGroup.jpeg, + ); + + _cameraSearchQrSubscription = cameraSearchQr?.listen((text) { + if (text.isNotEmpty) { + setState(() { + code = text; + }); + } + }); + + await controller.initialize(); + return controller; + } + + @override + void initState() { + _controller = _createController(); + super.initState(); + } + + @override + Widget build(final BuildContext context) => Scaffold( + appBar: AppBar( + backgroundColor: Theme.of(context).colorScheme.inversePrimary, + title: const Text('Отсканируйте qr код пароля приложения'), + ), + body: Center( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + FutureBuilder( + future: _controller, + builder: (final context, final snapshot) { + if (snapshot.hasData) { + if (code != null) { + String? url; + try { + print(code); + url = code; + if (url == null) { + throw const InvalidQRcodeException(); + } + final match = LoginQRcode.tryParse(url); + if (match == null) { + throw const InvalidQRcodeException(); + } + + _cameraSearchQrSubscription?.cancel(); + + LoginCheckServerStatusRoute.withCredentials( + serverUrl: match.serverURL, + loginName: match.username, + password: match.password, + ).pushReplacement(context); + } catch (e, s) { + if (_lastErrorURL != url) { + code = ''; + debugPrint(e.toString()); + debugPrint(s.toString()); + + _lastErrorURL = url; + NeonError.showSnackbar(context, e); + } + } + } + + return Expanded( + child: Stack( + children: [ + SizedBox( + width: double.maxFinite, + height: double.maxFinite, + child: snapshot.data!.buildPreview(), + // builder: (final context, final constraints) => AspectRatio( + // aspectRatio: max(constraints.maxHeight, constraints.maxWidth) / + // min(constraints.maxHeight, constraints.maxWidth), + // child: snapshot.data!.buildPreview(), + // ), + ), + ClipPath( + clipper: InvertedClipper(), + child: Container( + width: double.maxFinite, + height: double.maxFinite, + color: Colors.blue.withOpacity(0.7), + ), + ), + ], + ), + ); + } else if (snapshot.hasError) { + return Text(snapshot.error.toString()); + } + + return const CircularProgressIndicator(); + }, + ) + ], + ), + ), + ); +} + +class InvertedClipper extends CustomClipper { + @override + Path getClip(final Size size) { + final clipSize = min(size.width, size.height) * 0.6; + return Path() + ..addRect(Rect.fromLTWH(0, 0, size.width, size.height)) + ..addRect(Rect.fromLTWH((size.width / 2) - clipSize / 2, (size.height / 2) - clipSize / 2, clipSize, clipSize)) + ..fillType = PathFillType.evenOdd; + } + + @override + bool shouldReclip(final CustomClipper oldClipper) => true; +} diff --git a/packages/neon/neon/lib/src/platform/linux.dart b/packages/neon/neon/lib/src/platform/linux.dart index 53eab2d1..e247af9b 100644 --- a/packages/neon/neon/lib/src/platform/linux.dart +++ b/packages/neon/neon/lib/src/platform/linux.dart @@ -31,7 +31,7 @@ class LinuxNeonPlatform implements NeonPlatform { bool get canUseWindowManager => true; @override - bool get canUseCamera => false; + bool get canUseCamera => true; @override bool get canUsePushNotifications => false; diff --git a/packages/neon/neon/lib/src/router.dart b/packages/neon/neon/lib/src/router.dart index 5ba8289f..937c79e0 100644 --- a/packages/neon/neon/lib/src/router.dart +++ b/packages/neon/neon/lib/src/router.dart @@ -1,15 +1,18 @@ // ignore_for_file: unnecessary_overrides import 'dart:async'; +import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; import 'package:go_router/go_router.dart'; import 'package:meta/meta.dart'; +import 'package:meta/meta_meta.dart'; import 'package:neon/src/blocs/accounts.dart'; import 'package:neon/src/models/account.dart'; import 'package:neon/src/models/app_implementation.dart'; import 'package:neon/src/pages/account_settings.dart'; +import 'package:neon/src/pages/aurora_login_qr_code.dart'; import 'package:neon/src/pages/home.dart'; import 'package:neon/src/pages/login.dart'; import 'package:neon/src/pages/login_check_account.dart'; @@ -241,7 +244,10 @@ class LoginQRcodeRoute extends GoRouteData { const LoginQRcodeRoute(); @override - Widget build(final BuildContext context, final GoRouterState state) => const LoginQRcodePage(); + Widget build(final BuildContext context, final GoRouterState state) => + TargetPlatform.aurora == defaultTargetPlatform || Platform.isLinux + ? const AuroraLoginQRcodePage() + : const LoginQRcodePage(); @override FutureOr redirect(final BuildContext context, final GoRouterState state) { diff --git a/packages/neon/neon/pubspec.yaml b/packages/neon/neon/pubspec.yaml index ecb24451..6675ee15 100644 --- a/packages/neon/neon/pubspec.yaml +++ b/packages/neon/neon/pubspec.yaml @@ -64,6 +64,7 @@ dependencies: window_manager: ^0.3.0 xml: ^6.0.0 + dev_dependencies: build_runner: ^2.4.6 go_router_builder: ^2.3.4 diff --git a/packages/neon/neon_dashboard/lib/l10n/localizations.dart b/packages/neon/neon_dashboard/lib/l10n/localizations.dart index 796e67c9..2292d5ee 100644 --- a/packages/neon/neon_dashboard/lib/l10n/localizations.dart +++ b/packages/neon/neon_dashboard/lib/l10n/localizations.dart @@ -87,7 +87,9 @@ abstract class DashboardLocalizations { ]; /// A list of this localizations delegate's supported locales. - static const List supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @noEntries. /// @@ -112,14 +114,17 @@ class _DashboardLocalizationsDelegate extends LocalizationsDelegate supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @actionYes. /// @@ -376,14 +378,17 @@ class _FilesLocalizationsDelegate extends LocalizationsDelegate supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @actionClose. /// @@ -442,14 +444,17 @@ class _NewsLocalizationsDelegate extends LocalizationsDelegate supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @errorChangedOnServer. /// @@ -280,14 +282,17 @@ class _NotesLocalizationsDelegate extends LocalizationsDelegate supportedLocales = [Locale('en')]; + static const List supportedLocales = [ + Locale('en') + ]; /// No description provided for @actionClose. /// @@ -124,14 +126,17 @@ class _NotificationsLocalizationsDelegate extends LocalizationsDelegate