mirror of
https://github.com/zarzet/SpotiFLAC-Mobile.git
synced 2026-05-22 07:56:55 +02:00
345 lines
8.8 KiB
Dart
345 lines
8.8 KiB
Dart
import 'dart:io';
|
|
import 'package:flutter_local_notifications/flutter_local_notifications.dart';
|
|
|
|
class NotificationService {
|
|
static final NotificationService _instance = NotificationService._internal();
|
|
factory NotificationService() => _instance;
|
|
NotificationService._internal();
|
|
|
|
final FlutterLocalNotificationsPlugin _notifications = FlutterLocalNotificationsPlugin();
|
|
bool _isInitialized = false;
|
|
|
|
static const int downloadProgressId = 1;
|
|
static const int updateDownloadId = 2;
|
|
static const String channelId = 'download_progress';
|
|
static const String channelName = 'Download Progress';
|
|
static const String channelDescription = 'Shows download progress for tracks';
|
|
|
|
Future<void> initialize() async {
|
|
if (_isInitialized) return;
|
|
|
|
const androidSettings = AndroidInitializationSettings('@mipmap/ic_launcher');
|
|
const iosSettings = DarwinInitializationSettings(
|
|
requestAlertPermission: true,
|
|
requestBadgePermission: true,
|
|
requestSoundPermission: false,
|
|
);
|
|
|
|
const initSettings = InitializationSettings(
|
|
android: androidSettings,
|
|
iOS: iosSettings,
|
|
);
|
|
|
|
await _notifications.initialize(initSettings);
|
|
|
|
if (Platform.isAndroid) {
|
|
await _notifications
|
|
.resolvePlatformSpecificImplementation<AndroidFlutterLocalNotificationsPlugin>()
|
|
?.createNotificationChannel(
|
|
const AndroidNotificationChannel(
|
|
channelId,
|
|
channelName,
|
|
description: channelDescription,
|
|
importance: Importance.low,
|
|
showBadge: false,
|
|
playSound: false,
|
|
enableVibration: false,
|
|
),
|
|
);
|
|
}
|
|
|
|
_isInitialized = true;
|
|
}
|
|
|
|
Future<void> showDownloadProgress({
|
|
required String trackName,
|
|
required String artistName,
|
|
required int progress,
|
|
required int total,
|
|
}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
final percentage = total > 0 ? (progress * 100 ~/ total) : 0;
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.low,
|
|
priority: Priority.low,
|
|
showProgress: true,
|
|
maxProgress: 100,
|
|
progress: percentage,
|
|
ongoing: true,
|
|
autoCancel: false,
|
|
playSound: false,
|
|
enableVibration: false,
|
|
onlyAlertOnce: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: false,
|
|
presentBadge: false,
|
|
presentSound: false,
|
|
);
|
|
|
|
final details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
downloadProgressId,
|
|
'Downloading $trackName',
|
|
'$artistName • $percentage%',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> showDownloadFinalizing({
|
|
required String trackName,
|
|
required String artistName,
|
|
}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.low,
|
|
priority: Priority.low,
|
|
showProgress: true,
|
|
maxProgress: 100,
|
|
progress: 100,
|
|
indeterminate: false,
|
|
ongoing: true,
|
|
autoCancel: false,
|
|
playSound: false,
|
|
enableVibration: false,
|
|
onlyAlertOnce: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: false,
|
|
presentBadge: false,
|
|
presentSound: false,
|
|
);
|
|
|
|
final details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
downloadProgressId,
|
|
'Finalizing $trackName',
|
|
'$artistName • Embedding metadata...',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> showDownloadComplete({
|
|
required String trackName,
|
|
required String artistName,
|
|
int? completedCount,
|
|
int? totalCount,
|
|
}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
final title = completedCount != null && totalCount != null
|
|
? 'Download Complete ($completedCount/$totalCount)'
|
|
: 'Download Complete';
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.defaultImportance,
|
|
priority: Priority.defaultPriority,
|
|
autoCancel: true,
|
|
playSound: false,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: false,
|
|
);
|
|
|
|
const details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
downloadProgressId,
|
|
title,
|
|
'$trackName - $artistName',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> showQueueComplete({
|
|
required int completedCount,
|
|
required int failedCount,
|
|
}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
final title = failedCount > 0
|
|
? 'Downloads Finished ($completedCount done, $failedCount failed)'
|
|
: 'All Downloads Complete';
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.defaultImportance,
|
|
priority: Priority.defaultPriority,
|
|
autoCancel: true,
|
|
playSound: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
downloadProgressId,
|
|
title,
|
|
'$completedCount tracks downloaded successfully',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> cancelDownloadNotification() async {
|
|
await _notifications.cancel(downloadProgressId);
|
|
}
|
|
|
|
Future<void> showUpdateDownloadProgress({
|
|
required String version,
|
|
required int received,
|
|
required int total,
|
|
}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
final percentage = total > 0 ? (received * 100 ~/ total) : 0;
|
|
final receivedMB = (received / 1024 / 1024).toStringAsFixed(1);
|
|
final totalMB = (total / 1024 / 1024).toStringAsFixed(1);
|
|
|
|
final androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.low,
|
|
priority: Priority.low,
|
|
showProgress: true,
|
|
maxProgress: 100,
|
|
progress: percentage,
|
|
ongoing: true,
|
|
autoCancel: false,
|
|
playSound: false,
|
|
enableVibration: false,
|
|
onlyAlertOnce: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: false,
|
|
presentBadge: false,
|
|
presentSound: false,
|
|
);
|
|
|
|
final details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
updateDownloadId,
|
|
'Downloading SpotiFLAC v$version',
|
|
'$receivedMB / $totalMB MB • $percentage%',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> showUpdateDownloadComplete({required String version}) async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.defaultImportance,
|
|
priority: Priority.defaultPriority,
|
|
autoCancel: true,
|
|
playSound: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: true,
|
|
presentSound: true,
|
|
);
|
|
|
|
const details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
updateDownloadId,
|
|
'Update Ready',
|
|
'SpotiFLAC v$version downloaded. Tap to install.',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> showUpdateDownloadFailed() async {
|
|
if (!_isInitialized) await initialize();
|
|
|
|
const androidDetails = AndroidNotificationDetails(
|
|
channelId,
|
|
channelName,
|
|
channelDescription: channelDescription,
|
|
importance: Importance.defaultImportance,
|
|
priority: Priority.defaultPriority,
|
|
autoCancel: true,
|
|
icon: '@mipmap/ic_launcher',
|
|
);
|
|
|
|
const iosDetails = DarwinNotificationDetails(
|
|
presentAlert: true,
|
|
presentBadge: false,
|
|
presentSound: false,
|
|
);
|
|
|
|
const details = NotificationDetails(
|
|
android: androidDetails,
|
|
iOS: iosDetails,
|
|
);
|
|
|
|
await _notifications.show(
|
|
updateDownloadId,
|
|
'Update Failed',
|
|
'Could not download update. Try again later.',
|
|
details,
|
|
);
|
|
}
|
|
|
|
Future<void> cancelUpdateNotification() async {
|
|
await _notifications.cancel(updateDownloadId);
|
|
}
|
|
}
|