components/Sidebar
The dashboard sidebar: every control the reference dashboard offers on top
of selkies-core, talking to the core through window.postMessage alone.
Renders a draggable toggle handle, the core action buttons (video, audio, microphone, webcam, gamepad), the soft modifier keys and virtual keyboard button for touch clients, the collapsible video, screen, audio, stats, clipboard, files, apps, sharing, gamepads and shortcuts sections, the upload and clipboard notifications, the apps and files modals, and the second-screen placement arrows.
Messages it consumes from the core: serverSettings (the settings payload
that gates which controls render and seeds their values),
pipelineStatusUpdate and sidebarButtonStatusUpdate,
effectiveCursorState, scalingDpiFollowed (the UI-scaling default the
core re-derived), clientRoleUpdate, gamingModeUpdate,
toggleDashboard and toggleTouchGamepad (the core-owned Ctrl+Shift+M and
Ctrl+Shift+G chords), gamepadControl, clipboardContentUpdate,
audioDeviceSelected (its own selection mirrored back, so the dropdowns
show what the core was told), gamepadButtonUpdate and
gamepadAxisUpdate, fileUpload (upload progress and every notification
the core raises), and trackpadModeUpdate.
Messages it posts: settings (debounced), pipelineControl,
gamepadControl, setManualResolution, resetResolutionToWindow,
setScaleLocally, setAntiAliasing, audioDeviceSelected,
clipboardUpdateFromUI, clipboardImageUpdate, requestFullscreen,
requestGamingMode, mode, setSynth, sidebarVisibilityChanged, TOUCH_GAMEPAD_SETUP,
TOUCH_GAMEPAD_VISIBILITY, touchinput:trackpad and touchinput:touch,
plus whatever channel a conditional-settings spec propagates through; the
stats section (StreamStats.jsx) posts statsOpen and reads its own. The
soft keys dispatch synthetic KeyboardEvents on window, and the files
section dispatches the requestFileUpload DOM event.
window state it reads: webrtcInput.gamingMode,
__SELKIES_STREAMING_MODE__ and __SELKIES_DUAL_MODE__; it sets
__selkiesModeSwitching around a transport switch.
Persistence: every setting lives in localStorage under
<storageAppName>_<key>, the keys in PER_DISPLAY_SETTINGS gaining a
_display2 suffix on the #display2 hash so a secondary display keeps its
own values; an explicit user choice of a derived setting writes a
_explicit_choice marker beside its value. The theme is stored unprefixed
because it is a per-browser preference.
Functions
roundDownToEven()
function roundDownToEven(num): number;Defined in: components/Sidebar.jsx:210
Parses a dimension and rounds it down to an even number; non-numbers become 0.
Parameters
| Parameter | Type |
|---|---|
num | any |
Returns
number
debounce()
function debounce(func, delay): Function;Defined in: components/Sidebar.jsx:222
Trailing debounce: only the last call within delay milliseconds runs.
Parameters
| Parameter | Type | Description |
|---|---|---|
func | Function | - |
delay | number | - |
Returns
Function
GamingModeIcon()
function GamingModeIcon(): Element;Defined in: components/Sidebar.jsx:244
Crosshair marking gaming mode, the wish dashboard's icon for it: one glyph names the control in both front ends and reads as a target, not a plus sign. Drawn to the ink span of the fullscreen brackets beside it, which cover only the middle of their box, so the header pair reads as one size.
Returns
Element
SelkiesLogo()
function SelkiesLogo(props): Element;Defined in: components/Sidebar.jsx:375
The mark from docs/assets/logo/selkies.svg. The gradient identifier is per-instance: two logos sharing one identifier would leave the second unpainted as soon as the instance that owns the definition unmounts.
Parameters
| Parameter | Type | Description |
|---|---|---|
props | { width?: number; height?: number; className?: string; t: Function; } | - |
props.width? | number | - |
props.height? | number | - |
props.className? | string | - |
props.t | Function | Translator, for the accessible label. |
Returns
Element
AppsModal()
function AppsModal(props): Element;Defined in: components/Sidebar.jsx:423
Catalog of proot-apps with install, remove, update and launch actions, posted as app commands through app-commands.js.
Parameters
| Parameter | Type | Description |
|---|---|---|
props | { isOpen: boolean; onClose: () => void; t: Function; commandsAvailable: boolean; commandsKnown: boolean; installedFromServer: string[]; } | - |
props.isOpen | boolean | Renders nothing while false. |
props.onClose | () => void | - |
props.t | Function | Translator. |
props.commandsAvailable | boolean | Whether the server accepts remote commands; actions are disabled otherwise. |
props.commandsKnown | boolean | Whether serverSettings have arrived, so the disabled notice is only shown once known. |
props.installedFromServer | string[] | App names the runner reports installed; the stored list is only a cache of it. |
Returns
Element
handleInstall()
function handleInstall(appName): void;Defined in: components/Sidebar.jsx:550
The apps command contract both dashboards share: app-commands.js posts the selkies-proot wrapper commands and tracks them for rollback, and the installed list is updated optimistically.
Parameters
| Parameter | Type |
|---|---|
appName | any |
Returns
void
getPrefixedKey()
function getPrefixedKey(key): string;Defined in: components/Sidebar.jsx:751
The localStorage key for a setting: the session prefix, plus the
_display2 suffix for per-display settings on the secondary display.
Parameters
| Parameter | Type | Description |
|---|---|---|
key | string | - |
Returns
string
readStored()
function readStored(key): string;Defined in: components/Sidebar.jsx:760
Reads a setting's stored value under its prefixed key.
Parameters
| Parameter | Type |
|---|---|
key | any |
Returns
string
deriveDpi()
function deriveDpi(manual): number;Defined in: components/Sidebar.jsx:777
The scaling_dpi default, derived as the core derives it
(lib/stream-density.js): from a manual resolution when one is set, since
that framebuffer decides how large the desktop draws its UI and the local
screen says nothing about it, and otherwise from the local display scaling
(devicePixelRatio), so the remote UI matches the local environment. An
explicit picker value wins over either. A manual resolution is read off its
shorter side -- an ultrawide is wide rather than dense -- and snapping to
the nearest option puts a density the options do not name on the closest one
and clamps at both ends.
Parameters
| Parameter | Type |
|---|---|
manual | any |
Returns
number
One of the dpiScalingOptions values.
manualResolution()
function manualResolution(serverSettings): object;Defined in: components/Sidebar.jsx:794
The manual resolution in force, as the cores resolve it: a deployment that
forces one and names its size wins, since the core takes the server's over
the client's there; otherwise the stored pick, and {w: 0, h: 0} for a
session sized to its window.
Parameters
| Parameter | Type | Description |
|---|---|---|
serverSettings | any | The server's settings payload. |
Returns
object
w
w: number;h
h: number;explicitChoiceKey()
function explicitChoiceKey(spec): string;Defined in: components/Sidebar.jsx:819
The marker key, suffixed onto the already-prefixed value key so it inherits the per-display suffix and a secondary display keeps its own choice.
Parameters
| Parameter | Type |
|---|---|
spec | any |
Returns
string
readExplicitStored()
function readExplicitStored(spec): (key) => string;Defined in: components/Sidebar.jsx:822
A storage reader for a spec that returns the stored value only when it was an explicit choice.
Parameters
| Parameter | Type |
|---|---|
spec | any |
Returns
(key) => string
useConditionalSetting()
function useConditionalSetting(
spec,
serverSettings,
ctx,
deps,
read?
): [any, Function];Defined in: components/Sidebar.jsx:841
Drives a conditional setting: lazy init, then a re-resolve whenever the
server settings or any dependency in deps changes, which covers the
server sync and the encoder or manual-resolution re-derivation uniformly.
The resolver honors explicit choices, so a re-resolve never clobbers a
pinned value. A re-resolve writes state rather than deriving during render
because the caller edits the value afterwards; deriving would discard that.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
spec | any | undefined | A spec from conditional-settings.js. |
serverSettings | any | undefined | The last serverSettings payload. |
ctx | any | undefined | Resolution context the spec reads. |
deps | any[] | undefined | Values whose change triggers a re-resolve. |
read? | (key) => string | readStored | Storage reader. |
Returns
[any, Function]
The value and its setter, as useState returns them.
clampToggleHandleTopPct()
function clampToggleHandleTopPct(pct): number;Defined in: components/Sidebar.jsx:862
Clamps the toggle handle's vertical position, a percentage of the viewport
height, so the handle stays fully inside the viewport. The handle's inline
top positions its center (Overlay.css keeps the translateY(-50%)), so
the clamp is by half the handle height. Without a finite viewport height
(headless, pre-layout) that half would be Infinity, so the clamp is a plain
0 to 100 until a real height is known; a handle at least as tall as the
viewport inverts the bounds, so it is centered instead of pinned to an edge.
Parameters
| Parameter | Type | Description |
|---|---|---|
pct | number | - |
Returns
number
Sidebar()
function Sidebar(): Element;Defined in: components/Sidebar.jsx:876
The sidebar component; see the module docblock for the message and storage
contract it implements. Renders nothing when the server hides the sidebar
(ui_show_sidebar), and viewer-role clients get no toggle handle.
Returns
Element
launchWindow()
function launchWindow(direction, screen?): boolean;Defined in: components/Sidebar.jsx:1073
Opens the secondary display in a new window, sized to screen when the
Window Management API found one in that direction.
Parameters
| Parameter | Type | Default value | Description |
|---|---|---|---|
direction | "up" | "down" | "left" | "right" | undefined | - |
screen? | any | null | - |
Returns
boolean
Whether the window opened.
handleAddScreenClick()
function handleAddScreenClick(): Promise<void>;Defined in: components/Sidebar.jsx:1107
Add Screen: places the second display on an adjacent physical screen when the Window Management API reports exactly one, and otherwise offers the placement arrows. Asking beats guessing: the API answers nothing without the window-management permission, and a display silently opened to the right of a monitor that sits above or left of this one is the one thing the arrows exist to avoid. A refused popup falls back to the arrows too, so the button is never seen to do nothing at all.
Returns
Promise<void>
sendKeyEvent()
function sendKeyEvent(
type,
key,
code,
modifierState
): void;Defined in: components/Sidebar.jsx:1194
Dispatches a synthetic keyboard event on window for the input core to forward.
Parameters
| Parameter | Type |
|---|---|
type | any |
key | any |
code | any |
modifierState | any |
Returns
void
handleHoldKeyClick()
function handleHoldKeyClick(key, code): void;Defined in: components/Sidebar.jsx:1210
Soft modifier key: toggles the key held, and switches the core's synth mode on with the first held modifier and off with the last release.
Parameters
| Parameter | Type |
|---|---|
key | any |
code | any |
Returns
void
handleOnceKeyClick()
function handleOnceKeyClick(key, code): void;Defined in: components/Sidebar.jsx:1232
Soft momentary key: a press and release carrying the held modifiers.
Parameters
| Parameter | Type |
|---|---|
key | any |
code | any |
Returns
void
writeConditional()
function writeConditional(
spec,
uiValue,
setValue,
opts?
): void;Defined in: components/Sidebar.jsx:1498
Uniform write path for conditional settings: optimistic setState, an optional persist (explicit choices pin, derived ones do not), and propagation through the spec.
Parameters
| Parameter | Type | Description |
|---|---|---|
spec | any | - |
uiValue | any | The value as the UI holds it. |
setValue | Function | The setting's state setter. |
opts? | { persist?: boolean; } | - |
opts.persist? | boolean | - |
Returns
void
handleDpiScalingChange()
function handleDpiScalingChange(event): void;Defined in: components/Sidebar.jsx:1723
UI scaling pick: persisted, so it pins across reloads and stops the startup derived-default post.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleTogglePointerUp()
function handleTogglePointerUp(e): void;Defined in: components/Sidebar.jsx:1816
Ends a handle drag and persists its position. pointerId is null when
the pointerup had no matching pointerdown (capture lost), and
hasPointerCapture(null) coerces to id 0 and could release a foreign
capture, so capture is only released for the tracked pointer.
Parameters
| Parameter | Type |
|---|---|
e | any |
Returns
void
handleCopyLink()
function handleCopyLink(textToCopy, label): Promise<void>;Defined in: components/Sidebar.jsx:1998
Copies a sharing link and reports the outcome as a notification.
Parameters
| Parameter | Type |
|---|---|
textToCopy | any |
label | any |
Returns
Promise<void>
rederiveRateControl()
function rederiveRateControl(ctxOverrides): void;Defined in: components/Sidebar.jsx:2043
Re-derives rate control after an encoder or software-encoding change. Rate control follows those unless pinned by an explicit client or server choice, and a derived change is not persisted, so it keeps following.
Parameters
| Parameter | Type | Description |
|---|---|---|
ctxOverrides | any | The value just chosen, ahead of the re-render that would put it in conditionalCtx. |
Returns
void
handleEncoderChange()
function handleEncoderChange(event): void;Defined in: components/Sidebar.jsx:2060
Encoder pick, one knob for both transports; the server switches the
pipeline encoder on it. The choice is persisted immediately so
conditionalCtx.activeEncoder, which reads localStorage, does not lag
during the post debounce and let a serverSettings sync re-derive rate
control off the stale encoder.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleVideoBitrateChange()
function handleVideoBitrateChange(event): void;Defined in: components/Sidebar.jsx:2085
Video bitrate slider: its value is an index into videoBitrateOptions.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleRateControlChange()
function handleRateControlChange(event): void;Defined in: components/Sidebar.jsx:2136
Rate control pick: an explicit choice, persisted so encoder changes stop overriding it.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleManualWidthChange()
function handleManualWidthChange(event): void;Defined in: components/Sidebar.jsx:2189
A half-typed size stays in component state: the stored manual_width
and manual_height mean "a manual resolution is applied", which the
HiDPI and UI-scaling derivations read, so only Set, a preset, or Reset
may write them.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleHidpiToggle()
function handleHidpiToggle(): void;Defined in: components/Sidebar.jsx:2206
HiDPI toggle: an explicit choice, pinned; the core persists useCssScaling when it applies the message.
Returns
void
deriveHidpiForResolution()
function deriveHidpiForResolution(manual): void;Defined in: components/Sidebar.jsx:2216
Manual and preset resolutions pair with CSS scaling: HiDPI off when one is set, on when reset, as a derived (unpinned) write through the uniform path. An explicit toggle or a locked or overridden server value pins HiDPI and stops the resolution buttons from re-deriving it.
Parameters
| Parameter | Type | Description |
|---|---|---|
manual | boolean | Whether a manual resolution is now applied. |
Returns
void
deriveDpiForResolution()
function deriveDpiForResolution(): void;Defined in: components/Sidebar.jsx:2226
A resolution the operator sets carries its own UI-scaling default, since the framebuffer asked for decides how large the desktop draws its UI. Not stored, so it stays a default: a stored pick, or a locked or operator-explicit server value, outranks it as it does at connect.
Returns
void
resetDpiToDerivedDefault()
function resetDpiToDerivedDefault(): void;Defined in: components/Sidebar.jsx:2242
Reset-to-window also returns UI scaling to its derived default, which with no resolution of its own left to read is the local display's scaling: the pinned client choice is dropped so the derived default governs again, and the value propagates like a user change. Locked or operator-explicit (overridden) values govern scaling instead, the same gate as the startup derived-default post.
Returns
void
resetHidpiToDerivedDefault()
function resetHidpiToDerivedDefault(): void;Defined in: components/Sidebar.jsx:2260
Reset-to-window also restores HiDPI to its default. Unlike the
resolution-derived writes, which respect a pinned choice, a reset means
"back to defaults", so the client's own pin is dropped even under an
operator-explicit value: use_css_scaling's overridden does not imply
locked, and a kept pin would keep outranking the operator's value in the
resolution ladder. The operator value when explicit, else the derived
default, is then applied without storing; only a locked value leaves
everything alone.
Returns
void
handleUseBrowserCursorsToggle()
function handleUseBrowserCursorsToggle(): void;Defined in: components/Sidebar.jsx:2286
Browser cursors toggle. The core owns persistence: the new preference is propagated and the core reports the effective value back. The next value derives from the displayed one: while multi-monitor forces the toggle on the base preference may be off, and negating the base would silently persist the forced value over the user's real choice.
Returns
void
handleRawPointerMotionToggle()
function handleRawPointerMotionToggle(): void;Defined in: components/Sidebar.jsx:2290
Raw pointer motion toggle; the core owns persistence, as for browser cursors.
Returns
void
handleMacCmdAsCtrlToggle()
function handleMacCmdAsCtrlToggle(): void;Defined in: components/Sidebar.jsx:2294
Command-as-Control toggle; the core owns persistence, as above.
Returns
void
toggleClientSetting()
function toggleClientSetting(
key,
value,
setValue
): void;Defined in: components/Sidebar.jsx:2303
One clipboard or shortcut switch: optimistic, then posted like any setting.
Parameters
| Parameter | Type |
|---|---|
key | any |
value | any |
setValue | any |
Returns
void
exitFullscreen()
function exitFullscreen(): void;Defined in: components/Sidebar.jsx:2380
Leaves fullscreen through whichever prefixed API exists. Entering is handed to the core, which owns what each mode locks; exiting is the browser's own call either way.
Returns
void
handleClipboardImageUpload()
function handleClipboardImageUpload(event): void;Defined in: components/Sidebar.jsx:2402
Hands a picked image to the core's clipboardImageUpdate path (a File
is a Blob), which sends it through the binary clipboard exactly like a
focus-synced local clipboard image; any other file raises a warning
notification. Same contract as the wish dashboard.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleClipboardBlur()
function handleClipboardBlur(event): void;Defined in: components/Sidebar.jsx:2429
Pushes the edited clipboard text to the server on blur, never a truncated preview.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
void
handleStreamModeChange()
function handleStreamModeChange(event): Promise<void>;Defined in: components/Sidebar.jsx:2454
Switches the transport through /api/switch, then posts mode so the
core reloads into it. window.__selkiesModeSwitching is set before the
request because the server tears down the old peer (WebSocket close code
4000) before it responds, and without the flag the active core would
surface a spurious "Server disconnected" alert. The request carries this
client's own session token, which a controller's is enough for; a stored
master token overrides it, and where neither is accepted a 401 prompts for
the master token once, keeps it in sessionStorage and retries, dropping one
the server rejects so the next attempt re-prompts. A viewer is refused 403
and is not asked for anything. A failed switch clears the flag again, since
no reload follows and a kept flag would hide a real disconnect.
Parameters
| Parameter | Type |
|---|---|
event | any |
Returns
Promise<void>
References
default
Renames and re-exports Sidebar