UI changes, Logs viewer
version bumped to 0.2.0
This commit is contained in:
parent
c0a8012357
commit
9e1e60492e
147
lib/LogsPage.dart
Normal file
147
lib/LogsPage.dart
Normal file
|
@ -0,0 +1,147 @@
|
|||
import 'dart:convert';
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:http/http.dart' as http;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:OpenshockCompanion/settings_page.dart' show SettingsPage;
|
||||
class LogsPage extends StatefulWidget {
|
||||
const LogsPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_LogsPageState createState() => _LogsPageState();
|
||||
}
|
||||
|
||||
class _LogsPageState extends State<LogsPage> {
|
||||
List<Map<String, dynamic>> logs = [];
|
||||
|
||||
@override
|
||||
void initState() {
|
||||
super.initState();
|
||||
fetchLogs();
|
||||
}
|
||||
|
||||
Future<void> fetchLogs() async {
|
||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||
final apiKey = prefs.getString('apiKey');
|
||||
final shockerId = prefs.getString('shockerId');
|
||||
|
||||
if (apiKey == null || shockerId == null) {
|
||||
// Handle missing API key or shockerId
|
||||
return;
|
||||
}
|
||||
|
||||
final url = 'https://api.shocklink.net/1/shockers/$shockerId/logs?offset=0&limit=30';
|
||||
|
||||
final response = await http.get(Uri.parse(url), headers: {
|
||||
'accept': 'application/json',
|
||||
'OpenShockToken': apiKey,
|
||||
});
|
||||
|
||||
if (response.statusCode == 200) {
|
||||
final jsonData = json.decode(response.body);
|
||||
|
||||
if (jsonData['data'] != null) {
|
||||
setState(() {
|
||||
logs = List<Map<String, dynamic>>.from(jsonData['data']);
|
||||
});
|
||||
}
|
||||
} else {
|
||||
// Handle API request error
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> _handleRefresh() async {
|
||||
await fetchLogs();
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return Scaffold(
|
||||
appBar: AppBar(
|
||||
title: const Text('Logs'),
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
onRefresh: _handleRefresh,
|
||||
child: Scrollbar(
|
||||
thumbVisibility: true,
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
const Text('Logs'),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: DataTable(
|
||||
columns: const [
|
||||
DataColumn(label: Text('Name')),
|
||||
DataColumn(label: Text('Intensity')),
|
||||
DataColumn(label: Text('Duration (s)')),
|
||||
],
|
||||
rows: logs.map((log) {
|
||||
final controlledBy = log['controlledBy'] as Map<String, dynamic>?;
|
||||
|
||||
// Add null check for controlledBy
|
||||
if (controlledBy != null) {
|
||||
final name = controlledBy['name'] as String?;
|
||||
final intensity = log['intensity'] as int?;
|
||||
final duration = (log['duration'] as int?)! / 1000; // Convert to seconds
|
||||
|
||||
// Add null checks for name and intensity
|
||||
if (name != null && intensity != null) {
|
||||
return DataRow(
|
||||
cells: [
|
||||
DataCell(Text(name)),
|
||||
DataCell(Text(intensity.toString())),
|
||||
DataCell(Text(duration.toString())),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return const DataRow(cells: []);
|
||||
}).toList(),
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.home),
|
||||
label: 'Home',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'Settings',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.list),
|
||||
label: 'Logs',
|
||||
),
|
||||
],
|
||||
currentIndex: 2, // Set the current index to 2 for the Logs page
|
||||
onTap: (index) {
|
||||
if (index == 0) {
|
||||
// Navigate back to the main page
|
||||
Navigator.popUntil(context, (route) => route.isFirst);
|
||||
} else if (index == 1) {
|
||||
// Navigate to the Settings page
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const SettingsPage()),
|
||||
);
|
||||
}
|
||||
},
|
||||
selectedItemColor: const Color.fromARGB(255, 211, 187, 255), // or any color you prefer
|
||||
unselectedItemColor: Theme.of(context).textTheme.bodySmall?.color,
|
||||
showUnselectedLabels: true,
|
||||
selectedLabelStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
|
|||
import 'package:flutter/services.dart';
|
||||
import 'package:fluttertoast/fluttertoast.dart';
|
||||
import 'package:OpenshockCompanion/settings_page.dart' show SettingsPage;
|
||||
import 'package:OpenshockCompanion/LogsPage.dart' show LogsPage;
|
||||
import 'package:OpenshockCompanion/api_handler.dart' show sendApiRequest;
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
|
@ -10,7 +11,7 @@ void main() {
|
|||
}
|
||||
|
||||
class MyApp extends StatelessWidget {
|
||||
const MyApp({super.key});
|
||||
const MyApp({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -36,7 +37,7 @@ class MyApp extends StatelessWidget {
|
|||
}
|
||||
|
||||
class SliderPage extends StatefulWidget {
|
||||
const SliderPage({super.key});
|
||||
const SliderPage({Key? key}) : super(key: key);
|
||||
|
||||
@override
|
||||
_SliderPageState createState() => _SliderPageState();
|
||||
|
@ -45,6 +46,7 @@ class SliderPage extends StatefulWidget {
|
|||
class _SliderPageState extends State<SliderPage> {
|
||||
int intensityValue = 0;
|
||||
int timeValue = 0;
|
||||
int currentIndex = 0;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
@ -124,18 +126,49 @@ class _SliderPageState extends State<SliderPage> {
|
|||
),
|
||||
],
|
||||
),
|
||||
ElevatedButton(
|
||||
child: const Text('Settings'),
|
||||
onPressed: () {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const SettingsPage()),
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
currentIndex: currentIndex,
|
||||
onTap: (index) {
|
||||
setState(() {
|
||||
currentIndex = index;
|
||||
if (index == 0) {
|
||||
// Home tab
|
||||
} else if (index == 1) {
|
||||
// Settings tab
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const SettingsPage()),
|
||||
);
|
||||
} else if (index == 2) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const LogsPage()),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.home),
|
||||
label: 'Home',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'Settings',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.list),
|
||||
label: 'Logs',
|
||||
),
|
||||
],
|
||||
selectedItemColor: const Color.fromARGB(255, 211, 187, 255), // or any color you prefer
|
||||
unselectedItemColor: Theme.of(context).textTheme.bodySmall?.color,
|
||||
showUnselectedLabels: true,
|
||||
selectedLabelStyle: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -180,4 +213,4 @@ final ThemeData darkTheme = ThemeData(
|
|||
seedColor: Colors.deepPurple,
|
||||
brightness: Brightness.dark,
|
||||
),
|
||||
);
|
||||
);
|
|
@ -1,9 +1,9 @@
|
|||
// settings_page.dart
|
||||
import 'package:OpenshockCompanion/LogsPage.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:shared_preferences/shared_preferences.dart';
|
||||
|
||||
class SettingsPage extends StatefulWidget {
|
||||
const SettingsPage({super.key});
|
||||
const SettingsPage({Key? key});
|
||||
|
||||
@override
|
||||
_SettingsPageState createState() => _SettingsPageState();
|
||||
|
@ -106,6 +106,38 @@ class _SettingsPageState extends State<SettingsPage> {
|
|||
],
|
||||
),
|
||||
),
|
||||
bottomNavigationBar: BottomNavigationBar(
|
||||
items: const [
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.home),
|
||||
label: 'Home',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.settings),
|
||||
label: 'Settings',
|
||||
),
|
||||
BottomNavigationBarItem(
|
||||
icon: Icon(Icons.list),
|
||||
label: 'Logs',
|
||||
),
|
||||
],
|
||||
currentIndex: 1, // Set the current index to 1 for the Settings page
|
||||
onTap: (index) {
|
||||
if (index == 0) {
|
||||
// Navigate back to the main page
|
||||
Navigator.popUntil(context, (route) => route.isFirst);
|
||||
} else if (index == 2) {
|
||||
Navigator.push(
|
||||
context,
|
||||
MaterialPageRoute(builder: (context) => const LogsPage()),
|
||||
);
|
||||
}
|
||||
},
|
||||
selectedItemColor: const Color.fromARGB(255, 211, 187, 255), // or any color you prefer
|
||||
unselectedItemColor: Theme.of(context).textTheme.caption?.color,
|
||||
showUnselectedLabels: true,
|
||||
selectedLabelStyle: TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@ description: Companion app for managing openshock-compatible devices
|
|||
# pub.dev using `flutter pub publish`. This is preferred for private packages.
|
||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||
|
||||
version: 0.1.4
|
||||
version: 0.2.0
|
||||
|
||||
environment:
|
||||
sdk: '>=3.1.2 <4.0.0'
|
||||
|
|
Loading…
Reference in a new issue