Add Episodes panel: search a series, browse a season's episode list
New src-tauri/src/episodes.rs exposes browse_episodes, reusing the existing AnyTvClient::fetch_season machinery Fetch Data already built (via a build_tv_client helper factored out of metadata.rs) so this panel needs no credentials of its own - it reads whatever TV source (TMDB/TVmaze/OMDb) is already configured in Fetch Data Settings. New EpisodesPanel.tsx/.css: series name + season stepper, an episode list (number/title/air date), and a Copy list button that copies the season as plain text. Wired into App.tsx's sidebar routing as the second stub panel (after Subtitles) to become a real screen. 145/145 Rust tests passing (+1), npm run build clean, 15/15 Playwright checks against npm run dev (mocked Tauri bridge) covering search, the empty-season case, a not-found series, the season stepper, Copy list, and the blank-query guard.
This commit is contained in:
@@ -0,0 +1,134 @@
|
||||
.episodes-panel {
|
||||
height: 100%;
|
||||
min-width: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 14px;
|
||||
padding: 18px;
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.episodes-search-form {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 8px;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--surface-deep);
|
||||
border-radius: 12px;
|
||||
padding: 14px;
|
||||
}
|
||||
|
||||
.episodes-search-row-inline {
|
||||
display: flex;
|
||||
align-items: flex-end;
|
||||
gap: 12px;
|
||||
}
|
||||
|
||||
.episodes-search-row-inline > label {
|
||||
font-size: 11.5px;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.episodes-series-field,
|
||||
.episodes-season-field {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 4px;
|
||||
min-width: 0;
|
||||
}
|
||||
|
||||
.episodes-series-field {
|
||||
flex: 1;
|
||||
min-width: 140px;
|
||||
}
|
||||
|
||||
.episodes-series-field label,
|
||||
.episodes-season-field label {
|
||||
font-size: 11.5px;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.episodes-season-field {
|
||||
flex: 0 0 auto;
|
||||
}
|
||||
|
||||
.episodes-season-stepper {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.episodes-season-input {
|
||||
width: 56px;
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.episodes-hint {
|
||||
font-size: 11.5px;
|
||||
color: var(--muted-text);
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.episodes-results {
|
||||
flex: 1;
|
||||
min-height: 0;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 6px;
|
||||
}
|
||||
|
||||
.episodes-results-header {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
gap: 12px;
|
||||
padding: 2px 2px 4px;
|
||||
}
|
||||
|
||||
.episodes-series-name {
|
||||
font-size: 13.5px;
|
||||
font-weight: 600;
|
||||
}
|
||||
|
||||
.episodes-row {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 12px;
|
||||
background: var(--card);
|
||||
border: 1px solid var(--surface-deep);
|
||||
border-radius: 10px;
|
||||
padding: 9px 12px;
|
||||
}
|
||||
|
||||
.episodes-row-number {
|
||||
flex: 0 0 28px;
|
||||
font-size: 12px;
|
||||
font-weight: 700;
|
||||
color: var(--aurora-cyan);
|
||||
}
|
||||
|
||||
.episodes-row-title {
|
||||
flex: 1;
|
||||
min-width: 0;
|
||||
font-size: 12.5px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.episodes-row-date {
|
||||
flex: 0 0 auto;
|
||||
font-size: 11.5px;
|
||||
color: var(--muted-text);
|
||||
}
|
||||
|
||||
.episodes-empty-note {
|
||||
color: var(--muted-text);
|
||||
font-size: 12.5px;
|
||||
padding: 8px 2px;
|
||||
}
|
||||
|
||||
.episodes-status {
|
||||
font-size: 12px;
|
||||
color: var(--aurora-cyan);
|
||||
}
|
||||
Reference in New Issue
Block a user