Skip to main content

MediaItem Interface

Core data structure representing all media types (movies, TV shows, episodes).
src/services/api.ts
export interface MediaItem {
    id: number;
    title: string;
    year?: number;
    overview?: string;
    cast_names?: string;
    poster_path?: string;
    file_path?: string;
    media_type: 'movie' | 'tvshow' | 'tvepisode';
    duration_seconds?: number;
    resume_position_seconds?: number;
    last_watched?: string;
    season_number?: number;
    episode_number?: number;
    progress_percent?: number;
    parent_id?: number;
    tmdb_id?: string;
    episode_title?: string;
    still_path?: string;
    // Cloud storage fields
    is_cloud?: boolean;
    cloud_file_id?: string;
}
id
number
required
Unique database identifier
title
string
required
Media title (show name for TV shows, movie title for movies)
media_type
'movie' | 'tvshow' | 'tvepisode'
required
Type of media item:
  • movie - Standalone movie file
  • tvshow - TV series container (no file, just metadata)
  • tvepisode - Individual episode linked to parent show
year
number
Release year
overview
string
Plot description from TMDB
poster_path
string
Cached poster image filename (use getCachedImageUrl() to convert to URL)
file_path
string
Local file system path or cloud file name
duration_seconds
number
Total runtime in seconds
resume_position_seconds
number
Last playback position (0 if not started or completed)
progress_percent
number
Watch progress percentage (calculated field)
season_number
number
Season number (TV episodes only)
episode_number
number
Episode number (TV episodes only)
parent_id
number
ID of parent TV show (episodes only)
tmdb_id
string
TMDB identifier for metadata lookups
episode_title
string
Episode-specific title (TV episodes only)
still_path
string
Episode thumbnail image (TV episodes only)
is_cloud
boolean
Whether this is a cloud-stored file
cloud_file_id
string
Google Drive file ID (cloud files only)

Get Library

Retrieve movies or TV shows with optional search.
src/services/api.ts
export const getLibrary = async (
  type: 'movie' | 'tv',
  search: string = ''
): Promise<MediaItem[]>
type
'movie' | 'tv'
required
Media type to retrieve:
  • 'movie' - Returns all movies
  • 'tv' - Returns all TV shows (not individual episodes)
Case-insensitive title search filter
items
MediaItem[]
Array of media items sorted by title

Example Usage

import { getLibrary } from '@/services/api';

// Get all movies
const movies = await getLibrary('movie');

// Search for specific movie
const inception = await getLibrary('movie', 'inception');

// Get all TV shows
const shows = await getLibrary('tv');

Backend Command

src-tauri/src/main.rs
#[tauri::command]
async fn get_library(
    state: State<'_, AppState>,
    media_type: String,
    search: Option<String>,
) -> Result<Vec<database::MediaItem>, String>

Get Library Filtered

Retrieve library with cloud storage filtering.
src/services/api.ts
export const getLibraryFiltered = async (
    type: 'movie' | 'tv',
    search: string = '',
    isCloud?: boolean
): Promise<MediaItem[]>
type
'movie' | 'tv'
required
Media type to retrieve
search
string
default:""
Title search filter
isCloud
boolean
Filter by storage location:
  • true - Only cloud files
  • false - Only local files
  • undefined - All files

Example Usage

// Get only cloud movies
const cloudMovies = await getLibraryFiltered('movie', '', true);

// Get only local TV shows
const localShows = await getLibraryFiltered('tv', '', false);

// Search cloud library
const results = await getLibraryFiltered('movie', 'avatar', true);

Get Episodes

Retrieve all episodes for a TV show.
src/services/api.ts
export const getEpisodes = async (seriesId: number): Promise<MediaItem[]>
seriesId
number
required
ID of parent TV show
episodes
MediaItem[]
Array of episodes sorted by season and episode number

Example Usage

import { getLibrary, getEpisodes } from '@/services/api';

// Get a TV show
const shows = await getLibrary('tv', 'breaking bad');
const show = shows[0];

// Get all episodes
const episodes = await getEpisodes(show.id);

// Group by season
const seasons = episodes.reduce((acc, ep) => {
  const season = ep.season_number || 1;
  if (!acc[season]) acc[season] = [];
  acc[season].push(ep);
  return acc;
}, {} as Record<number, MediaItem[]>);

Get Watch History

Retrieve recently watched content.
src/services/api.ts
export const getWatchHistory = async (): Promise<MediaItem[]>
history
MediaItem[]
Up to 50 most recently watched items, sorted by last_watched descending

Example Usage

const history = await getWatchHistory();

history.forEach(item => {
  console.log(`Watched: ${item.title}`);
  console.log(`Progress: ${item.progress_percent}%`);
  console.log(`Last watched: ${item.last_watched}`);
});

Add/Remove from Watch History

src/services/api.ts
// Remove single item
export const removeFromWatchHistory = async (id: number): Promise<void>

// Clear all history
export const clearAllWatchHistory = async (): Promise<void>
id
number
required
Media item ID to remove from history

Example Usage

import { removeFromWatchHistory, clearAllWatchHistory } from '@/services/api';

// Remove specific item
await removeFromWatchHistory(123);

// Clear all watch history
await clearAllWatchHistory();

Mark as Complete

Mark content as fully watched (100%).
src/services/api.ts
export const markAsComplete = async (mediaId: number): Promise<{ message: string }>
mediaId
number
required
ID of media to mark as complete

Example Usage

const response = await markAsComplete(movieId);
console.log(response.message); // "Marked 'Movie Title' as complete"

Search & Filter

Search TMDB for metadata matching.
src/services/api.ts
export interface TmdbSearchResult {
    id: number;
    title?: string;
    name?: string;
    media_type: 'movie' | 'tv';
    poster_path?: string;
    backdrop_path?: string;
    overview?: string;
    release_date?: string;
    first_air_date?: string;
    vote_average?: number;
}

export interface TmdbSearchResponse {
    results: TmdbSearchResult[];
    total_results: number;
}

export const searchTmdb = async (query: string): Promise<TmdbSearchResponse>

Example Usage

import { searchTmdb } from '@/services/api';

const results = await searchTmdb('inception');

results.results.forEach(item => {
  console.log(`${item.title || item.name} (${item.media_type})`);
});

Fix Match

Update media metadata from TMDB.
src/services/api.ts
export const fixMatch = async (
  id: number,
  tmdbId: string,
  type: 'movie' | 'tv'
): Promise<void>
id
number
required
Media item ID to update
tmdbId
string
required
TMDB ID for correct metadata
type
'movie' | 'tv'
required
Media type

Example Usage

import { searchTmdb, fixMatch } from '@/services/api';

// User selects correct match
const results = await searchTmdb('inception');
const correctMatch = results.results[0];

// Update media with correct metadata
await fixMatch(mediaId, correctMatch.id.toString(), 'movie');

Delete Media

Delete media files from disk.
src/services/api.ts
export interface DeleteResponse {
    success: boolean;
    deleted_count: number;
    failed_count: number;
    message: string;
}

export const deleteMediaFiles = async (mediaIds: number[]): Promise<DeleteResponse>
mediaIds
number[]
required
Array of media IDs to delete

Example Usage

import { deleteMediaFiles } from '@/services/api';

const result = await deleteMediaFiles([123, 456, 789]);

if (result.success) {
  console.log(`Deleted ${result.deleted_count} files`);
  if (result.failed_count > 0) {
    console.warn(`Failed to delete ${result.failed_count} files`);
  }
}

Image Handling

Convert cached image names to usable URLs.
src/services/api.ts
export const getCachedImageUrl = (imageName: string): Promise<string | null>
imageName
string
required
Image filename from poster_path or still_path
url
string | null
Asset protocol URL or null if image doesn’t exist

Example Usage

import { getLibrary, getCachedImageUrl } from '@/services/api';

const movies = await getLibrary('movie');

for (const movie of movies) {
  if (movie.poster_path) {
    const posterUrl = await getCachedImageUrl(movie.poster_path);
    if (posterUrl) {
      // Use in <img src={posterUrl} />
    }
  }
}

Episode Metadata

Rich episode information from TMDB.
src/services/api.ts
export interface TmdbEpisodeInfo {
    episode_number: number;
    name: string;
    overview?: string;
    still_path?: string;
    is_cloud?: boolean;
    cloud_file_id?: string;
    air_date?: string;
    runtime?: number;
    vote_average?: number;
}

export interface TmdbSeasonDetails {
    season_number: number;
    name: string;
    episodes: TmdbEpisodeInfo[];
}

export const getTvSeasonEpisodes = async (
  tvId: number,
  seasonNumber: number
): Promise<TmdbSeasonDetails | null>

Example Usage

import { getTvSeasonEpisodes } from '@/services/api';

const season = await getTvSeasonEpisodes(1399, 1); // Breaking Bad S01

if (season) {
  console.log(`${season.name} - ${season.episodes.length} episodes`);
  
  season.episodes.forEach(ep => {
    console.log(`E${ep.episode_number}: ${ep.name}`);
  });
}

Build docs developers (and LLMs) love