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
··· 31 31 import MicRecorder from "./components/MicRecorder"; 32 32 import { Link } from "./components/ui/link"; 33 33 import { css } from "styled-system/css"; 34 + import { toggleToRecord } from "./lib/settings"; 34 35 35 36 const App = () => { 36 37 const collection = () => ··· 273 274 </Button> 274 275 )} 275 276 /> 276 - <MicRecorder selectedAccount={selectedAccount} /> 277 + <MicRecorder 278 + selectedAccount={selectedAccount} 279 + holdToRecord={!toggleToRecord()} 280 + /> 277 281 {/*<IconButton 278 282 size="sm" 279 283 onClick={() =>
+30 -8
src/components/MicRecorder.tsx
··· 1 - import { createSignal, onCleanup } from "solid-js"; 2 - import { MicIcon } from "lucide-solid"; 1 + import { createSignal, onCleanup, Show } from "solid-js"; 2 + import { CircleStopIcon, MicIcon } from "lucide-solid"; 3 3 import { IconButton } from "./ui/icon-button"; 4 4 import { Popover } from "./ui/popover"; 5 5 import { AtprotoDid } from "@atcute/lexicons/syntax"; ··· 9 9 10 10 type MicRecorderProps = { 11 11 selectedAccount: () => AtprotoDid | undefined; 12 + holdToRecord?: boolean; 12 13 }; 13 14 14 15 const MicRecorder = (props: MicRecorderProps) => { ··· 33 34 const fallbackMimeType = isSafari ? "audio/mp4" : "audio/webm"; 34 35 35 36 const startRecording = async () => { 37 + if (isRecording()) return; 38 + 36 39 try { 37 40 audioChunks = []; 38 41 ··· 168 171 size="md" 169 172 variant={isRecording() ? "solid" : "subtle"} 170 173 colorPalette={isRecording() ? "red" : undefined} 171 - onMouseDown={startRecording} 172 - onMouseUp={stopRecording} 173 - onMouseLeave={stopRecording} 174 - onTouchStart={startRecording} 175 - onTouchEnd={stopRecording} 174 + onClick={ 175 + !props.holdToRecord 176 + ? () => (isRecording() ? stopRecording() : startRecording()) 177 + : undefined 178 + } 179 + onMouseDown={props.holdToRecord ? startRecording : undefined} 180 + onMouseUp={props.holdToRecord ? stopRecording : undefined} 181 + onMouseLeave={props.holdToRecord ? stopRecording : undefined} 182 + onTouchStart={ 183 + props.holdToRecord 184 + ? (e) => { 185 + e.preventDefault(); // Prevent mouse emulation 186 + startRecording(); 187 + } 188 + : undefined 189 + } 190 + onTouchEnd={ 191 + props.holdToRecord 192 + ? (e) => { 193 + e.preventDefault(); 194 + stopRecording(); 195 + } 196 + : undefined 197 + } 176 198 > 177 - <MicIcon /> 199 + {isRecording() ? <CircleStopIcon /> : <MicIcon />} 178 200 </IconButton> 179 201 )} 180 202 />
+18
src/components/Settings.tsx
··· 34 34 backgroundColor as backgroundColorSetting, 35 35 frameRate as frameRateSetting, 36 36 useDominantColorAsBg as useDominantColorAsBgSetting, 37 + toggleToRecordSetting, 37 38 Setting, 39 + toggleToRecord, 40 + setToggleToRecord, 38 41 } from "~/lib/settings"; 39 42 import { handleResolver } from "~/lib/at"; 40 43 import { toaster } from "~/components/Toaster"; ··· 351 354 <Drawer.Body> 352 355 <Stack gap="4"> 353 356 <Accounts /> 357 + <Stack> 358 + <FormLabel>user interface</FormLabel> 359 + <Stack 360 + gap="0" 361 + border="1px solid var(--colors-border-default)" 362 + borderBottomWidth="3px" 363 + rounded="xs" 364 + > 365 + <SettingCheckbox 366 + label="use toggle to record" 367 + setting={toggleToRecordSetting} 368 + signal={[toggleToRecord, setToggleToRecord]} 369 + /> 370 + </Stack> 371 + </Stack> 354 372 <Stack> 355 373 <FormLabel>processing</FormLabel> 356 374 <Stack
+14
src/lib/settings.ts
··· 1 + import { createSignal } from "solid-js"; 2 + 1 3 export const setting = <T>(key: string) => { 2 4 return { 3 5 get: () => { ··· 17 19 export const useDominantColorAsBg = setting<boolean>("useDominantColorAsBg"); 18 20 export const backgroundColor = setting<string>("backgroundColor"); 19 21 export const frameRate = setting<number>("frameRate"); 22 + 23 + export const toggleToRecordSetting = setting<boolean>("toggleToRecord"); 24 + const [_toggleToRecord, _setToggleToRecord] = createSignal<boolean>( 25 + toggleToRecordSetting.get() ?? false, 26 + ); 27 + export const toggleToRecord = _toggleToRecord; 28 + export const setToggleToRecord = ( 29 + value: boolean | ((prev: boolean) => boolean), 30 + ) => { 31 + const newAccounts = _setToggleToRecord(value); 32 + toggleToRecordSetting.set(newAccounts); 33 + };