Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -46,4 +46,5 @@ app.*.map.json
/android/app/release

lib/generated
lib/oss_licenses.dart
lib/oss_licenses.dart
/pubspec.lock
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

<h3 align="center">Just Another Workout Timer</h3>


<p align="center">
A simple timer for your workouts, built with Flutter!
<br />
Expand Down
4 changes: 2 additions & 2 deletions android/settings.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,8 @@ pluginManagement {

plugins {
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
id "com.android.application" version '8.4.1' apply false
id "org.jetbrains.kotlin.android" version "2.0.0" apply false
id "com.android.application" version '8.6.0' apply false
id "org.jetbrains.kotlin.android" version "2.1.0" apply false
}

include ":app"
3 changes: 3 additions & 0 deletions lib/l10n/intl_en.arb
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
"duplicate": "Duplicate",
"durationLeft": "{timeLeft} of {timeTotal} left",
"durationWithTime": "Duration: {formattedTime}",
"editSetName" : "Edit set name",
"editWorkout": "Edit workout",
"enterWorkoutName": "Please enter a name for the workout!",
"exercise": "Exercise",
Expand Down Expand Up @@ -57,7 +58,9 @@
"settingHalfway": "Play sound or announcement halfway during exercise",
"settings": "Settings",
"soundOutput": "Sound output",
"spinnerStep": "Editor time granularity",
"startWorkout": "Start workout",
"tapToEdit": "Tap to edit",
"title": "Just Another Workout Timer",
"tts": "Text-to-Speech (TTS)",
"ttsLang": "TTS Language",
Expand Down
5 changes: 5 additions & 0 deletions lib/layouts/home_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -207,5 +207,10 @@ class HomePageState extends State<HomePage> {
tooltip: S.of(context).addWorkout,
child: const Icon(Icons.add),
),
// Empty App Bar prevents drawing under nav buttons.
bottomNavigationBar: const BottomAppBar(
elevation : 1,
height: 1,
)
);
}
2 changes: 2 additions & 0 deletions lib/layouts/oss_license_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ class OssLicensesPage extends StatelessWidget {
isMarkdown: false,
isSdk: false,
dependencies: [],
devDependencies: []
),
);
}
Expand All @@ -54,6 +55,7 @@ class OssLicensesPage extends StatelessWidget {
isSdk: false,
homepage: 'https://freesound.org/people/unfa/sounds/243749/',
dependencies: [],
devDependencies: []
),
);

Expand Down
29 changes: 29 additions & 0 deletions lib/layouts/settings_page.dart
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,35 @@ class SettingsPageState extends State<SettingsPage> {
subtitle: Text(S.of(context).expanded_setlist_info),
pref: 'expanded_setlist',
),

PrefTitle(
title: Text(
S.of(context).editWorkout,
),
),
PrefDropdown<int>(
title: Text(S.of(context).spinnerStep),
pref: 'spinner_step',
items: [
DropdownMenuItem(
value: 5,
child: Text("5 ${S.of(context).seconds}"),
),
DropdownMenuItem(
value: 10,
child: Text("10 ${S.of(context).seconds}"),
),
DropdownMenuItem(
value: 15,
child: Text("15 ${S.of(context).seconds}"),
),
],
),
PrefSwitch(
title: Text(S.of(context).tapToEdit),
pref: 'tap_to_edit',
),

PrefTitle(
title: Text(
S.of(context).backup,
Expand Down
46 changes: 41 additions & 5 deletions lib/layouts/workout_builder.dart
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:prefs/prefs.dart';
import 'package:prompt_dialog/prompt_dialog.dart';
import 'package:uuid/uuid.dart';

import '../generated/l10n.dart';
Expand Down Expand Up @@ -56,7 +58,7 @@ class BuilderPageState extends State<BuilderPage> {
var newSet = Set.fromJson(_workout.sets[index].toJson());
newSet.id = const Uuid().v4();
setState(() {
_workout.sets.insert(index, newSet);
_workout.sets.insert(index + 1, newSet);
_dirty = true;
});
}
Expand Down Expand Up @@ -149,6 +151,20 @@ class BuilderPageState extends State<BuilderPage> {
});
}

void _editSetName(int setIndex) async {
var existingName = _workout.sets[setIndex].name ?? "";
var newName = await prompt(
context,
initialValue: existingName,
maxLength: 15);
if (newName != null && newName != existingName) {
setState(() {
_workout.sets[setIndex].name = newName.isEmpty ? null : newName;
_dirty = true;
});
}
}

Widget _buildSetList() => ReorderableListView(
onReorder: (oldIndex, newIndex) {
if (oldIndex < newIndex) {
Expand Down Expand Up @@ -186,17 +202,26 @@ class BuilderPageState extends State<BuilderPage> {
Expanded(
child: ListTile(
title: Text(
set.name ??
S.of(context).setIndex(_workout.sets.indexOf(set) + 1),
style: const TextStyle(
decoration: TextDecoration.underline,
),
),
subtitle: Text(Utils.formatSeconds(set.duration)),
onLongPress: () {
_editSetName(index);
},
),
),
Text(S.of(context).repetitions),
NumberStepper(
lowerLimit: 1,
upperLimit: 99,
largeSteps: false,
step: 1,
formatNumber: false,
tapToEdit: false,
value: set.repetitions,
valueChanged: (repetitions) {
setState(() {
Expand Down Expand Up @@ -232,12 +257,21 @@ class BuilderPageState extends State<BuilderPage> {
Row(
children: [
IconButton(
icon: const Icon(Icons.delete),
tooltip: S.of(context).deleteSet,
icon: Icon(set.hidden ? Icons.visibility : Icons.visibility_off),
onPressed: () {
_deleteSet(index);
setState(() {
set.hidden = !set.hidden;
_dirty = true;
});
},
),
IconButton(
icon: const Icon(Icons.delete),
tooltip: S.of(context).deleteSet,
onPressed: () {
_deleteSet(index);
}
),
IconButton(
icon: const Icon(Icons.copy),
tooltip: S.of(context).duplicate,
Expand All @@ -264,7 +298,7 @@ class BuilderPageState extends State<BuilderPage> {
_workout.sets[setIndex].exercises.insert(newIndex, ex);
});
},
children: set.exercises
children: set.hidden ? [] : set.exercises
.asMap()
.keys
.map(
Expand Down Expand Up @@ -337,7 +371,9 @@ class BuilderPageState extends State<BuilderPage> {
lowerLimit: 0,
upperLimit: 10800,
largeSteps: true,
step: Prefs.getInt('spinner_step', 10) ,
formatNumber: true,
tapToEdit: Prefs.getBool('tap_to_edit', false),
value: _workout.sets[setIndex].exercises[exIndex].duration,
valueChanged: (duration) {
setState(() {
Expand Down
11 changes: 10 additions & 1 deletion lib/layouts/workout_runner.dart
Original file line number Diff line number Diff line change
Expand Up @@ -166,6 +166,7 @@ class WorkoutPageState extends State<WorkoutPageContent> {
),
),
),

// right side of footer
Expanded(
child: ListTile(
Expand Down Expand Up @@ -198,7 +199,15 @@ class WorkoutPageState extends State<WorkoutPageContent> {
child: Column(
children: [
Text(
'${S.of(context).setIndex(_workout.sets.indexOf(timetable.currentSet) + 1)} - ${Utils.formatSeconds(timetable.remainingSeconds)}',
timetable.currentSet.name ?? S.of(context).setIndex(_workout.sets.indexOf(timetable.currentSet) + 1),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 40,
fontWeight: FontWeight.bold,
),
),
Text(
Utils.formatSeconds(timetable.remainingSeconds),
textAlign: TextAlign.center,
style: const TextStyle(
fontSize: 48,
Expand Down
7 changes: 5 additions & 2 deletions lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ void main() async {
'tts_next_announce': true,
'sound': 'tts',
'expanded_setlist': false,
'spinner_step': 10,
'tap_to_edit' : false,
},
).then(
(service) => Future.wait([
Expand All @@ -49,6 +51,7 @@ void main() async {
}

class JAWTApp extends StatelessWidget {
// TODO this shouldn't exist in a StatelessWidget
ThemeMode? _brightness;

JAWTApp({super.key});
Expand Down Expand Up @@ -84,14 +87,14 @@ class JAWTApp extends StatelessWidget {
brightness: Brightness.light,
colorScheme: lightDynamic,
colorSchemeSeed: lightDynamic != null ? null : Colors.blue,
cardTheme: const CardTheme(
cardTheme: const CardThemeData(
elevation: 4,
),
),
darkTheme: ThemeData(
useMaterial3: true,
brightness: Brightness.dark,
cardTheme: const CardTheme(elevation: 4),
cardTheme: const CardThemeData(elevation: 4),
colorScheme: darkDynamic,
colorSchemeSeed: darkDynamic != null ? null : Colors.blue,
),
Expand Down
Loading
Loading