mirror of
https://github.com/zoriya/v10.git
synced 2026-08-05 21:57:29 +00:00
2.7 KiB
2.7 KiB
status, date
| status | date |
|---|---|
| draft | 2025-01-27 |
Feature Availability Design
Problem
Features may target capabilities the platform doesn't support.
// iOS Safari doesn't allow programmatic volume control
request: {
setVolume: (vol, { target }) => {
target.volume = vol; // silently fails on iOS
},
}
UI needs to know: hide control? disable it? show it normally?
Solution
Single availability state per feature:
type FeatureAvailability = 'available' | 'unavailable' | 'unsupported';
| Value | Meaning |
|---|---|
'unsupported' |
Platform can never do this (e.g., iOS volume) |
'unavailable' |
Could work, not ready yet (e.g., waiting for manifest) |
'available' |
Ready to use |
Related: Missing Feature vs Unavailable Capability
See rfc/player-api for feature access patterns.
| Concept | Cause | Detection |
|---|---|---|
| Missing feature | Feature not included | slice === undefined |
| Unavailable capability | Platform limitation | *Availability === 'unsupported' |
Implementation
Naming Convention
Property: {feature}Availability
volumeAvailabilityqualityAvailabilitypipAvailability
Default Value
Always start 'unsupported' (pessimistic). Must be proven otherwise.
Async Capability Detection
Use module-level cache + update() pattern. No API changes needed.
let availability: FeatureAvailability = 'unsupported';
const volumeFeature = createFeature<HTMLMediaElement>()({
initialState: {
volume: 1,
volumeAvailability: 'unsupported',
},
getSnapshot: ({ target }) => ({
volume: target.volume,
volumeAvailability: availability,
}),
subscribe: ({ target, update, signal }) => {
listen(target, 'volumechange', update, { signal });
// Async detection
canChangeVolume().then((supported) => {
if (signal.aborted) return;
availability = supported ? 'available' : 'unsupported';
update();
});
},
request: {
setVolume: {
guard: () => availability === 'available',
handler: (vol, { target }) => {
target.volume = vol;
},
},
},
});
Guards
Guards receive { target, signal }, not state. Check capability on target directly.
References
- Media Chrome uses similar pattern with
*Unavailableproperties - Vidstack uses
canSetVolume,canSetQualitycomputed properties