creates video voice memos from audio clips; with bluesky integration. trill.ptr.pet

feat: add toggle to record

ptr.pet cf4b246c 65dd3b06

verified
Changed files
+67 -9
src
+5 -1
src/App.tsx
···
import MicRecorder from "./components/MicRecorder";
import { Link } from "./components/ui/link";
import { css } from "styled-system/css";
+
import { toggleToRecord } from "./lib/settings";
const App = () => {
const collection = () =>
···
</Button>
)}
/>
-
<MicRecorder selectedAccount={selectedAccount} />
+
<MicRecorder
+
selectedAccount={selectedAccount}
+
holdToRecord={!toggleToRecord()}
+
/>
{/*<IconButton
size="sm"
onClick={() =>
+30 -8
src/components/MicRecorder.tsx
···
-
import { createSignal, onCleanup } from "solid-js";
-
import { MicIcon } from "lucide-solid";
+
import { createSignal, onCleanup, Show } from "solid-js";
+
import { CircleStopIcon, MicIcon } from "lucide-solid";
import { IconButton } from "./ui/icon-button";
import { Popover } from "./ui/popover";
import { AtprotoDid } from "@atcute/lexicons/syntax";
···
type MicRecorderProps = {
selectedAccount: () => AtprotoDid | undefined;
+
holdToRecord?: boolean;
};
const MicRecorder = (props: MicRecorderProps) => {
···
const fallbackMimeType = isSafari ? "audio/mp4" : "audio/webm";
const startRecording = async () => {
+
if (isRecording()) return;
+
try {
audioChunks = [];
···
size="md"
variant={isRecording() ? "solid" : "subtle"}
colorPalette={isRecording() ? "red" : undefined}
-
onMouseDown={startRecording}
-
onMouseUp={stopRecording}
-
onMouseLeave={stopRecording}
-
onTouchStart={startRecording}
-
onTouchEnd={stopRecording}
+
onClick={
+
!props.holdToRecord
+
? () => (isRecording() ? stopRecording() : startRecording())
+
: undefined
+
}
+
onMouseDown={props.holdToRecord ? startRecording : undefined}
+
onMouseUp={props.holdToRecord ? stopRecording : undefined}
+
onMouseLeave={props.holdToRecord ? stopRecording : undefined}
+
onTouchStart={
+
props.holdToRecord
+
? (e) => {
+
e.preventDefault(); // Prevent mouse emulation
+
startRecording();
+
}
+
: undefined
+
}
+
onTouchEnd={
+
props.holdToRecord
+
? (e) => {
+
e.preventDefault();
+
stopRecording();
+
}
+
: undefined
+
}
>
-
<MicIcon />
+
{isRecording() ? <CircleStopIcon /> : <MicIcon />}
</IconButton>
)}
/>
+18
src/components/Settings.tsx
···
backgroundColor as backgroundColorSetting,
frameRate as frameRateSetting,
useDominantColorAsBg as useDominantColorAsBgSetting,
+
toggleToRecordSetting,
Setting,
+
toggleToRecord,
+
setToggleToRecord,
} from "~/lib/settings";
import { handleResolver } from "~/lib/at";
import { toaster } from "~/components/Toaster";
···
<Drawer.Body>
<Stack gap="4">
<Accounts />
+
<Stack>
+
<FormLabel>user interface</FormLabel>
+
<Stack
+
gap="0"
+
border="1px solid var(--colors-border-default)"
+
borderBottomWidth="3px"
+
rounded="xs"
+
>
+
<SettingCheckbox
+
label="use toggle to record"
+
setting={toggleToRecordSetting}
+
signal={[toggleToRecord, setToggleToRecord]}
+
/>
+
</Stack>
+
</Stack>
<Stack>
<FormLabel>processing</FormLabel>
<Stack
+14
src/lib/settings.ts
···
+
import { createSignal } from "solid-js";
+
export const setting = <T>(key: string) => {
return {
get: () => {
···
export const useDominantColorAsBg = setting<boolean>("useDominantColorAsBg");
export const backgroundColor = setting<string>("backgroundColor");
export const frameRate = setting<number>("frameRate");
+
+
export const toggleToRecordSetting = setting<boolean>("toggleToRecord");
+
const [_toggleToRecord, _setToggleToRecord] = createSignal<boolean>(
+
toggleToRecordSetting.get() ?? false,
+
);
+
export const toggleToRecord = _toggleToRecord;
+
export const setToggleToRecord = (
+
value: boolean | ((prev: boolean) => boolean),
+
) => {
+
const newAccounts = _setToggleToRecord(value);
+
toggleToRecordSetting.set(newAccounts);
+
};