Last active
June 10, 2020 21:18
-
-
Save jaggzh/8b94065620867b7f84b208fdb504f282 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Cfg { | |
static final apiUrl = 'https://www.this-is-my-backend-api-site.com/api'; | |
static final urlAuth = apiUrl+'/auth'; | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//import 'dart:async'; | |
import 'package:flutter/rendering.dart'; | |
//import 'package:provider/provider.dart'; | |
import 'package:flutter/material.dart'; | |
//import '../models/user.dart'; | |
//import '../util/login_form_validator.dart'; | |
import '../ui/bb_convex.dart'; | |
class ScreenHome extends StatefulWidget { | |
@override | |
_ScreenHomeState createState() => _ScreenHomeState(); | |
} | |
class _ScreenHomeState extends State<ScreenHome> { | |
final formKey = GlobalKey<FormState>(); | |
final scaffoldKey = GlobalKey<ScaffoldState>(); | |
// var _context; | |
Widget build(BuildContext context) { | |
// _context = context; | |
return Stack(children: [ | |
Container( | |
decoration: new BoxDecoration( | |
gradient: new LinearGradient( | |
colors: [ | |
//const Color(0xFF3366FF), | |
//const Color(0xFF00CCFF), | |
const Color(0xFFc0CCFF), | |
const Color(0xFF5366cF), | |
], | |
begin: const FractionalOffset(0.0, 0.0), | |
end: const FractionalOffset(1.2, .5), | |
//begin: Alignment.topLeft, | |
//end: Alignment(0.8, 0.0), | |
stops: [0.0, 1.0], | |
tileMode: TileMode.clamp), | |
), | |
), | |
Scaffold( | |
key: scaffoldKey, | |
extendBodyBehindAppBar: false, | |
//backgroundColor: Colors.white, | |
backgroundColor: Colors.transparent, | |
appBar: AppBar( | |
title: Text( | |
'Le\'App', | |
style: TextStyle(color: Colors.white70), | |
), | |
elevation: 0.0, | |
backgroundColor: Colors.transparent, | |
flexibleSpace: Container( | |
decoration: new BoxDecoration( | |
gradient: new LinearGradient( | |
colors: [ | |
////const Color(0xFF3366FF), const Color(0xFF00CCFF), | |
//const Color(0xf05346FF), const Color(0x005346FF), | |
const Color(0x20ffffff), const Color(0x00ffffff), | |
], | |
begin: const FractionalOffset(.6, 1 - (-0.2)), | |
end: const FractionalOffset(1 - 0.475, 1 - 1.1), | |
stops: [0.0, 1.0], | |
tileMode: TileMode.clamp), | |
), | |
), | |
automaticallyImplyLeading: false, | |
leading: null, | |
actions: <Widget>[ | |
new IconButton( | |
icon: new Icon(Icons.account_circle), | |
onPressed: () => Navigator.of(context).pop(null), | |
), | |
], | |
), | |
body: Stack( | |
children: [ | |
Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 16.0), | |
child: SingleChildScrollView( | |
child: Center(child: Text("You are here"))), | |
), | |
], | |
), | |
bottomNavigationBar: BBar(), | |
) | |
]); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/cupertino.dart'; | |
import 'package:flutter/rendering.dart'; | |
import 'package:http/http.dart' as http; | |
import 'dart:convert'; | |
class HttpSession extends ChangeNotifier { | |
Map<String, String> headers = {}; | |
//HttpSession() => {}; | |
Future<Map> get(String url) async { | |
http.Response response = await http.get(url, headers: headers); | |
updateCookie(response); | |
return json.decode(response.body); | |
} | |
Future<Map> post(String url, dynamic data) async { | |
http.Response response = await http.post(url, body: data, headers: headers); | |
updateCookie(response); | |
return json.decode(response.body); | |
} | |
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); | |
} | |
} | |
} | |
/* | |
static InheritedHttpSession of(BuildContext context) { | |
return context.dependOnInheritedWidgetOfExactType<InheritedHttpSession>(); | |
} | |
@override | |
bool updateShouldNotify(HttpSession old) => session != old.session;} | |
bool updateShouldNotify(HttpSession old) => session != old.session;} | |
class InheritedHttpSession extends InheritedWidget { | |
HttpSession session = HttpSession(); | |
static InheritedHttpSession of(BuildContext context) { | |
return context.dependOnInheritedWidgetOfExactType<InheritedHttpSession>(); | |
} | |
@override | |
bool updateShouldNotify(HttpSession session) => session != old.session; | |
} | |
*/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//import 'dart:async'; | |
import 'package:flutter/rendering.dart'; | |
import 'package:provider/provider.dart'; | |
import 'package:flutter/material.dart'; | |
import '../models/user.dart'; | |
import '../util/login_form_validator.dart'; | |
class OffsiteUserChangeListener extends StatelessWidget { | |
final scaffoldKey; | |
final user; | |
const OffsiteUserChangeListener({ | |
Key key, | |
this.scaffoldKey, | |
this.user, | |
}) : super(key: key); | |
@override | |
Widget build(BuildContext context) { | |
// Haven't tried logging in yet. Also, we might not even have build()'ed | |
if (user.loginState == LoginState.loggedIn) { | |
// We handled this ourselves. This is just a reminder for me | |
} else if (user.loginState == LoginState.success) { | |
user.loginState = LoginState.loggedIn; | |
WidgetsBinding.instance.addPostFrameCallback((_) { | |
Navigator.pushReplacementNamed(context, '/home'); | |
}); | |
} else if (user.loginState == LoginState.inProgress) { | |
return Stack(children: [ | |
Positioned.fill(child: Container(color: Color.fromRGBO(255, 255, 255, .7))), | |
//Opacity( opacity:1.0, | |
Center(child: CircularProgressIndicator()), | |
]); | |
} else if (user.loginState == LoginState.failed) { | |
final snackbar = SnackBar( | |
content: Text("Couldn't log in: ${user.loginMsg}"), | |
); | |
WidgetsBinding.instance.addPostFrameCallback((_) { | |
Scaffold.of(context).showSnackBar(snackbar); | |
}); | |
} | |
return Offstage(child: Container(width:0, height:0)); // Dummy so we exist. | |
} | |
} | |
class ScreenLogin extends StatefulWidget { | |
@override | |
_ScreenLoginState createState() => _ScreenLoginState(); | |
} | |
class _ScreenLoginState extends State<ScreenLogin> { | |
final formKey = GlobalKey<FormState>(); | |
final scaffoldKey = GlobalKey<ScaffoldState>(); | |
String _userid; // For the form fields. | |
String _pw; | |
var _context; | |
void _submitCommand() { | |
final form = formKey.currentState; | |
var _user = Provider.of<User>(_context, listen:false); | |
if (form.validate()) { | |
form.save(); // userid & pw passed val rules and are in _userid & _pw fields | |
_user.loginUnknownID(id: _userid, pw: _pw); //_loginCommand(); | |
} | |
} | |
@override | |
Widget build(BuildContext context) { | |
_context = context; | |
return Scaffold( | |
key: scaffoldKey, | |
backgroundColor: Colors.white, | |
appBar: AppBar( | |
title: Text('Login'), | |
), | |
body: | |
Stack(children: [ | |
Padding( | |
padding: const EdgeInsets.symmetric(horizontal: 16.0), | |
child: SingleChildScrollView( | |
child: Form( | |
key: formKey, | |
child: Column( | |
children: <Widget>[ | |
GestureDetector( | |
onTap: () { Navigator.pop(context); }, | |
child: Hero( | |
tag: 'splash_img', | |
child: Image.asset('lib/assets/videos/0128.png', width: 150, height: 150, | |
), | |
), | |
), | |
TextFormField( | |
initialValue: "Username", | |
decoration: InputDecoration(labelText: 'Username / Email'), | |
validator: (val) => !ValidatorUsernameOrEmail.validate(val) ? 'Invalid Username or Email.' : null, | |
onSaved: (val) => _userid = val, | |
), | |
TextFormField( | |
initialValue: "Password", | |
decoration: InputDecoration(labelText: 'Password'), | |
validator: (val) => val.length < 4 ? 'Password too short..' : null, | |
onSaved: (val) => _pw = val, | |
obscureText: true, | |
), | |
RaisedButton( | |
onPressed: _submitCommand, | |
child: Text('Sign in'), | |
), | |
], | |
), | |
), | |
), | |
), | |
Consumer<User>( | |
builder: (context, user, child) => OffsiteUserChangeListener( | |
scaffoldKey: scaffoldKey, | |
user: user, | |
), | |
), | |
],) | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/foundation.dart'; | |
import 'package:provider/provider.dart'; | |
import 'package:flutter/material.dart'; | |
import 'models/user.dart'; | |
import 'screens/splash.dart'; | |
import 'screens/login.dart'; | |
import 'screens/home.dart'; | |
import 'util/http_session.dart'; | |
void main() => runApp(AppMain()); | |
class Session extends InheritedWidget { | |
final HttpSession httpSession = HttpSession(); | |
Session(child): super(child: child); | |
@override | |
bool updateShouldNotify(Session old) => | |
httpSession != old.httpSession; | |
} | |
class AppMain extends StatefulWidget { | |
AppMain({Key key}) : super(key: key); | |
@override | |
_AppMainState createState() => _AppMainState(); | |
} | |
class _AppMainState extends State<AppMain> { | |
@override | |
void initState() { | |
super.initState(); | |
} | |
@override | |
Widget build(BuildContext context) { | |
return ChangeNotifierProvider( | |
create: (context) => User(), | |
//return MultiProvider( | |
// providers: [ | |
// Provider<User>(create: (_) => User()), | |
// Provider<HttpSession>(create: (_) => HttpSession()), | |
//], | |
child: Session(MaterialApp( | |
title: 'Named Routes Demo', | |
initialRoute: '/', | |
routes: { | |
'/': (context) => ScreenSplash(), | |
'/login': (context) => ScreenLogin(), | |
'/home': (context) => ScreenHome(), | |
}, | |
)), | |
); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:video_player/video_player.dart'; | |
import 'package:flutter/material.dart'; | |
import 'package:flutter/foundation.dart' show kIsWeb; | |
import '../util/common.dart'; | |
class ScreenSplash extends StatefulWidget { | |
@override | |
_ScreenSplashState createState() => _ScreenSplashState(); | |
} | |
class _ScreenSplashState extends State<ScreenSplash> { | |
VideoPlayerController _controller; | |
Future<void> _initializeVideoPlayerFuture; | |
ScreenState _screenState = ScreenState.here; | |
// bool _haveLeftScreen = false; | |
//bool _userHasInteracted = false; // used for web video, so we get an interaction | |
// in and then can play audio. | |
@override | |
void initState() { | |
super.initState(); | |
_controller = VideoPlayerController.asset( | |
'lib/assets/videos/vid.mp4', | |
); | |
_initializeVideoPlayerFuture = _controller.initialize(); | |
super.initState(); | |
if (kIsWeb) _controller.setVolume(0.0); // needed for autovideo play | |
_controller.play(); | |
_controller.addListener(() async { | |
if (!_controller.value.isPlaying) { | |
if (_screenState != ScreenState.here) { | |
//_controller.dispose(); | |
} else { | |
//_haveLeftScreen = true; | |
_screenState = ScreenState.left; | |
await Navigator.pushNamed(context, '/login'); | |
_screenState = ScreenState.returned; | |
//_haveLeftScreen = false; | |
_controller.setVolume(1.0); | |
} | |
} | |
}); | |
/* ..setVolume(1.0)..initialize()..play(); | |
.then((_) { | |
// Ensure the first frame is shown after the | |
// video is initialized, even before the | |
// play button has been pressed. | |
setState(() {}); | |
}); */ | |
} | |
@override | |
Widget build(BuildContext context) { | |
return Scaffold( | |
drawer: Drawer(), | |
backgroundColor: Colors.white, | |
appBar: AppBar( | |
title: Text('Veedios'), | |
backgroundColor: Colors.black87, | |
), | |
body: Column( | |
mainAxisAlignment: MainAxisAlignment.center, | |
crossAxisAlignment: CrossAxisAlignment.center, | |
children: [ | |
FutureBuilder( | |
future: _initializeVideoPlayerFuture, | |
builder: (context, snapshot) { | |
if (snapshot.connectionState == ConnectionState.done) { | |
return AspectRatio( | |
aspectRatio: _controller.value.aspectRatio, | |
child: GestureDetector( | |
behavior: HitTestBehavior.opaque, | |
onTap: () async { | |
//_userHasInteracted = true; | |
_controller.setVolume(1.0); | |
if (!_controller.value.isPlaying) { | |
_controller.seekTo(Duration(seconds: 0)); | |
_controller.play(); | |
} else { | |
//_controller.pause(); | |
//_haveLeftScreen = true; | |
_screenState = ScreenState.left; | |
await Navigator.pushNamed(context, '/login'); | |
_screenState = ScreenState.returned; | |
//_haveLeftScreen = false; | |
} | |
}, | |
child: IgnorePointer( | |
ignoring: true, | |
child: Stack(children: <Widget>[ | |
// Image.asset( | |
// 'lib/assets/video/0019.png', | |
// width: 100, | |
// height: 100, | |
// ), | |
Padding( | |
padding: const EdgeInsets.all(72.0), | |
child: Hero( | |
tag: 'splash_img', | |
//child: Image.asset('lib/assets/videos/0128.png',), | |
child: VideoPlayer(_controller), | |
), | |
), | |
/* Hero( | |
tag: 'splash_img', | |
child: Image.asset('lib/assets/video/vid.png'), | |
), */ | |
])), | |
)); | |
} else { | |
return Center(child: CircularProgressIndicator()); | |
} | |
}) | |
]), | |
/* | |
floatingActionButton: FloatingActionButton( | |
onPressed: () { | |
setState(() { | |
_controller.value.isPlaying | |
? _controller.pause() | |
: _controller.play(); | |
}); | |
}, | |
child: Icon( | |
_controller.value.isPlaying ? Icons.pause : Icons.play_arrow, | |
), | |
), | |
*/ | |
); | |
} | |
@override | |
void dispose() { | |
_controller.dispose(); | |
super.dispose(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import 'package:flutter/foundation.dart'; | |
import '../util/cfg.dart'; | |
import 'package:http/http.dart' as http; | |
import 'dart:async'; | |
import 'dart:convert'; | |
import '../util/http_session.dart'; | |
import 'package:provider/provider.dart'; | |
//import 'dart:io'; | |
enum LoginState { | |
pre, | |
inProgress, | |
failed, | |
success, // when login succeeds | |
loggedIn, // callers of sign in should set this themselves | |
// once they've detected the success. | |
} | |
class User extends ChangeNotifier { | |
String id; | |
String username; | |
String pw; | |
String token; | |
LoginState loginState = LoginState.pre; | |
String loginMsg; | |
LoginResponse loginResponse; | |
void loginUnknownID({ // Not sure if username or email yet... | |
@required id, | |
@required pw, | |
}) async { | |
assert(id != null && pw != null, | |
'We need a username or email and a password.'); | |
this.id = id; // No login yet. Just pretend | |
this.pw = pw; | |
loginState = LoginState.inProgress; | |
notifyListeners(); // But pretend slowly \/ \/ \/ | |
loginResponse = await userGetLoginResponse(id: id, pw: pw); | |
if (loginResponse.success == 1) { | |
this.username = loginResponse.username; | |
this.token = loginResponse.token; | |
this.loginState = LoginState.success; | |
this.pw = null; | |
} else { | |
this.loginMsg = loginResponse.msg ?? "Unknown login error"; | |
this.loginState = LoginState.failed; | |
} | |
//await Future.delayed(const Duration(seconds: 2), () {}); | |
notifyListeners(); | |
} | |
} | |
Future<LoginResponse> userGetLoginResponse({id, pw}) async { | |
LoginResponse loginResponse; | |
var http = Provider.of<HttpSession>(_context, listen:false); | |
final response = await http.get( | |
Cfg.urlAuth, | |
headers: { | |
'Authorization': "Basic $id:$pw" | |
//HttpHeaders.authorizationHeader: "$id:$pw" | |
}, | |
); | |
if (response.statusCode == 200) { | |
final responseJson = json.decode(response.body); | |
loginResponse = LoginResponse.fromJsonIsSuccess(responseJson); | |
} else { | |
loginResponse = LoginResponse.bad(404); | |
} | |
return loginResponse; | |
} | |
class LoginResponse { | |
final String username; | |
final String token; | |
final String msg; | |
final int success; | |
final int statusCode; | |
LoginResponse({this.username, this.token, | |
this.success, this.msg, this.statusCode}); | |
factory LoginResponse.fromJsonIsSuccess(Map<String, dynamic> json) { | |
if (json.containsKey('username') && | |
json.containsKey('token') && | |
json.containsKey('success')) { | |
return LoginResponse( | |
username: json['username'], | |
token: json['token'], | |
success: json['success'], | |
msg: json['msg'] ?? "", | |
statusCode: 200, | |
); | |
} else { | |
return LoginResponse( | |
username: "", | |
token: "", | |
success: 0, | |
msg: json['msg'] ?? "Unknown error. We're sorry too.", | |
statusCode: 200, | |
); | |
} | |
} | |
factory LoginResponse.bad(int code) { | |
return LoginResponse( | |
username: "", | |
token: "", | |
success: 0, | |
msg: "HTTP error ($code)", | |
statusCode: code, | |
); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment