4 changed files with 113 additions and 29 deletions
@ -0,0 +1,83 @@ |
|||||||
|
import { |
||||||
|
ProgressEpisodeItem, |
||||||
|
ProgressItem, |
||||||
|
ProgressMediaItem, |
||||||
|
ProgressSeasonItem, |
||||||
|
} from "@/stores/progress"; |
||||||
|
|
||||||
|
export interface ShowProgressResult { |
||||||
|
episode?: ProgressEpisodeItem; |
||||||
|
season?: ProgressSeasonItem; |
||||||
|
progress: ProgressItem; |
||||||
|
show: boolean; |
||||||
|
} |
||||||
|
|
||||||
|
const defaultProgress = { |
||||||
|
duration: 0, |
||||||
|
watched: 0, |
||||||
|
}; |
||||||
|
|
||||||
|
function progressIsCompleted(duration: number, watched: number): boolean { |
||||||
|
const timeFromEnd = duration - watched; |
||||||
|
|
||||||
|
// too close to the end, is completed
|
||||||
|
if (timeFromEnd < 60 * 2) return true; |
||||||
|
|
||||||
|
// satisfies all constraints, not completed
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
function progressIsNotStarted(duration: number, watched: number): boolean { |
||||||
|
// too short watch time
|
||||||
|
if (watched < 20) return true; |
||||||
|
|
||||||
|
// satisfies all constraints, not completed
|
||||||
|
return false; |
||||||
|
} |
||||||
|
|
||||||
|
function progressIsAcceptableRange(duration: number, watched: number): boolean { |
||||||
|
// not started enough yet, not acceptable
|
||||||
|
if (progressIsNotStarted(duration, watched)) return false; |
||||||
|
|
||||||
|
// is already at the end, not acceptable
|
||||||
|
if (progressIsCompleted(duration, watched)) return false; |
||||||
|
|
||||||
|
// satisfied all constraints
|
||||||
|
return true; |
||||||
|
} |
||||||
|
|
||||||
|
export function shouldShowProgress( |
||||||
|
item: ProgressMediaItem |
||||||
|
): ShowProgressResult { |
||||||
|
// non shows just hide or show depending on acceptable ranges
|
||||||
|
if (item.type !== "show") { |
||||||
|
return { |
||||||
|
show: progressIsAcceptableRange( |
||||||
|
item.progress?.duration ?? 0, |
||||||
|
item.progress?.watched ?? 0 |
||||||
|
), |
||||||
|
progress: item.progress ?? defaultProgress, |
||||||
|
}; |
||||||
|
} |
||||||
|
|
||||||
|
// shows only hide an item if its too early in episode, it still shows if its near the end.
|
||||||
|
// Otherwise you would lose episode progress
|
||||||
|
const ep = Object.values(item.episodes) |
||||||
|
.sort((a, b) => b.updatedAt - a.updatedAt) |
||||||
|
.filter( |
||||||
|
(epi) => |
||||||
|
!progressIsNotStarted(epi.progress.duration, epi.progress.watched) |
||||||
|
)[0]; |
||||||
|
const season = item.seasons[ep?.seasonId]; |
||||||
|
if (!ep || !season) |
||||||
|
return { |
||||||
|
show: false, |
||||||
|
progress: defaultProgress, |
||||||
|
}; |
||||||
|
return { |
||||||
|
season, |
||||||
|
episode: ep, |
||||||
|
show: true, |
||||||
|
progress: ep.progress, |
||||||
|
}; |
||||||
|
} |
Loading…
Reference in new issue