big huge wip

This commit is contained in:
Daniel Ponte 2024-08-13 23:07:35 -04:00
parent db99eeb43a
commit 0d150d73d8
10 changed files with 135 additions and 11 deletions

View file

@ -1,5 +1,6 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:web_socket_channel/io.dart'; import 'package:web_socket_channel/io.dart';
import 'package:http/http.dart' as http;
import 'package:flutter_secure_storage/flutter_secure_storage.dart'; 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';
@ -16,6 +17,7 @@ class Stillbox extends ChangeNotifier {
Filter? currentFilter; Filter? currentFilter;
Call? _currentCall; Call? _currentCall;
Map<String, String> headers = {}; Map<String, String> headers = {};
Uri? baseUri = Uri.base;
set state(LiveState newState) { set state(LiveState newState) {
channel.sink.add(Live(state: newState, filter: currentFilter)); channel.sink.add(Live(state: newState, filter: currentFilter));
@ -34,18 +36,56 @@ class Stillbox extends ChangeNotifier {
} }
Stillbox() { Stillbox() {
String socketUrl = 'ws://xenon:3050/ws'; setUris();
Uri baseUri = Uri.base; }
if (baseUri.scheme == 'http' || baseUri.scheme == 'https') {
final port = (baseUri.hasPort ? ':${baseUri.port}' : ''); void setUris() {
if (baseUri != null && (baseUri!.scheme == 'http' || baseUri!.scheme == 'https')) {
String socketUrl;
final port = (baseUri!.hasPort ? ':${baseUri!.port}' : '');
socketUrl = socketUrl =
'${baseUri.scheme == 'http' ? 'ws' : 'wss'}://${baseUri.host}$port/ws'; '${baseUri!.scheme == 'http' ? 'ws' : 'wss'}://${baseUri!.host}$port/ws';
_wsUri = Uri.parse(socketUrl);
} else {
baseUri = null;
} }
_wsUri = Uri.parse(socketUrl); }
void updateCookie(http.Response response) {
String? rawCookie = response.headers['set-cookie'];
if (rawCookie != null) {
int index = rawCookie.indexOf(';');
headers['cookie'] =
(index == -1) ? rawCookie : rawCookie.substring(0, index);
}
}
Future<bool> doLogin(String uri, String username, String password) async {
if(baseUri == null) {
baseUri = Uri.parse(uri);
setUris();
}
Uri loginUri = Uri.parse(baseUri!.toString() + '/login');
final form = <String, dynamic>{};
form['username'] = username;
form['password'] = password;
http.Response response = await http.post(
loginUri,
body: form,
);
if(response.statusCode == 200) {
updateCookie(response);
await storage.write(key: 'token', value: headers['cookie']);
await connect();
return true;
}
return false;
} }
Future<void> connect() async { Future<void> connect() async {
await setBearer(); if (connected = true) {
return;
}
channel = IOWebSocketChannel.connect(_wsUri, headers: headers); channel = IOWebSocketChannel.connect(_wsUri, headers: headers);
channel.stream.listen((event) => _handleData(event), onDone: () { channel.stream.listen((event) => _handleData(event), onDone: () {
connected = false; connected = false;

View file

@ -50,7 +50,9 @@ class CallsHomeState extends State<CallsHome> {
Future<void> loadData() async { Future<void> loadData() async {
// Ensure the navigation happens in the context of this widget's subtree // Ensure the navigation happens in the context of this widget's subtree
try { try {
await Provider.of<Stillbox>(context, listen: false).connect(); final sb = Provider.of<Stillbox>(context, listen: false);
await sb.setBearer();
await sb.connect();
} catch (e) { } catch (e) {
if (mounted) { if (mounted) {
Navigator.pushReplacement( Navigator.pushReplacement(

View file

@ -1,4 +1,7 @@
import 'package:calls/main.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import '../controller/stillbox.dart';
import 'package:provider/provider.dart';
class Login extends StatefulWidget { class Login extends StatefulWidget {
const Login({super.key}); const Login({super.key});
@ -9,6 +12,7 @@ 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();
TextEditingController userController = TextEditingController(); TextEditingController userController = TextEditingController();
TextEditingController passwordController = TextEditingController(); TextEditingController passwordController = TextEditingController();
@ -24,6 +28,31 @@ class _LoginState extends State<Login> {
child: Padding( child: Padding(
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) {
if (!(Uri.base.scheme == 'http' ||
Uri.base.scheme == 'https')) {
return Padding(
padding: const EdgeInsets.symmetric(
horizontal: 8, vertical: 10),
child: TextFormField(
controller: uriController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: "Server URL"),
validator: (value) {
if (value != null) {
return Uri.parse(value).isAbsolute
? null
: 'Please enter a valid URL.';
} else {
return 'Please enter a valid URL.';
}
},
));
}
return Container();
}),
Padding( Padding(
padding: padding:
const EdgeInsets.symmetric(horizontal: 8, vertical: 10), const EdgeInsets.symmetric(horizontal: 8, vertical: 10),
@ -60,7 +89,29 @@ class _LoginState extends State<Login> {
child: ElevatedButton( child: ElevatedButton(
onPressed: () { onPressed: () {
if (_formKey.currentState!.validate()) { if (_formKey.currentState!.validate()) {
// TODO do login here Provider.of<Stillbox>(context, listen: false)
.doLogin(
uriController.text,
userController.text,
passwordController.text)
.then((result) {
if (result == true && mounted) {
Navigator.pushReplacement(
context,
PageRouteBuilder(
pageBuilder: (context, animation,
secondaryAnimation) =>
const CallsHome(),
transitionsBuilder: (context, animation,
secondaryAnimation, child) {
return child;
},
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

@ -1,20 +1,32 @@
PODS: PODS:
- audioplayers_darwin (0.0.1):
- FlutterMacOS
- flutter_secure_storage_macos (6.1.1):
- FlutterMacOS
- FlutterMacOS (1.0.0) - FlutterMacOS (1.0.0)
- path_provider_foundation (0.0.1): - path_provider_foundation (0.0.1):
- Flutter - Flutter
- FlutterMacOS - FlutterMacOS
DEPENDENCIES: DEPENDENCIES:
- audioplayers_darwin (from `Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos`)
- flutter_secure_storage_macos (from `Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos`)
- FlutterMacOS (from `Flutter/ephemeral`) - FlutterMacOS (from `Flutter/ephemeral`)
- path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`) - path_provider_foundation (from `Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin`)
EXTERNAL SOURCES: EXTERNAL SOURCES:
audioplayers_darwin:
:path: Flutter/ephemeral/.symlinks/plugins/audioplayers_darwin/macos
flutter_secure_storage_macos:
:path: Flutter/ephemeral/.symlinks/plugins/flutter_secure_storage_macos/macos
FlutterMacOS: FlutterMacOS:
:path: Flutter/ephemeral :path: Flutter/ephemeral
path_provider_foundation: path_provider_foundation:
:path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin :path: Flutter/ephemeral/.symlinks/plugins/path_provider_foundation/darwin
SPEC CHECKSUMS: SPEC CHECKSUMS:
audioplayers_darwin: dcad41de4fbd0099cb3749f7ab3b0cb8f70b810c
flutter_secure_storage_macos: 59459653abe1adb92abbc8ea747d79f8d19866c9
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24 FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46 path_provider_foundation: 2b6b4c569c0fb62ec74538f866245ac84301af46

View file

@ -195,7 +195,6 @@
2C35E72338A581BA4B223314 /* Pods-RunnerTests.release.xcconfig */, 2C35E72338A581BA4B223314 /* Pods-RunnerTests.release.xcconfig */,
308BAD42558871EC233F8F66 /* Pods-RunnerTests.profile.xcconfig */, 308BAD42558871EC233F8F66 /* Pods-RunnerTests.profile.xcconfig */,
); );
name = Pods;
path = Pods; path = Pods;
sourceTree = "<group>"; sourceTree = "<group>";
}; };
@ -574,6 +573,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = HPWYU9LLXA;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -706,6 +706,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/DebugProfile.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = HPWYU9LLXA;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",
@ -726,6 +727,7 @@
CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements; CODE_SIGN_ENTITLEMENTS = Runner/Release.entitlements;
CODE_SIGN_STYLE = Automatic; CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES; COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = HPWYU9LLXA;
INFOPLIST_FILE = Runner/Info.plist; INFOPLIST_FILE = Runner/Info.plist;
LD_RUNPATH_SEARCH_PATHS = ( LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)", "$(inherited)",

View file

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>PreviewsEnabled</key>
<false/>
</dict>
</plist>

View file

@ -8,5 +8,9 @@
<true/> <true/>
<key>com.apple.security.network.server</key> <key>com.apple.security.network.server</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array/>
</dict> </dict>
</plist> </plist>

View file

@ -4,5 +4,9 @@
<dict> <dict>
<key>com.apple.security.app-sandbox</key> <key>com.apple.security.app-sandbox</key>
<true/> <true/>
<key>com.apple.security.network.client</key>
<true/>
<key>keychain-access-groups</key>
<array/>
</dict> </dict>
</plist> </plist>

View file

@ -225,7 +225,7 @@ packages:
source: hosted source: hosted
version: "6.2.1" version: "6.2.1"
http: http:
dependency: transitive dependency: "direct main"
description: description:
name: http name: http
sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010 sha256: b9c29a161230ee03d3ccf545097fccd9b87a5264228c5d348202e0f0c28f9010

View file

@ -42,6 +42,7 @@ dependencies:
provider: ^6.1.2 provider: ^6.1.2
audioplayers: ^5.2.1 audioplayers: ^5.2.1
flutter_secure_storage: ^9.2.2 flutter_secure_storage: ^9.2.2
http: ^1.2.2
dev_dependencies: dev_dependencies:
flutter_test: flutter_test: