check if browser is allowing us to use AudioContext and tell user if not
This commit is contained in:
parent
1b33260520
commit
059931e202
|
@ -6,12 +6,29 @@ import ToggleButton from 'react-toggle-button';
|
|||
import { MdCheck, MdClose } from 'react-icons/md';
|
||||
|
||||
|
||||
const MdToggleButton = ({ value, onToggle }) => (
|
||||
const MdToggleButton = ({ value, onToggle, deactivated }) => (
|
||||
<ToggleButton
|
||||
inactiveLabel={<MdClose />}
|
||||
activeLabel={<MdCheck />}
|
||||
value={value}
|
||||
onToggle={onToggle}
|
||||
colors={(deactivated)
|
||||
? {
|
||||
activeThumb: {
|
||||
base: '#b2b2b2',
|
||||
},
|
||||
inactiveTumb: {
|
||||
base: '#b2b2b2',
|
||||
},
|
||||
active: {
|
||||
base: '#cbcbcb',
|
||||
},
|
||||
inactive: {
|
||||
base: '#cbcbcb',
|
||||
},
|
||||
}
|
||||
: {}}
|
||||
thumbStyleHover={{ backgroundColor: '#ededed' }}
|
||||
/>
|
||||
);
|
||||
|
||||
|
|
|
@ -1,33 +0,0 @@
|
|||
/**
|
||||
*/
|
||||
|
||||
import React from 'react';
|
||||
import MdToggleButton from './MdToggleButton';
|
||||
|
||||
|
||||
const MdToggleButtonHover = ({ value, onToggle }) => (
|
||||
<MdToggleButton
|
||||
value={value}
|
||||
onToggle={onToggle}
|
||||
thumbStyle={{
|
||||
position: 'absolute',
|
||||
width: 30,
|
||||
height: 30,
|
||||
boxShadow: '0 0 2px rgba(0,0,0,.12),0 2px 4px rgba(0,0,0,.24)',
|
||||
display: 'flex',
|
||||
borderRadius: 15,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
}}
|
||||
thumbStyleHover={{
|
||||
width: 32,
|
||||
height: 32,
|
||||
}}
|
||||
animateThumbStyleHover={(n) => ({
|
||||
// eslint-disable-next-line max-len
|
||||
boxShadow: `0 0 ${2 + (4 * n)}px rgba(0,0,0,.16),0 ${2 + (3 * n)}px ${4 + (8 * n)}px rgba(0,0,0,.32)`,
|
||||
})}
|
||||
/>
|
||||
);
|
||||
|
||||
export default MdToggleButtonHover;
|
|
@ -11,7 +11,7 @@ import {
|
|||
setBlockingDm,
|
||||
setUserBlock,
|
||||
} from '../actions';
|
||||
import MdToggleButtonHover from './MdToggleButtonHover';
|
||||
import MdToggleButton from './MdToggleButton';
|
||||
|
||||
const SocialSettings = ({ done }) => {
|
||||
const blocked = useSelector((state) => state.chat.blocked);
|
||||
|
@ -37,7 +37,7 @@ const SocialSettings = ({ done }) => {
|
|||
>
|
||||
{t`Block all Private Messages`}
|
||||
</span>
|
||||
<MdToggleButtonHover
|
||||
<MdToggleButton
|
||||
value={blockDm}
|
||||
onToggle={() => {
|
||||
if (!fetching) {
|
||||
|
|
|
@ -8,7 +8,7 @@ import { useSelector, useDispatch, shallowEqual } from 'react-redux';
|
|||
import { c, t } from 'ttag';
|
||||
|
||||
import LanguageSelect from '../LanguageSelect';
|
||||
import MdToggleButtonHover from '../MdToggleButtonHover';
|
||||
import MdToggleButton from '../MdToggleButton';
|
||||
import {
|
||||
toggleGrid,
|
||||
togglePixelNotify,
|
||||
|
@ -48,7 +48,7 @@ const rowStyles = {
|
|||
};
|
||||
|
||||
const SettingsItemSelect = ({
|
||||
title, description, values, selected, onSelect, icon,
|
||||
title, values, selected, onSelect, icon, children,
|
||||
}) => (
|
||||
<div style={itemStyles}>
|
||||
<div style={rowStyles}>
|
||||
|
@ -72,13 +72,13 @@ const SettingsItemSelect = ({
|
|||
}
|
||||
</select>
|
||||
</div>
|
||||
{description && <div className="modaldesc">{description} </div>}
|
||||
<div className="modaldesc">{children}</div>
|
||||
<div className="modaldivider" />
|
||||
</div>
|
||||
);
|
||||
|
||||
const SettingsItem = ({
|
||||
title, description, keyBind, value, onToggle,
|
||||
const SettingsItem = React.memo(({
|
||||
title, keyBind, value, onToggle, children, deactivated,
|
||||
}) => (
|
||||
<div style={itemStyles}>
|
||||
<div style={rowStyles}>
|
||||
|
@ -88,12 +88,16 @@ const SettingsItem = ({
|
|||
>
|
||||
{title} {keyBind && <kbd>{keyBind}</kbd>}
|
||||
</h3>
|
||||
<MdToggleButtonHover value={value} onToggle={onToggle} />
|
||||
<MdToggleButton
|
||||
value={value}
|
||||
onToggle={onToggle}
|
||||
deactivated={deactivated}
|
||||
/>
|
||||
</div>
|
||||
{description && <div className="modaldesc">{description} </div>}
|
||||
<div className="modaldesc">{children}</div>
|
||||
<div className="modaldivider" />
|
||||
</div>
|
||||
);
|
||||
), (prevProps, nextProps) => prevProps.value === nextProps.value);
|
||||
|
||||
function Settings() {
|
||||
const [
|
||||
|
@ -121,79 +125,98 @@ function Settings() {
|
|||
], shallowEqual);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
const audioAvailable = window.AudioContext || window.webkitAudioContext;
|
||||
|
||||
return (
|
||||
<div style={{ paddingLeft: '5%', paddingRight: '5%', paddingTop: 30 }}>
|
||||
<SettingsItem
|
||||
title={t`Show Grid`}
|
||||
description={t`Turn on grid to highlight pixel borders.`}
|
||||
keyBind={c('keybinds').t`G`}
|
||||
value={isGridShown}
|
||||
onToggle={() => dispatch(toggleGrid())}
|
||||
/>
|
||||
>
|
||||
{t`Turn on grid to highlight pixel borders.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Show Pixel Activity`}
|
||||
description={t`Show circles where pixels are placed.`}
|
||||
keyBind={c('keybinds').t`X`}
|
||||
value={isPixelNotifyShown}
|
||||
onToggle={() => dispatch(togglePixelNotify())}
|
||||
/>
|
||||
>
|
||||
{t`Show circles where pixels are placed.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Disable Game Sounds`}
|
||||
// eslint-disable-next-line max-len
|
||||
description={t`All sound effects will be disabled.`}
|
||||
keyBind={c('keybinds').t`M`}
|
||||
value={isMuted}
|
||||
deactivated={(!audioAvailable)}
|
||||
value={!audioAvailable || isMuted}
|
||||
onToggle={() => dispatch(toggleMute())}
|
||||
/>
|
||||
>
|
||||
{[t`All sound effects will be disabled.`,
|
||||
(!audioAvailable) && (
|
||||
<p className="warn">
|
||||
{/* eslint-disable-next-line max-len */}
|
||||
{t`Your Browser doesn't allow us to use AudioContext to play sounds. Do you have some privacy feature blocking us?`}
|
||||
</p>
|
||||
),
|
||||
]}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Enable chat notifications`}
|
||||
description={t`Play a sound when new chat messages arrive`}
|
||||
value={chatNotify}
|
||||
onToggle={() => dispatch(toggleChatNotify())}
|
||||
/>
|
||||
>
|
||||
{t`Play a sound when new chat messages arrive`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Auto Zoom In`}
|
||||
// eslint-disable-next-line max-len
|
||||
description={t`Zoom in instead of placing a pixel when you tap the canvas and your zoom is small.`}
|
||||
value={autoZoomIn}
|
||||
onToggle={() => dispatch(toggleAutoZoomIn())}
|
||||
/>
|
||||
>
|
||||
{/* eslint-disable-next-line max-len */}
|
||||
{t`Zoom in instead of placing a pixel when you tap the canvas and your zoom is small.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Compact Palette`}
|
||||
// eslint-disable-next-line max-len
|
||||
description={t`Display Palette in a compact form that takes less screen space.`}
|
||||
value={compactPalette}
|
||||
onToggle={() => dispatch(toggleCompactPalette())}
|
||||
/>
|
||||
>
|
||||
{t`Display Palette in a compact form that takes less screen space.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Potato Mode`}
|
||||
description={t`For when you are playing on a potato.`}
|
||||
value={isPotato}
|
||||
onToggle={() => dispatch(togglePotatoMode())}
|
||||
/>
|
||||
>
|
||||
{t`For when you are playing on a potato.`}
|
||||
</SettingsItem>
|
||||
<SettingsItem
|
||||
title={t`Light Grid`}
|
||||
description={t`Show Grid in white instead of black.`}
|
||||
value={isLightGrid}
|
||||
onToggle={() => dispatch(toggleLightGrid())}
|
||||
/>
|
||||
>
|
||||
{t`Show Grid in white instead of black.`}
|
||||
</SettingsItem>
|
||||
{(window.ssv && window.ssv.backupurl) && (
|
||||
<SettingsItem
|
||||
title={t`Historical View`}
|
||||
description={t`Check out past versions of the canvas.`}
|
||||
value={isHistoricalView}
|
||||
keyBind={c('keybinds').t`H`}
|
||||
onToggle={() => dispatch(toggleHistoricalView())}
|
||||
/>
|
||||
>
|
||||
{t`Check out past versions of the canvas.`}
|
||||
</SettingsItem>
|
||||
)}
|
||||
{(window.ssv && window.ssv.availableStyles) && (
|
||||
<SettingsItemSelect
|
||||
title={t`Themes`}
|
||||
description={t`How pixelplanet should look like.`}
|
||||
values={Object.keys(window.ssv.availableStyles)}
|
||||
selected={selectedStyle}
|
||||
onSelect={(style) => dispatch(selectStyle(style))}
|
||||
/>
|
||||
>
|
||||
{t`How pixelplanet should look like.`}
|
||||
</SettingsItemSelect>
|
||||
)}
|
||||
{(window.ssv && navigator.cookieEnabled && window.ssv.langs) && (
|
||||
<div style={itemStyles}>
|
||||
|
|
|
@ -7,245 +7,240 @@
|
|||
|
||||
// iPhone needs this
|
||||
const AudioContext = window.AudioContext || window.webkitAudioContext;
|
||||
const context = new AudioContext();
|
||||
const context = AudioContext && new AudioContext();
|
||||
|
||||
export default (store) => (next) => (action) => {
|
||||
const state = store.getState();
|
||||
const { mute, chatNotify } = state.audio;
|
||||
|
||||
switch (action.type) {
|
||||
case 'SELECT_COLOR': {
|
||||
if (mute) break;
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
if (!mute && context) {
|
||||
switch (action.type) {
|
||||
case 'SELECT_COLOR': {
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -600;
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -600;
|
||||
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(700, context.currentTime + 0.1);
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(700, context.currentTime + 0.1);
|
||||
|
||||
|
||||
gainNode.gain.setValueAtTime(0.3, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
gainNode.gain.setValueAtTime(0.3, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.2);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'SET_NOTIFICATION': {
|
||||
if (mute) break;
|
||||
const { notification } = action;
|
||||
if (typeof notification !== 'string') {
|
||||
break;
|
||||
}
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -1200;
|
||||
|
||||
oscillatorNode.frequency.setValueAtTime(500, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime + 0.1);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.3, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.2);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PIXEL_WAIT': {
|
||||
if (mute) break;
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
// oscillatorNode.detune.value = -600
|
||||
|
||||
oscillatorNode.frequency.setValueAtTime(1479.98, context.currentTime);
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
493.88,
|
||||
context.currentTime + 0.01,
|
||||
);
|
||||
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PIXEL_FAILURE': {
|
||||
if (mute) break;
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -900;
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
1400,
|
||||
context.currentTime + 0.025,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
1200,
|
||||
context.currentTime + 0.05,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
900,
|
||||
context.currentTime + 0.075,
|
||||
);
|
||||
|
||||
const lfo = context.createOscillator();
|
||||
lfo.type = 'sine';
|
||||
lfo.frequency.value = 2.0;
|
||||
lfo.connect(gainNode.gain);
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
lfo.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.3);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PLACED_PIXELS': {
|
||||
if (mute) break;
|
||||
const { palette, selectedColor: color } = state.canvas;
|
||||
const colorsAmount = palette.colors.length;
|
||||
|
||||
const clrFreq = 100 + Math.log(color / colorsAmount + 1) * 300;
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(clrFreq, context.currentTime);
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
1400,
|
||||
context.currentTime + 0.2,
|
||||
);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'COOLDOWN_END': {
|
||||
if (mute) break;
|
||||
|
||||
// do not play sound if last cooldown end was <5s ago
|
||||
const { lastCoolDownEnd } = state.user;
|
||||
if (lastCoolDownEnd && lastCoolDownEnd.getTime() + 5000 > Date.now()) {
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.2);
|
||||
break;
|
||||
}
|
||||
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
case 'SET_NOTIFICATION': {
|
||||
const { notification } = action;
|
||||
if (typeof notification !== 'string') {
|
||||
break;
|
||||
}
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(349.23, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
523.25,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
698.46,
|
||||
context.currentTime + 0.2,
|
||||
);
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -1200;
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.15,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(500, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime + 0.1);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
gainNode.gain.setValueAtTime(0.3, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.3);
|
||||
break;
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.2);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PIXEL_WAIT': {
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
// oscillatorNode.detune.value = -600
|
||||
|
||||
oscillatorNode.frequency.setValueAtTime(1479.98, context.currentTime);
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
493.88,
|
||||
context.currentTime + 0.01,
|
||||
);
|
||||
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PIXEL_FAILURE': {
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.detune.value = -900;
|
||||
oscillatorNode.frequency.setValueAtTime(600, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
1400,
|
||||
context.currentTime + 0.025,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
1200,
|
||||
context.currentTime + 0.05,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
900,
|
||||
context.currentTime + 0.075,
|
||||
);
|
||||
|
||||
const lfo = context.createOscillator();
|
||||
lfo.type = 'sine';
|
||||
lfo.frequency.value = 2.0;
|
||||
lfo.connect(gainNode.gain);
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
lfo.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.3);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'PLACED_PIXELS': {
|
||||
const { palette, selectedColor: color } = state.canvas;
|
||||
const colorsAmount = palette.colors.length;
|
||||
|
||||
const clrFreq = 100 + Math.log(color / colorsAmount + 1) * 300;
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(clrFreq, context.currentTime);
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
1400,
|
||||
context.currentTime + 0.2,
|
||||
);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.1);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'COOLDOWN_END': {
|
||||
// do not play sound if last cooldown end was <5s ago
|
||||
const { lastCoolDownEnd } = state.user;
|
||||
if (lastCoolDownEnd && lastCoolDownEnd.getTime() + 5000 > Date.now()) {
|
||||
break;
|
||||
}
|
||||
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(349.23, context.currentTime);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
523.25,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
oscillatorNode.frequency.setValueAtTime(
|
||||
698.46,
|
||||
context.currentTime + 0.2,
|
||||
);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.5, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.2,
|
||||
context.currentTime + 0.15,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.3);
|
||||
break;
|
||||
}
|
||||
|
||||
case 'RECEIVE_CHAT_MESSAGE': {
|
||||
if (chatNotify) break;
|
||||
|
||||
const { isPing, channel } = action;
|
||||
const { mute: muteCh, chatChannel } = state.chatRead;
|
||||
if (muteCh.includes(channel)) break;
|
||||
if (muteCh.includes(`${channel}`)) break;
|
||||
const { channels } = state.chat;
|
||||
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(310, context.currentTime);
|
||||
/*
|
||||
* ping if user mention or
|
||||
* message in DM channel that is not currently open
|
||||
*/
|
||||
const freq = (isPing
|
||||
|| (
|
||||
channels[channel]
|
||||
&& channels[channel][1] === 1
|
||||
// eslint-disable-next-line eqeqeq
|
||||
&& channel != chatChannel
|
||||
)
|
||||
) ? 540 : 355;
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
freq,
|
||||
context.currentTime + 0.025,
|
||||
);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.1, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.1,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.075);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
case 'RECEIVE_CHAT_MESSAGE': {
|
||||
if (mute || !chatNotify) break;
|
||||
|
||||
const { isPing, channel } = action;
|
||||
const { mute: muteCh, chatChannel } = state.chatRead;
|
||||
if (muteCh.includes(channel)) break;
|
||||
if (muteCh.includes(`${channel}`)) break;
|
||||
const { channels } = state.chat;
|
||||
|
||||
const oscillatorNode = context.createOscillator();
|
||||
const gainNode = context.createGain();
|
||||
|
||||
oscillatorNode.type = 'sine';
|
||||
oscillatorNode.frequency.setValueAtTime(310, context.currentTime);
|
||||
/*
|
||||
* ping if user mention or
|
||||
* message in DM channel that is not currently open
|
||||
*/
|
||||
const freq = (isPing
|
||||
|| (
|
||||
channels[channel]
|
||||
&& channels[channel][1] === 1
|
||||
// eslint-disable-next-line eqeqeq
|
||||
&& channel != chatChannel
|
||||
)
|
||||
) ? 540 : 355;
|
||||
oscillatorNode.frequency.exponentialRampToValueAtTime(
|
||||
freq,
|
||||
context.currentTime + 0.025,
|
||||
);
|
||||
|
||||
gainNode.gain.setValueAtTime(0.1, context.currentTime);
|
||||
gainNode.gain.exponentialRampToValueAtTime(
|
||||
0.1,
|
||||
context.currentTime + 0.1,
|
||||
);
|
||||
|
||||
oscillatorNode.connect(gainNode);
|
||||
gainNode.connect(context.destination);
|
||||
|
||||
oscillatorNode.start();
|
||||
oscillatorNode.stop(context.currentTime + 0.075);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
// nothing
|
||||
}
|
||||
|
||||
return next(action);
|
||||
|
|
|
@ -57,6 +57,10 @@ a:hover {
|
|||
font-weight: bold;
|
||||
}
|
||||
|
||||
.warn {
|
||||
color: #e53737;
|
||||
}
|
||||
|
||||
.modallink {
|
||||
text-decoration: none;
|
||||
color: #428bca;
|
||||
|
|
Loading…
Reference in New Issue
Block a user