1 | // Copyright 2014 The Flutter Authors. All rights reserved. |
2 | // Use of this source code is governed by a BSD-style license that can be |
3 | // found in the LICENSE file. |
4 | |
5 | import 'package:flutter/material.dart'; |
6 | |
7 | import 'colors.dart'; |
8 | |
9 | class LoginPage extends StatefulWidget { |
10 | const LoginPage({super.key}); |
11 | |
12 | @override |
13 | State<LoginPage> createState() => _LoginPageState(); |
14 | } |
15 | |
16 | class _LoginPageState extends State<LoginPage> { |
17 | final TextEditingController _usernameController = TextEditingController(); |
18 | final TextEditingController _passwordController = TextEditingController(); |
19 | static const ShapeDecoration _decoration = ShapeDecoration( |
20 | shape: BeveledRectangleBorder( |
21 | side: BorderSide(color: kShrineBrown900, width: 0.5), |
22 | borderRadius: BorderRadius.all(Radius.circular(7.0)), |
23 | ), |
24 | ); |
25 | |
26 | @override |
27 | Widget build(BuildContext context) { |
28 | return Scaffold( |
29 | appBar: AppBar( |
30 | elevation: 0.0, |
31 | backgroundColor: Colors.white, |
32 | leading: IconButton( |
33 | icon: const BackButtonIcon(), |
34 | tooltip: MaterialLocalizations.of(context).backButtonTooltip, |
35 | onPressed: () { |
36 | // The login screen is immediately displayed on top of the Shrine |
37 | // home screen using onGenerateRoute and so rootNavigator must be |
38 | // set to true in order to get out of Shrine completely. |
39 | Navigator.of(context, rootNavigator: true).pop(); |
40 | }, |
41 | ), |
42 | ), |
43 | body: SafeArea( |
44 | child: ListView( |
45 | padding: const EdgeInsets.symmetric(horizontal: 24.0), |
46 | children: <Widget>[ |
47 | const SizedBox(height: 80.0), |
48 | Column( |
49 | children: <Widget>[ |
50 | Image.asset('packages/shrine_images/diamond.png' ), |
51 | const SizedBox(height: 16.0), |
52 | Text('SHRINE' , style: Theme.of(context).textTheme.headlineSmall), |
53 | ], |
54 | ), |
55 | const SizedBox(height: 120.0), |
56 | PrimaryColorOverride( |
57 | color: kShrineBrown900, |
58 | child: Container( |
59 | decoration: _decoration, |
60 | child: TextField( |
61 | controller: _usernameController, |
62 | decoration: const InputDecoration(labelText: 'Username' ), |
63 | ), |
64 | ), |
65 | ), |
66 | const SizedBox(height: 12.0), |
67 | PrimaryColorOverride( |
68 | color: kShrineBrown900, |
69 | child: Container( |
70 | decoration: _decoration, |
71 | child: TextField( |
72 | controller: _passwordController, |
73 | decoration: const InputDecoration(labelText: 'Password' ), |
74 | ), |
75 | ), |
76 | ), |
77 | const SizedBox(height: 12.0), |
78 | OverflowBar( |
79 | spacing: 8, |
80 | alignment: MainAxisAlignment.end, |
81 | children: <Widget>[ |
82 | TextButton( |
83 | style: TextButton.styleFrom( |
84 | shape: const BeveledRectangleBorder( |
85 | borderRadius: BorderRadius.all(Radius.circular(7.0)), |
86 | ), |
87 | ), |
88 | onPressed: () { |
89 | // The login screen is immediately displayed on top of |
90 | // the Shrine home screen using onGenerateRoute and so |
91 | // rootNavigator must be set to true in order to get out |
92 | // of Shrine completely. |
93 | Navigator.of(context, rootNavigator: true).pop(); |
94 | }, |
95 | child: Text('CANCEL' , style: Theme.of(context).textTheme.bodySmall), |
96 | ), |
97 | ElevatedButton( |
98 | style: ElevatedButton.styleFrom( |
99 | elevation: 8.0, |
100 | shape: const BeveledRectangleBorder( |
101 | borderRadius: BorderRadius.all(Radius.circular(7.0)), |
102 | ), |
103 | ), |
104 | onPressed: () { |
105 | Navigator.pop(context); |
106 | }, |
107 | child: Text('NEXT' , style: Theme.of(context).textTheme.bodySmall), |
108 | ), |
109 | ], |
110 | ), |
111 | ], |
112 | ), |
113 | ), |
114 | ); |
115 | } |
116 | } |
117 | |
118 | class PrimaryColorOverride extends StatelessWidget { |
119 | const PrimaryColorOverride({super.key, this.color, this.child}); |
120 | |
121 | final Color? color; |
122 | final Widget? child; |
123 | |
124 | @override |
125 | Widget build(BuildContext context) { |
126 | return Theme(data: Theme.of(context).copyWith(primaryColor: color), child: child!); |
127 | } |
128 | } |
129 | |