Implement everything

Thanks claude!"
This commit is contained in:
2025-03-14 23:27:55 +01:00
parent 61a3baae06
commit 969b146b35

View File

@@ -1,4 +1,6 @@
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
void main() {
runApp(const MyApp());
@@ -27,13 +29,180 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State<MyHomePage> {
Timer? _timer;
DateTime? _startTime;
DateTime? _pauseTime;
Duration _elapsedTime = Duration.zero;
bool _isRunning = false;
List<String> _laps = [];
final FocusNode _focusNode = FocusNode();
void _startTimer() {
final now = DateTime.now();
if (_pauseTime != null) {
// Resuming from pause
final pausedDuration = now.difference(_pauseTime!);
_startTime = _startTime?.add(pausedDuration);
_pauseTime = null;
} else {
// Starting fresh
_startTime = now;
_elapsedTime = Duration.zero;
_laps = [];
}
_timer = Timer.periodic(const Duration(milliseconds: 100), (timer) {
setState(() {
_elapsedTime = DateTime.now().difference(_startTime!);
});
});
setState(() {
_isRunning = true;
});
}
void _pauseTimer() {
_timer?.cancel();
_pauseTime = DateTime.now();
setState(() {
_isRunning = false;
});
}
void _stopTimer() {
_timer?.cancel();
setState(() {
_isRunning = false;
_startTime = null;
_pauseTime = null;
_elapsedTime = Duration.zero;
});
}
void _recordLap() {
if (_isRunning) {
final now = DateTime.now();
setState(() {
_laps.add(now.toIso8601String());
});
}
}
String _formatDuration(Duration duration) {
// Format the duration as ISO 8601 duration format: PT[hours]H[minutes]M[seconds]S
final hours = duration.inHours;
final minutes = duration.inMinutes.remainder(60);
final seconds = duration.inSeconds.remainder(60);
final milliseconds = duration.inMilliseconds.remainder(1000);
return 'PT${hours}H${minutes}M${seconds}.${milliseconds}S';
}
void _handleKeyEvent(RawKeyEvent event) {
if (event is RawKeyDownEvent) {
if (event.logicalKey == LogicalKeyboardKey.space) {
// Space: Start if paused, Lap if running
if (_isRunning) {
_recordLap();
} else {
_startTimer();
}
} else if (event.logicalKey == LogicalKeyboardKey.enter) {
// Enter: Stop if paused, Pause if running
if (_isRunning) {
_pauseTimer();
} else {
_stopTimer();
}
}
}
}
@override
void initState() {
super.initState();
_focusNode.requestFocus();
}
@override
void dispose() {
_timer?.cancel();
_focusNode.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
return Scaffold(
return RawKeyboardListener(
focusNode: _focusNode,
onKey: _handleKeyEvent,
autofocus: true,
child: Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
title: Text(widget.title),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(
'Time Elapsed:',
style: Theme.of(context).textTheme.headlineSmall,
),
const SizedBox(height: 10),
Text(
_formatDuration(_elapsedTime),
style: Theme.of(context).textTheme.headlineMedium,
),
const SizedBox(height: 30),
Row(
mainAxisAlignment: MainAxisAlignment.center,
children: [
ElevatedButton(
onPressed: _isRunning ? _pauseTimer : _startTimer,
child: Text(_isRunning ? 'Pause' : 'Start'),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: _stopTimer,
child: const Text('Stop'),
),
const SizedBox(width: 20),
ElevatedButton(
onPressed: _recordLap,
child: const Text('Lap'),
),
],
),
const SizedBox(height: 10),
Text(
'Keyboard: SPACE for Start/Lap, ENTER for Pause/Stop',
style: Theme.of(context).textTheme.bodySmall,
),
const SizedBox(height: 20),
if (_laps.isNotEmpty) ...[
Text(
'Laps:',
style: Theme.of(context).textTheme.titleLarge,
),
const SizedBox(height: 10),
Expanded(
child: ListView.builder(
itemCount: _laps.length,
itemBuilder: (context, index) {
return ListTile(
title: Text('Lap ${index + 1}: ${_laps[index]}'),
);
},
),
),
],
],
),
),
),
);
}
}