This commit is contained in:
Daniel 2024-08-15 08:52:14 -04:00
parent c21a0f2021
commit b45899558c
8 changed files with 100 additions and 61 deletions

View file

@ -42,4 +42,5 @@
<data android:mimeType="text/plain"/> <data android:mimeType="text/plain"/>
</intent> </intent>
</queries> </queries>
<uses-permission android:name="android.permission.INTERNET" />
</manifest> </manifest>

View file

@ -1,14 +1,16 @@
import 'package:flutter/material.dart'; import 'package:flutter/foundation.dart';
import 'package:web_socket_channel/io.dart'; import 'package:web_socket_channel/io.dart';
import 'package:http/http.dart' as http; import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
import '../pb/stillbox.pb.dart'; import '../pb/stillbox.pb.dart';
import 'play.dart'; import 'play.dart';
import 'storage_none.dart'
if (dart.library.io) 'storage_secure.dart'
if (dart.library.html) 'storage_web.dart';
class BadAuthException implements Exception {} class BadAuthException implements Exception {}
class Stillbox extends ChangeNotifier { class Stillbox extends ChangeNotifier {
final storage = const FlutterSecureStorage(); final storage = Storer();
Player player = Player(); Player player = Player();
late IOWebSocketChannel channel; late IOWebSocketChannel channel;
bool connected = false; bool connected = false;
@ -62,10 +64,8 @@ class Stillbox extends ChangeNotifier {
} }
Future<bool> doLogin(String uri, String username, String password) async { Future<bool> doLogin(String uri, String username, String password) async {
if (baseUri == null) { baseUri = Uri.parse(uri);
baseUri = Uri.parse(uri); setUris();
setUris();
}
String baseUriString = baseUri.toString(); String baseUriString = baseUri.toString();
// trim trailing slash since gordio router really dislikes it // trim trailing slash since gordio router really dislikes it
if (baseUriString.endsWith('/')) { if (baseUriString.endsWith('/')) {
@ -81,8 +81,10 @@ class Stillbox extends ChangeNotifier {
); );
if (response.statusCode == 200) { if (response.statusCode == 200) {
updateCookie(response); updateCookie(response);
await storage.write(key: 'token', value: headers['cookie']); storage.setKey('baseURL', uri);
await storage.write(key: 'baseURL', value: uri); if (!kIsWeb) {
storage.setKey('token', headers['cookie']!);
}
await connect(); await connect();
return true; return true;
} }
@ -104,8 +106,9 @@ class Stillbox extends ChangeNotifier {
} }
Future<void> getBearer() async { Future<void> getBearer() async {
String? storedToken = await storage.read(key: 'token'); String? storedToken = await storage.getKey('token');
String? storedUri = await storage.read(key: 'baseURL'); late String? storedUri;
storedUri = await storage.getKey('baseURL');
if (storedToken == null || storedUri == null) { if (storedToken == null || storedUri == null) {
throw (BadAuthException); throw (BadAuthException);
} }

View file

@ -0,0 +1,9 @@
class Storer {
Future<String?> getKey(String key) async {
return null;
}
void setKey(String key, String value) {
return;
}
}

View file

@ -0,0 +1,12 @@
import 'package:flutter_secure_storage/flutter_secure_storage.dart';
class Storer {
final storage = const FlutterSecureStorage();
Future<String?> getKey(String key) async {
return await storage.read(key: 'token');
}
void setKey(String key, String value) async {
await storage.write(key: 'token', value: value);
}
}

View file

@ -0,0 +1,11 @@
import 'dart:html';
class Storer {
Future<String?> getKey(String key) async {
return window.localStorage[key];
}
void setKey(String key, String value) {
window.localStorage[key] = value;
}
}

View file

@ -12,10 +12,18 @@ class Login extends StatefulWidget {
class _LoginState extends State<Login> { class _LoginState extends State<Login> {
final _formKey = GlobalKey<FormState>(); final _formKey = GlobalKey<FormState>();
TextEditingController uriController = TextEditingController(); late TextEditingController uriController;
TextEditingController userController = TextEditingController(); TextEditingController userController = TextEditingController();
TextEditingController passwordController = TextEditingController(); TextEditingController passwordController = TextEditingController();
_LoginState() {
if (Uri.base.scheme == 'http' || Uri.base.scheme == 'https') {
uriController = TextEditingController(text: Uri.base.toString());
} else {
uriController = TextEditingController();
}
}
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return Scaffold( return Scaffold(
@ -29,29 +37,24 @@ class _LoginState extends State<Login> {
padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16), padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 16),
child: Column(children: [ child: Column(children: [
Builder(builder: (context) { Builder(builder: (context) {
if (!(Uri.base.scheme == 'http' || return Padding(
Uri.base.scheme == 'https')) { padding: const EdgeInsets.symmetric(
return Padding( horizontal: 8, vertical: 10),
padding: const EdgeInsets.symmetric( child: TextFormField(
horizontal: 8, vertical: 10), controller: uriController,
child: TextFormField( decoration: const InputDecoration(
controller: uriController, border: OutlineInputBorder(),
decoration: const InputDecoration( labelText: "Server URL"),
border: OutlineInputBorder(), validator: (value) {
labelText: "Server URL"), if (value != null) {
validator: (value) { return Uri.parse(value).isAbsolute
if (value != null) { ? null
return Uri.parse(value).isAbsolute : 'Please enter a valid URL.';
? null } else {
: 'Please enter a valid URL.'; return 'Please enter a valid URL.';
} else { }
return 'Please enter a valid URL.'; },
} ));
},
));
}
return Container();
}), }),
Padding( Padding(
padding: padding:
@ -87,33 +90,30 @@ class _LoginState extends State<Login> {
horizontal: 8, vertical: 16.0), horizontal: 8, vertical: 16.0),
child: Center( child: Center(
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () async {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
Provider.of<Stillbox>(context, listen: false) final result = await Provider.of<Stillbox>(context,
listen: false)
.doLogin( .doLogin(
uriController.text, uriController.text,
userController.text, userController.text,
passwordController.text) passwordController.text);
.then((result) { if (context.mounted && result == true) {
if (result == true) { Navigator.pushReplacement(
if (context.mounted) { context,
Navigator.pushReplacement( PageRouteBuilder(
context, pageBuilder: (context, animation,
PageRouteBuilder( secondaryAnimation) =>
pageBuilder: (context, animation, const CallsHome(),
secondaryAnimation) => transitionsBuilder: (context, animation,
const CallsHome(), secondaryAnimation, child) {
transitionsBuilder: (context, animation, return child;
secondaryAnimation, child) { },
return child; transitionDuration:
}, const Duration(milliseconds: 0),
transitionDuration: ),
const Duration(milliseconds: 0), );
), }
);
}
}
});
} else { } else {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
const SnackBar(content: Text('Please login.')), const SnackBar(content: Text('Please login.')),

View file

@ -329,7 +329,7 @@ packages:
source: hosted source: hosted
version: "1.1.4" version: "1.1.4"
media_kit_libs_linux: media_kit_libs_linux:
dependency: transitive dependency: "direct main"
description: description:
name: media_kit_libs_linux name: media_kit_libs_linux
sha256: e186891c31daa6bedab4d74dcdb4e8adfccc7d786bfed6ad81fe24a3b3010310 sha256: e186891c31daa6bedab4d74dcdb4e8adfccc7d786bfed6ad81fe24a3b3010310
@ -345,7 +345,7 @@ packages:
source: hosted source: hosted
version: "1.1.4" version: "1.1.4"
media_kit_libs_windows_audio: media_kit_libs_windows_audio:
dependency: transitive dependency: "direct main"
description: description:
name: media_kit_libs_windows_audio name: media_kit_libs_windows_audio
sha256: c2fd558cc87b9d89a801141fcdffe02e338a3b21a41a18fbd63d5b221a1b8e53 sha256: c2fd558cc87b9d89a801141fcdffe02e338a3b21a41a18fbd63d5b221a1b8e53
@ -353,7 +353,7 @@ packages:
source: hosted source: hosted
version: "1.0.9" version: "1.0.9"
media_kit_native_event_loop: media_kit_native_event_loop:
dependency: transitive dependency: "direct main"
description: description:
name: media_kit_native_event_loop name: media_kit_native_event_loop
sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e sha256: a605cf185499d14d58935b8784955a92a4bf0ff4e19a23de3d17a9106303930e

View file

@ -46,6 +46,9 @@ dependencies:
just_audio_media_kit: ^2.0.5 just_audio_media_kit: ^2.0.5
media_kit_libs_audio: ^1.0.4 media_kit_libs_audio: ^1.0.4
patch_package: ^0.0.8 patch_package: ^0.0.8
media_kit_libs_linux: ^1.1.3
media_kit_native_event_loop: ^1.0.8
media_kit_libs_windows_audio: ^1.0.9
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: