Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Configured linting and added linting CI #110

Merged
merged 11 commits into from
Aug 9, 2024
Merged
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
31 changes: 31 additions & 0 deletions .github/workflows/linting.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
name: Linting

on:
pull_request:
branches:
- "*"
workflow_dispatch:

jobs:
build:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
with:
flutter-version: '3.22.2'
channel: 'stable'
- run: flutter --version

- name: Install dependencies
run: dart pub get

- name: Verify formatting
run: dart format --output=none --set-exit-if-changed .

#- name: Analyze project source
# run: dart analyze --fatal-infos

#- name: Run tests
# run: flutter test
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
[![GitHub Downloads](https://img.shields.io/github/downloads/andreped/IronFlow/total?label=GitHub%20downloads&logo=github)](https://github.com/andreped/IronFlow/releases)
![CI](https://github.com/andreped/IronFlow/workflows/Build%20APK/badge.svg)
![CI](https://github.com/andreped/IronFlow/workflows/Build%20IPA/badge.svg)
![CI](https://github.com/andreped/IronFlow/workflows/Linting/badge.svg)
</h3>

**IronFlow** was developed to allow free, private, and seemless tracking of training progress and activities.
Expand Down Expand Up @@ -45,6 +46,7 @@ The app is compatible with both Android and iOS.
| **Build APK** | ![CI](https://github.com/andreped/IronFlow/workflows/Build%20APK/badge.svg) |
| **Build IPA** | ![CI](https://github.com/andreped/IronFlow/workflows/Build%20IPA/badge.svg) |
| **Create Release** | ![CI](https://github.com/andreped/IronFlow/workflows/Create%20Release/badge.svg) |
| **Linting** | ![CI](https://github.com/andreped/IronFlow/workflows/Linting/badge.svg) |

## [Getting Started](https://github.com/andreped/IronFlow#Getting-Started)

Expand Down
35 changes: 18 additions & 17 deletions lib/core/database.dart
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,8 @@ class DatabaseHelper {
await _initializePredefinedExercises(db);
}

Future<void> _upgradeDatabase(Database db, int oldVersion, int newVersion) async {
Future<void> _upgradeDatabase(
Database db, int oldVersion, int newVersion) async {
// Placeholder for future upgrade logic
if (oldVersion < newVersion) {
// Example: if (oldVersion < 2) {
Expand Down Expand Up @@ -104,9 +105,8 @@ class DatabaseHelper {

Future<List<DateTime>> getExerciseDates() async {
final db = await database;
final List<Map<String, dynamic>> datesResult = await db.rawQuery(
'SELECT DISTINCT date(timestamp) as date FROM exercises'
);
final List<Map<String, dynamic>> datesResult = await db
.rawQuery('SELECT DISTINCT date(timestamp) as date FROM exercises');

return datesResult.map((row) {
return DateTime.parse(row['date']);
Expand Down Expand Up @@ -136,8 +136,8 @@ class DatabaseHelper {
);
}


Future<bool> isNewHighScore(String exerciseName, double newWeight, int newReps) async {
Future<bool> isNewHighScore(
String exerciseName, double newWeight, int newReps) async {
final db = await database;

// Query to get the current highest weight and corresponding reps for that weight
Expand All @@ -157,7 +157,8 @@ class DatabaseHelper {
final maxReps = row['reps'] as int;

// Check if both weight and reps are greater than the current record
if (newWeight > maxWeight || (newWeight == maxWeight && newReps > maxReps)) {
if (newWeight > maxWeight ||
(newWeight == maxWeight && newReps > maxReps)) {
return true; // New record found
}
}
Expand Down Expand Up @@ -234,7 +235,8 @@ class DatabaseHelper {

Future<List<String>> getPredefinedExercises() async {
final db = await database;
final List<Map<String, dynamic>> result = await db.query('predefined_exercises');
final List<Map<String, dynamic>> result =
await db.query('predefined_exercises');
return result.map((row) => row['name'] as String).toList();
}

Expand All @@ -243,16 +245,16 @@ class DatabaseHelper {
await db.insert(
'predefined_exercises',
{'name': exerciseName},
conflictAlgorithm: ConflictAlgorithm.ignore, // Handle if exercise already exists
conflictAlgorithm:
ConflictAlgorithm.ignore, // Handle if exercise already exists
);
}

Future<Map<String, Map<String, dynamic>>> getMaxWeightsForExercises() async {
final db = await database;

// Query to get the maximum weight and corresponding highest reps for each exercise
final List<Map<String, dynamic>> results = await db.rawQuery(
'''
final List<Map<String, dynamic>> results = await db.rawQuery('''
SELECT exercise, weight, reps
FROM exercises
WHERE (exercise, CAST(weight AS REAL)) IN (
Expand All @@ -261,8 +263,7 @@ class DatabaseHelper {
GROUP BY exercise
)
ORDER BY exercise, CAST(weight AS REAL) DESC, reps DESC
'''
);
''');

Map<String, Map<String, dynamic>> maxWeights = {};
for (var result in results) {
Expand Down Expand Up @@ -291,8 +292,8 @@ class DatabaseHelper {
return maxWeights;
}


Future<Map<String, dynamic>?> getLastLoggedExercise(String exerciseName) async {
Future<Map<String, dynamic>?> getLastLoggedExercise(
String exerciseName) async {
final db = await database;
final List<Map<String, dynamic>> result = await db.query(
'exercises',
Expand All @@ -306,12 +307,12 @@ class DatabaseHelper {
final row = result.first;
return {
'exercise': row['exercise'],
'weight': double.tryParse(row['weight']) ?? 0.0, // Convert weight to double
'weight':
double.tryParse(row['weight']) ?? 0.0, // Convert weight to double
'reps': row['reps'] as int,
'sets': row['sets'] as int,
};
}
return null;
}

}
89 changes: 48 additions & 41 deletions lib/tabs/home.dart
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ class ExerciseStoreHomePage extends StatefulWidget {
_ExerciseStoreHomePageState createState() => _ExerciseStoreHomePageState();
}

class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with SingleTickerProviderStateMixin {
class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage>
with SingleTickerProviderStateMixin {
final DatabaseHelper _dbHelper = DatabaseHelper();
DateTime _selectedDay = DateTime.now();
late TabController _tabController;
Expand Down Expand Up @@ -91,7 +92,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
builder: (BuildContext context) {
return AlertDialog(
title: const Text('⚠️ Confirm Deletion'),
content: const Text('🚨 Clicking this button deletes all the recorded exercise data. Are you sure you want to do this?'),
content: const Text(
'🚨 Clicking this button deletes all the recorded exercise data. Are you sure you want to do this?'),
actions: <Widget>[
TextButton(
child: const Text('No'),
Expand All @@ -112,7 +114,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
builder: (BuildContext context) {
return AlertDialog(
title: const Text('❗️ Are you really sure?'),
content: const Text('💥 Are you really sure you want to lose all your data? There is no going back!'),
content: const Text(
'💥 Are you really sure you want to lose all your data? There is no going back!'),
actions: <Widget>[
TextButton(
child: const Text('No'),
Expand Down Expand Up @@ -164,7 +167,9 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
tabs: const [
Tab(icon: Icon(Icons.add), text: 'Log\nExercise'),
Tab(icon: Icon(Icons.calendar_today), text: 'Summary'),
Tab(icon: Icon(Icons.celebration), text: 'Records'), // New Records tab
Tab(
icon: Icon(Icons.celebration),
text: 'Records'), // New Records tab
Tab(icon: Icon(Icons.show_chart), text: 'Visualize\nData'),
Tab(icon: Icon(Icons.table_chart), text: 'View\nTable'),
],
Expand All @@ -174,7 +179,8 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
bucket: bucket,
child: PageView(
controller: _pageController,
physics: const NeverScrollableScrollPhysics(), // Disable swipe gesture
physics:
const NeverScrollableScrollPhysics(), // Disable swipe gesture
onPageChanged: (index) {
_tabController.animateTo(index);
},
Expand Down Expand Up @@ -213,43 +219,44 @@ class _ExerciseStoreHomePageState extends State<ExerciseStoreHomePage> with Sing
}
final exercises = snapshot.data!;
return DataTable(
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Exercise')),
DataColumn(label: Text('Weight')),
DataColumn(label: Text('Reps')),
DataColumn(label: Text('Sets')),
DataColumn(label: Text('Timestamp')),
DataColumn(label: Text('Actions')),
],
rows: exercises.map((exercise) {
return DataRow(cells: [
DataCell(Text(exercise['id'].toString())),
DataCell(Text(exercise['exercise'])),
DataCell(Text(exercise['weight'])),
DataCell(Text(exercise['reps'].toString())),
DataCell(Text(exercise['sets'].toString())),
DataCell(Text(exercise['timestamp'])), // Display the timestamp
DataCell(
Row(
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
_showEditDialog(exercise);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteExercise(exercise['id']);
},
),
],
),
columns: const [
DataColumn(label: Text('ID')),
DataColumn(label: Text('Exercise')),
DataColumn(label: Text('Weight')),
DataColumn(label: Text('Reps')),
DataColumn(label: Text('Sets')),
DataColumn(label: Text('Timestamp')),
DataColumn(label: Text('Actions')),
],
rows: exercises.map((exercise) {
return DataRow(cells: [
DataCell(Text(exercise['id'].toString())),
DataCell(Text(exercise['exercise'])),
DataCell(Text(exercise['weight'])),
DataCell(Text(exercise['reps'].toString())),
DataCell(Text(exercise['sets'].toString())),
DataCell(Text(
exercise['timestamp'])), // Display the timestamp
DataCell(
Row(
children: [
IconButton(
icon: const Icon(Icons.edit),
onPressed: () {
_showEditDialog(exercise);
},
),
IconButton(
icon: const Icon(Icons.delete),
onPressed: () async {
await _deleteExercise(exercise['id']);
},
),
],
),
]);
}).toList(),
),
]);
}).toList(),
);
},
),
Expand Down
27 changes: 19 additions & 8 deletions lib/tabs/inputs.dart
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
List<String> exercises = await _dbHelper.getPredefinedExercises();
setState(() {
_predefinedExercises = exercises;
_selectedExercise = _predefinedExercises.isNotEmpty ? _predefinedExercises.first : null;
_selectedExercise =
_predefinedExercises.isNotEmpty ? _predefinedExercises.first : null;
if (_selectedExercise != null) {
_loadLastLoggedExercise();
}
Expand All @@ -46,7 +47,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {

Future<void> _loadLastLoggedExercise() async {
if (_selectedExercise != null) {
final lastLogged = await _dbHelper.getLastLoggedExercise(_selectedExercise!);
final lastLogged =
await _dbHelper.getLastLoggedExercise(_selectedExercise!);
if (lastLogged != null) {
setState(() {
_lastExerciseName = lastLogged['exercise'];
Expand All @@ -71,7 +73,8 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
final reps = int.parse(_repsController.text);
final sets = int.parse(_setsController.text);

final isNewHighScore = await _dbHelper.isNewHighScore(exerciseName, weight, reps);
final isNewHighScore =
await _dbHelper.isNewHighScore(exerciseName, weight, reps);

await _dbHelper.insertExercise(
exercise: exerciseName,
Expand Down Expand Up @@ -169,10 +172,16 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
child: GestureDetector(
onTap: _openExerciseSelectionSheet,
child: InputDecorator(
decoration: const InputDecoration(labelText: 'Select Exercise'),
decoration:
const InputDecoration(labelText: 'Select Exercise'),
child: Text(
_isAddingNewExercise ? 'Add New Exercise' : _selectedExercise ?? 'Select Exercise',
style: TextStyle(color: _selectedExercise == null ? Colors.grey : Colors.black),
_isAddingNewExercise
? 'Add New Exercise'
: _selectedExercise ?? 'Select Exercise',
style: TextStyle(
color: _selectedExercise == null
? Colors.grey
: Colors.black),
),
),
),
Expand All @@ -184,9 +193,11 @@ class _ExerciseSetterState extends State<ExerciseSetter> {
padding: const EdgeInsets.only(top: 16.0),
child: TextFormField(
controller: _newExerciseController,
decoration: const InputDecoration(labelText: 'New Exercise Name'),
decoration:
const InputDecoration(labelText: 'New Exercise Name'),
validator: (value) {
if (_isAddingNewExercise && (value == null || value.isEmpty)) {
if (_isAddingNewExercise &&
(value == null || value.isEmpty)) {
return 'Please enter a new exercise name';
}
return null;
Expand Down
6 changes: 4 additions & 2 deletions lib/tabs/summary.dart
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ class _SummaryTabState extends State<SummaryTab> {
const Text('Select Day: '),
TextButton(
onPressed: () => _selectDate(context),
child: Text('${widget.selectedDay.year}-${widget.selectedDay.month}-${widget.selectedDay.day}'),
child: Text(
'${widget.selectedDay.year}-${widget.selectedDay.month}-${widget.selectedDay.day}'),
),
],
),
Expand All @@ -65,7 +66,8 @@ class _SummaryTabState extends State<SummaryTab> {
final totalSets = details['totalSets'];
final totalReps = details['totalReps'];
final avgWeight = details['avgWeight'];
final records = details['records'] as List<Map<String, dynamic>>;
final records =
details['records'] as List<Map<String, dynamic>>;

return Card(
child: ExpansionTile(
Expand Down
Loading
Loading