Compare commits
No commits in common. "0f7d938ad72a20463790a81a4e4daa5e70d70a42" and "ff9f3263aefdd63f1a67e4ebd21929c9a22b71c7" have entirely different histories.
0f7d938ad7
...
ff9f3263ae
|
@ -1,5 +1,30 @@
|
||||||
|
# This file configures the analyzer, which statically analyzes Dart code to
|
||||||
|
# check for errors, warnings, and lints.
|
||||||
|
#
|
||||||
|
# The issues identified by the analyzer are surfaced in the UI of Dart-enabled
|
||||||
|
# IDEs (https://dart.dev/tools#ides-and-editors). The analyzer can also be
|
||||||
|
# invoked from the command line by running `flutter analyze`.
|
||||||
|
|
||||||
|
# The following line activates a set of recommended lints for Flutter apps,
|
||||||
|
# packages, and plugins designed to encourage good coding practices.
|
||||||
include: package:flutter_lints/flutter.yaml
|
include: package:flutter_lints/flutter.yaml
|
||||||
|
|
||||||
linter:
|
linter:
|
||||||
|
# The lint rules applied to this project can be customized in the
|
||||||
|
# section below to disable rules from the `package:flutter_lints/flutter.yaml`
|
||||||
|
# included above or to enable additional rules. A list of all available lints
|
||||||
|
# and their documentation is published at
|
||||||
|
# https://dart-lang.github.io/linter/lints/index.html.
|
||||||
|
#
|
||||||
|
# Instead of disabling a lint rule for the entire project in the
|
||||||
|
# section below, it can also be suppressed for a single line of code
|
||||||
|
# or a specific dart file by using the `// ignore: name_of_lint` and
|
||||||
|
# `// ignore_for_file: name_of_lint` syntax on the line or in the file
|
||||||
|
# producing the lint.
|
||||||
rules:
|
rules:
|
||||||
curly_braces_in_flow_control_structures: false
|
curly_braces_in_flow_control_structures: false
|
||||||
|
# avoid_print: false # Uncomment to disable the `avoid_print` rule
|
||||||
|
# prefer_single_quotes: true # Uncomment to enable the `prefer_single_quotes` rule
|
||||||
|
|
||||||
|
# Additional information about this file can be found at
|
||||||
|
# https://dart.dev/guides/language/analysis-options
|
||||||
|
|
|
@ -2,7 +2,6 @@ import 'dart:io';
|
||||||
|
|
||||||
import 'package:fmassive/gym_set.dart';
|
import 'package:fmassive/gym_set.dart';
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
import 'package:fmassive/plans.dart';
|
|
||||||
import 'package:moor/ffi.dart';
|
import 'package:moor/ffi.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
import 'package:path/path.dart';
|
import 'package:path/path.dart';
|
||||||
|
@ -12,7 +11,7 @@ import 'settings.dart';
|
||||||
|
|
||||||
part 'database.g.dart';
|
part 'database.g.dart';
|
||||||
|
|
||||||
@UseMoor(tables: [Settings, GymSets, Plans])
|
@UseMoor(tables: [Settings, GymSets])
|
||||||
class MyDatabase extends _$MyDatabase {
|
class MyDatabase extends _$MyDatabase {
|
||||||
MyDatabase() : super(_openConnection());
|
MyDatabase() : super(_openConnection());
|
||||||
|
|
||||||
|
@ -36,6 +35,7 @@ LazyDatabase _openConnection() {
|
||||||
return LazyDatabase(() async {
|
return LazyDatabase(() async {
|
||||||
final dbFolder = await getDatabasesPath();
|
final dbFolder = await getDatabasesPath();
|
||||||
final file = File(join(dbFolder, 'massive.db'));
|
final file = File(join(dbFolder, 'massive.db'));
|
||||||
|
print('file.path=${file.path}');
|
||||||
return VmDatabase(file, logStatements: true);
|
return VmDatabase(file, logStatements: true);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -1239,220 +1239,12 @@ class $GymSetsTable extends GymSets with TableInfo<$GymSetsTable, GymSet> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Plan extends DataClass implements Insertable<Plan> {
|
|
||||||
final int id;
|
|
||||||
final String days;
|
|
||||||
final String workouts;
|
|
||||||
Plan({required this.id, required this.days, required this.workouts});
|
|
||||||
factory Plan.fromData(Map<String, dynamic> data, GeneratedDatabase db,
|
|
||||||
{String? prefix}) {
|
|
||||||
final effectivePrefix = prefix ?? '';
|
|
||||||
return Plan(
|
|
||||||
id: const IntType()
|
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}id'])!,
|
|
||||||
days: const StringType()
|
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}days'])!,
|
|
||||||
workouts: const StringType()
|
|
||||||
.mapFromDatabaseResponse(data['${effectivePrefix}workouts'])!,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@override
|
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
|
||||||
final map = <String, Expression>{};
|
|
||||||
map['id'] = Variable<int>(id);
|
|
||||||
map['days'] = Variable<String>(days);
|
|
||||||
map['workouts'] = Variable<String>(workouts);
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
PlansCompanion toCompanion(bool nullToAbsent) {
|
|
||||||
return PlansCompanion(
|
|
||||||
id: Value(id),
|
|
||||||
days: Value(days),
|
|
||||||
workouts: Value(workouts),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
factory Plan.fromJson(Map<String, dynamic> json,
|
|
||||||
{ValueSerializer? serializer}) {
|
|
||||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
|
||||||
return Plan(
|
|
||||||
id: serializer.fromJson<int>(json['id']),
|
|
||||||
days: serializer.fromJson<String>(json['days']),
|
|
||||||
workouts: serializer.fromJson<String>(json['workouts']),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson({ValueSerializer? serializer}) {
|
|
||||||
serializer ??= moorRuntimeOptions.defaultSerializer;
|
|
||||||
return <String, dynamic>{
|
|
||||||
'id': serializer.toJson<int>(id),
|
|
||||||
'days': serializer.toJson<String>(days),
|
|
||||||
'workouts': serializer.toJson<String>(workouts),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
Plan copyWith({int? id, String? days, String? workouts}) => Plan(
|
|
||||||
id: id ?? this.id,
|
|
||||||
days: days ?? this.days,
|
|
||||||
workouts: workouts ?? this.workouts,
|
|
||||||
);
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return (StringBuffer('Plan(')
|
|
||||||
..write('id: $id, ')
|
|
||||||
..write('days: $days, ')
|
|
||||||
..write('workouts: $workouts')
|
|
||||||
..write(')'))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(id, days, workouts);
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) =>
|
|
||||||
identical(this, other) ||
|
|
||||||
(other is Plan &&
|
|
||||||
other.id == this.id &&
|
|
||||||
other.days == this.days &&
|
|
||||||
other.workouts == this.workouts);
|
|
||||||
}
|
|
||||||
|
|
||||||
class PlansCompanion extends UpdateCompanion<Plan> {
|
|
||||||
final Value<int> id;
|
|
||||||
final Value<String> days;
|
|
||||||
final Value<String> workouts;
|
|
||||||
const PlansCompanion({
|
|
||||||
this.id = const Value.absent(),
|
|
||||||
this.days = const Value.absent(),
|
|
||||||
this.workouts = const Value.absent(),
|
|
||||||
});
|
|
||||||
PlansCompanion.insert({
|
|
||||||
this.id = const Value.absent(),
|
|
||||||
required String days,
|
|
||||||
required String workouts,
|
|
||||||
}) : days = Value(days),
|
|
||||||
workouts = Value(workouts);
|
|
||||||
static Insertable<Plan> custom({
|
|
||||||
Expression<int>? id,
|
|
||||||
Expression<String>? days,
|
|
||||||
Expression<String>? workouts,
|
|
||||||
}) {
|
|
||||||
return RawValuesInsertable({
|
|
||||||
if (id != null) 'id': id,
|
|
||||||
if (days != null) 'days': days,
|
|
||||||
if (workouts != null) 'workouts': workouts,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
PlansCompanion copyWith(
|
|
||||||
{Value<int>? id, Value<String>? days, Value<String>? workouts}) {
|
|
||||||
return PlansCompanion(
|
|
||||||
id: id ?? this.id,
|
|
||||||
days: days ?? this.days,
|
|
||||||
workouts: workouts ?? this.workouts,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
|
||||||
final map = <String, Expression>{};
|
|
||||||
if (id.present) {
|
|
||||||
map['id'] = Variable<int>(id.value);
|
|
||||||
}
|
|
||||||
if (days.present) {
|
|
||||||
map['days'] = Variable<String>(days.value);
|
|
||||||
}
|
|
||||||
if (workouts.present) {
|
|
||||||
map['workouts'] = Variable<String>(workouts.value);
|
|
||||||
}
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return (StringBuffer('PlansCompanion(')
|
|
||||||
..write('id: $id, ')
|
|
||||||
..write('days: $days, ')
|
|
||||||
..write('workouts: $workouts')
|
|
||||||
..write(')'))
|
|
||||||
.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class $PlansTable extends Plans with TableInfo<$PlansTable, Plan> {
|
|
||||||
@override
|
|
||||||
final GeneratedDatabase attachedDatabase;
|
|
||||||
final String? _alias;
|
|
||||||
$PlansTable(this.attachedDatabase, [this._alias]);
|
|
||||||
final VerificationMeta _idMeta = const VerificationMeta('id');
|
|
||||||
@override
|
|
||||||
late final GeneratedColumn<int?> id = GeneratedColumn<int?>(
|
|
||||||
'id', aliasedName, false,
|
|
||||||
type: const IntType(),
|
|
||||||
requiredDuringInsert: false,
|
|
||||||
defaultConstraints: 'PRIMARY KEY AUTOINCREMENT');
|
|
||||||
final VerificationMeta _daysMeta = const VerificationMeta('days');
|
|
||||||
@override
|
|
||||||
late final GeneratedColumn<String?> days = GeneratedColumn<String?>(
|
|
||||||
'days', aliasedName, false,
|
|
||||||
type: const StringType(), requiredDuringInsert: true);
|
|
||||||
final VerificationMeta _workoutsMeta = const VerificationMeta('workouts');
|
|
||||||
@override
|
|
||||||
late final GeneratedColumn<String?> workouts = GeneratedColumn<String?>(
|
|
||||||
'workouts', aliasedName, false,
|
|
||||||
type: const StringType(), requiredDuringInsert: true);
|
|
||||||
@override
|
|
||||||
List<GeneratedColumn> get $columns => [id, days, workouts];
|
|
||||||
@override
|
|
||||||
String get aliasedName => _alias ?? 'plans';
|
|
||||||
@override
|
|
||||||
String get actualTableName => 'plans';
|
|
||||||
@override
|
|
||||||
VerificationContext validateIntegrity(Insertable<Plan> instance,
|
|
||||||
{bool isInserting = false}) {
|
|
||||||
final context = VerificationContext();
|
|
||||||
final data = instance.toColumns(true);
|
|
||||||
if (data.containsKey('id')) {
|
|
||||||
context.handle(_idMeta, id.isAcceptableOrUnknown(data['id']!, _idMeta));
|
|
||||||
}
|
|
||||||
if (data.containsKey('days')) {
|
|
||||||
context.handle(
|
|
||||||
_daysMeta, days.isAcceptableOrUnknown(data['days']!, _daysMeta));
|
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_daysMeta);
|
|
||||||
}
|
|
||||||
if (data.containsKey('workouts')) {
|
|
||||||
context.handle(_workoutsMeta,
|
|
||||||
workouts.isAcceptableOrUnknown(data['workouts']!, _workoutsMeta));
|
|
||||||
} else if (isInserting) {
|
|
||||||
context.missing(_workoutsMeta);
|
|
||||||
}
|
|
||||||
return context;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Set<GeneratedColumn> get $primaryKey => {id};
|
|
||||||
@override
|
|
||||||
Plan map(Map<String, dynamic> data, {String? tablePrefix}) {
|
|
||||||
return Plan.fromData(data, attachedDatabase,
|
|
||||||
prefix: tablePrefix != null ? '$tablePrefix.' : null);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
$PlansTable createAlias(String alias) {
|
|
||||||
return $PlansTable(attachedDatabase, alias);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
abstract class _$MyDatabase extends GeneratedDatabase {
|
abstract class _$MyDatabase extends GeneratedDatabase {
|
||||||
_$MyDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
_$MyDatabase(QueryExecutor e) : super(SqlTypeSystem.defaultInstance, e);
|
||||||
late final $SettingsTable settings = $SettingsTable(this);
|
late final $SettingsTable settings = $SettingsTable(this);
|
||||||
late final $GymSetsTable gymSets = $GymSetsTable(this);
|
late final $GymSetsTable gymSets = $GymSetsTable(this);
|
||||||
late final $PlansTable plans = $PlansTable(this);
|
|
||||||
@override
|
@override
|
||||||
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
Iterable<TableInfo> get allTables => allSchemaEntities.whereType<TableInfo>();
|
||||||
@override
|
@override
|
||||||
List<DatabaseSchemaEntity> get allSchemaEntities =>
|
List<DatabaseSchemaEntity> get allSchemaEntities => [settings, gymSets];
|
||||||
[settings, gymSets, plans];
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,113 +0,0 @@
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:flutter/material.dart' as material;
|
|
||||||
import 'package:fmassive/database.dart';
|
|
||||||
import 'package:fmassive/main.dart';
|
|
||||||
import 'package:moor_flutter/moor_flutter.dart';
|
|
||||||
|
|
||||||
class EditPlanPage extends StatefulWidget {
|
|
||||||
final PlansCompanion plan;
|
|
||||||
|
|
||||||
const EditPlanPage({required this.plan, super.key});
|
|
||||||
|
|
||||||
@override
|
|
||||||
createState() => _EditPlanPageState();
|
|
||||||
}
|
|
||||||
|
|
||||||
class _EditPlanPageState extends State<EditPlanPage> {
|
|
||||||
final TextEditingController _daysController = TextEditingController();
|
|
||||||
final TextEditingController _workoutsController = TextEditingController();
|
|
||||||
late PlansCompanion plan;
|
|
||||||
final daysNode = FocusNode();
|
|
||||||
final workoutsNode = FocusNode();
|
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
plan = widget.plan;
|
|
||||||
_daysController.text = plan.days.value;
|
|
||||||
_workoutsController.text = plan.workouts.value;
|
|
||||||
if (plan.id.present)
|
|
||||||
workoutsNode.requestFocus();
|
|
||||||
else
|
|
||||||
daysNode.requestFocus();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
dispose() {
|
|
||||||
daysNode.dispose();
|
|
||||||
workoutsNode.dispose();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
List<Widget> actions = [];
|
|
||||||
if (widget.plan.id.present)
|
|
||||||
actions.add(IconButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await db.plans.deleteOne(widget.plan);
|
|
||||||
if (!mounted) return;
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.delete)));
|
|
||||||
|
|
||||||
return SafeArea(
|
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(title: const Text('Edit Plan'), actions: actions),
|
|
||||||
body: Padding(
|
|
||||||
padding: const EdgeInsets.all(16.0),
|
|
||||||
child: material.Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
TextFormField(
|
|
||||||
controller: _daysController,
|
|
||||||
focusNode: daysNode,
|
|
||||||
decoration: const InputDecoration(labelText: 'Days'),
|
|
||||||
onTap: () {
|
|
||||||
_daysController.selection = TextSelection(
|
|
||||||
baseOffset: 0, extentOffset: _daysController.text.length);
|
|
||||||
},
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
plan = plan.copyWith(days: Value(value));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
TextFormField(
|
|
||||||
controller: _workoutsController,
|
|
||||||
focusNode: workoutsNode,
|
|
||||||
onTap: () {
|
|
||||||
_workoutsController.selection = TextSelection(
|
|
||||||
baseOffset: 0,
|
|
||||||
extentOffset: _workoutsController.text.length);
|
|
||||||
},
|
|
||||||
decoration: const InputDecoration(labelText: 'Workouts'),
|
|
||||||
onChanged: (value) {
|
|
||||||
setState(() {
|
|
||||||
plan = plan.copyWith(workouts: Value(value));
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () async {
|
|
||||||
if (_daysController.text.isEmpty) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Please enter days')));
|
|
||||||
daysNode.requestFocus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (plan.id.present)
|
|
||||||
await db.update(db.plans).write(plan);
|
|
||||||
else
|
|
||||||
await db.into(db.plans).insert(plan);
|
|
||||||
if (!mounted) return;
|
|
||||||
Navigator.pop(context);
|
|
||||||
},
|
|
||||||
child: const Icon(Icons.check),
|
|
||||||
),
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -54,8 +54,7 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
},
|
},
|
||||||
icon: const Icon(Icons.delete)));
|
icon: const Icon(Icons.delete)));
|
||||||
|
|
||||||
return SafeArea(
|
return Scaffold(
|
||||||
child: Scaffold(
|
|
||||||
appBar: AppBar(title: const Text('Edit Gym Set'), actions: actions),
|
appBar: AppBar(title: const Text('Edit Gym Set'), actions: actions),
|
||||||
body: Padding(
|
body: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
@ -112,12 +111,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () async {
|
onPressed: () async {
|
||||||
if (_nameController.text.isEmpty) {
|
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
|
||||||
const SnackBar(content: Text('Please enter a name')));
|
|
||||||
nameNode.requestFocus();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (gymSet.id.present)
|
if (gymSet.id.present)
|
||||||
await db.update(db.gymSets).write(gymSet);
|
await db.update(db.gymSets).write(gymSet);
|
||||||
else {
|
else {
|
||||||
|
@ -130,6 +123,6 @@ class _EditGymSetPageState extends State<EditGymSetPage> {
|
||||||
},
|
},
|
||||||
child: const Icon(Icons.check),
|
child: const Icon(Icons.check),
|
||||||
),
|
),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ class RootPage extends State<HomePage> {
|
||||||
case 'Best':
|
case 'Best':
|
||||||
return const BestPage();
|
return const BestPage();
|
||||||
case 'Plans':
|
case 'Plans':
|
||||||
return PlansPage(search: search);
|
return const PlansPage();
|
||||||
default:
|
default:
|
||||||
return _HomePageWidget(search: search);
|
return _HomePageWidget(search: search);
|
||||||
}
|
}
|
||||||
|
@ -59,8 +59,7 @@ class RootPage extends State<HomePage> {
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return SafeArea(
|
return Scaffold(
|
||||||
child: Scaffold(
|
|
||||||
drawer: Drawer(
|
drawer: Drawer(
|
||||||
child: ListView.builder(
|
child: ListView.builder(
|
||||||
itemCount: routes.length,
|
itemCount: routes.length,
|
||||||
|
@ -104,7 +103,7 @@ class RootPage extends State<HomePage> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: getBody(),
|
body: getBody(),
|
||||||
));
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
import 'package:moor/moor.dart';
|
|
||||||
|
|
||||||
class Plans extends Table {
|
|
||||||
IntColumn get id => integer().autoIncrement()();
|
|
||||||
TextColumn get days => text()();
|
|
||||||
TextColumn get workouts => text()();
|
|
||||||
}
|
|
|
@ -1,102 +1,163 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/material.dart' as material;
|
||||||
import 'package:fmassive/database.dart';
|
import 'package:fmassive/database.dart';
|
||||||
import 'package:fmassive/edit_plan.dart';
|
|
||||||
import 'package:fmassive/main.dart';
|
import 'package:fmassive/main.dart';
|
||||||
|
import 'package:fmassive/settings.dart';
|
||||||
import 'package:moor/moor.dart';
|
import 'package:moor/moor.dart';
|
||||||
|
|
||||||
class PlansPage extends StatelessWidget {
|
class PlansPage extends StatelessWidget {
|
||||||
const PlansPage({super.key, required this.search});
|
const PlansPage({super.key});
|
||||||
|
|
||||||
final String search;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return const Scaffold(
|
||||||
body: Center(
|
body: Center(
|
||||||
child: _PlansPage(search: search),
|
child: _PlansPage(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PlansPage extends StatefulWidget {
|
class _PlansPage extends StatefulWidget {
|
||||||
const _PlansPage({Key? key, required this.search}) : super(key: key);
|
const _PlansPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
final String search;
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
createState() => _PlansPageState();
|
createState() => _PlansPageState();
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PlansPageState extends State<_PlansPage> {
|
class _PlansPageState extends State<_PlansPage> {
|
||||||
bool showSearch = false;
|
late Stream<Setting> stream;
|
||||||
late Stream<List<Plan>> stream;
|
|
||||||
|
|
||||||
@override
|
final TextEditingController searchController = TextEditingController();
|
||||||
initState() {
|
|
||||||
super.initState();
|
|
||||||
setStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
void setStream() {
|
void reset() async {
|
||||||
stream = (db.select(db.plans)
|
var data = await db.select(db.settings).get();
|
||||||
..where((gymSet) => gymSet.days.contains(widget.search))
|
if (data.isEmpty) await db.into(db.settings).insert(defaultSettings);
|
||||||
..limit(10, offset: 0))
|
|
||||||
.watch();
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
didUpdateWidget(covariant _PlansPage oldWidget) {
|
|
||||||
super.didUpdateWidget(oldWidget);
|
|
||||||
setStream();
|
|
||||||
}
|
|
||||||
|
|
||||||
void toggleSearch() {
|
|
||||||
setState(() {
|
setState(() {
|
||||||
showSearch = !showSearch;
|
if (data.isEmpty) return;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
stream = db.select(db.settings).watchSingle();
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
body: StreamBuilder<List<Plan>>(
|
body: StreamBuilder<Setting>(
|
||||||
stream: stream,
|
stream: stream,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final plans = snapshot.data;
|
final settings = snapshot.data;
|
||||||
|
|
||||||
if (plans == null)
|
if (settings == null)
|
||||||
return const Center(child: CircularProgressIndicator());
|
return const Center(child: CircularProgressIndicator());
|
||||||
|
|
||||||
return ListView.builder(
|
return SingleChildScrollView(
|
||||||
itemCount: plans.length,
|
padding: const EdgeInsets.all(8.0),
|
||||||
itemBuilder: (context, index) {
|
child: material.Column(
|
||||||
return ListTile(
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
title: Text(plans[index].days),
|
children: [
|
||||||
subtitle: Text(plans[index].workouts),
|
SwitchListTile(
|
||||||
onTap: () async {
|
title: const Text('Alarm'),
|
||||||
await Navigator.push(
|
value: settings.alarm,
|
||||||
context,
|
onChanged: (value) {
|
||||||
MaterialPageRoute(
|
db
|
||||||
builder: (context) => EditPlanPage(
|
.update(db.settings)
|
||||||
plan: plans[index].toCompanion(false)),
|
.write(SettingsCompanion(alarm: Value(value)));
|
||||||
),
|
|
||||||
);
|
|
||||||
});
|
|
||||||
},
|
},
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Vibrate'),
|
||||||
|
value: settings.vibrate,
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(vibrate: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Notify'),
|
||||||
|
value: settings.notify,
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(notify: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Images'),
|
||||||
|
value: settings.images,
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(images: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Show Unit'),
|
||||||
|
value: settings.showUnit,
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(showUnit: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Steps'),
|
||||||
|
value: settings.steps,
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(steps: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Sound',
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(sound: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Light Color',
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(lightColor: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Dark Color',
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(darkColor: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
TextField(
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Date',
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
db
|
||||||
|
.update(db.settings)
|
||||||
|
.write(SettingsCompanion(date: Value(value)));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}),
|
}),
|
||||||
floatingActionButton: FloatingActionButton(
|
|
||||||
onPressed: () async {
|
|
||||||
await Navigator.push(
|
|
||||||
context,
|
|
||||||
MaterialPageRoute(
|
|
||||||
builder: (context) => const EditPlanPage(
|
|
||||||
plan:
|
|
||||||
PlansCompanion(days: Value(''), workouts: Value(''))),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
|
||||||
child: const Icon(Icons.add)));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user