Files
lyrics-grabbr/lib/main.dart
T

193 lines
5.5 KiB
Dart
Raw Normal View History

2022-02-24 02:50:11 +02:00
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'notification_listener.dart';
2022-02-24 02:50:11 +02:00
Future<void> main() async {
runApp(const LyricsGrabbr());
}
class LyricsGrabbr extends StatelessWidget {
const LyricsGrabbr({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Lyrics Grabbr',
theme: ThemeData(
primarySwatch: Colors.purple,
2022-02-24 02:50:11 +02:00
),
home: const HomePage(title: 'Lyrics Grabbr'),
);
}
}
class HomePage extends StatefulWidget {
const HomePage({Key? key, required this.title}) : super(key: key);
final String title;
@override
State<HomePage> createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> with WidgetsBindingObserver {
late AndroidNotificationListener _notifications;
late StreamSubscription<NotificationEvent> _subscription;
2022-02-24 02:50:11 +02:00
BuildContext? permissionDialogCtx;
2022-03-01 00:04:30 +02:00
NotificationEvent? currentlyPlaying;
2022-02-24 02:50:11 +02:00
bool running = false;
@override
void initState() {
WidgetsBinding.instance?.addObserver(this);
super.initState();
initPlatformState();
2022-02-24 02:50:11 +02:00
}
@override
void dispose() {
WidgetsBinding.instance?.removeObserver(this);
super.dispose();
}
@override
void didChangeAppLifecycleState(AppLifecycleState state) async {
if (state == AppLifecycleState.resumed) {
if (permissionDialogCtx == null) {
return;
}
var perm = await AndroidNotificationListener.hasPermission;
if (perm != null && perm) {
Navigator.pop(permissionDialogCtx!);
startListening();
}
}
}
2022-03-01 00:04:30 +02:00
void _showNotificationPermDialog() {
showDialog(
context: context,
barrierDismissible: false,
builder: (BuildContext buildCtx) {
permissionDialogCtx = buildCtx;
return WillPopScope(
onWillPop: () {
SystemNavigator.pop();
return Future.value(false);
},
child: AlertDialog(
title: const Text(
'Notifications Access Permission',
style: TextStyle(fontWeight: FontWeight.bold),
),
content: const Text(
'This app requires permission to listen to notifications to function properly. Please grant permission in the next screen.',
style: TextStyle(color: Colors.blueGrey),
),
actions: [
TextButton(
onPressed: () async {
await AndroidNotificationListener
.openPermissionSettings();
},
child: const Text("OK")),
],
2022-02-24 02:50:11 +02:00
),
);
});
2022-02-24 02:50:11 +02:00
}
Future<void> initPlatformState() async {
var perm = await AndroidNotificationListener.hasPermission;
if (perm != null && perm) {
startListening();
} else {
2022-03-01 00:04:30 +02:00
_showNotificationPermDialog();
2022-02-24 02:50:11 +02:00
}
}
void onData(NotificationEvent event) {
2022-02-28 21:30:40 +02:00
// TODO: if the app is in the background, only update our notif
// if the app is in the foreground, update the notif, and
// fetch the new lyrics and display them.
setState(() {
2022-03-01 00:04:30 +02:00
currentlyPlaying = event;
2022-02-28 21:30:40 +02:00
});
2022-02-24 02:50:11 +02:00
}
void startListening() {
// TODO: make the FAB start and stop a local notification service
// that keeps track of which song is playing
// and if pressed will fetch the lyrics and display them.
2022-03-01 00:04:30 +02:00
_notifications = AndroidNotificationListener();
2022-02-24 02:50:11 +02:00
2022-03-01 00:04:30 +02:00
_subscription = _notifications.notificationStream.listen(onData);
2022-02-24 02:50:11 +02:00
setState(() => running = true);
}
void stopListening() {
setState(() => running = false);
2022-03-01 00:04:30 +02:00
_subscription.cancel();
2022-02-24 02:50:11 +02:00
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
2022-03-01 00:04:30 +02:00
body: Container(
padding: const EdgeInsets.all(20),
child: Center(
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
running ? RichText(
text: TextSpan(
text: currentlyPlaying?.songTitle,
style: const TextStyle(
fontSize: 24.0,
color: Colors.black,
fontWeight: FontWeight.w700,
),
children: [
const TextSpan(
text: "\n",
),
TextSpan(
text: currentlyPlaying?.artist,
style: const TextStyle(
fontSize: 20.0,
color: Color(0xFF303030),
)
)
]
),
textAlign: TextAlign.center,
) :
const Text("Listener stopped"),
running ? Text(
currentlyPlaying?.playbackState == PlaybackState.STATE_PLAYING ? "Spotify Playing" : "Spotify Paused",
style: Theme.of(context).textTheme.headline6,
) :
const Text("")
],
),
),
),
2022-02-24 02:50:11 +02:00
floatingActionButton: FloatingActionButton(
onPressed: running ? stopListening : startListening,
2022-03-01 00:04:30 +02:00
tooltip: running ? 'Stop listener' : "Start listener",
2022-02-24 02:50:11 +02:00
child: running ? const Icon(Icons.stop) : const Icon(Icons.play_arrow),
),
);
}
}