Skip to content

Commit

Permalink
media button refinement
Browse files Browse the repository at this point in the history
  • Loading branch information
dankoster committed Jan 1, 2025
1 parent 98ea13a commit d527715
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 75 deletions.
15 changes: 0 additions & 15 deletions src/MediaButton.tsx

This file was deleted.

7 changes: 6 additions & 1 deletion src/Settings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,8 @@ import "./Settings.css"

export let ShowSettings: () => void = () => { throw new Error('NOT READY - <Settings /> element not mounted') }

type SettingName = 'Start Call Muted (audio)'
type SettingName = 'Start video on load'
| 'Start Call Muted (audio)'
| 'Start Call Muted (video)'
| 'Mute when focus is lost'
| 'Restore mute state when refocused'
Expand All @@ -15,6 +16,10 @@ type Setting = {


const SettingsData: Setting[] = [
{
name: "Start video on load",
value: false
},
{
name: 'Start Call Muted (audio)',
value: true
Expand Down
6 changes: 5 additions & 1 deletion src/SvgIcon.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
export type svgIcon = 'camera' | 'camera_muted' | 'microphone' | 'microphone_muted' | 'share_screen';
export type svgIcon = 'camera' | 'camera_muted' | 'microphone' | 'microphone_muted' | 'share_screen' | 'mute' | 'unmute';
export function SvgIcon(props: { icon: svgIcon; }) {
// Font Awesome Free 6.7.2 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license/free Copyright 2024 Fonticons, Inc.
switch (props.icon) {
Expand All @@ -12,6 +12,10 @@ export function SvgIcon(props: { icon: svgIcon; }) {
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M38.8 5.1C28.4-3.1 13.3-1.2 5.1 9.2S-1.2 34.7 9.2 42.9l592 464c10.4 8.2 25.5 6.3 33.7-4.1s6.3-25.5-4.1-33.7L472.1 344.7c15.2-26 23.9-56.3 23.9-88.7l0-40c0-13.3-10.7-24-24-24s-24 10.7-24 24l0 40c0 21.2-5.1 41.1-14.2 58.7L416 300.8 416 96c0-53-43-96-96-96s-96 43-96 96l0 54.3L38.8 5.1zM344 430.4c20.4-2.8 39.7-9.1 57.3-18.2l-43.1-33.9C346.1 382 333.3 384 320 384c-70.7 0-128-57.3-128-128l0-8.7L144.7 210c-.5 1.9-.7 3.9-.7 6l0 40c0 89.1 66.2 162.7 152 174.4l0 33.6-48 0c-13.3 0-24 10.7-24 24s10.7 24 24 24l72 0 72 0c13.3 0 24-10.7 24-24s-10.7-24-24-24l-48 0 0-33.6z" /></svg>;
case 'share_screen':
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 512 512"><path d="M320 0c-17.7 0-32 14.3-32 32s14.3 32 32 32l82.7 0L201.4 265.4c-12.5 12.5-12.5 32.8 0 45.3s32.8 12.5 45.3 0L448 109.3l0 82.7c0 17.7 14.3 32 32 32s32-14.3 32-32l0-160c0-17.7-14.3-32-32-32L320 0zM80 32C35.8 32 0 67.8 0 112L0 432c0 44.2 35.8 80 80 80l320 0c44.2 0 80-35.8 80-80l0-112c0-17.7-14.3-32-32-32s-32 14.3-32 32l0 112c0 8.8-7.2 16-16 16L80 448c-8.8 0-16-7.2-16-16l0-320c0-8.8 7.2-16 16-16l112 0c17.7 0 32-14.3 32-32s-14.3-32-32-32L80 32z" /></svg>;
case 'mute':
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 576 512"><path d="M301.1 34.8C312.6 40 320 51.4 320 64l0 384c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352 64 352c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l67.8 0L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3zM425 167l55 55 55-55c9.4-9.4 24.6-9.4 33.9 0s9.4 24.6 0 33.9l-55 55 55 55c9.4 9.4 9.4 24.6 0 33.9s-24.6 9.4-33.9 0l-55-55-55 55c-9.4 9.4-24.6 9.4-33.9 0s-9.4-24.6 0-33.9l55-55-55-55c-9.4-9.4-9.4-24.6 0-33.9s24.6-9.4 33.9 0z" /></svg>
case 'unmute':
return <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 512"><path d="M533.6 32.5C598.5 85.2 640 165.8 640 256s-41.5 170.7-106.4 223.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C557.5 398.2 592 331.2 592 256s-34.5-142.2-88.7-186.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM473.1 107c43.2 35.2 70.9 88.9 70.9 149s-27.7 113.8-70.9 149c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C475.3 341.3 496 301.1 496 256s-20.7-85.3-53.2-111.8c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zm-60.5 74.5C434.1 199.1 448 225.9 448 256s-13.9 56.9-35.4 74.5c-10.3 8.4-25.4 6.8-33.8-3.5s-6.8-25.4 3.5-33.8C393.1 284.4 400 271 400 256s-6.9-28.4-17.7-37.3c-10.3-8.4-11.8-23.5-3.5-33.8s23.5-11.8 33.8-3.5zM301.1 34.8C312.6 40 320 51.4 320 64l0 384c0 12.6-7.4 24-18.9 29.2s-25 3.1-34.4-5.3L131.8 352 64 352c-35.3 0-64-28.7-64-64l0-64c0-35.3 28.7-64 64-64l67.8 0L266.7 40.1c9.4-8.4 22.9-10.4 34.4-5.3z" /></svg>

default: throw new Error('must specify an icon');
}
Expand Down
24 changes: 7 additions & 17 deletions src/VideoCall.css
Original file line number Diff line number Diff line change
Expand Up @@ -48,26 +48,16 @@
right: 0.25rem;
display: flex;
backdrop-filter: brightness(0.5);
padding-inline: 0.5rem;
border-radius: 0.5rem;

svg {
width: 1rem;
height: 2rem;
vertical-align: middle;
fill: var(--text-color);
}

.active {
svg {
fill: var(--media-active);
}
}

.muted {
.media-button {
padding: 0.3rem;
padding-inline: 0.4rem;

svg {
fill: var(--media-muted);
}
width: 0.7rem;
height: 0.7rem;
}
}
}
}
Expand Down
34 changes: 22 additions & 12 deletions src/VideoCall.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { displayName, shortId } from "./helpers";
import { PeerConnection } from "./PeerConnection";
import { GetSettingValue } from "./Settings";
import { onVisibilityChange } from "./onVisibilityChange";
import { MediaButton } from "./MediaButton";
import { MediaButton } from "./component/MediaButton";



Expand Down Expand Up @@ -200,6 +200,10 @@ export default function VideoCall() {
peersById.get(message.senderId)?.handleMessage(JSON.parse(message.message))
})

const startVideoOnLoad = GetSettingValue('Start video on load')
if (startVideoOnLoad) {
startLocalVideo()
}

//BUG: something weird here on Chrome
let savedMuteState: { micEnabled: boolean; camEnabled: boolean; }
Expand All @@ -221,15 +225,6 @@ export default function VideoCall() {
toggleVideo(savedMuteState.camEnabled)
}
});


// //handle style changes when videos are added and removed
// observer = new MutationObserver(() => {
// const isAlone = videoContainer.children.length <= 1
// console.log("isAlone", isAlone, videoContainer.children)
// localVideoContainer?.classList.toggle('alone', isAlone)
// })
// observer.observe(videoContainer, { childList: true })
})

onCleanup(() => {
Expand All @@ -252,19 +247,24 @@ export default function VideoCall() {
})

return <div id="videos-container" class="video-call" ref={videoContainer}>
<div class={`video-ui local ${isAlone() ? 'alone' : ''}`} ref={localVideoContainer}>
<div class="video-ui local" classList={{ alone: isAlone() }} ref={localVideoContainer}>
<video id="local-video" ref={localVideo} autoplay playsinline />
<span class="name">{myName()}</span>
<Show when={!isAlone()}>

<div class="buttons">
<MediaButton
className="audio"
enabled={micEnabled}
onClick={() => toggleMic()}
enabledIcon="microphone"
disabledIcon="microphone_muted"
/>
<MediaButton
enabled={camEnabled}
onClick={() => toggleVideo()}
enabledIcon="camera"
disabledIcon="camera_muted"
/>
</div>
</Show>
</div>
Expand All @@ -289,6 +289,7 @@ function PeerVideo(props: { peer: PeerConnection }) {
}

const [name, setName] = createSignal('')
const [soundEnabled, setSoundEnabled] = createSignal(true)

onMount(() => {
const con = server.connections.find(con => con.id === props.peer.conId)
Expand All @@ -313,5 +314,14 @@ function PeerVideo(props: { peer: PeerConnection }) {
return <div class="video-ui peer" ref={containerElement}>
<video id={props.peer.conId} class="remote" ref={videoElement} autoplay playsinline />
<span class="name">{name()}</span>
<div class="buttons">
<MediaButton
enabled={soundEnabled}
onClick={() => setSoundEnabled(!soundEnabled())}
enabledIcon="unmute"
disabledIcon="mute"
/>
</div>

</div>
}
29 changes: 29 additions & 0 deletions src/component/MediaButton.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.media-button {
/* outline: 1px solid gold; */
padding: 0.5rem;
display: grid;
cursor: pointer;

&+.media-button {
border-left: 1px solid var(--button-outline-color);
}

svg {
fill: var(--text-color);
width: 1rem;
height: 1rem;
vertical-align: middle;
}

&.active {
svg {
fill: var(--media-active);
}
}

&.muted {
svg {
fill: var(--media-muted);
}
}
}
17 changes: 17 additions & 0 deletions src/component/MediaButton.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import { Accessor, Switch, Match } from "solid-js";
import { svgIcon, SvgIcon } from "../SvgIcon";

import './MediaButton.css'

export function MediaButton(props: { className?: string; enabled: Accessor<boolean>; onClick: () => void; enabledIcon: svgIcon; disabledIcon: svgIcon; }) {
return <div class={`media-button ${props.className} ${props.enabled() ? 'active' : 'muted'}`} onclick={props.onClick}>
<Switch>
<Match when={props.enabled()}>
<SvgIcon icon={props.enabledIcon} />
</Match>
<Match when={!props.enabled()}>
<SvgIcon icon={props.disabledIcon} />
</Match>
</Switch>
</div>
}
30 changes: 2 additions & 28 deletions src/main.css
Original file line number Diff line number Diff line change
Expand Up @@ -255,34 +255,8 @@ body {
position: relative;
font-weight: bold;
padding-inline: 1rem;
}

.screen,
.audio,
.video {

padding-inline: 1rem;
border-left: 1px solid var(--button-outline-color);

svg {
fill: var(--text-color);
width: 1rem;
height: 1rem;
vertical-align: text-top;
}
}

.active {
svg {
fill: var(--media-active);
}
}

.muted {
svg {
fill: var(--media-muted);
}
}
border-right: 1px solid var(--button-outline-color);
}

img {
max-width: 2.5rem;
Expand Down
2 changes: 1 addition & 1 deletion src/main.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import "./main.css"
import { FigmentMenu, MenuItem } from "./Menu";
import VideoCall, * as videoCall from "./VideoCall";
import Settings, { ShowSettings } from "./Settings";
import { MediaButton } from "./MediaButton";
import { MediaButton } from "./component/MediaButton";

type SelectedView = 'people' | 'planet'

Expand Down

0 comments on commit d527715

Please sign in to comment.