diff --git a/ACKNOWLEDGMENTS.md b/ACKNOWLEDGMENTS.md
index 19b4d8545876..df1b48ce5cce 100644
--- a/ACKNOWLEDGMENTS.md
+++ b/ACKNOWLEDGMENTS.md
@@ -5,55 +5,6 @@
Signal Desktop makes use of the following open source projects.
-## @evanhahn/lottie-web-light
-
- The MIT License (MIT)
-
- Copyright (c) 2022 Evan Hahn
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-
- ************
-
- Original lottie-web license:
- The MIT License (MIT)
-
- Copyright (c) 2015 Bodymovin
-
- Permission is hereby granted, free of charge, to any person obtaining a copy
- of this software and associated documentation files (the "Software"), to deal
- in the Software without restriction, including without limitation the rights
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- copies of the Software, and to permit persons to whom the Software is
- furnished to do so, subject to the following conditions:
-
- The above copyright notice and this permission notice shall be included in all
- copies or substantial portions of the Software.
-
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- SOFTWARE.
-
## @popperjs/core
License: MIT
diff --git a/package.json b/package.json
index a86db026612a..713317cbae7d 100644
--- a/package.json
+++ b/package.json
@@ -77,7 +77,6 @@
"fs-xattr": "0.3.0"
},
"dependencies": {
- "@evanhahn/lottie-web-light": "5.8.1",
"@popperjs/core": "2.9.2",
"@react-spring/web": "9.4.1",
"@signalapp/libsignal-client": "0.16.0",
diff --git a/stylesheets/components/CallingAudioIndicator.scss b/stylesheets/components/CallingAudioIndicator.scss
index ea6e54fcb2ed..650095499767 100644
--- a/stylesheets/components/CallingAudioIndicator.scss
+++ b/stylesheets/components/CallingAudioIndicator.scss
@@ -18,15 +18,15 @@
}
&__content {
- $size: 16px;
+ $size: 14px;
width: $size;
height: $size;
+ /* Center Lottie animation */
+ display: flex;
+ align-items: center;
+ justify-content: center;
&--muted {
- $size: 14px;
- width: $size;
- height: $size;
-
@include color-svg(
'../images/icons/v2/mic-off-solid-28.svg',
$color-white
diff --git a/ts/components/CallingAudioIndicator.stories.tsx b/ts/components/CallingAudioIndicator.stories.tsx
index 08a0e0a20395..bacf97d764e9 100644
--- a/ts/components/CallingAudioIndicator.stories.tsx
+++ b/ts/components/CallingAudioIndicator.stories.tsx
@@ -1,17 +1,53 @@
// Copyright 2022 Signal Messenger, LLC
// SPDX-License-Identifier: AGPL-3.0-only
-import React from 'react';
+import React, { useState, useEffect } from 'react';
import { storiesOf } from '@storybook/react';
-import { boolean, select } from '@storybook/addon-knobs';
+import { boolean } from '@storybook/addon-knobs';
import { CallingAudioIndicator } from './CallingAudioIndicator';
+import { AUDIO_LEVEL_INTERVAL_MS } from '../calling/constants';
const story = storiesOf('Components/CallingAudioIndicator', module);
-story.add('Default', () => (
-
-));
+story.add('Extreme', () => {
+ const [audioLevel, setAudioLevel] = useState(1);
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setAudioLevel(1 - audioLevel);
+ }, 2 * AUDIO_LEVEL_INTERVAL_MS);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [audioLevel, setAudioLevel]);
+
+ return (
+
+ );
+});
+
+story.add('Random', () => {
+ const [audioLevel, setAudioLevel] = useState(1);
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ setAudioLevel(Math.random());
+ }, AUDIO_LEVEL_INTERVAL_MS);
+
+ return () => {
+ clearTimeout(timer);
+ };
+ }, [audioLevel, setAudioLevel]);
+
+ return (
+
+ );
+});
diff --git a/ts/components/CallingAudioIndicator.tsx b/ts/components/CallingAudioIndicator.tsx
index 179c0fe53938..cac86276956c 100644
--- a/ts/components/CallingAudioIndicator.tsx
+++ b/ts/components/CallingAudioIndicator.tsx
@@ -4,7 +4,7 @@
import classNames from 'classnames';
import { noop } from 'lodash';
import type { ReactElement } from 'react';
-import React, { useEffect, useCallback, useState } from 'react';
+import React, { useEffect, useState } from 'react';
import { useSpring, animated } from '@react-spring/web';
import { AUDIO_LEVEL_INTERVAL_MS } from '../calling/constants';
@@ -20,11 +20,11 @@ const SIDE_SCALE_FACTOR = 0.75;
const MAX_CENTRAL_BAR_DELTA = 9;
/* Should match css */
-const CONTENT_WIDTH = 16;
-const CONTENT_HEIGHT = 16;
+const CONTENT_WIDTH = 14;
+const CONTENT_HEIGHT = 14;
const BAR_WIDTH = 2;
-const CONTENT_PADDING = 2;
+const CONTENT_PADDING = 1;
enum BarPosition {
Left,
@@ -37,13 +37,15 @@ function generateBarPath(position: BarPosition, audioLevel: number): string {
if (position === BarPosition.Left) {
x = CONTENT_PADDING;
} else if (position === BarPosition.Center) {
- x = CONTENT_WIDTH / 2 - CONTENT_PADDING + BAR_WIDTH / 2;
+ x = CONTENT_WIDTH / 2 - BAR_WIDTH / 2;
} else if (position === BarPosition.Right) {
x = CONTENT_WIDTH - CONTENT_PADDING - BAR_WIDTH;
} else {
throw missingCaseError(position);
}
+ x = Math.round(x);
+
let height: number;
if (position === BarPosition.Left || position === BarPosition.Right) {
height =
@@ -58,37 +60,34 @@ function generateBarPath(position: BarPosition, audioLevel: number): string {
height -= 2;
const y = (CONTENT_HEIGHT - height) / 2;
- const top = y;
- const bottom = top + height;
+ const left = x;
+ const right = x + BAR_WIDTH;
+ const top = y.toFixed(2);
+ const bottom = (y + height).toFixed(2);
return (
- `M ${x} ${top} ` +
- `L ${x} ${bottom} ` +
- `A 0.5 0.5 0 0 0 ${x + BAR_WIDTH} ${bottom} ` +
- `L ${x + BAR_WIDTH} ${top} ` +
- `A 0.5 0.5 0 0 0 ${x} ${top}`
+ `M ${left} ${top} ` +
+ `L ${left} ${bottom} ` +
+ `A 0.5 0.5 0 0 0 ${right} ${bottom} ` +
+ `L ${right} ${top} ` +
+ `A 0.5 0.5 0 0 0 ${left} ${top}`
);
}
-function Bar({
- position,
- audioLevel,
-}: {
- position: BarPosition;
- audioLevel: number;
-}): ReactElement {
+function generateCombinedPath(audioLevel: number): string {
+ return (
+ `${generateBarPath(BarPosition.Left, audioLevel)} ` +
+ `${generateBarPath(BarPosition.Center, audioLevel)} ` +
+ `${generateBarPath(BarPosition.Right, audioLevel)} `
+ );
+}
+
+function Bars({ audioLevel }: { audioLevel: number }): ReactElement {
const animatedProps = useSpring({
from: { audioLevel: 0 },
config: { duration: AUDIO_LEVEL_INTERVAL_MS },
});
- const levelToPath = useCallback(
- (animatedLevel: number): string => {
- return generateBarPath(position, animatedLevel);
- },
- [position]
- );
-
useEffect(() => {
animatedProps.audioLevel.stop();
animatedProps.audioLevel.start(audioLevel);
@@ -96,7 +95,7 @@ function Bar({
return (
);
@@ -148,10 +147,15 @@ export function CallingAudioIndicator({
`${BASE_CLASS_NAME}--with-content`
)}
>
-