From e827549c1d1d6cdac67842c6637ef0c6d4f8e6ab Mon Sep 17 00:00:00 2001 From: Pato05 Date: Sat, 10 Feb 2024 18:13:27 +0100 Subject: [PATCH] merge? --- lib/ui/login_screen.dart | 166 ++++++++++++++++++ macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 16 ++ pubspec.yaml | 2 +- 4 files changed, 185 insertions(+), 1 deletion(-) diff --git a/lib/ui/login_screen.dart b/lib/ui/login_screen.dart index 91c60c0..770db7e 100644 --- a/lib/ui/login_screen.dart +++ b/lib/ui/login_screen.dart @@ -1,9 +1,17 @@ +import 'dart:async'; +import 'dart:convert'; import 'dart:io'; +import 'dart:math'; +import 'package:async/async.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; +import 'package:flutter_screenutil/flutter_screenutil.dart'; import 'package:freezer/api/deezer.dart'; import 'package:freezer/translations.i18n.dart'; +import 'package:logging/logging.dart'; +import 'package:network_info_plus/network_info_plus.dart'; +import 'package:rxdart/rxdart.dart'; import 'package:url_launcher/url_launcher_string.dart'; import 'package:webview_flutter/webview_flutter.dart'; @@ -209,6 +217,16 @@ class _LoginWidgetState extends State { style: const TextStyle(fontSize: 16.0), ), const SizedBox(height: 16.0), + ElevatedButton( + child: + Text('Login using other device'.i18n), + onPressed: () { + showDialog( + context: context, + builder: (context) => + OtherDeviceLogin(_update)); + }), + const SizedBox(height: 16.0), //Email login dialog (Not working anymore) // ElevatedButton( // child: Text( @@ -407,6 +425,154 @@ class _LoginBrowserState extends State { } } +class OtherDeviceLogin extends StatefulWidget { + final VoidCallback callback; + const OtherDeviceLogin(this.callback, {super.key}); + + @override + State createState() => _OtherDeviceLoginState(); +} + +class _OtherDeviceLoginState extends State { + late final HttpServer _server; + late final StreamSubscription _serverSubscription; + late final String? _deviceIP; + late final Future _serverReady; + late int _code; + late Timer _codeTimer; + final _timerNotifier = ValueNotifier(0.0); + bool step2 = false; + final _logger = Logger('OtherDeviceLogin'); + + void _generateCode() { + _code = Random.secure().nextInt(899999) + 100000; + } + + Future _initServer() async { + _server = await HttpServer.bind(InternetAddress.anyIPv4, 0); + _deviceIP = await NetworkInfo().getWifiIP(); + _generateCode(); + const tps = 30 * 1000 / 50; + _codeTimer = Timer.periodic(const Duration(milliseconds: 50), (timer) { + final a = timer.tick / tps; + _timerNotifier.value = a - a.truncate(); + if (timer.tick % tps == 0) { + setState(() => _generateCode()); + } + }); + _serverSubscription = _server.listen((request) async { + final buffer = Uint8List(0); + final reqCompleter = Completer(); + final subs = request.listen( + (data) { + if (data.length + buffer.length > 8192) { + _logger.severe('Request too big!'); + request.response.close(); + } + + buffer.addAll(data); + }, + onDone: () { + reqCompleter.complete(); + }, + ); + await reqCompleter.future; + subs.cancel(); + try { + jsonDecode(utf8.decode(buffer)); + } catch (e) { + _logger.severe('Error $e'); + request.response.close(); + } + }); + } + + @override + void initState() { + _serverReady = _initServer(); + super.initState(); + } + + @override + void dispose() { + _server.close(); + _serverSubscription.cancel(); + _codeTimer.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AlertDialog( + title: Text('Login using other device'.i18n), + contentPadding: const EdgeInsets.only(top: 12), + content: step2 + ? Text('Please follow the on-screen instructions'.i18n, + style: Theme.of(context).textTheme.bodyLarge) + : FutureBuilder( + future: _serverReady, + builder: (context, snapshot) { + if (snapshot.connectionState != ConnectionState.done) { + return const Row(children: [CircularProgressIndicator()]); + } + + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + ValueListenableBuilder( + valueListenable: _timerNotifier, + builder: (context, value, _) => + LinearProgressIndicator(value: value), + ), + Padding( + padding: const EdgeInsets.fromLTRB(24, 18, 24, 24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'On your other device, go to Freezer\'s settings > General > Login on other device, input the parameters below and follow the on-screen instructions.' + .i18n), + RichText( + textAlign: TextAlign.start, + text: TextSpan( + style: + Theme.of(context).textTheme.bodyMedium, + children: [ + TextSpan(text: 'IP Address: '.i18n), + TextSpan( + text: + _deviceIP ?? 'Could not get IP!', + style: TextStyle(fontSize: 32.sp)), + const TextSpan(text: ':'), + TextSpan( + text: _server.port.toString(), + style: TextStyle(fontSize: 32.sp)), + ])), + RichText( + text: TextSpan( + style: + Theme.of(context).textTheme.bodyMedium, + children: [ + TextSpan(text: 'Code: '.i18n), + TextSpan( + text: '$_code', + style: TextStyle(fontSize: 32.sp)), + ])), + ], + ), + ) + ]); + }), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), child: Text('Cancel'.i18n)) + ], + ); + } +} + // email login is removed cuz not working = USELESS //class EmailLogin extends StatefulWidget { diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index fcd3f4c..edc83b7 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -12,6 +12,7 @@ import dynamic_color import flutter_local_notifications import isar_flutter_libs import just_audio +import network_info_plus import package_info_plus import path_provider_foundation import share_plus @@ -27,6 +28,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) IsarFlutterLibsPlugin.register(with: registry.registrar(forPlugin: "IsarFlutterLibsPlugin")) JustAudioPlugin.register(with: registry.registrar(forPlugin: "JustAudioPlugin")) + NetworkInfoPlusPlugin.register(with: registry.registrar(forPlugin: "NetworkInfoPlusPlugin")) FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) diff --git a/pubspec.lock b/pubspec.lock index 25ff371..ca6b45b 100644 --- a/pubspec.lock +++ b/pubspec.lock @@ -929,6 +929,22 @@ packages: url: "https://pub.dev" source: hosted version: "1.0.0" + network_info_plus: + dependency: "direct main" + description: + name: network_info_plus + sha256: "4601b815b1c6a46d84839f65cd774a7d999738471d910fae00d813e9e98b04e1" + url: "https://pub.dev" + source: hosted + version: "4.1.0+1" + network_info_plus_platform_interface: + dependency: transitive + description: + name: network_info_plus_platform_interface + sha256: "881f5029c5edaf19c616c201d3d8b366c5b1384afd5c1da5a49e4345de82fb8b" + url: "https://pub.dev" + source: hosted + version: "1.1.3" nm: dependency: transitive description: diff --git a/pubspec.yaml b/pubspec.yaml index 1f5414d..538167f 100644 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -96,7 +96,7 @@ dependencies: flex_color_picker: ^3.3.0 webview_flutter: ^4.4.4 - + network_info_plus: ^4.1.0+1 #deezcryptor: #path: deezcryptor/