Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
57 changes: 48 additions & 9 deletions src/adapters/VideoPlayerFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,54 @@ export class VideoPlayerFactory {
*/
static getAvailableAdapter(): VideoPlayerAdapter {
this.initializeAdapters();
// Find the first available adapter and collect availability info
const availabilityInfos: { name: string; info: { isAvailable: boolean; error?: string; installCommand?: string; packageName?: string } }[] = [];

// Find the first available adapter
for (const adapter of this.adapters) {
const isAvailable = adapter.isAvailable();

if (isAvailable) {
const info = typeof (adapter as any).getAvailabilityInfo === 'function'
? (adapter as any).getAvailabilityInfo()
: { isAvailable: adapter.isAvailable() };

availabilityInfos.push({ name: adapter.getAdapterName(), info });

if (info.isAvailable) {
return adapter;
}
}

// If no adapter is available, return fallback
return new FallbackVideoAdapter('No video player library found. Install expo-video or expo-av.');
// Build a helpful, actionable error message listing why adapters are unavailable
const details = availabilityInfos.map(ai => {
if (ai.info.isAvailable) return `${ai.name}: available`;
const parts: string[] = [];
if (ai.info.error) parts.push(ai.info.error);
if (ai.info.installCommand) parts.push(`To install: ${ai.info.installCommand}`);
if (ai.info.packageName && !ai.info.installCommand) parts.push(`Package: ${ai.info.packageName}`);
return `${ai.name}: ${parts.join(' ').trim()}`.trim();
}).join('\n\n');

const message = `No video player library found. Please install one of the supported players:\n\n${details}`;

return new FallbackVideoAdapter(message);
}

/**
* Get a specific adapter by type
*/
static getAdapterByType(type: VideoPlayerType): VideoPlayerAdapter {
this.initializeAdapters();

const adapter = this.adapters.find(adapter => adapter.getAdapterName() === type);
if (adapter && adapter.isAvailable()) {
return adapter;
if (adapter) {
const info = typeof (adapter as any).getAvailabilityInfo === 'function'
? (adapter as any).getAvailabilityInfo()
: { isAvailable: adapter.isAvailable() };

if (info.isAvailable) {
return adapter;
}

const installHint = info.installCommand ? `\nTo fix: ${info.installCommand}` : '';
const errorMsg = info.error ? `${info.error}${installHint}` : `Adapter for ${type} is not available.${installHint}`;
throw new Error(errorMsg);
}

throw new Error(`Adapter for ${type} is not available`);
Expand All @@ -66,6 +91,20 @@ export class VideoPlayerFactory {
}));
}

/**
* Return detailed availability info (including install commands) for each adapter.
*/
static getAdaptersAvailabilityInfo(): { name: string; info: { isAvailable: boolean; error?: string; installCommand?: string; packageName?: string } }[] {
this.initializeAdapters();

return this.adapters.map(adapter => ({
name: adapter.getAdapterName(),
info: typeof (adapter as any).getAvailabilityInfo === 'function'
? (adapter as any).getAvailabilityInfo()
: { isAvailable: adapter.isAvailable() }
}));
}

/**
* Check if a specific video player type is available
*/
Expand Down