Compare commits

..

No commits in common. "main" and "alpha" have entirely different histories.
main ... alpha

11 changed files with 16 additions and 234 deletions

28
Jenkinsfile vendored
View file

@ -44,33 +44,5 @@ pipeline {
}
}
}
stage("Build Web App") {
agent {
label 'linux'
}
steps {
script {
sh '''
#!/bin/bash
flutter build web
cd build/web
tar -cvf ../../web.tgz .
cd ../..
'''
}
}
post {
always {
archiveArtifacts artifacts: "web.tgz"
cleanWs()
}
}
}
}
}

View file

@ -1,4 +1,3 @@
{
"alpha": "1.0.0-dev.10",
"beta": "1.0.0-beta.31"
"alpha": "1.0.0-dev.10"
}

View file

@ -1,4 +1,5 @@
import 'dart:convert';
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:geolocator/geolocator.dart';
@ -6,13 +7,10 @@ import 'package:geolocator/geolocator.dart';
class TTConsts {
static get UPDATE_URL =>
"https://git.zontreck.com/AriasCreations/TimeTracker/raw/branch/main/latest-releases.json";
static get SESSION_SERVER =>
"https://api.zontreck.com/timetrack/${UPDATE_CHANNEL}/timetrack.php";
static const VERSION = "1.0.0-beta.3";
static const VERSION = "1.0.0-dev.10";
static bool UPDATE_AVAILABLE = false;
static UpdateChannel UPDATE_CHANNEL = UpdateChannel.beta;
static UpdateChannel UPDATE_CHANNEL = UpdateChannel.alpha;
static final LocationSettings LOCATION_SETTINGS = LocationSettings(
accuracy: LocationAccuracy.bestForNavigation,
distanceFilter: 15,

View file

@ -3,8 +3,6 @@ import 'dart:convert';
import 'dart:math' as math;
import 'dart:ui';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:geolocator/geolocator.dart';
import 'package:libac_dart/nbt/Stream.dart';
import 'package:timetrack/consts.dart';
@ -21,8 +19,6 @@ class SessionData {
static List<Position> positions = [];
static late StreamSubscription<Position> _listener;
static Callbacks Calls = Callbacks();
static String LastSessionID = "";
static String DisplayError = "";
/// This flag is usually set when data is loaded from a saved state. Or when accessed using the Web version of the app.
static bool IsReadOnly = false;
@ -189,22 +185,10 @@ class SessionData {
Trips = [];
positions = [];
Dio dio = Dio();
Map<String, dynamic> payload = {"cmd": "create", "data": saveData};
var reply = await dio.post(
TTConsts.SESSION_SERVER,
data: json.encode(payload),
);
Map<String, dynamic> replyJs = json.decode(reply.data as String);
if (replyJs["status"] == "ok") {
print("Successful upload");
LastSessionID = replyJs['session'] as String;
Calls.dispatch();
}
// TODO: Upload to the server.
}
static Map<String, dynamic> SaveData() {
static String SaveData() {
Map<String, dynamic> saveData = {};
List<Map<String, dynamic>> _trips = [];
@ -220,28 +204,11 @@ class SessionData {
saveData["trips"] = _trips;
saveData["positions"] = _pos;
return saveData;
return json.encode(saveData);
}
static Future<void> DownloadData() async {
Dio dio = Dio();
Map<String, dynamic> payload = {"cmd": "get", "id": LastSessionID};
// Send the data, and get the response
var reply = await dio.post(
TTConsts.SESSION_SERVER,
data: json.encode(payload),
);
LoadData(reply.data as String);
}
static void LoadData(String js) {
void LoadData(String js) {
Map<String, dynamic> _js = json.decode(js);
if (_js.containsKey("error")) {
LastSessionID = "";
return;
}
List<Map<String, dynamic>> _trips =
_js['trips'] as List<Map<String, dynamic>>;
List<Map<String, dynamic>> _pos =

View file

@ -1,19 +1,9 @@
import 'package:flutter/material.dart';
import 'package:timetrack/consts.dart';
import 'package:timetrack/data.dart';
import 'package:timetrack/pages/MainApp.dart';
Future<void> main() async {
await TTConsts.checkUpdate();
var sess = Uri.base.queryParameters["code"] ?? "";
SessionData.LastSessionID = sess;
if (SessionData.LastSessionID.isNotEmpty) {
await SessionData.DownloadData();
if (SessionData.LastSessionID.isEmpty) {
// Invalid session token
SessionData.DisplayError = "The URL and or session token is invalid";
}
}
runApp(MainApp());
}

View file

@ -1,5 +1,4 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:libacflutter/Constants.dart';
import 'package:libacflutter/Prompt.dart';
import 'package:timetrack/consts.dart';
@ -113,22 +112,10 @@ class _HomePageState extends State<HomePage> {
body: SingleChildScrollView(
child: Column(
children: [
if (!SessionData.IsOnTheClock)
Text(
"Hit engage when you are ready to go online and start tracking location data, and trips.",
style: TextStyle(fontSize: 18),
),
if (SessionData.LastSessionID.isNotEmpty)
ListTile(
title: Text("Session ID"),
subtitle: Text("${SessionData.LastSessionID} - Tap to copy"),
onTap: () {
Clipboard.setData(
ClipboardData(text: SessionData.LastSessionID),
);
},
),
Text(
"Hit engage when you are ready to go online and start tracking location data, and trips.",
style: TextStyle(fontSize: 18),
),
if (!SessionData.IsOnTheClock)
Center(
child: ElevatedButton(

View file

@ -1,10 +1,7 @@
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:timetrack/pages/HomePage.dart';
import 'package:timetrack/pages/MapPage.dart';
import 'package:timetrack/pages/UpdateSettings.dart';
import 'package:timetrack/pages/WebMainPage.dart';
import 'package:timetrack/pages/WorkData.dart';
class MainApp extends StatefulWidget {
@ -27,7 +24,7 @@ class MainAppState extends State<MainApp> {
return MaterialApp(
title: "Time Tracker",
routes: {
"/": (ctx) => Platform.isAndroid ? HomePage() : WebMain(),
"/": (ctx) => HomePage(),
"/upd": (ctx) => UpdateSettingsPage(),
"/map": (ctx) => MapPage(),
"/work": (ctx) => WorkDataPage(),

View file

@ -1,128 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:libacflutter/Constants.dart';
import 'package:timetrack/consts.dart';
import 'package:timetrack/data.dart';
class WebMain extends StatefulWidget {
@override
State<StatefulWidget> createState() {
return _WebMain();
}
}
class _WebMain extends State<WebMain> {
TextEditingController sessionIDController = TextEditingController();
@override
void didChangeDependencies() {
sessionIDController.text = SessionData.LastSessionID;
super.didChangeDependencies();
}
@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(() {});
},
),
],
),
),
),
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.",
),
ElevatedButton(
onPressed: () async {
SessionData.IsReadOnly = false;
SessionData.Trips = [];
SessionData.positions = [];
SessionData.DisplayError = "";
},
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 {
await SessionData.DownloadData();
setState(() {});
},
child: Text("Load Session", style: TextStyle(fontSize: 18)),
),
],
);
}
}

View file

@ -1,6 +1,7 @@
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:libacflutter/Constants.dart';
import 'package:timetrack/consts.dart';
import 'package:timetrack/data.dart';
class WorkDataPage extends StatefulWidget {
@ -69,7 +70,7 @@ class _WorkData extends State<WorkDataPage> {
),
SizedBox(height: 20),
Text(
"Total Estimated Miles: ${SessionData.GetTotalMilesAsString()}\n(Note: The miles displayed above may not be 100% accurate)",
"Total Miles: ${SessionData.GetTotalMilesAsString()}",
style: TextStyle(fontSize: 24),
),
],

View file

@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
# In Windows, build-name is used as the major, minor, and patch parts
# of the product and file versions while build-number is used as the build suffix.
version: 1.0.0-beta.3
version: 1.0.0-dev.10
environment:
sdk: ^3.7.2

View file

@ -10,7 +10,6 @@ $DB = get_DB("timetrack");
$jsx = json_decode(file_get_contents("php://input"), true);
// Get operation information
// DISCLAIMER: All php code below this point is AI Generated
switch($jsx['cmd']) {
case "create": {
// Get UUID from MySQL and insert into sessions table