✨ Sound effects on notifications
This commit is contained in:
BIN
assets/audio/messages.mp3
Normal file
BIN
assets/audio/messages.mp3
Normal file
Binary file not shown.
@@ -1,5 +1,7 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Alamofire (5.11.0)
|
- Alamofire (5.11.0)
|
||||||
|
- audio_session (0.0.1):
|
||||||
|
- Flutter
|
||||||
- connectivity_plus (0.0.1):
|
- connectivity_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- croppy (0.0.1):
|
- croppy (0.0.1):
|
||||||
@@ -219,6 +221,9 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- irondash_engine_context (0.0.1):
|
- irondash_engine_context (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- just_audio (0.0.1):
|
||||||
|
- Flutter
|
||||||
|
- FlutterMacOS
|
||||||
- KeychainAccess (4.2.2)
|
- KeychainAccess (4.2.2)
|
||||||
- Kingfisher (8.6.2)
|
- Kingfisher (8.6.2)
|
||||||
- KingfisherWebP (1.7.2):
|
- KingfisherWebP (1.7.2):
|
||||||
@@ -333,6 +338,7 @@ PODS:
|
|||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
|
- audio_session (from `.symlinks/plugins/audio_session/ios`)
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- croppy (from `.symlinks/plugins/croppy/ios`)
|
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
@@ -357,6 +363,7 @@ DEPENDENCIES:
|
|||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
- in_app_review (from `.symlinks/plugins/in_app_review/ios`)
|
||||||
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
||||||
|
- just_audio (from `.symlinks/plugins/just_audio/darwin`)
|
||||||
- Kingfisher (~> 8.0)
|
- Kingfisher (~> 8.0)
|
||||||
- KingfisherWebP
|
- KingfisherWebP
|
||||||
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||||
@@ -418,6 +425,8 @@ SPEC REPOS:
|
|||||||
- WebRTC-SDK
|
- WebRTC-SDK
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
audio_session:
|
||||||
|
:path: ".symlinks/plugins/audio_session/ios"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
croppy:
|
croppy:
|
||||||
@@ -466,6 +475,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/in_app_review/ios"
|
:path: ".symlinks/plugins/in_app_review/ios"
|
||||||
irondash_engine_context:
|
irondash_engine_context:
|
||||||
:path: ".symlinks/plugins/irondash_engine_context/ios"
|
:path: ".symlinks/plugins/irondash_engine_context/ios"
|
||||||
|
just_audio:
|
||||||
|
:path: ".symlinks/plugins/just_audio/darwin"
|
||||||
livekit_client:
|
livekit_client:
|
||||||
:path: ".symlinks/plugins/livekit_client/ios"
|
:path: ".symlinks/plugins/livekit_client/ios"
|
||||||
local_auth_darwin:
|
local_auth_darwin:
|
||||||
@@ -519,6 +530,7 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: bd5e7b23a1a750975288482c1831d71e74415f86
|
Alamofire: bd5e7b23a1a750975288482c1831d71e74415f86
|
||||||
|
audio_session: 9bb7f6c970f21241b19f5a3658097ae459681ba0
|
||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
||||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
@@ -559,6 +571,7 @@ SPEC CHECKSUMS:
|
|||||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937
|
in_app_review: 7dd1ea365263f834b8464673f9df72c80c17c937
|
||||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||||
|
just_audio: 4e391f57b79cad2b0674030a00453ca5ce817eed
|
||||||
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
KeychainAccess: c0c4f7f38f6fc7bbe58f5702e25f7bd2f65abf51
|
||||||
Kingfisher: 23d18f54677d973b713e54ce6a8f5eef6e7056ba
|
Kingfisher: 23d18f54677d973b713e54ce6a8f5eef6e7056ba
|
||||||
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402
|
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402
|
||||||
|
|||||||
@@ -2,6 +2,8 @@ import "dart:async";
|
|||||||
import "dart:convert";
|
import "dart:convert";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||||
|
import "package:just_audio/just_audio.dart";
|
||||||
|
import "package:island/pods/config.dart";
|
||||||
import "package:island/models/chat.dart";
|
import "package:island/models/chat.dart";
|
||||||
import "package:island/pods/chat/chat_room.dart";
|
import "package:island/pods/chat/chat_room.dart";
|
||||||
import "package:island/pods/lifecycle.dart";
|
import "package:island/pods/lifecycle.dart";
|
||||||
@@ -198,7 +200,7 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
|
|||||||
return _typingStatuses;
|
return _typingStatuses;
|
||||||
}
|
}
|
||||||
|
|
||||||
void onMessage(WebSocketPacket pkt) {
|
Future<void> onMessage(WebSocketPacket pkt) async {
|
||||||
if (!pkt.type.startsWith('messages')) return;
|
if (!pkt.type.startsWith('messages')) return;
|
||||||
if (['messages.read'].contains(pkt.type)) return;
|
if (['messages.read'].contains(pkt.type)) return;
|
||||||
|
|
||||||
@@ -238,6 +240,17 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
|
|||||||
_messagesNotifier.receiveMessage(message);
|
_messagesNotifier.receiveMessage(message);
|
||||||
// Send read receipt for new message
|
// Send read receipt for new message
|
||||||
sendReadReceipt();
|
sendReadReceipt();
|
||||||
|
// Play sound for new messages when app is unfocused
|
||||||
|
if (pkt.type == 'messages.new' &&
|
||||||
|
message.senderId != _chatIdentity.id &&
|
||||||
|
ref.read(appLifecycleStateProvider).value != AppLifecycleState.resumed &&
|
||||||
|
ref.read(appSettingsProvider).soundEffects) {
|
||||||
|
final player = AudioPlayer();
|
||||||
|
await player.setVolume(0.75);
|
||||||
|
await player.setAudioSource(AudioSource.asset('assets/audio/messages.mp3'));
|
||||||
|
await player.play();
|
||||||
|
player.dispose();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -275,4 +288,4 @@ class ChatSubscribeNotifier extends _$ChatSubscribeNotifier {
|
|||||||
_typingCooldownTimer = null;
|
_typingCooldownTimer = null;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -107,13 +107,10 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
|
|||||||
}
|
}
|
||||||
if (settings.soundEffects) {
|
if (settings.soundEffects) {
|
||||||
final player = AudioPlayer();
|
final player = AudioPlayer();
|
||||||
player
|
await player.setVolume(0.75);
|
||||||
.setAudioSource(
|
await player.setAudioSource(AudioSource.asset('assets/audio/notification.mp3'));
|
||||||
AudioSource.asset('assets/audio/notification.mp3'),
|
await player.play();
|
||||||
)
|
player.dispose();
|
||||||
.then((_) {
|
|
||||||
player.play().then((_) => player.dispose());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
showTopSnackBar(
|
showTopSnackBar(
|
||||||
globalOverlay.currentState!,
|
globalOverlay.currentState!,
|
||||||
@@ -231,4 +228,4 @@ Future<void> _putTokenToRemote(
|
|||||||
"/ring/notifications/subscription",
|
"/ring/notifications/subscription",
|
||||||
data: {"provider": provider, "device_token": token},
|
data: {"provider": provider, "device_token": token},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -70,13 +70,10 @@ StreamSubscription<WebSocketPacket> setupNotificationListener(
|
|||||||
}
|
}
|
||||||
if (settings.soundEffects) {
|
if (settings.soundEffects) {
|
||||||
final player = AudioPlayer();
|
final player = AudioPlayer();
|
||||||
player
|
await player.setVolume(0.75);
|
||||||
.setAudioSource(
|
await player.setAudioSource(AudioSource.asset('assets/audio/notification.mp3'));
|
||||||
AudioSource.asset('assets/audio/notification.mp3'),
|
await player.play();
|
||||||
)
|
player.dispose();
|
||||||
.then((_) {
|
|
||||||
player.play().then((_) => player.dispose());
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
showTopSnackBar(
|
showTopSnackBar(
|
||||||
globalOverlay.currentState!,
|
globalOverlay.currentState!,
|
||||||
@@ -224,4 +221,4 @@ Future<void> _putTokenToRemote(
|
|||||||
"/ring/notifications/subscription",
|
"/ring/notifications/subscription",
|
||||||
data: {"provider": provider, "device_token": token},
|
data: {"provider": provider, "device_token": token},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -275,7 +275,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
if (activeTasks.any(
|
if (activeTasks.any(
|
||||||
(task) =>
|
(task) =>
|
||||||
task.status == DriveTaskStatus.inProgress,
|
task.status == DriveTaskStatus.inProgress &&
|
||||||
|
task.uploadedBytes < task.fileSize,
|
||||||
))
|
))
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
value: null, // Indeterminate
|
value: null, // Indeterminate
|
||||||
@@ -378,7 +379,8 @@ class _TaskOverlayContent extends HookConsumerWidget {
|
|||||||
if (activeTasks.any(
|
if (activeTasks.any(
|
||||||
(task) =>
|
(task) =>
|
||||||
task.status ==
|
task.status ==
|
||||||
DriveTaskStatus.inProgress,
|
DriveTaskStatus.inProgress &&
|
||||||
|
task.uploadedBytes < task.fileSize,
|
||||||
))
|
))
|
||||||
CircularProgressIndicator(
|
CircularProgressIndicator(
|
||||||
value: null, // Indeterminate
|
value: null, // Indeterminate
|
||||||
@@ -533,14 +535,9 @@ class _TaskOverlayContent extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
double? _getTaskProgress(DriveTask task) {
|
double? _getTaskProgress(DriveTask task) {
|
||||||
if (task.status == DriveTaskStatus.completed) return 1.0;
|
if (task.status == DriveTaskStatus.completed || (task.uploadedBytes >= task.fileSize && task.fileSize > 0)) return 1.0;
|
||||||
if (task.status != DriveTaskStatus.inProgress) return 0.0;
|
if (task.status != DriveTaskStatus.inProgress) return 0.0;
|
||||||
|
|
||||||
// If all bytes are uploaded but still in progress, show indeterminate
|
|
||||||
if (task.uploadedBytes >= task.fileSize && task.fileSize > 0) {
|
|
||||||
return null; // Indeterminate progress
|
|
||||||
}
|
|
||||||
|
|
||||||
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
|
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -672,14 +669,9 @@ class UploadTaskTile extends StatefulWidget {
|
|||||||
State<UploadTaskTile> createState() => _UploadTaskTileState();
|
State<UploadTaskTile> createState() => _UploadTaskTileState();
|
||||||
|
|
||||||
static double? _getTaskProgress(DriveTask task) {
|
static double? _getTaskProgress(DriveTask task) {
|
||||||
if (task.status == DriveTaskStatus.completed) return 1.0;
|
if (task.status == DriveTaskStatus.completed || (task.uploadedBytes >= task.fileSize && task.fileSize > 0)) return 1.0;
|
||||||
if (task.status == DriveTaskStatus.inProgress) return null;
|
if (task.status == DriveTaskStatus.inProgress) return null;
|
||||||
|
|
||||||
// If all bytes are uploaded but still in progress, show indeterminate
|
|
||||||
if (task.uploadedBytes >= task.fileSize && task.fileSize > 0) {
|
|
||||||
return null; // Indeterminate progress
|
|
||||||
}
|
|
||||||
|
|
||||||
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
|
return task.fileSize > 0 ? task.uploadedBytes / task.fileSize : 0.0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1029,4 +1021,4 @@ class _UploadTaskTileState extends State<UploadTaskTile>
|
|||||||
return '${duration.inSeconds}s';
|
return '${duration.inSeconds}s';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user