Merge pull request #5970 from matrix-org/travis/voicemessages/colors
Update colours and sizing for voice messages
This commit is contained in:
commit
3e1265b9bb
9 changed files with 48 additions and 41 deletions
|
@ -39,14 +39,14 @@ limitations under the License.
|
|||
width: 14px; // w&h are size of icon
|
||||
height: 18px;
|
||||
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;
|
||||
mask-repeat: no-repeat;
|
||||
mask-size: contain;
|
||||
mask-image: url('$(res)/img/element-icons/trashcan.svg');
|
||||
}
|
||||
|
||||
.mx_VoiceMessagePrimaryContainer {
|
||||
.mx_VoiceRecordComposerTile_recording.mx_VoiceMessagePrimaryContainer {
|
||||
// Note: remaining class properties are in the PlayerContainer CSS.
|
||||
|
||||
margin: 6px; // force the composer area to put a gutter around us
|
||||
|
@ -55,7 +55,9 @@ limitations under the License.
|
|||
position: relative; // important for the live circle
|
||||
|
||||
&.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 {
|
||||
animation: recording-pulse 2s infinite;
|
||||
|
@ -65,8 +67,8 @@ limitations under the License.
|
|||
width: 10px;
|
||||
height: 10px;
|
||||
position: absolute;
|
||||
left: 8px;
|
||||
top: 16px; // vertically center
|
||||
left: 12px; // 12px from the left edge for container padding
|
||||
top: 18px; // vertically center (middle align with clock)
|
||||
border-radius: 10px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,8 +19,9 @@ limitations under the License.
|
|||
|
||||
// Container for live recording and playback controls
|
||||
.mx_VoiceMessagePrimaryContainer {
|
||||
padding: 6px; // makes us 4px taller than the send/stop button
|
||||
padding-right: 5px; // there's 1px from the waveform itself, so account for that
|
||||
// 7px top and bottom for visual design. 12px left & right, but the waveform (right)
|
||||
// has a 1px padding on it that we want to account for.
|
||||
padding: 7px 12px 7px 11px;
|
||||
background-color: $voice-record-waveform-bg-color;
|
||||
border-radius: 12px;
|
||||
|
||||
|
@ -30,11 +31,9 @@ limitations under the License.
|
|||
|
||||
color: $voice-record-waveform-fg-color;
|
||||
font-size: $font-14px;
|
||||
line-height: $font-24px;
|
||||
|
||||
.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 {
|
||||
background-color: $voice-record-waveform-incomplete-fg-color;
|
||||
|
||||
|
@ -47,8 +46,8 @@ limitations under the License.
|
|||
}
|
||||
|
||||
.mx_Clock {
|
||||
padding-right: 4px; // isolate from waveform
|
||||
padding-left: 8px; // isolate from live circle
|
||||
width: 40px; // we're not using a monospace font, so fake it
|
||||
width: 42px; // we're not using a monospace font, so fake it
|
||||
padding-right: 6px; // with the fixed width this ends up as a visual 8px most of the time, as intended.
|
||||
padding-left: 8px; // isolate from recording circle / play control
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ $header-panel-text-primary-color: #B9BEC6;
|
|||
$header-panel-text-secondary-color: #c8c8cd;
|
||||
$text-primary-color: #ffffff;
|
||||
$text-secondary-color: #B9BEC6;
|
||||
$quaternary-fg-color: #6F7882;
|
||||
$search-bg-color: #181b21;
|
||||
$search-placeholder-color: #61708b;
|
||||
$room-highlight-color: #343a46;
|
||||
|
@ -42,13 +43,13 @@ $preview-bar-bg-color: $header-panel-bg-color;
|
|||
$groupFilterPanel-bg-color: rgba(38, 39, 43, 0.82);
|
||||
$inverted-bg-color: $base-color;
|
||||
|
||||
$voice-record-stop-border-color: #6F7882; // "Quarterly"
|
||||
$voice-record-stop-border-color: $quaternary-fg-color;
|
||||
$voice-record-waveform-bg-color: #394049; // "Dark Tile"
|
||||
$voice-record-waveform-fg-color: $tertiary-fg-color;
|
||||
$voice-record-waveform-incomplete-fg-color: #5b646d;
|
||||
$voice-record-icon-color: $tertiary-fg-color;
|
||||
$voice-record-waveform-fg-color: $secondary-fg-color;
|
||||
$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color;
|
||||
$voice-record-icon-color: $quaternary-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
|
||||
$selected-color: $room-highlight-color;
|
||||
|
|
|
@ -127,11 +127,11 @@ $groupFilterPanel-divider-color: $roomlist-header-color;
|
|||
// See non-legacy dark for variable information
|
||||
$voice-record-stop-border-color: #6F7882;
|
||||
$voice-record-waveform-bg-color: #394049;
|
||||
$voice-record-waveform-fg-color: $tertiary-fg-color;
|
||||
$voice-record-waveform-incomplete-fg-color: #5b646d;
|
||||
$voice-record-icon-color: $tertiary-fg-color;
|
||||
$voice-record-waveform-fg-color: $secondary-fg-color;
|
||||
$voice-record-waveform-incomplete-fg-color: #6F7882;
|
||||
$voice-record-icon-color: #6F7882;
|
||||
$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-default-badge-bg-color: #61708b;
|
||||
|
|
|
@ -192,15 +192,15 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%)
|
|||
$groupFilterPanel-divider-color: $roomlist-header-color;
|
||||
|
||||
// See non-legacy _light for variable information
|
||||
$voice-record-stop-border-color: #E3E8F0;
|
||||
$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-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-fg-color: $muted-fg-color;
|
||||
$voice-playback-button-fg-color: $secondary-fg-color;
|
||||
|
||||
$roomtile-preview-color: #9e9e9e;
|
||||
$roomtile-default-badge-bg-color: #61708b;
|
||||
|
|
|
@ -21,6 +21,7 @@ $notice-primary-bg-color: rgba(255, 75, 85, 0.16);
|
|||
$primary-fg-color: #2e2f32;
|
||||
$secondary-fg-color: #737D8C;
|
||||
$tertiary-fg-color: #8D99A5;
|
||||
$quaternary-fg-color: #C1C6CD;
|
||||
$header-panel-bg-color: #f3f8fd;
|
||||
|
||||
// typical text (dark-on-white in light skin)
|
||||
|
@ -182,15 +183,18 @@ $roomsublist-skeleton-ui-bg: linear-gradient(180deg, #ffffff 0%, #ffffff00 100%)
|
|||
|
||||
$groupFilterPanel-divider-color: $roomlist-header-color;
|
||||
|
||||
$voice-record-stop-border-color: #E3E8F0;
|
||||
$voice-record-stop-symbol-color: #ff4b55; // $warning-color, but without letting people change it in themes
|
||||
$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; // $warning-color, but without letting people change it in themes
|
||||
$voice-record-icon-color: $muted-fg-color;
|
||||
// These two don't change between themes. They are the $warning-color, but we don't
|
||||
// want custom themes to affect them by accident.
|
||||
$voice-record-stop-symbol-color: #ff4b55;
|
||||
$voice-record-live-circle-color: #ff4b55;
|
||||
|
||||
$voice-record-stop-border-color: #E3E8F0; // "Separator"
|
||||
$voice-record-waveform-bg-color: #E3E8F0; // "Separator"
|
||||
$voice-record-waveform-fg-color: $secondary-fg-color;
|
||||
$voice-record-waveform-incomplete-fg-color: $quaternary-fg-color;
|
||||
$voice-record-icon-color: $tertiary-fg-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-default-badge-bg-color: #61708b;
|
||||
|
|
|
@ -15,12 +15,11 @@ limitations under the License.
|
|||
*/
|
||||
|
||||
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 {arrayFastResample, arraySeed} from "../../../utils/arrays";
|
||||
import {percentageOf} from "../../../utils/numbers";
|
||||
import Waveform from "./Waveform";
|
||||
import {PLAYBACK_WAVEFORM_SAMPLES} from "../../../voice/Playback";
|
||||
|
||||
interface IProps {
|
||||
recorder: VoiceRecording;
|
||||
|
@ -38,14 +37,14 @@ export default class LiveRecordingWaveform extends React.PureComponent<IProps, I
|
|||
public constructor(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);
|
||||
}
|
||||
|
||||
private onRecordingUpdate = (update: IRecordingUpdate) => {
|
||||
// The waveform and the downsample target are pretty close, so we should be fine to
|
||||
// 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({
|
||||
// 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
|
||||
|
|
|
@ -29,7 +29,7 @@ export enum PlaybackState {
|
|||
Playing = "playing", // active progress through timeline
|
||||
}
|
||||
|
||||
export const PLAYBACK_WAVEFORM_SAMPLES = 35;
|
||||
export const PLAYBACK_WAVEFORM_SAMPLES = 39;
|
||||
const DEFAULT_WAVEFORM = arraySeed(0, PLAYBACK_WAVEFORM_SAMPLES);
|
||||
|
||||
export class Playback extends EventEmitter implements IDestroyable {
|
||||
|
|
|
@ -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_WARN_TIME_LEFT = 10; // 10 seconds, also somewhat arbitrary.
|
||||
|
||||
export const RECORDING_PLAYBACK_SAMPLES = 44;
|
||||
|
||||
export interface IRecordingUpdate {
|
||||
waveform: number[]; // floating points between 0 (low) and 1 (high).
|
||||
timeSeconds: number; // float
|
||||
|
|
Loading…
Reference in a new issue