您最多选择25个主题 主题必须以字母或数字开头,可以包含连字符 (-),并且长度不得超过35个字符

middleware.js 5.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  1. // @flow
  2. import { setNoAudioSignalNotificationUid } from './actions';
  3. import { APP_WILL_MOUNT, APP_WILL_UNMOUNT } from '../base/app';
  4. import { CONFERENCE_JOINED } from '../base/conference';
  5. import {
  6. ACTIVE_DEVICE_DETECTED,
  7. ActiveDeviceDetector,
  8. filterAudioDevices,
  9. formatDeviceLabel,
  10. getAvailableDevices,
  11. setAudioInputDevice
  12. } from '../base/devices';
  13. import { JitsiConferenceEvents } from '../base/lib-jitsi-meet';
  14. import { MiddlewareRegistry } from '../base/redux';
  15. import { updateSettings } from '../base/settings';
  16. import { playSound, registerSound, unregisterSound } from '../base/sounds';
  17. import { NO_AUDIO_SIGNAL_SOUND_ID } from './constants';
  18. import { hideNotification, showNotification } from '../notifications';
  19. import { NO_AUDIO_SIGNAL_SOUND_FILE } from './sounds';
  20. MiddlewareRegistry.register(store => next => async action => {
  21. const result = next(action);
  22. const { dispatch, getState } = store;
  23. const { conference } = action;
  24. let audioDetectService = null;
  25. switch (action.type) {
  26. case APP_WILL_MOUNT:
  27. dispatch(registerSound(NO_AUDIO_SIGNAL_SOUND_ID, NO_AUDIO_SIGNAL_SOUND_FILE));
  28. break;
  29. case APP_WILL_UNMOUNT:
  30. dispatch(unregisterSound(NO_AUDIO_SIGNAL_SOUND_ID));
  31. break;
  32. case CONFERENCE_JOINED: {
  33. conference.on(JitsiConferenceEvents.TRACK_ADDED, track => {
  34. const { noAudioSignalNotificationUid } = getState()['features/no-audio-signal'];
  35. if (track.isAudioTrack() && track.isLocal()) {
  36. // In case the device is switched attempt to destroy, this should prevent the notification firing
  37. // when the device was switched, however it is possible that a user switches the device and the
  38. // notification from the previous devices pops up, but this will probably happen very rarely and even
  39. // if it does it's not that disruptive to the ux.
  40. if (audioDetectService) {
  41. audioDetectService.destroy();
  42. audioDetectService = null;
  43. }
  44. // When a new track is added hide the current notification is one is displayed, and reset the redux
  45. // state so that we begin monitoring on the new device as well.
  46. if (noAudioSignalNotificationUid) {
  47. dispatch(hideNotification(noAudioSignalNotificationUid));
  48. dispatch(setNoAudioSignalNotificationUid());
  49. }
  50. }
  51. });
  52. conference.on(JitsiConferenceEvents.NO_AUDIO_INPUT, async () => {
  53. const { noSrcDataNotiUid } = getState()['features/base/no-src-data'];
  54. // In case the 'no data detected from source' notification was already shown, we prevent the
  55. // no audio signal notification as it's redundant i.e. it's clear that the users microphone is
  56. // muted from system settings.
  57. if (noSrcDataNotiUid) {
  58. return;
  59. }
  60. const devices = await dispatch(getAvailableDevices());
  61. const audioDevices = filterAudioDevices(devices);
  62. audioDetectService = await ActiveDeviceDetector.create(audioDevices);
  63. audioDetectService.on(ACTIVE_DEVICE_DETECTED, detectEvent => {
  64. let descriptionKey = 'toolbar.noAudioSignalDesc';
  65. let customActionNameKey = null;
  66. let customActionHandler = null;
  67. // In case the detector picked up a device show a notification with a device suggestion
  68. if (detectEvent.deviceLabel !== '') {
  69. descriptionKey = 'toolbar.noAudioSignalDescSuggestion';
  70. // Preferably the label should be passed as an argument paired with a i18next string, however
  71. // at the point of the implementation the showNotification function only supports doing that for
  72. // the description.
  73. // TODO Add support for arguments to showNotification title and customAction strings.
  74. customActionNameKey = `Use ${formatDeviceLabel(detectEvent.deviceLabel)}`;
  75. customActionHandler = () => {
  76. // Select device callback
  77. dispatch(
  78. updateSettings({
  79. userSelectedMicDeviceId: detectEvent.deviceId,
  80. userSelectedMicDeviceLabel: detectEvent.deviceLabel
  81. })
  82. );
  83. dispatch(setAudioInputDevice(detectEvent.deviceId));
  84. };
  85. }
  86. const notification = showNotification({
  87. titleKey: 'toolbar.noAudioSignalTitle',
  88. descriptionKey,
  89. customActionNameKey,
  90. customActionHandler
  91. });
  92. dispatch(notification);
  93. dispatch(playSound(NO_AUDIO_SIGNAL_SOUND_ID));
  94. // Store the current notification uid so we can check for this state and hide it in case
  95. // a new track was added, thus changing the context of the notification
  96. dispatch(setNoAudioSignalNotificationUid(notification.uid));
  97. });
  98. });
  99. break;
  100. }
  101. }
  102. return result;
  103. });