Update colours and sizing for voice messages

Fixes https://github.com/vector-im/element-web/issues/17162
This commit is contained in:
Travis Ralston 2021-05-04 20:45:15 -06:00
parent 2bf931b9d3
commit a94c1a90c1
9 changed files with 45 additions and 40 deletions

View file

@ -39,7 +39,7 @@ limitations under the License.
width: 14px; // w&h are size of icon width: 14px; // w&h are size of icon
height: 18px; height: 18px;
vertical-align: middle; vertical-align: middle;
margin-right: 7px; // distance from left edge of waveform container (container has some margin too) margin-right: 11px; // distance from left edge of waveform container (container has some margin too)
background-color: $voice-record-icon-color; background-color: $voice-record-icon-color;
mask-repeat: no-repeat; mask-repeat: no-repeat;
mask-size: contain; mask-size: contain;
@ -55,7 +55,9 @@ limitations under the License.
position: relative; // important for the live circle position: relative; // important for the live circle
&.mx_VoiceRecordComposerTile_recording { &.mx_VoiceRecordComposerTile_recording {
padding-left: 16px; // +10px for the live circle, +6px for regular padding // We are putting the circle in this padding, so we need +10px from the regular
// padding on the left side.
padding-left: 22px;
&::before { &::before {
animation: recording-pulse 2s infinite; animation: recording-pulse 2s infinite;
@ -65,8 +67,8 @@ limitations under the License.
width: 10px; width: 10px;
height: 10px; height: 10px;
position: absolute; position: absolute;
left: 8px; left: 12px; // 12px from the left edge for container padding
top: 16px; // vertically center top: 18px; // vertically center (middle align with clock)
border-radius: 10px; border-radius: 10px;
} }
} }

View file

@ -19,8 +19,9 @@ limitations under the License.
// Container for live recording and playback controls // Container for live recording and playback controls
.mx_VoiceMessagePrimaryContainer { .mx_VoiceMessagePrimaryContainer {
padding: 6px; // makes us 4px taller than the send/stop button // 7px top and bottom for visual design. 12px left & right, but the waveform (right)
padding-right: 5px; // there's 1px from the waveform itself, so account for that // has a 1px padding on it that we want to account for.
padding: 7px 12px 7px 11px;
background-color: $voice-record-waveform-bg-color; background-color: $voice-record-waveform-bg-color;
border-radius: 12px; border-radius: 12px;
@ -30,11 +31,9 @@ limitations under the License.
color: $voice-record-waveform-fg-color; color: $voice-record-waveform-fg-color;
font-size: $font-14px; font-size: $font-14px;
line-height: $font-24px;
.mx_Waveform { .mx_Waveform {
// We want the bars to be 2px shorter than the play/pause button in the waveform control
height: 28px; // default is 30px, so we're subtracting the 2px border off the bars
.mx_Waveform_bar { .mx_Waveform_bar {
background-color: $voice-record-waveform-incomplete-fg-color; background-color: $voice-record-waveform-incomplete-fg-color;
@ -47,8 +46,8 @@ limitations under the License.
} }
.mx_Clock { .mx_Clock {
padding-right: 4px; // isolate from waveform width: 42px; // we're not using a monospace font, so fake it
padding-left: 8px; // isolate from live circle padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended.
width: 40px; // we're not using a monospace font, so fake it padding-left: 8px; // isolate from recording circle / play control
} }
} }

View file

@ -42,13 +42,13 @@ $preview-bar-bg-color: $header-panel-bg-color;
$groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82); $groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82);
$inverted-bg-color: $base-color; $inverted-bg-color: $base-color;
$voice-record-stop-border-color: #6F7882; // "Quarterly" $voice-record-stop-border-color: #6F7882; // "Quartary"
$voice-record-waveform-bg-color: #394049; // "Dark Tile" $voice-record-waveform-bg-color: #394049; // "Dark Tile"
$voice-record-waveform-fg-color: $tertiary-fg-color; $voice-record-waveform-fg-color: $secondary-fg-color;
$voice-record-waveform-incomplete-fg-color: #5b646d; $voice-record-waveform-incomplete-fg-color: #6F7882; // "Quartary"
$voice-record-icon-color: $tertiary-fg-color; $voice-record-icon-color: #6F7882; // "Quartary"
$voice-playback-button-bg-color: $tertiary-fg-color; $voice-playback-button-bg-color: $tertiary-fg-color;
$voice-playback-button-fg-color: $bg-color; $voice-playback-button-fg-color: #21262C; // "Separator"
// used by AddressSelector // used by AddressSelector
$selected-color: $room-highlight-color; $selected-color: $room-highlight-color;

View file

@ -127,11 +127,11 @@ $groupFilterPanel-divider-color: $roomlist-header-color;
// See non-legacy dark for variable information // See non-legacy dark for variable information
$voice-record-stop-border-color: #6F7882; $voice-record-stop-border-color: #6F7882;
$voice-record-waveform-bg-color: #394049; $voice-record-waveform-bg-color: #394049;
$voice-record-waveform-fg-color: $tertiary-fg-color; $voice-record-waveform-fg-color: $secondary-fg-color;
$voice-record-waveform-incomplete-fg-color: #5b646d; $voice-record-waveform-incomplete-fg-color: #6F7882;
$voice-record-icon-color: $tertiary-fg-color; $voice-record-icon-color: #6F7882;
$voice-playback-button-bg-color: $tertiary-fg-color; $voice-playback-button-bg-color: $tertiary-fg-color;
$voice-playback-button-fg-color: $bg-color; $voice-playback-button-fg-color: #21262C;
$roomtile-preview-color: #9e9e9e; $roomtile-preview-color: #9e9e9e;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;

View file

@ -192,15 +192,15 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%)
$groupFilterPanel-divider-color: $roomlist-header-color; $groupFilterPanel-divider-color: $roomlist-header-color;
// See non-legacy _light for variable information // See non-legacy _light for variable information
$voice-record-stop-border-color: #E3E8F0;
$voice-record-stop-symbol-color: #ff4b55; $voice-record-stop-symbol-color: #ff4b55;
$voice-record-waveform-bg-color: #E3E8F0;
$voice-record-waveform-fg-color: $muted-fg-color;
$voice-record-waveform-incomplete-fg-color: #C1C6CD;
$voice-record-live-circle-color: #ff4b55; $voice-record-live-circle-color: #ff4b55;
$voice-record-icon-color: $muted-fg-color; $voice-record-stop-border-color: #E3E8F0;
$voice-record-waveform-bg-color: #E3E8F0;
$voice-record-waveform-fg-color: $secondary-fg-color;
$voice-record-waveform-incomplete-fg-color: #C1C6CD;
$voice-record-icon-color: $tertiary-fg-color;
$voice-playback-button-bg-color: $primary-bg-color; $voice-playback-button-bg-color: $primary-bg-color;
$voice-playback-button-fg-color: $muted-fg-color; $voice-playback-button-fg-color: $secondary-fg-color;
$roomtile-preview-color: #9e9e9e; $roomtile-preview-color: #9e9e9e;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;

View file

@ -182,15 +182,18 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%)
$groupFilterPanel-divider-color: $roomlist-header-color; $groupFilterPanel-divider-color: $roomlist-header-color;
$voice-record-stop-border-color: #E3E8F0; // These two don't change between themes. They are the $warning-color, but we don't
$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes // want custom themes to affect them by accident.
$voice-record-waveform-bg-color: #E3E8F0; $voice-record-stop-symbol-color: #ff4b55;
$voice-record-waveform-fg-color: $muted-fg-color; $voice-record-live-circle-color: #ff4b55;
$voice-record-waveform-incomplete-fg-color: #C1C6CD;
$voice-record-live-circle-color: #ff4b55; // $warning-color, but without letting people change it in themes $voice-record-stop-border-color: #E3E8F0; // "Separator"
$voice-record-icon-color: $muted-fg-color; $voice-record-waveform-bg-color: #E3E8F0; // "Separator"
$voice-record-waveform-fg-color: $secondary-fg-color;
$voice-record-waveform-incomplete-fg-color: #C1C6CD; // "Quartary"
$voice-record-icon-color: $tertiary-fg-color;
$voice-playback-button-bg-color: $primary-bg-color; $voice-playback-button-bg-color: $primary-bg-color;
$voice-playback-button-fg-color: $muted-fg-color; $voice-playback-button-fg-color: $secondary-fg-color;
$roomtile-preview-color: $secondary-fg-color; $roomtile-preview-color: $secondary-fg-color;
$roomtile-default-badge-bg-color: #61708b; $roomtile-default-badge-bg-color: #61708b;

View file

@ -15,12 +15,11 @@ limitations under the License.
*/ */
import React from "react"; import React from "react";
import {IRecordingUpdate, VoiceRecording} from "../../../voice/VoiceRecording"; import {IRecordingUpdate, RECORDING_PLAYBACK_SAMPLES, VoiceRecording} from "../../../voice/VoiceRecording";
import {replaceableComponent} from "../../../utils/replaceableComponent"; import {replaceableComponent} from "../../../utils/replaceableComponent";
import {arrayFastResample, arraySeed} from "../../../utils/arrays"; import {arrayFastResample, arraySeed} from "../../../utils/arrays";
import {percentageOf} from "../../../utils/numbers"; import {percentageOf} from "../../../utils/numbers";
import Waveform from "./Waveform"; import Waveform from "./Waveform";
import {PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback";
interface IProps { interface IProps {
recorder: VoiceRecording; recorder: VoiceRecording;
@ -38,14 +37,14 @@ export default class LiveRecordingWaveform extends React.PureComponent<IProps, I
public constructor(props) { public constructor(props) {
super(props); super(props);
this.state = {heights: arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES)}; this.state = {heights: arraySeed(0, RECORDING_PLAYBACK_SAMPLES)};
this.props.recorder.liveData.onUpdate(this.onRecordingUpdate); this.props.recorder.liveData.onUpdate(this.onRecordingUpdate);
} }
private onRecordingUpdate = (update: IRecordingUpdate) => { private onRecordingUpdate = (update: IRecordingUpdate) => {
// The waveform and the downsample target are pretty close, so we should be fine to // The waveform and the downsample target are pretty close, so we should be fine to
// do this, despite the docs on arrayFastResample. // do this, despite the docs on arrayFastResample.
const bars = arrayFastResample(Array.from(update.waveform), PLAYBACK_WAVEFORM_SAMPLES); const bars = arrayFastResample(Array.from(update.waveform), RECORDING_PLAYBACK_SAMPLES);
this.setState({ this.setState({
// The incoming data is between zero and one, but typically even screaming into a // The incoming data is between zero and one, but typically even screaming into a
// microphone won't send you over 0.6, so we artificially adjust the gain for the // microphone won't send you over 0.6, so we artificially adjust the gain for the

View file

@ -29,7 +29,7 @@ export enum PlaybackState {
Playing = "playing", // active progress through timeline Playing = "playing", // active progress through timeline
} }
export const PLAYBACK_WAVEFORM_SAMPLES = 35; export const PLAYBACK_WAVEFORM_SAMPLES = 38;
const DEFAULT_WAVEFORM = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES); const DEFAULT_WAVEFORM = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES);
export class Playback extends EventEmitter implements IDestroyable { export class Playback extends EventEmitter implements IDestroyable {

View file

@ -33,6 +33,8 @@ const BITRATE = 24000; // 24kbps is pretty high quality for our use case in opus
const TARGET_MAX_LENGTH = 120; // 2 minutes in seconds. Somewhat arbitrary, though longer == larger files. const TARGET_MAX_LENGTH = 120; // 2 minutes in seconds. Somewhat arbitrary, though longer == larger files.
const TARGET_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary. const TARGET_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary.
export const RECORDING_PLAYBACK_SAMPLES = 43;
export interface IRecordingUpdate { export interface IRecordingUpdate {
waveform: number[]; // floating points between 0 (low) and 1 (high). waveform: number[]; // floating points between 0 (low) and 1 (high).
timeSeconds: number; // float timeSeconds: number; // float