TimeTracker/lib/pages/WebMainPage.dart

248 lines
8.3 KiB
Dart

import 'dart:async';
import 'package:flutter/material.dart';
import 'package:libacflutter/Constants.dart';
import 'package:timetrack/consts.dart';
import 'package:timetrack/data.dart';
import 'package:url_launcher/url_launcher.dart';
class WebMain extends StatefulWidget {
const WebMain({super.key});
@override
State<StatefulWidget> createState() {
return _WebMain();
}
}
class _WebMain extends State<WebMain> {
TextEditingController sessionIDController = TextEditingController();
@override
void didChangeDependencies() {
sessionIDController.text = SessionData.LastSessionID;
// Check if FirstRun
if (SessionData.Calls.HomeCallback == null) {
SessionData.Calls.HomeCallback = _callback;
// After doing this, we also want to schedule the timer
Timer.periodic(Duration(seconds: 5), (timer) async {
if (!SessionData.Recording) {
timer.cancel();
return;
}
// Fetch the latest version number, compare, then redownload the data.
int ver = await SessionData.FetchVersion();
if (ver != SessionData.RecordingVersion) {
await SessionData.DownloadData();
}
});
}
super.didChangeDependencies();
}
Future<void> _callback() async {
setState(() {});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Time Tracker"),
backgroundColor: LibACFlutterConstants.TITLEBAR_COLOR,
),
drawer: Drawer(
elevation: 8,
child: SingleChildScrollView(
child: Column(
children: [
DrawerHeader(
child: Column(
children: [
Text("Time Tracker"),
Text("Created by Tara Piccari"),
Text("Copyright 2025 - Present"),
Text("Version: ${TTConsts.VERSION}"),
],
),
),
if (SessionData.IsReadOnly)
ListTile(
title: Text("Trip Map"),
leading: Icon(Icons.map),
subtitle: Text(
"View a map of the route\n(NOTE: This is not live, and reflects the current state as of the time the map is opened.)",
),
onTap: () async {
await Navigator.pushNamed(context, "/map");
},
),
if (SessionData.IsReadOnly)
ListTile(
title: Text("Work Data"),
subtitle: Text("View work data"),
leading: Icon(Icons.work_history),
onTap: () async {
// Open up the work data viewer and editor.
// Edit will be disabled for web or read only mode.
await Navigator.pushNamed(context, "/work");
setState(() {});
},
),
ListTile(
title: Text("Source Code"),
subtitle: Text("Licensed under the GPLv3"),
leading: Icon(Icons.code_rounded),
onTap: () async {
final Uri url = Uri.parse(
'https://git.zontreck.com/AriasCreations/TimeTracker',
);
if (!await launchUrl(url)) {
throw Exception('Could not launch $url');
}
},
),
ListTile(
title: Text("Download Mobile App"),
subtitle: Text(
"Click to go to the download page, from there you will want the APK file.",
),
leading: Icon(Icons.download),
onTap: () async {
final Uri url = Uri.parse(
"https://ci.zontreck.com/job/Projects/job/Dart/job/Time%20Tracker/",
);
if (!await launchUrl(url)) {
throw Exception("Could not launch $url");
}
},
),
],
),
),
),
body: Padding(
padding: EdgeInsets.all(8),
child: SingleChildScrollView(
child: Column(
children: [
// Start doing magic!
if (SessionData.DisplayError.isNotEmpty)
Text(SessionData.DisplayError, style: TextStyle(fontSize: 18)),
// Check what widgets need to be displayed.
if (SessionData.IsReadOnly) GetReadOnlyWidgets(),
if (!SessionData.IsReadOnly) GetLoadWidgets(),
],
),
),
),
);
}
Widget GetReadOnlyWidgets() {
return Column(
children: [
Text(
"Use the top left menu to show the various pages for the data viewer.",
),
if (SessionData.IsSavedData)
ListTile(
title: Text("You are viewing saved data"),
subtitle: Text(
"This data was saved in the ${SessionData.SaveDataType} format.\n\nThis data is read-only. You will not be able to edit it.",
),
tileColor: const Color.fromARGB(255, 7, 123, 255),
),
if (SessionData.Recording)
ListTile(
title: Text("LIVE SESSION"),
subtitle: Text(
"This session is live! Recording is still in progress. Over time this live view will automatically refresh until the recording is ended.\n\nSession Version: ${SessionData.RecordingVersion}",
),
tileColor: LibACFlutterConstants.TITLEBAR_COLOR,
),
ElevatedButton(
onPressed: () async {
await showDialog(
context: context,
builder: (builder) {
return AlertDialog(
icon: Icon(Icons.warning_amber),
title: Text("Are you sure?"),
content: Text(
"If you close the session, you will need to re-enter the session code if you wish to load it again.",
),
actions: [
ElevatedButton(
onPressed: () async {
SessionData.IsReadOnly = false;
SessionData.Trips = [];
SessionData.positions = [];
SessionData.DisplayError = "";
SessionData.StartTime = DateTime(0);
SessionData.EndTime = DateTime(0);
SessionData.LastSessionID = "";
sessionIDController.text = "";
setState(() {});
Navigator.pop(context);
},
child: Text("Yes"),
),
ElevatedButton(
onPressed: () {
Navigator.pop(context);
},
child: Text("Cancel"),
),
],
);
},
);
},
child: Text("Close Session"),
),
],
);
}
Widget GetLoadWidgets() {
return Column(
children: [
// Present a text box for the session ID, and a button for loading.
ListTile(title: Text("Session ID")),
TextField(
controller: sessionIDController,
decoration: InputDecoration(border: OutlineInputBorder()),
),
ElevatedButton(
onPressed: () async {
SessionData.LastSessionID = sessionIDController.text;
bool success = await SessionData.DownloadData();
if (!success) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
"ERROR: The provided session code was not found on the server",
style: TextStyle(fontSize: 18, color: Colors.white),
),
backgroundColor: LibACFlutterConstants.TITLEBAR_COLOR,
),
snackBarAnimationStyle: AnimationStyle(
duration: Duration(seconds: 5),
),
);
}
setState(() {});
},
child: Text("Load Session", style: TextStyle(fontSize: 18)),
),
],
);
}
}