Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: LEAP-1893: LEAP-1900: Add setting to toggle region looping and autoplay #7166

Open
wants to merge 7 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
margin-top: 10px;
padding: 2px 0;
border-top: 1px solid var(--sand_200);
font-size: 16px;
font-size: 14px;
cursor: pointer;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,19 @@
left: 0;
top: 36px;
position: absolute;
width: 232px;
width: 260px;
background: var(--sand_0);
border-radius: 4px;
padding: 22px 0 0;
padding: 12px 0 0;
box-shadow: 0 4px 10px 0 var(--sand_300);
z-index: 10;
}

&__toggle {
padding: 8px 16px;
font-size: 12px;
}

&__range {
margin: 0 20px;
width: calc(100% - 40px);
Expand All @@ -23,7 +28,7 @@
margin-top: 10px;
padding: 2px 0;
border-top: 1px solid var(--sand_200);
font-size: 16px;
font-size: 14px;
cursor: pointer;
}

Expand Down
25 changes: 23 additions & 2 deletions web/libs/editor/src/components/Timeline/Controls/ConfigControl.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
import type React from "react";
import { type FC, type MouseEvent, useEffect, useState } from "react";
import { type FC, type MouseEvent, useContext, useEffect, useState } from "react";
import { Toggle } from "@humansignal/ui";
import { Block, Elem } from "../../../utils/bem";

import "./ConfigControl.scss";
import { IconConfig } from "../../../assets/icons/timeline";
import { TimelineContext } from "../Context";
import { ControlButton } from "../Controls";
import { Slider } from "./Slider";
import "./ConfigControl.scss";

const MAX_SPEED = 2.5;
const MAX_ZOOM = 150;
Expand Down Expand Up @@ -36,6 +38,7 @@ export const ConfigControl: FC<ConfigControlProps> = ({
const playbackSpeed = speed ?? 1;
const [isTimeline, setTimeline] = useState(true);
const [isAudioWave, setAudioWave] = useState(true);
const { settings, changeSetting } = useContext(TimelineContext);

useEffect(() => {
if (layerVisibility) {
Expand Down Expand Up @@ -105,6 +108,24 @@ export const ConfigControl: FC<ConfigControlProps> = ({
info={"Increase or decrease the appearance of amplitude"}
onChange={handleChangeAmp}
/>
<Elem name="toggle">
<Toggle
checked={settings?.loopRegion}
onChange={(e) => changeSetting?.("loopRegion", e.target.checked)}
label="Loop Regions"
// there are no "normal" size, so that's the hack to reset size
labelProps={{ size: "normal" }}
/>
</Elem>
<Elem name="toggle">
<Toggle
checked={settings?.autoPlayNewSegments}
onChange={(e) => changeSetting?.("autoPlayNewSegments", e.target.checked)}
label="Auto-play New Regions"
// there are no "normal" size, so that's the hack to reset size
labelProps={{ size: "normal" }}
/>
</Elem>
{renderLayerToggles()}
</Elem>
);
Expand Down
28 changes: 0 additions & 28 deletions web/libs/editor/src/components/Timeline/Controls/Info.scss

This file was deleted.

18 changes: 0 additions & 18 deletions web/libs/editor/src/components/Timeline/Controls/Info.tsx

This file was deleted.

11 changes: 8 additions & 3 deletions web/libs/editor/src/components/Timeline/Controls/Slider.scss
Original file line number Diff line number Diff line change
Expand Up @@ -19,17 +19,22 @@
}

&__control {
padding: 0 16px;
margin-top: 10px;
padding: 4px 16px 8px;
display: flex;
flex-wrap: wrap;
justify-content: space-between;
align-items: center;
font-size: 11px;
font-size: 14px;
}

&__info {
display: flex;
align-items: center;
gap: 8px;

svg {
display: block;
}
}

&__input {
Expand Down
9 changes: 7 additions & 2 deletions web/libs/editor/src/components/Timeline/Controls/Slider.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
import type React from "react";
import { type FC, useEffect, useRef, useState } from "react";
import { IconInfoConfig } from "../../../assets/icons/timeline";
import { Tooltip } from "../../../common/Tooltip/Tooltip";
import { Block, Elem } from "../../../utils/bem";

import "./Slider.scss";
import { Info } from "./Info";

export interface SliderProps {
description?: string;
Expand Down Expand Up @@ -59,7 +60,11 @@ export const Slider: FC<SliderProps> = ({ description, info, max, min, value, st
<Elem name="control">
<Elem name="info">
{description}
{info && <Info text={info} />}
{info && (
<Tooltip title={info}>
<IconInfoConfig />
</Tooltip>
)}
</Elem>
<Elem
name="input"
Expand Down
3 changes: 3 additions & 0 deletions web/libs/editor/src/components/Timeline/Types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,6 +109,7 @@ export interface TimelineContextValue {
visibleWidth: number;
seekOffset: number;
settings?: TimelineSettings;
changeSetting?: (key: string, value: any) => void;
data?: any;
}

Expand All @@ -131,6 +132,8 @@ export type TimelineSettings = {
fastTravelSize?: TimelineStepFunction;
stepSize?: TimelineStepFunction;
leftOffset?: number;
loopRegion?: boolean;
autoPlayNewSegments?: boolean;
};

export type TimelineStepFunction = (
Expand Down
17 changes: 13 additions & 4 deletions web/libs/editor/src/lib/AudioUltra/Controls/Player.ts
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,7 @@ export abstract class Player extends Destructable {

protected abstract playAudio(start?: number, duration?: number): void;

// This function just sets up the playing, but doesn't actually play
protected playSelection(from?: number, to?: number) {
const selected = this.wf.regions.selected;

Expand All @@ -262,7 +263,11 @@ export abstract class Player extends Destructable {
const regionsStart = Math.min(...selected.map((r) => r.start));
const regionsEnd = Math.max(...selected.map((r) => r.end));

const start = clamp(this.currentTime, regionsStart, regionsEnd);
// if we are outside of the selected region, start at the beginning
let start = this.currentTime;
if (start < regionsStart || start >= regionsEnd) {
start = regionsStart;
}

this.loop = { start: regionsStart, end: regionsEnd };

Expand Down Expand Up @@ -320,9 +325,13 @@ export abstract class Player extends Destructable {
protected updateLoop(time: number) {
if (this.isDestroyed || !this.loop) return;
if (time >= this.loop.end) {
this.currentTime = this.loop.start;
this.playing = false;
this.play();
if (this.wf.settings.loopRegion) {
this.currentTime = this.loop.start;
this.playing = false;
this.play();
} else {
this.pause();
}
}
}

Expand Down
10 changes: 8 additions & 2 deletions web/libs/editor/src/lib/AudioUltra/Regions/Regions.ts
Original file line number Diff line number Diff line change
Expand Up @@ -309,7 +309,10 @@ export class Regions {

const addRegion = () => {
const { container, zoomedWidth, fullWidth } = this.visualizer;
const { autoPlayNewSegments, duration } = this.waveform;
const {
settings: { autoPlayNewSegments },
duration,
} = this.waveform;
const scrollLeft = this.visualizer.getScrollLeftPx();

startX = clamp(getCursorPositionX(e, container) + scrollLeft, 0, fullWidth);
Expand Down Expand Up @@ -352,7 +355,10 @@ export class Regions {
};

const handleMouseUp = () => {
const { player, autoPlayNewSegments } = this.waveform;
const {
player,
settings: { autoPlayNewSegments },
} = this.waveform;

document.removeEventListener("mousemove", handleMouseMove);
document.removeEventListener("mouseup", handleMouseUp);
Expand Down
9 changes: 4 additions & 5 deletions web/libs/editor/src/lib/AudioUltra/Waveform.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import type { TimelineSettings } from "../../components/Timeline/Types";
import { Events } from "./Common/Events";
import { MediaLoader } from "./Media/MediaLoader";
import type { Player } from "./Controls/Player";
Expand Down Expand Up @@ -138,8 +139,6 @@ export interface WaveformOptions {

padding?: Padding;

autoPlayNewSegments?: boolean;

// Cursor options
cursor?: CursorOptions;

Expand Down Expand Up @@ -201,7 +200,9 @@ export class Waveform extends Events<WaveformEventTypes> {
regions!: Regions;
loaded = false;
renderedChannels = false;
autoPlayNewSegments = false;
// for now that's just an object to store setting and access them when needed;
// but if we need to react on changes we can convert it into getter/setter.
settings: TimelineSettings = {};

constructor(params: WaveformOptions) {
super();
Expand Down Expand Up @@ -254,8 +255,6 @@ export class Waveform extends Events<WaveformEventTypes> {
this.visualizer,
);

this.autoPlayNewSegments = this.params.autoPlayNewSegments ?? this.autoPlayNewSegments;

this.player = this.params.playerType === "html5" ? new Html5Player(this) : new WebAudioPlayer(this);

this.initEvents();
Expand Down
9 changes: 8 additions & 1 deletion web/libs/editor/src/lib/AudioUltra/react/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { type MutableRefObject, useEffect, useMemo, useRef, useState } from "react";
import { type MutableRefObject, useContext, useEffect, useMemo, useRef, useState } from "react";

import { TimelineContext } from "../../../components/Timeline/Context";
import { isTimeRelativelySimilar } from "../Common/Utils";
import type { Layer } from "../Visual/Layer";
import { Waveform, type WaveformFrameState, type WaveformOptions } from "../Waveform";
Expand Down Expand Up @@ -30,6 +31,12 @@ export const useWaveform = (
const [layers, setLayers] = useState<Layer[]>([]);
const [layerVisibility, setLayerVisibility] = useState(new Map());

const { settings } = useContext(TimelineContext);
useEffect(() => {
if (!waveform.current || !settings) return;
waveform.current.settings = settings;
}, [settings]);

const onFrameChangedRef = useRef(options?.onFrameChanged);
onFrameChangedRef.current = options?.onFrameChanged;

Expand Down
Loading
Loading