initial commit
Some checks failed
xiao_pet_tracker / semantic-pull-request (push) Has been cancelled
xiao_pet_tracker / build (push) Has been cancelled
xiao_pet_tracker / spell-check (push) Has been cancelled

This commit is contained in:
2025-02-23 20:50:34 +01:00
commit 2fe59fee0d
360 changed files with 14384 additions and 0 deletions

View File

@@ -0,0 +1,193 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart';
class CaptureView extends StatefulWidget {
const CaptureView({super.key});
@override
State<CaptureView> createState() => _CaptureViewState();
}
class _CaptureViewState extends State<CaptureView> {
late TextEditingController _controller;
bool _isTextFieldFocused = false;
@override
void initState() {
super.initState();
_controller = TextEditingController();
}
@override
void dispose() {
_controller.dispose();
super.dispose();
}
@override
Widget build(BuildContext context) {
// final count = context.select((XiaoConnectorCubit cubit) => cubit.state);
final lastCapturePoint = context
.select((XiaoConnectorCubit cubit) => cubit.state.lastCapturedPoint);
return Scaffold(
appBar: AppBar(
title: const Text('Live Feed'),
),
body: SingleChildScrollView(
child: Center(
child: Column(
children: [
const SizedBox(
height: 8,
),
ElevatedButton(
onPressed: () {
context.read<XiaoConnectorCubit>().stopCapturing();
},
child: const Text('Close Live Feed'),
),
const SizedBox(
height: 12,
),
const Text(
'Last Captured Point',
style: TextStyle(fontWeight: FontWeight.bold),
),
const Divider(
indent: 80,
endIndent: 80,
),
const Text(
'Received Time',
style: TextStyle(fontWeight: FontWeight.bold),
),
Text(
'${DateTime.fromMillisecondsSinceEpoch(
lastCapturePoint?.millisecondsSinceEpochReceived ?? 0,
)}',
),
const Text(
'Send Time',
style: TextStyle(fontWeight: FontWeight.bold),
),
const Text('(time the controller send the data)'),
Text(
'${DateTime.fromMillisecondsSinceEpoch(
lastCapturePoint?.millisecondsSinceEpochSend ?? 0,
)}',
),
const SizedBox(
height: 12,
),
ElevatedButton.icon(
onPressed: () {
// context.read<XiaoConnectorCubit>().startCapturing(
// captureType: 'test',
// );
final timeToSend = DateTime.now().millisecondsSinceEpoch;
context.read<XiaoConnectorCubit>().setTime(timeToSend);
},
icon: const Icon(Icons.watch_later_outlined),
label: const Text('Sync Clocks'),
),
const SizedBox(
height: 12,
),
const Divider(
indent: 80,
endIndent: 80,
),
Text('Acceleration X: ${lastCapturePoint?.accelerationX}'),
Text('Acceleration Y: ${lastCapturePoint?.accelerationY}'),
Text('Acceleration Z: ${lastCapturePoint?.accelerationZ}'),
const Divider(
indent: 80,
endIndent: 80,
),
Text('Rotation X: ${lastCapturePoint?.rotationX}'),
Text('Rotation Y: ${lastCapturePoint?.rotationY}'),
Text('Rotation Z: ${lastCapturePoint?.rotationZ}'),
const SizedBox(
height: 16,
),
Padding(
padding: const EdgeInsets.only(left: 32, right: 32, top: 16),
child: FocusScope(
child: Focus(
onFocusChange: (focus) {
_isTextFieldFocused = focus;
setState(() {});
},
child: TextField(
controller: _controller,
decoration: const InputDecoration(
label: Text('Capture Name'),
),
),
),
),
),
const SizedBox(
height: 16,
)
],
),
),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: _isTextFieldFocused
? null
: FloatingActionButton.large(
child: context.read<XiaoConnectorCubit>().isRecording
? const Stack(
children: [
Align(
child: Icon(Icons.pause),
),
Align(
child: SizedBox.expand(
child: Padding(
padding: EdgeInsets.all(12),
child: CircularProgressIndicator(),
),
),
),
],
)
: const Icon(Icons.play_arrow),
onPressed: () {
if (_controller.value.text == '') {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text(
'Please enter Capture Name',
),
content: const Text(
'You need to enter a capture name before you can start capturing data.',
),
actions: <Widget>[
TextButton(
onPressed: () {
Navigator.of(context).pop();
},
child: const Text(
'Ok',
),
),
],
);
},
);
} else {
context.read<XiaoConnectorCubit>().toggleRecording(
captureType: _controller.value.text,
);
}
},
),
);
}
}

View File

@@ -0,0 +1,51 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart';
class ConnectedView extends StatelessWidget {
const ConnectedView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Xiao Connector'),
),
body: Center(
child: SingleChildScrollView(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'''
You are connected to the Xiao Sense.
Now you can open the live feed.''',
textAlign: TextAlign.center,
),
const SizedBox(
height: 48,
),
ElevatedButton(
onPressed: () {
context.read<XiaoConnectorCubit>().startCapturing();
},
child: const Text('Open Live Feed'),
),
const SizedBox(
height: 48,
),
ElevatedButton(
onPressed: () {
context.read<XiaoConnectorCubit>().disconnectDevice();
},
child: const Text('Disconnect'),
),
],
),
),
),
);
}
}

View File

@@ -0,0 +1,10 @@
import 'package:flutter/material.dart';
class FailureView extends StatelessWidget {
const FailureView({super.key});
@override
Widget build(BuildContext context) {
return const Text('Oops. Something bad happened! :(');
}
}

View File

@@ -0,0 +1,38 @@
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart';
class InitialView extends StatelessWidget {
const InitialView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('Xiao Connector'),
),
body: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
const Text(
'''
You are currently not connected to the Xiao Sense.
Click on `Connect` to try to connect to the device.''',
textAlign: TextAlign.center,
),
const SizedBox(
height: 8,
),
ElevatedButton(
onPressed: () {
context.read<XiaoConnectorCubit>().connect();
},
child: const Text('Connect'),
),
],
),
),
);
}
}

View File

@@ -0,0 +1,12 @@
import 'package:flutter/material.dart';
class LoadingView extends StatelessWidget {
const LoadingView({super.key});
@override
Widget build(BuildContext context) {
return const Center(
child: CircularProgressIndicator(),
);
}
}

View File

@@ -0,0 +1 @@
export 'xiao_connector_page.dart';

View File

@@ -0,0 +1,40 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:xiao_pet_tracker/xiao_connector/cubit/xiao_connector_cubit.dart';
import 'package:xiao_pet_tracker/xiao_connector/view/capture_view.dart';
import 'package:xiao_pet_tracker/xiao_connector/view/connected_view.dart';
import 'package:xiao_pet_tracker/xiao_connector/view/failure_view.dart';
import 'package:xiao_pet_tracker/xiao_connector/view/initial_view.dart';
import 'package:xiao_pet_tracker/xiao_connector/view/loading_view.dart';
@RoutePage()
class XiaoConnectorPage extends StatelessWidget {
const XiaoConnectorPage({super.key});
@override
Widget build(BuildContext context) {
return const XiaoConnectorView();
}
}
class XiaoConnectorView extends StatelessWidget {
const XiaoConnectorView({super.key});
@override
Widget build(BuildContext context) {
return Scaffold(
body: BlocBuilder<XiaoConnectorCubit, XiaoConnectorState>(
builder: (context, state) {
return switch (state.status) {
XiaoConnectorStatus.initial => const InitialView(),
XiaoConnectorStatus.loading => const LoadingView(),
XiaoConnectorStatus.connected => const ConnectedView(),
XiaoConnectorStatus.capturing => const CaptureView(),
XiaoConnectorStatus.failure => const FailureView(),
};
},
),
);
}
}

View File

@@ -0,0 +1,22 @@
import 'package:auto_route/auto_route.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
@RoutePage()
class XiaoDataPage extends StatelessWidget {
const XiaoDataPage({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}
class XiaoDataView extends StatelessWidget {
const XiaoDataView({super.key});
@override
Widget build(BuildContext context) {
return const Placeholder();
}
}