nice
This commit is contained in:
@@ -1,8 +1,12 @@
|
||||
|
||||
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:bus_infotainment/audio_cache.dart';
|
||||
import 'package:bus_infotainment/backend/live_information.dart';
|
||||
import 'package:bus_infotainment/backend/modules/commands.dart';
|
||||
import 'package:bus_infotainment/utils/delegates.dart';
|
||||
import 'package:file_picker/file_picker.dart';
|
||||
import 'package:flutter/gestures.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
@@ -71,20 +75,75 @@ class _pages_SettingsState extends State<pages_Settings> {
|
||||
|
||||
child: SingleChildScrollView(
|
||||
child: Column(
|
||||
|
||||
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
|
||||
children: [
|
||||
|
||||
|
||||
SizedBox(
|
||||
height: 8
|
||||
),
|
||||
|
||||
AnnouncementUpload(),
|
||||
|
||||
SizedBox(
|
||||
height: 8
|
||||
),
|
||||
|
||||
Container(
|
||||
margin: const EdgeInsets.all(8),
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 8
|
||||
),
|
||||
child: SettingsField(
|
||||
label: "Announce distance",
|
||||
defaultValue: "150m",
|
||||
)
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8
|
||||
),
|
||||
|
||||
Container(
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 8
|
||||
),
|
||||
child: SettingsField(
|
||||
label: "Announce time",
|
||||
defaultValue: "10s",
|
||||
)
|
||||
),
|
||||
|
||||
Container(
|
||||
|
||||
margin: EdgeInsets.only(
|
||||
left: 8,
|
||||
top: 2
|
||||
),
|
||||
|
||||
child: Text(
|
||||
"Console",
|
||||
style: GoogleFonts.teko(
|
||||
fontSize: 24
|
||||
),
|
||||
),
|
||||
),
|
||||
|
||||
Container(
|
||||
margin: const EdgeInsets.symmetric(
|
||||
horizontal: 8
|
||||
),
|
||||
child: Console()
|
||||
),
|
||||
|
||||
if (false)
|
||||
Container(
|
||||
height: 2,
|
||||
width: double.infinity,
|
||||
color: Colors.white70,
|
||||
),
|
||||
|
||||
if (false)
|
||||
Container(
|
||||
|
||||
padding: const EdgeInsets.all(8),
|
||||
@@ -101,6 +160,253 @@ class _pages_SettingsState extends State<pages_Settings> {
|
||||
}
|
||||
}
|
||||
|
||||
class AnnouncementUpload extends StatefulWidget {
|
||||
|
||||
Function onUploaded = () {};
|
||||
|
||||
AnnouncementUpload({Key? key, this.onUploaded = _defaultOnUploaded}) : super(key: key);
|
||||
|
||||
static void _defaultOnUploaded() {}
|
||||
|
||||
@override
|
||||
State<AnnouncementUpload> createState() => _AnnouncementUploadState();
|
||||
}
|
||||
|
||||
class _AnnouncementUploadState extends State<AnnouncementUpload> {
|
||||
|
||||
Future<void> UploadButtonPressed() async {
|
||||
|
||||
// Pick the file
|
||||
FilePickerResult? result = await FilePicker.platform.pickFiles();
|
||||
|
||||
if (result != null) {
|
||||
print("Got file");
|
||||
|
||||
AnnouncementCache cache = LiveInformation().announcementModule.announcementCache;
|
||||
|
||||
LiveInformation().announcementModule.setBundleBytes(result.files[0].bytes!);
|
||||
|
||||
// load a random announcement to ensure that the file is usable
|
||||
await cache.loadAnnouncementsFromBytes(result.files[0].bytes!, ["S_WALTHAMSTOW_CENTRAL_001.mp3"]);
|
||||
|
||||
print("Loaded announcements");
|
||||
|
||||
setState(() {
|
||||
|
||||
});
|
||||
|
||||
widget.onUploaded();
|
||||
|
||||
} else {
|
||||
// User canceled the picker
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: implement build
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.white70,
|
||||
width: 2
|
||||
),
|
||||
),
|
||||
|
||||
margin: EdgeInsets.symmetric(
|
||||
horizontal: 8
|
||||
),
|
||||
padding: EdgeInsets.all(8),
|
||||
|
||||
// height: 100,
|
||||
|
||||
child: Column(
|
||||
|
||||
children: [
|
||||
|
||||
Row(
|
||||
|
||||
children: [
|
||||
|
||||
Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
size: 18,
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
|
||||
Transform.translate(
|
||||
offset: Offset(0, 0),
|
||||
child: Text(
|
||||
"IMPORTANT",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
|
||||
),
|
||||
|
||||
Row(
|
||||
|
||||
children: [
|
||||
|
||||
if (LiveInformation().announcementModule.announcementCache.keys.length == 0)
|
||||
Icon(
|
||||
Icons.error,
|
||||
color: Colors.red,
|
||||
size: 18,
|
||||
)
|
||||
else
|
||||
Icon(
|
||||
Icons.check,
|
||||
color: Colors.green,
|
||||
size: 18,
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: 4,
|
||||
),
|
||||
|
||||
if (LiveInformation().announcementModule.announcementCache.keys.length == 0)
|
||||
Transform.translate(
|
||||
offset: Offset(0, 0),
|
||||
child: Text(
|
||||
"No announcements",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
),
|
||||
),
|
||||
)
|
||||
else
|
||||
Transform.translate(
|
||||
offset: Offset(0, 0),
|
||||
child: Text(
|
||||
"Announcements loaded successfully",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 18,
|
||||
fontWeight: FontWeight.bold,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
Text(
|
||||
"Disclaimer: It is illegal to redistribute Transport for London's intellectual property. Even if it were permissible, the files are too large to be packaged into a website...",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
height: 1
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
Text(
|
||||
"...because of these reasons, you will have to provide the announcement files yourself.",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
height: 1
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
Text(
|
||||
"A ZIP file should be provided containg audio files with the correct naming scheme (e.g. S_WALTHAMSTOW_CENTRAL_001.mp3).",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
height: 1
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
Text(
|
||||
"No specific folder structure is required. The files will be sorted and indexed.",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 12,
|
||||
fontWeight: FontWeight.w400,
|
||||
color: Colors.white70,
|
||||
letterSpacing: 0.1,
|
||||
height: 1
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 8,
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
height: 32,
|
||||
width: double.infinity,
|
||||
child: ElevatedButton(
|
||||
onPressed: (){
|
||||
UploadButtonPressed();
|
||||
},
|
||||
|
||||
// make the corner radius 4, background color match the theme, and text colour white, fill to width of parent
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
foregroundColor: Colors.white,
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(4)
|
||||
),
|
||||
),
|
||||
|
||||
child: Text(
|
||||
"Upload file",
|
||||
style: GoogleFonts.interTight(
|
||||
fontSize: 15,
|
||||
fontWeight: FontWeight.w600,
|
||||
color: Colors.white,
|
||||
letterSpacing: 0.5
|
||||
)
|
||||
)
|
||||
),
|
||||
),
|
||||
],
|
||||
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
enum _LoginType {
|
||||
login,
|
||||
signup
|
||||
@@ -808,4 +1114,148 @@ class _ConsoleState extends State<Console> {
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SettingsField<T> extends StatelessWidget {
|
||||
|
||||
String label = "Untitled Field";
|
||||
|
||||
T defaultValue;
|
||||
|
||||
SettingsField({super.key, this.label = "Untitled Field", required this.defaultValue});
|
||||
|
||||
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
// TODO: implement build
|
||||
return Container(
|
||||
decoration: BoxDecoration(
|
||||
border: Border.all(
|
||||
color: Colors.white70,
|
||||
width: 2
|
||||
),
|
||||
),
|
||||
|
||||
height: 50,
|
||||
|
||||
padding: EdgeInsets.all(4),
|
||||
|
||||
child: Row(
|
||||
|
||||
children: [
|
||||
|
||||
SizedBox(
|
||||
width: 4
|
||||
),
|
||||
|
||||
Text(
|
||||
label,
|
||||
style: GoogleFonts.teko(
|
||||
fontSize: 25,
|
||||
height: 1,
|
||||
letterSpacing: 0.02,
|
||||
color: Colors.white70
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: 8
|
||||
),
|
||||
|
||||
Expanded(
|
||||
child: Container(
|
||||
|
||||
height: double.infinity,
|
||||
|
||||
alignment: Alignment.center,
|
||||
|
||||
decoration: BoxDecoration(
|
||||
|
||||
border: Border.all(
|
||||
color: Colors.white70,
|
||||
width: 2
|
||||
)
|
||||
|
||||
),
|
||||
|
||||
child: Text(
|
||||
defaultValue.toString(),
|
||||
style: GoogleFonts.teko(
|
||||
fontSize: 25,
|
||||
height: 1
|
||||
)
|
||||
)
|
||||
|
||||
),
|
||||
),
|
||||
|
||||
SizedBox(
|
||||
width: 4
|
||||
),
|
||||
|
||||
AspectRatio(
|
||||
aspectRatio: 1,
|
||||
child: Stack(
|
||||
children: [
|
||||
Container(
|
||||
|
||||
height: double.infinity,
|
||||
width: double.infinity,
|
||||
|
||||
decoration: BoxDecoration(
|
||||
|
||||
border: Border.all(
|
||||
color: Colors.white70,
|
||||
width: 2
|
||||
)
|
||||
|
||||
),
|
||||
|
||||
child: Icon(
|
||||
Icons.edit,
|
||||
color: Colors.white70,
|
||||
size: 20,
|
||||
)
|
||||
|
||||
),
|
||||
|
||||
Container(
|
||||
|
||||
padding: EdgeInsets.all(2),
|
||||
|
||||
child: Positioned.fill(
|
||||
child: ElevatedButton(
|
||||
onPressed: () {
|
||||
|
||||
},
|
||||
|
||||
style: ElevatedButton.styleFrom(
|
||||
backgroundColor: Colors.transparent,
|
||||
shadowColor: Colors.transparent,
|
||||
surfaceTintColor: Colors.transparent,
|
||||
foregroundColor: Colors.transparent,
|
||||
|
||||
shape: RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.circular(0),
|
||||
),
|
||||
|
||||
),
|
||||
|
||||
child: Container()
|
||||
),
|
||||
),
|
||||
)
|
||||
|
||||
],
|
||||
)
|
||||
)
|
||||
|
||||
],
|
||||
|
||||
)
|
||||
|
||||
);
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user