Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 9 additions & 1 deletion app/containers/InAppNotification/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ import { getActiveRoute } from '../../lib/methods/helpers/navigation';
import { useAppSelector } from '../../lib/hooks/useAppSelector';
import { setInAppFeedback } from '../../actions/inAppFeedback';
import I18n from '../../i18n';
import { getSubscriptionByRoomId } from '../../lib/database/services/Subscription';
import { playNotificationSound } from '../../lib/methods/helpers/playNotificationSound';

export const INAPP_NOTIFICATION_EMITTER = 'NotificationInApp';

Expand All @@ -21,7 +23,7 @@ const InAppNotification = memo(() => {

const dispatch = useDispatch();

const show = (
const show = async (
notification: INotifierComponent['notification'] & {
customComponent?: ElementType;
customTime?: number;
Expand All @@ -44,6 +46,12 @@ const InAppNotification = memo(() => {
return;
}

const sub = payload?.rid ? await getSubscriptionByRoomId(payload.rid) : null;
if (sub?.audioNotificationValue) {
// eslint-disable-next-line no-void
void playNotificationSound(sub.audioNotificationValue);
}
Comment thread
psrsingh marked this conversation as resolved.

if (payload?.name && payload?.message) {
AccessibilityInfo.announceForAccessibility(
I18n.t('A11y_in_app_notification', {
Expand Down
5 changes: 5 additions & 0 deletions app/definitions/IRoom.ts
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ export interface IRoom {
onHold?: boolean;
waitingResponse?: boolean;
federated?: boolean;
audioNotificationsValue?: string;
audioNotificationValue?: string;
}

export interface IRoomSettings {
Expand Down Expand Up @@ -238,6 +240,8 @@ export interface IServerRoom extends IRocketChatRecord {

isLastOwner?: boolean;
federated?: boolean;
audioNotificationsValue?: string;
audioNotificationValue?: string;
abacAttributes?: { key: string; values: string[] }[];
}

Expand All @@ -247,6 +251,7 @@ export interface IRoomNotifications {
muteGroupMentions?: boolean;
hideUnreadStatus?: boolean;
audioNotificationsValue?: string;
audioNotificationValue?: string;
desktopNotifications?: TNotifications;
mobilePushNotifications?: TNotifications;
emailNotifications?: TNotifications;
Expand Down
3 changes: 2 additions & 1 deletion app/definitions/ISubscription.ts
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@ export interface ISubscription {
threadMessages: RelationModified<TThreadMessageModel>;
uploads: RelationModified<TUploadModel>;
disableNotifications?: boolean;
audioNotificationValue?: string;
federated?: boolean;
abacAttributes?: { key: string; values: string[] }[];
federation?: {
Expand Down Expand Up @@ -179,7 +180,7 @@ export interface IServerSubscription extends IRocketChatRecord {

code?: unknown;
archived?: unknown;
audioNotificationValue?: unknown;
audioNotificationValue?: string;
desktopNotifications?: unknown;
mobilePushNotifications?: unknown;
emailNotifications?: unknown;
Expand Down
5 changes: 4 additions & 1 deletion app/lib/database/model/Subscription.js
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,8 @@ export default class Subscription extends Model {

@json('inviter', sanitizer) inviter;

@field('audio_notification_value') audioNotificationValue;

asPlain() {
return {
_id: this._id,
Expand Down Expand Up @@ -231,7 +233,8 @@ export default class Subscription extends Model {
abacAttributes: this.abacAttributes,
federation: this.federation,
status: this.status,
inviter: this.inviter
inviter: this.inviter,
audioNotificationValue: this.audioNotificationValue
};
}
}
9 changes: 9 additions & 0 deletions app/lib/database/model/migrations.js
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,15 @@ export default schemaMigrations({
]
})
]
},
{
toVersion: 29,
steps: [
addColumns({
table: 'subscriptions',
columns: [{ name: 'audio_notification_value', type: 'string', isOptional: true }]
})
]
}
]
});
5 changes: 3 additions & 2 deletions app/lib/database/schema/app.js
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { appSchema, tableSchema } from '@nozbe/watermelondb';

export default appSchema({
version: 28,
version: 29,
tables: [
tableSchema({
name: 'subscriptions',
Expand Down Expand Up @@ -74,7 +74,8 @@ export default appSchema({
{ name: 'abac_attributes', type: 'string', isOptional: true },
{ name: 'federation', type: 'string', isOptional: true },
{ name: 'status', type: 'string', isOptional: true },
{ name: 'inviter', type: 'string', isOptional: true }
{ name: 'inviter', type: 'string', isOptional: true },
{ name: 'audio_notification_value', type: 'string', isOptional: true }
]
}),
tableSchema({
Expand Down
5 changes: 5 additions & 0 deletions app/lib/methods/helpers/mergeSubscriptionsRooms.ts
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,11 @@ export const merge = (
if (room && 'federation' in room) {
mergedSubscription.federation = room.federation;
}
if (room && 'audioNotificationValue' in room) {
mergedSubscription.audioNotificationValue = room.audioNotificationValue;
} else if (room && 'audioNotificationsValue' in room) {
mergedSubscription.audioNotificationValue = room.audioNotificationsValue;
}
Comment thread
coderabbitai[bot] marked this conversation as resolved.
}

if (!mergedSubscription.name) {
Expand Down
69 changes: 69 additions & 0 deletions app/lib/methods/helpers/playNotificationSound.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
import { Audio } from 'expo-av';

const RINGTONE_SOUND = require('../../../containers/Ringer/ringtone.mp3');
const CALL_ENDED_SOUND = require('../../../containers/Ringer/call-ended.mp3');

const sounds: Record<string, any> = {
0: CALL_ENDED_SOUND,
default: CALL_ENDED_SOUND,
beep: RINGTONE_SOUND,
ding: CALL_ENDED_SOUND,
chelle: RINGTONE_SOUND,
droplet: CALL_ENDED_SOUND,
highbell: RINGTONE_SOUND,
seasons: RINGTONE_SOUND
};

const DEFAULT_SOUND = CALL_ENDED_SOUND;

const WATCHDOG_MS = 5000;

const normalizeSoundName = (soundName: string) => soundName.trim().split(' ')[0].toLowerCase();

export const playNotificationSound = async (soundName: string): Promise<void> => {
if (!soundName) {
return;
}

const normalized = normalizeSoundName(soundName);

if (!normalized || normalized === 'none') {
return;
}

let sound: Audio.Sound | undefined;
let unloaded = false;
let watchdog: ReturnType<typeof setTimeout> | null = null;

const unload = () => {
if (unloaded || !sound) {
return;
}
unloaded = true;
if (watchdog) {
clearTimeout(watchdog);
watchdog = null;
}
sound.unloadAsync().catch(() => {
// best-effort unload
});
};

try {
const asset = sounds[normalized] || DEFAULT_SOUND;
({ sound } = await Audio.Sound.createAsync(asset));

sound.setOnPlaybackStatusUpdate(status => {
if (status.isLoaded && status.didJustFinish) {
unload();
}
});

await sound.playAsync();

watchdog = setTimeout(unload, WATCHDOG_MS);
} catch {
unload();
// best-effort notification sound
}
};