import 'dart:async'; import 'dart:convert'; import 'package:flutter/material.dart'; import 'package:http/http.dart' as http; import '../api/settings_api.dart'; import '../db/settings_db.dart'; import '../log/log.dart'; import 'login_context.dart'; class LoginScreen extends StatefulWidget { const LoginScreen({Key? key}) : super(key: key); @override _LoginScreenState createState() => _LoginScreenState(); } class _LoginScreenState extends State { final TextEditingController _domainTextController = TextEditingController(); final TextEditingController _passwordTextController = TextEditingController(); String error = ""; Future login(String password, String domain) async { Log.i("logging in..."); http.Response resp; try { resp = await http.post( Uri.parse(domain + '/api/login/login'), headers: { 'Content-Type': 'application/json; charset=UTF-8', }, body: jsonEncode({ 'Password': password, }), ); } catch (e) { return "error" + e.toString(); } if (resp.statusCode != 200) { return "error" + resp.body; } else { final json = jsonDecode(resp.body); final token = json["Token"]; SettingsT settings = await SettingsDB.getInstance().getSettings(); settings.domain = domain; settings.token = token; SettingsDB.getInstance().setSettings(settings); // we need two steps here because we need an authenticated api call for the videopath settings.videopath = (await loadInitialData()).videoPath; SettingsDB.getInstance().setSettings(settings); LoginContext.of(context).onLoggin(true); return ""; } } Future onLoginClick() async { Log.d("logging in"); final pwd = _passwordTextController.value.text; final domain = _domainTextController.value.text; var err = ""; if (domain.startsWith("https://") || domain.startsWith("http://")) { err = await login(pwd, domain); if (err.isEmpty) return; } else { // try to auto infering domain prefix err = await login(pwd, "https://" + domain); if (err.isEmpty) return; err = await login(pwd, "http://" + domain); if (err.isEmpty) return; } Log.i(err); setState(() { error = err; }); } @override void dispose() { _domainTextController.dispose(); _passwordTextController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Container( decoration: const BoxDecoration( image: DecorationImage( image: AssetImage('assets/images/login.png'), fit: BoxFit.cover), ), child: Scaffold( backgroundColor: Colors.transparent, body: Stack( children: [ Container( padding: const EdgeInsets.only(left: 35, top: 90), child: const Text( 'Welcome\nBack', style: TextStyle(color: Colors.white, fontSize: 33), ), ), SingleChildScrollView( child: Container( padding: EdgeInsets.only( top: MediaQuery.of(context).size.height * 0.5), child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Container( margin: const EdgeInsets.only(left: 35, right: 35), child: Column( children: [ TextField( controller: _domainTextController, style: const TextStyle(color: Colors.black), autofocus: true, decoration: InputDecoration( fillColor: Colors.grey.shade100, filled: true, hintText: "Domain", border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), )), ), const SizedBox( height: 30, ), TextField( controller: _passwordTextController, style: const TextStyle(), obscureText: true, autofocus: true, decoration: InputDecoration( fillColor: Colors.grey.shade100, filled: true, hintText: "Password", border: OutlineInputBorder( borderRadius: BorderRadius.circular(10), )), ), const SizedBox( height: 40, ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ const Text( 'Sign in', style: TextStyle( fontSize: 27, fontWeight: FontWeight.w700), ), CircleAvatar( radius: 30, backgroundColor: const Color(0xff4c505b), child: IconButton( color: Colors.white, onPressed: () async => await onLoginClick(), icon: const Icon( Icons.arrow_forward, )), ) ], ), error != "" ? Text(error) : const Text("") ], ), ) ], ), ), ), ], ), ), ); } }