reworked api handling, portrait behavior
This commit is contained in:
parent
3f112a857b
commit
8cad1e26df
266
lib/NewShareLinkPage.dart
Normal file
266
lib/NewShareLinkPage.dart
Normal file
|
@ -0,0 +1,266 @@
|
||||||
|
import 'dart:convert';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:http/http.dart' as http;
|
||||||
|
import 'package:intl/intl.dart';
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
class NewShareLinkPage extends StatefulWidget {
|
||||||
|
const NewShareLinkPage({Key? key}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
_NewShareLinkPageState createState() => _NewShareLinkPageState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _NewShareLinkPageState extends State<NewShareLinkPage> {
|
||||||
|
late TextEditingController linkNameController;
|
||||||
|
DateTime? selectedDateTime;
|
||||||
|
bool neverExpire = false;
|
||||||
|
double durationValue = 0;
|
||||||
|
double intensityValue = 0;
|
||||||
|
String? shareLink;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
linkNameController = TextEditingController();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> _getApiKey() async {
|
||||||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getString('apiKey');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<String?> _getShockerId() async {
|
||||||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
return prefs.getString('shockerId');
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> saveSettings() async {
|
||||||
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
final String? apiKey = prefs.getString('apiKey');
|
||||||
|
final String? shockerId = prefs.getString('shockerId');
|
||||||
|
|
||||||
|
if (apiKey != null && shockerId != null) {
|
||||||
|
final String linkName = linkNameController.text;
|
||||||
|
final int durationInMilliseconds = (durationValue * 1000).toInt();
|
||||||
|
|
||||||
|
final createLinkResponse = await http.post(
|
||||||
|
Uri.parse('https://api.shocklink.net/1/shares/links'),
|
||||||
|
headers: {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'OpenShockToken': apiKey,
|
||||||
|
},
|
||||||
|
body: jsonEncode({
|
||||||
|
'name': linkName,
|
||||||
|
'expiresOn': selectedDateTime?.toIso8601String(),
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (createLinkResponse.statusCode == 200) {
|
||||||
|
final responseData = jsonDecode(createLinkResponse.body);
|
||||||
|
final String linkId = responseData['data'];
|
||||||
|
|
||||||
|
final addShockerResponse = await http.put(
|
||||||
|
Uri.parse('https://api.shocklink.net/1/shares/links/$linkId/$shockerId'),
|
||||||
|
headers: {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'OpenShockToken': apiKey,
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (addShockerResponse.statusCode == 200) {
|
||||||
|
final setPermissionsResponse = await http.patch(
|
||||||
|
Uri.parse('https://api.shocklink.net/1/shares/links/$linkId/$shockerId'),
|
||||||
|
headers: {
|
||||||
|
'accept': 'application/json',
|
||||||
|
'OpenShockToken': apiKey,
|
||||||
|
},
|
||||||
|
body: jsonEncode({
|
||||||
|
'permissions': {
|
||||||
|
'vibrate': true,
|
||||||
|
'sound': false,
|
||||||
|
'shock': true,
|
||||||
|
},
|
||||||
|
'limits': {
|
||||||
|
'intensity': intensityValue,
|
||||||
|
'duration': durationInMilliseconds,
|
||||||
|
},
|
||||||
|
'cooldown': 30000,
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (setPermissionsResponse.statusCode == 200) {
|
||||||
|
setState(() {
|
||||||
|
shareLink = 'https://shockl.ink/s/$linkId';
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
// Handle failure in setting permissions
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle failure in adding shocker to the link
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle failure in creating the share link
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Handle missing apiKey or shockerId
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _selectDate(BuildContext context) async {
|
||||||
|
final DateTime? picked = await showDatePicker(
|
||||||
|
context: context,
|
||||||
|
initialDate: selectedDateTime ?? DateTime.now(),
|
||||||
|
firstDate: DateTime.now(),
|
||||||
|
lastDate: DateTime(DateTime.now().year + 1),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedDateTime = DateTime(picked.year, picked.month, picked.day,
|
||||||
|
selectedDateTime?.hour ?? 0, selectedDateTime?.minute ?? 0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _selectTime(BuildContext context) async {
|
||||||
|
final TimeOfDay? picked = await showTimePicker(
|
||||||
|
context: context,
|
||||||
|
initialTime: TimeOfDay.fromDateTime(selectedDateTime ?? DateTime.now()),
|
||||||
|
);
|
||||||
|
if (picked != null) {
|
||||||
|
setState(() {
|
||||||
|
selectedDateTime = DateTime(
|
||||||
|
selectedDateTime?.year ?? DateTime.now().year,
|
||||||
|
selectedDateTime?.month ?? DateTime.now().month,
|
||||||
|
selectedDateTime?.day ?? DateTime.now().day,
|
||||||
|
picked.hour,
|
||||||
|
picked.minute,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
title: const Text('New Share Link'),
|
||||||
|
),
|
||||||
|
body: Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Link Name'),
|
||||||
|
TextFormField(
|
||||||
|
controller: linkNameController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Enter link name',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: neverExpire,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
neverExpire = value!;
|
||||||
|
if (neverExpire) {
|
||||||
|
selectedDateTime = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Text('Never Expire'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (!neverExpire)
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text('Select Date and Time'),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => _selectDate(context),
|
||||||
|
child: const Text('Select Date'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => _selectTime(context),
|
||||||
|
child: const Text('Select Time'),
|
||||||
|
),
|
||||||
|
if (selectedDateTime != null)
|
||||||
|
Text(
|
||||||
|
'Selected: ${DateFormat.yMd().add_jm().format(selectedDateTime!)}',
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const Text('Duration'),
|
||||||
|
Slider(
|
||||||
|
value: durationValue,
|
||||||
|
min: 0,
|
||||||
|
max: 30,
|
||||||
|
divisions: 30,
|
||||||
|
label: durationValue.round().toString(),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
durationValue = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text('Selected Duration: ${durationValue.round()}'),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
const Text('Intensity'),
|
||||||
|
Slider(
|
||||||
|
value: intensityValue,
|
||||||
|
min: 0,
|
||||||
|
max: 100,
|
||||||
|
divisions: 100,
|
||||||
|
label: intensityValue.round().toString(),
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
intensityValue = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text('Selected Intensity: ${intensityValue.round()}'),
|
||||||
|
const SizedBox(height: 20),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
saveSettings();
|
||||||
|
},
|
||||||
|
child: const Text('Create Share Link'),
|
||||||
|
),
|
||||||
|
if (shareLink != null)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 20),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
const Text(
|
||||||
|
'Generated Share Link:',
|
||||||
|
style: TextStyle(fontWeight: FontWeight.bold),
|
||||||
|
),
|
||||||
|
const SizedBox(height: 8),
|
||||||
|
TextFormField(
|
||||||
|
initialValue: shareLink,
|
||||||
|
readOnly: true,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'Generated Share Link',
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -49,7 +49,7 @@ Future<void> saveSettings(String apiKey, String shockerId) async {
|
||||||
await prefs.setString('shockerId', shockerId);
|
await prefs.setString('shockerId', shockerId);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> sendApiRequest(int intensity, int time, int type) async {
|
Future<bool> sendApiRequest(int intensity, int time, int type) async {
|
||||||
// Fetch saved information from SharedPreferences
|
// Fetch saved information from SharedPreferences
|
||||||
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
final SharedPreferences prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
|
@ -82,13 +82,8 @@ Future<void> sendApiRequest(int intensity, int time, int type) async {
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
if (response.statusCode == 200) {
|
||||||
// Request successful, handle the response if needed
|
return true;
|
||||||
print('API request successful');
|
|
||||||
print(response.body);
|
|
||||||
} else {
|
} else {
|
||||||
// Request failed, handle the error
|
return false;
|
||||||
print('API request failed');
|
|
||||||
print('Status code: ${response.statusCode}');
|
|
||||||
print('Response body: ${response.body}');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -60,7 +60,6 @@ class _LogsPageState extends State<logs_page> {
|
||||||
}
|
}
|
||||||
|
|
||||||
Icon getIconForType(String type) {
|
Icon getIconForType(String type) {
|
||||||
print('Type: $type');
|
|
||||||
switch (type.toLowerCase()) {
|
switch (type.toLowerCase()) {
|
||||||
case 'vibrate':
|
case 'vibrate':
|
||||||
return const Icon(Icons.vibration);
|
return const Icon(Icons.vibration);
|
||||||
|
@ -82,62 +81,85 @@ class _LogsPageState extends State<logs_page> {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final appState = Provider.of<AppState>(context, listen: false);
|
final appState = Provider.of<AppState>(context, listen: false);
|
||||||
appState.currentIndex = 2;
|
appState.currentIndex = 2;
|
||||||
|
|
||||||
return Scaffold(
|
return Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Logs'),
|
title: const Text('Logs'),
|
||||||
),
|
),
|
||||||
body: RefreshIndicator(
|
body: LayoutBuilder(
|
||||||
onRefresh: _handleRefresh,
|
builder: (context, constraints) {
|
||||||
child: SingleChildScrollView(
|
final isLandscape =
|
||||||
scrollDirection: Axis.horizontal,
|
MediaQuery.of(context).orientation == Orientation.landscape;
|
||||||
child: SingleChildScrollView(
|
|
||||||
child: DataTable(
|
return RefreshIndicator(
|
||||||
columnSpacing: 10,
|
onRefresh: _handleRefresh,
|
||||||
dataRowMaxHeight: 50,
|
child: SingleChildScrollView(
|
||||||
columns: const [
|
scrollDirection: Axis.horizontal,
|
||||||
DataColumn(label: Text('Name')),
|
child: SingleChildScrollView(
|
||||||
DataColumn(label: Text('Intensity')),
|
child: DataTable(
|
||||||
DataColumn(label: Text('Duration')),
|
columnSpacing: 10,
|
||||||
DataColumn(label: Text('Type')),
|
columns: [
|
||||||
DataColumn(label: Text('Time')),
|
DataColumn(label: SizedBox(
|
||||||
],
|
width: isLandscape ? constraints.maxWidth * 0.25 : null,
|
||||||
rows: logs.map((log) {
|
child: Text('Name'),
|
||||||
final controlledBy =
|
)),
|
||||||
|
DataColumn(label: SizedBox(
|
||||||
|
width: isLandscape ? constraints.maxWidth * 0.15 : null,
|
||||||
|
child: Text('Intensity'),
|
||||||
|
)),
|
||||||
|
DataColumn(label: SizedBox(
|
||||||
|
width: isLandscape ? constraints.maxWidth * 0.15
|
||||||
|
: null,
|
||||||
|
child: Text('Duration'),
|
||||||
|
)),
|
||||||
|
DataColumn(label: SizedBox(
|
||||||
|
width: isLandscape ? constraints.maxWidth * 0.15 : null,
|
||||||
|
child: Text('Type'),
|
||||||
|
)),
|
||||||
|
DataColumn(label: SizedBox(
|
||||||
|
width: isLandscape ? constraints.maxWidth * 0.2 : null,
|
||||||
|
child: Text('Time'),
|
||||||
|
)),
|
||||||
|
],
|
||||||
|
rows: logs.map<DataRow>((log) {
|
||||||
|
final controlledBy =
|
||||||
log['controlledBy'] as Map<String, dynamic>?;
|
log['controlledBy'] as Map<String, dynamic>?;
|
||||||
if (controlledBy != null) {
|
if (controlledBy != null) {
|
||||||
final name = getDisplayName(controlledBy);
|
final name = getDisplayName(controlledBy);
|
||||||
final intensity = log['intensity'] as int?;
|
final intensity = log['intensity'] as int?;
|
||||||
final duration = (log['duration'] as int?)! / 1000;
|
final duration = (log['duration'] as int?)! / 1000;
|
||||||
final type = log['type'] as String?;
|
final type = log['type'] as String?;
|
||||||
final createdAt = log['createdOn'] as String?;
|
final createdAt = log['createdOn'] as String?;
|
||||||
|
|
||||||
if (intensity != null && type != null && createdAt != null) {
|
if (intensity != null &&
|
||||||
final userTimezone =
|
type != null &&
|
||||||
DateTime.now().timeZoneOffset; // Get user's timezone
|
createdAt != null) {
|
||||||
|
final userTimezone = DateTime.now().timeZoneOffset;
|
||||||
|
final utcDateTime = DateTime.parse(createdAt);
|
||||||
|
final localDateTime =
|
||||||
|
utcDateTime.add(userTimezone);
|
||||||
|
|
||||||
final utcDateTime = DateTime.parse(createdAt);
|
final formattedCreatedAt = DateFormat('dd/MM/yy - HH:mm')
|
||||||
final localDateTime = utcDateTime
|
.format(localDateTime);
|
||||||
.add(userTimezone); // Convert to local timezone
|
|
||||||
|
|
||||||
final formattedCreatedAt =
|
return DataRow(
|
||||||
DateFormat('dd/MM/yy - HH:mm').format(localDateTime);
|
cells: [
|
||||||
|
DataCell(Text(name)),
|
||||||
return DataRow(
|
DataCell(Text(intensity.toString())),
|
||||||
cells: [
|
DataCell(Text(duration.toString())),
|
||||||
DataCell(Text(name)),
|
DataCell(getIconForType(type)),
|
||||||
DataCell(Text(intensity.toString())),
|
DataCell(Text(formattedCreatedAt)),
|
||||||
DataCell(Text(duration.toString())),
|
],
|
||||||
DataCell(getIconForType(type)),
|
);
|
||||||
DataCell(Text(formattedCreatedAt)),
|
}
|
||||||
],
|
}
|
||||||
);
|
return DataRow(cells: []);
|
||||||
}
|
}).toList(),
|
||||||
}
|
),
|
||||||
return const DataRow(cells: []);
|
),
|
||||||
}).toList(),
|
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
},
|
||||||
),
|
),
|
||||||
bottomNavigationBar: BottomBar(
|
bottomNavigationBar: BottomBar(
|
||||||
currentIndex: appState.currentIndex,
|
currentIndex: appState.currentIndex,
|
||||||
|
|
|
@ -111,26 +111,35 @@ class _SliderPageState extends State<SliderPage> {
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.flash_on),
|
icon: const Icon(Icons.flash_on),
|
||||||
label: const Text('Shock'),
|
label: const Text('Shock'),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
if (intensityValue < 1 || timeValue < 1) {
|
if (intensityValue < 1 || timeValue < 1) {
|
||||||
// this whole thing was written by a silly little cat :3
|
// this whole thing was written by a silly little cat :3
|
||||||
} else {
|
} else {
|
||||||
HapticFeedback.vibrate();
|
HapticFeedback.vibrate();
|
||||||
sendApiRequest(intensityValue, timeValue, 1);
|
bool success = await sendApiRequest(
|
||||||
showToast('API request sent');
|
intensityValue, timeValue, 1);
|
||||||
|
if (success) {
|
||||||
|
showToast('Shock API request successful');
|
||||||
|
} else {
|
||||||
|
showToast('Failed to send Shock API request');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
),
|
),
|
||||||
const SizedBox(width: 8.0),
|
const SizedBox(width: 8.0),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.vibration),
|
icon: const Icon(Icons.vibration),
|
||||||
label: const Text('Vibrate'),
|
label: const Text('Vibrate'),
|
||||||
onPressed: () {
|
onPressed: () async {
|
||||||
if (intensityValue < 1 || timeValue < 1) {
|
if (intensityValue < 1 || timeValue < 1) {
|
||||||
} else {
|
} else {
|
||||||
HapticFeedback.vibrate();
|
HapticFeedback.vibrate();
|
||||||
sendApiRequest(intensityValue, timeValue, 2);
|
bool success = await sendApiRequest(intensityValue, timeValue, 2);
|
||||||
showToast('API request sent');
|
if (success) {
|
||||||
|
showToast('Vibrate API request successful');
|
||||||
|
} else {
|
||||||
|
showToast('Failed to send Vibrate API request');
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|
|
@ -7,6 +7,7 @@ import 'logs_page.dart';
|
||||||
import 'package:provider/provider.dart';
|
import 'package:provider/provider.dart';
|
||||||
import 'package:http/http.dart' as http;
|
import 'package:http/http.dart' as http;
|
||||||
import 'package:fluttertoast/fluttertoast.dart';
|
import 'package:fluttertoast/fluttertoast.dart';
|
||||||
|
import 'NewShareLinkPage.dart';
|
||||||
|
|
||||||
class settings_page extends StatefulWidget {
|
class settings_page extends StatefulWidget {
|
||||||
const settings_page({Key? key});
|
const settings_page({Key? key});
|
||||||
|
@ -39,8 +40,6 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
setState(() {
|
setState(() {
|
||||||
apiKeyController.text = prefs.getString('apiKey') ?? '';
|
apiKeyController.text = prefs.getString('apiKey') ?? '';
|
||||||
shockerIdController.text = prefs.getString('shockerId') ?? '';
|
shockerIdController.text = prefs.getString('shockerId') ?? '';
|
||||||
intensityLimitController.text = prefs.getString('intensityLimit') ?? '';
|
|
||||||
durationLimitController.text = prefs.getString('durationLimit') ?? '';
|
|
||||||
numberOfLogs = prefs.getDouble(logsSharedPreferenceKey) ?? 30;
|
numberOfLogs = prefs.getDouble(logsSharedPreferenceKey) ?? 30;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -50,8 +49,6 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
prefs.setString('apiKey', apiKeyController.text);
|
prefs.setString('apiKey', apiKeyController.text);
|
||||||
prefs.setString('shockerId', shockerIdController.text);
|
prefs.setString('shockerId', shockerIdController.text);
|
||||||
await runChecks();
|
await runChecks();
|
||||||
|
|
||||||
// Save the selected number of logs to shared preferences
|
|
||||||
prefs.setDouble(logsSharedPreferenceKey, numberOfLogs);
|
prefs.setDouble(logsSharedPreferenceKey, numberOfLogs);
|
||||||
|
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
|
@ -135,7 +132,8 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('Settings'),
|
title: const Text('Settings'),
|
||||||
),
|
),
|
||||||
body: Padding(
|
body: SingleChildScrollView(
|
||||||
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
@ -199,6 +197,26 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
child: const Text('Save'),
|
child: const Text('Save'),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 15),
|
const SizedBox(height: 15),
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(builder: (context) => const NewShareLinkPage()),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: const Text('New Share Link'),
|
||||||
|
),
|
||||||
|
ElevatedButton(
|
||||||
|
onPressed: () {
|
||||||
|
|
||||||
|
},
|
||||||
|
child: const Text('My Share Links'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
FutureBuilder<String>(
|
FutureBuilder<String>(
|
||||||
future: fetchCommitData(),
|
future: fetchCommitData(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
@ -208,7 +226,7 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
return Text('Error: ${snapshot.error}');
|
return Text('Error: ${snapshot.error}');
|
||||||
} else {
|
} else {
|
||||||
return Text(
|
return Text(
|
||||||
'App Version: 0.3-rc0[hf] - Build Date: Dec. 11, 2023\n'
|
'App Version: 0.3-rc3 - Build Date: Dec. 11, 2023\n'
|
||||||
'(C) Mercury, 2023\n'
|
'(C) Mercury, 2023\n'
|
||||||
'Connected to api.shocklink.org, version ${snapshot.data}',
|
'Connected to api.shocklink.org, version ${snapshot.data}',
|
||||||
textAlign: TextAlign.left,
|
textAlign: TextAlign.left,
|
||||||
|
@ -220,6 +238,7 @@ class _SettingsPageState extends State<settings_page> {
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
bottomNavigationBar: BottomBar(
|
bottomNavigationBar: BottomBar(
|
||||||
currentIndex: appState.currentIndex,
|
currentIndex: appState.currentIndex,
|
||||||
onTap: (index) {
|
onTap: (index) {
|
||||||
|
|
Loading…
Reference in a new issue