mirror of
https://github.com/yusufipk/OpenFrame.git
synced 2026-09-11 09:36:08 +00:00
chore(init): scaffold OpenFrame — Next.js + Bun + shadcn
Initialize OpenFrame project with core scaffold and UI foundation. - Project scaffold: Next.js 16.1 (App Router) + Bun runtime - UI: shadcn/ui + TailwindCSS; landing, dashboard, project, and auth UIs - Video support: provider abstraction (YouTube first), video player page with timestamped comments and custom timeline - Auth & DB: NextAuth skeleton and Prisma schema (Postgres) included - UX: dark-mode toggle, full-width layouts, comments sidebar, video route moved to /watch/[videoId] - Dev: added YouTube iframe integration, custom controls, and TypeScript types - Next steps: DB migrations, API routes (CRUD), real data wiring, voice-recording & sharing
This commit is contained in:
@@ -0,0 +1,129 @@
|
||||
// Video Provider Registry - Central place to manage all video providers
|
||||
|
||||
import { youtubeProvider } from './youtube';
|
||||
import { vimeoProvider } from './vimeo';
|
||||
import { directProvider } from './direct';
|
||||
import type { VideoProvider, VideoSource, VideoMetadata, VideoProviderType } from './types';
|
||||
|
||||
// Export types
|
||||
export * from './types';
|
||||
|
||||
// Registry of all available providers
|
||||
const providers: VideoProvider[] = [
|
||||
youtubeProvider,
|
||||
vimeoProvider,
|
||||
directProvider,
|
||||
];
|
||||
|
||||
// Provider lookup map for quick access
|
||||
const providerMap = new Map<string, VideoProvider>(
|
||||
providers.map(p => [p.id, p])
|
||||
);
|
||||
|
||||
/**
|
||||
* Detect which provider can handle a given URL
|
||||
*/
|
||||
export function detectProvider(url: string): VideoProvider | null {
|
||||
for (const provider of providers) {
|
||||
if (provider.canHandle(url)) {
|
||||
return provider;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a provider by its ID
|
||||
*/
|
||||
export function getProvider(providerId: VideoProviderType): VideoProvider | null {
|
||||
return providerMap.get(providerId) ?? null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all available providers
|
||||
*/
|
||||
export function getAllProviders(): VideoProvider[] {
|
||||
return [...providers];
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a video URL and return a VideoSource object
|
||||
*/
|
||||
export function parseVideoUrl(url: string): VideoSource | null {
|
||||
const provider = detectProvider(url);
|
||||
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const videoId = provider.extractVideoId(url);
|
||||
|
||||
if (!videoId) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return {
|
||||
providerId: provider.id as VideoProviderType,
|
||||
videoId,
|
||||
originalUrl: url,
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch metadata for a video source
|
||||
*/
|
||||
export async function fetchVideoMetadata(source: VideoSource): Promise<VideoMetadata | null> {
|
||||
const provider = getProvider(source.providerId);
|
||||
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
try {
|
||||
return await provider.getMetadata(source.videoId);
|
||||
} catch (error) {
|
||||
console.error('Failed to fetch video metadata:', error);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get embed URL for a video source
|
||||
*/
|
||||
export function getEmbedUrl(source: VideoSource, options?: Parameters<VideoProvider['getEmbedUrl']>[1]): string | null {
|
||||
const provider = getProvider(source.providerId);
|
||||
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return provider.getEmbedUrl(source.videoId, options);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get thumbnail URL for a video source
|
||||
*/
|
||||
export function getThumbnailUrl(source: VideoSource, size?: Parameters<VideoProvider['getThumbnailUrl']>[1]): string | null {
|
||||
const provider = getProvider(source.providerId);
|
||||
|
||||
if (!provider) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return provider.getThumbnailUrl(source.videoId, size);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a URL is a valid video URL from any supported provider
|
||||
*/
|
||||
export function isValidVideoUrl(url: string): boolean {
|
||||
return detectProvider(url) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the provider icon name for UI display
|
||||
*/
|
||||
export function getProviderIcon(providerId: VideoProviderType): string {
|
||||
const provider = getProvider(providerId);
|
||||
return provider?.icon ?? 'Video';
|
||||
}
|
||||
Reference in New Issue
Block a user