2019-06-27 17:29:40 -07:00
|
|
|
import 'package:flutter/cupertino.dart';
|
|
|
|
import 'package:flutter/material.dart';
|
|
|
|
import 'global_helper_functions.dart';
|
|
|
|
import 'timezones.dart';
|
|
|
|
|
|
|
|
class TimeZone extends StatefulWidget {
|
|
|
|
final int timeOffSet;
|
|
|
|
final int timeOffSetTime;
|
|
|
|
final int isAutoTimeOffSet;
|
|
|
|
|
|
|
|
final ValueChanged<int> parentAction;
|
|
|
|
|
|
|
|
TimeZone({
|
|
|
|
Key key,
|
|
|
|
this.timeOffSet,
|
|
|
|
this.timeOffSetTime,
|
|
|
|
this.parentAction,
|
|
|
|
this.isAutoTimeOffSet,
|
|
|
|
}) : super(key: key);
|
|
|
|
|
|
|
|
@override
|
|
|
|
_TimeZoneState createState() => _TimeZoneState();
|
|
|
|
}
|
|
|
|
|
|
|
|
class _TimeZoneState extends State<TimeZone> {
|
|
|
|
@override
|
|
|
|
Widget build(BuildContext context) {
|
|
|
|
int _localOffSet = 5;
|
|
|
|
final int now = newTimeStamp();
|
|
|
|
final int elapsedHours = ((now - widget.timeOffSetTime) / 3600).round();
|
|
|
|
final String offSet = (widget.timeOffSet < 0)
|
|
|
|
? '(UTC${widget.timeOffSet})'
|
|
|
|
: '(UTC+${widget.timeOffSet})';
|
|
|
|
final double textHeight = 1.5;
|
|
|
|
|
|
|
|
return Row(
|
2019-07-27 15:34:01 -07:00
|
|
|
children: <Widget>[
|
2019-06-27 17:29:40 -07:00
|
|
|
Expanded(
|
|
|
|
flex: 7,
|
|
|
|
child: InkWell(
|
2019-07-27 15:34:01 -07:00
|
|
|
child: Column(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.center,
|
|
|
|
children: <Widget>[
|
|
|
|
Text(
|
|
|
|
'Time Offset:',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: candyApple,
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
RichText(
|
|
|
|
text: TextSpan(
|
|
|
|
children: <TextSpan>[
|
|
|
|
TextSpan(
|
|
|
|
text: (widget.timeOffSet != 2000)
|
|
|
|
? '$offSet'
|
|
|
|
: 'INVALID',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.black,
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
TextSpan(
|
|
|
|
text: (widget.timeOffSet != 2000) ? ' minutes, ' : '',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.black,
|
|
|
|
fontSize: 16,
|
|
|
|
fontStyle: FontStyle.italic,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
],
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
RichText(
|
|
|
|
text: TextSpan(
|
|
|
|
children: <TextSpan>[
|
|
|
|
TextSpan(
|
|
|
|
text: (widget.isAutoTimeOffSet == 1)
|
|
|
|
? 'as of'
|
|
|
|
: 'MANUAL SETTING',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: candyApple,
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
TextSpan(
|
|
|
|
text: (widget.isAutoTimeOffSet == 1)
|
|
|
|
? ' $elapsedHours'
|
|
|
|
: '',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.black,
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
TextSpan(
|
|
|
|
text: (widget.isAutoTimeOffSet == 1) ? ' hrs' : '',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.black,
|
|
|
|
fontSize: 16,
|
|
|
|
fontStyle: FontStyle.italic,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
TextSpan(
|
|
|
|
text: (widget.isAutoTimeOffSet == 1) ? ' ago' : '',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.black,
|
|
|
|
fontSize: 16,
|
|
|
|
),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
],
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
onTap: () {
|
|
|
|
showDialog(
|
|
|
|
context: context,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
final FixedExtentScrollController scrollController =
|
|
|
|
FixedExtentScrollController(
|
|
|
|
initialItem: _getTimeZoneListIndex());
|
|
|
|
return AlertDialog(
|
|
|
|
backgroundColor: ivory,
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(6.0)),
|
|
|
|
),
|
|
|
|
content:
|
|
|
|
Column(mainAxisSize: MainAxisSize.min, children: <
|
|
|
|
Widget>[
|
2019-06-27 17:29:40 -07:00
|
|
|
ButtonTheme(
|
|
|
|
height: 75,
|
|
|
|
shape: RoundedRectangleBorder(
|
2019-07-27 15:34:01 -07:00
|
|
|
borderRadius:
|
|
|
|
BorderRadius.all(Radius.circular(6.0)),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
|
|
|
child: RaisedButton(
|
|
|
|
onPressed: () {
|
|
|
|
if (!mounted) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
if (_localOffSet != 5) {
|
|
|
|
widget.parentAction(_localOffSet);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
},
|
|
|
|
color: candyApple,
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
|
|
|
children: <Widget>[
|
|
|
|
Icon(
|
|
|
|
Icons.save,
|
|
|
|
size: 48.0,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
'save tz offset',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.white,
|
|
|
|
fontSize: 24,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Container(
|
|
|
|
height: (MediaQuery.of(context).size.height * .5),
|
|
|
|
child: CupertinoPicker(
|
|
|
|
scrollController: scrollController,
|
|
|
|
backgroundColor: ivory,
|
|
|
|
itemExtent: 100,
|
|
|
|
looping: true,
|
|
|
|
onSelectedItemChanged: (int index) {
|
|
|
|
if (!mounted) {
|
|
|
|
return;
|
|
|
|
} else {
|
|
|
|
setState(() {
|
|
|
|
_localOffSet = timeZoneList[index]['offset'];
|
|
|
|
});
|
|
|
|
}
|
|
|
|
},
|
2019-07-27 15:34:01 -07:00
|
|
|
children: List<Widget>.generate(timeZoneList.length,
|
|
|
|
(int index) {
|
2019-06-27 17:29:40 -07:00
|
|
|
return Column(
|
|
|
|
children: <Widget>[
|
|
|
|
Container(
|
|
|
|
height: 10,
|
|
|
|
color: ivory,
|
|
|
|
),
|
|
|
|
Container(
|
2019-07-27 15:34:01 -07:00
|
|
|
alignment: Alignment(0.0, 0.0),
|
2019-06-27 17:29:40 -07:00
|
|
|
height: 80,
|
2019-07-27 15:34:01 -07:00
|
|
|
width: (MediaQuery.of(context).size.width *
|
|
|
|
.9),
|
2019-06-27 17:29:40 -07:00
|
|
|
decoration: BoxDecoration(
|
|
|
|
color: peacockBlue,
|
|
|
|
border: Border.all(
|
|
|
|
width: 2.0,
|
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
borderRadius: BorderRadius.all(
|
|
|
|
Radius.circular(6.0)),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
|
|
|
child: Row(
|
2019-07-27 15:34:01 -07:00
|
|
|
mainAxisAlignment:
|
|
|
|
MainAxisAlignment.spaceEvenly,
|
2019-06-27 17:29:40 -07:00
|
|
|
children: <Widget>[
|
|
|
|
Text(
|
2019-07-27 15:34:01 -07:00
|
|
|
_parseTimeZoneOffSet(
|
|
|
|
timeZoneList[index]['offset']),
|
2019-06-27 17:29:40 -07:00
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.white,
|
|
|
|
fontSize: 24,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Text(
|
|
|
|
'${timeZoneList[index]['tz']}',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.white,
|
|
|
|
fontSize: 24,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Container(
|
2019-07-27 15:34:01 -07:00
|
|
|
height: 10,
|
2019-06-27 17:29:40 -07:00
|
|
|
color: ivory,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}),
|
|
|
|
),
|
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
]),
|
|
|
|
);
|
|
|
|
},
|
|
|
|
);
|
|
|
|
}),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
|
|
|
Expanded(
|
|
|
|
flex: 3,
|
|
|
|
child: Container(
|
|
|
|
decoration: BoxDecoration(
|
|
|
|
border: Border(
|
|
|
|
left: BorderSide(
|
|
|
|
width: 1.0,
|
|
|
|
color: Colors.black,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
child: InkWell(
|
|
|
|
child: Icon(
|
|
|
|
Icons.info,
|
|
|
|
size: 48.0,
|
|
|
|
color: Colors.black,
|
|
|
|
),
|
|
|
|
/*
|
|
|
|
onTap: () {
|
|
|
|
urlLaunch('https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations');
|
|
|
|
}
|
|
|
|
*/
|
|
|
|
onTap: () {
|
|
|
|
showDialog(
|
2019-07-27 15:34:01 -07:00
|
|
|
context: context,
|
|
|
|
builder: (BuildContext context) {
|
|
|
|
return AlertDialog(
|
|
|
|
backgroundColor: ivory,
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius: BorderRadius.all(Radius.circular(6.0)),
|
|
|
|
),
|
|
|
|
content: Column(
|
|
|
|
mainAxisSize: MainAxisSize.min,
|
|
|
|
children: <Widget>[
|
|
|
|
Text(
|
|
|
|
'The timezone offset should be set and refreshed automatically, '
|
|
|
|
'by querying an api from teleport. However, because the api is '
|
|
|
|
'free, the query is only refreshed once a week.\n'
|
|
|
|
'Additionally, in some cases the result is invalid. Tap the '
|
|
|
|
'left side of TimeZone Widget to manually set the timezone offset.',
|
|
|
|
textAlign: TextAlign.center,
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
Container(
|
|
|
|
margin: EdgeInsets.only(
|
|
|
|
top: 40,
|
|
|
|
bottom: 10,
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
child: ButtonTheme(
|
|
|
|
height: 75,
|
|
|
|
shape: RoundedRectangleBorder(
|
|
|
|
borderRadius:
|
|
|
|
BorderRadius.all(Radius.circular(6.0)),
|
|
|
|
),
|
|
|
|
child: RaisedButton(
|
|
|
|
color: peacockBlue,
|
|
|
|
child: Column(
|
|
|
|
children: <Widget>[
|
|
|
|
Container(
|
|
|
|
width: 150,
|
|
|
|
margin: EdgeInsets.only(
|
|
|
|
top: 10,
|
|
|
|
),
|
|
|
|
child: Row(
|
|
|
|
mainAxisAlignment:
|
|
|
|
MainAxisAlignment.spaceAround,
|
|
|
|
children: <Widget>[
|
|
|
|
Text(
|
|
|
|
'List',
|
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.white,
|
|
|
|
fontSize: 24,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Icon(
|
|
|
|
Icons.open_in_browser,
|
|
|
|
size: 48,
|
|
|
|
color: Colors.white,
|
|
|
|
),
|
|
|
|
],
|
|
|
|
),
|
|
|
|
),
|
|
|
|
Container(
|
|
|
|
margin: EdgeInsets.only(
|
|
|
|
bottom: 15,
|
|
|
|
),
|
|
|
|
child: Text(
|
|
|
|
'Of TimeZones',
|
2019-06-27 17:29:40 -07:00
|
|
|
style: TextStyle(
|
|
|
|
height: textHeight,
|
|
|
|
color: Colors.white,
|
|
|
|
fontSize: 24,
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
],
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
onPressed: () {
|
|
|
|
Navigator.of(context).pop();
|
|
|
|
urlLaunch(
|
|
|
|
'https://en.wikipedia.org/wiki/List_of_time_zone_abbreviations');
|
|
|
|
}),
|
2019-06-27 17:29:40 -07:00
|
|
|
),
|
|
|
|
),
|
2019-07-27 15:34:01 -07:00
|
|
|
],
|
|
|
|
),
|
|
|
|
);
|
|
|
|
});
|
2019-06-27 17:29:40 -07:00
|
|
|
},
|
|
|
|
),
|
|
|
|
),
|
|
|
|
),
|
|
|
|
],
|
|
|
|
);
|
|
|
|
}
|
|
|
|
|
|
|
|
int _getTimeZoneListIndex() {
|
|
|
|
// 2001 is a magic number which means auto
|
|
|
|
// as in the tz offset is automatically set
|
2019-07-27 15:34:01 -07:00
|
|
|
return timeZoneList.indexOf(timeZoneList.singleWhere((timeZone) =>
|
|
|
|
timeZone['offset'] ==
|
|
|
|
((widget.isAutoTimeOffSet == 1) ? 2001 : widget.timeOffSet)));
|
2019-06-27 17:29:40 -07:00
|
|
|
}
|
|
|
|
|
|
|
|
String _parseTimeZoneOffSet(int offset) {
|
|
|
|
if (offset < 2000) {
|
|
|
|
return offset.toString();
|
|
|
|
} else if (offset == 2000) {
|
|
|
|
return 'INVALID';
|
|
|
|
} else if (offset == 2001) {
|
|
|
|
return 'AUTO';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|