Skip to content

Commit

Permalink
Fix: Incorrectly fetched activeMediaSourceId (#40)
Browse files Browse the repository at this point in the history
* bumped jellyfin nuget packages to 10.10.0

* updated version for this fix

* Fix for not correctly fetched activeMediaSource
Removed PlaybackInfo fetch.
Getting Id now from last sent single item

* Updated manifest.json
  • Loading branch information
Namo2 authored Oct 26, 2024
1 parent f706149 commit 52c62bf
Show file tree
Hide file tree
Showing 5 changed files with 76 additions and 68 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public InPlayerEpisodePreviewPlugin(
string scriptReplace = "<script plugin=\"InPlayerEpisodePreview\".*?></script>";
string scriptElement =
string.Format(
"<script plugin=\"InPlayerEpisodePreview\" version=\"1.3.0.0\" src=\"{0}/InPlayerPreview/ClientScript\"></script>",
"<script plugin=\"InPlayerEpisodePreview\" version=\"1.3.1.0\" src=\"{0}/InPlayerPreview/ClientScript\"></script>",
basePath);

if (!indexContents.Contains(scriptElement))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,15 @@
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
<AssemblyVersion>1.3.0.0</AssemblyVersion>
<FileVersion>1.3.0.0</FileVersion>
<Version>1.3.0.0</Version>
<AssemblyVersion>1.3.1.0</AssemblyVersion>
<FileVersion>1.3.1.0</FileVersion>
<Version>1.3.1.0</Version>
<LangVersion>12</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Jellyfin.Controller" Version="10.9.11" />
<PackageReference Include="Jellyfin.Model" Version="10.9.11" />
<PackageReference Include="Jellyfin.Controller" Version="10.10.0" />
<PackageReference Include="Jellyfin.Model" Version="10.10.0" />
</ItemGroup>

<ItemGroup>
Expand Down
122 changes: 61 additions & 61 deletions Namo.Plugin.InPlayerEpisodePreview/Web/Services/DataFetcher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,96 +10,96 @@ import {ItemType} from "../Models/ItemType";
*/
export class DataFetcher {
constructor(private programDataStore: ProgramDataStore, private authService: AuthService, private logger: Logger) {
const {fetch: originalFetch} = window;
const {fetch: originalFetch} = window
window.fetch = async (...args): Promise<Response> => {
let resource: URL = args[0] as URL;
let config: RequestInit = args[1];
let resource: URL = args[0] as URL
let config: RequestInit = args[1]

if (config && config.headers) {
let auth: string = config.headers[this.authService.getAuthHeader()];
this.authService.setAuthHeaderValue(auth ? auth : '');
let auth: string = config.headers[this.authService.getAuthHeader()]
this.authService.setAuthHeaderValue(auth ? auth : '')
}

const response: Response = await originalFetch(resource, config);
const response: Response = await originalFetch(resource, config)

let url: URL = new URL(resource);
let urlPathname: string = url.pathname;

if (urlPathname.includes('PlaybackInfo')) {
this.logger.debug('Received PlaybackInfo');
if (urlPathname.includes('Episodes')) {
this.logger.debug('Received Episodes')

// save the media id of the currently played video
this.programDataStore.activeMediaSourceId = extractKeyFromString(urlPathname, 'Items/', '/');

} else if (urlPathname.includes('Episodes')) {
this.logger.debug('Received Episodes');

this.programDataStore.userId = extractKeyFromString(url.search, 'UserId=', '&');
response.clone().json().then((data: ItemDto): void => this.saveEpisodeData(data));
this.programDataStore.userId = extractKeyFromString(url.search, 'UserId=', '&')
response.clone().json().then((data: ItemDto): void => this.saveEpisodeData(data))

} else if (urlPathname.includes('Progress')) {
// update the playback state of the currently played video
const sliderCollection: HTMLCollectionOf<Element> = document.getElementsByClassName('osdPositionSlider')
const slider: Element = sliderCollection[sliderCollection.length - 1];
const currentPlaybackPercentage: number = parseFloat((slider as HTMLInputElement).value);
const episode: BaseItem = this.programDataStore.getItemById(this.programDataStore.activeMediaSourceId);
const slider: Element = sliderCollection[sliderCollection.length - 1]
const currentPlaybackPercentage: number = parseFloat((slider as HTMLInputElement).value)
const episode: BaseItem = this.programDataStore.getItemById(this.programDataStore.activeMediaSourceId)

episode.UserData.PlaybackPositionTicks = episode.RunTimeTicks * currentPlaybackPercentage / 100;
episode.UserData.PlayedPercentage = currentPlaybackPercentage;
this.programDataStore.updateItem(episode);
episode.UserData.PlaybackPositionTicks = episode.RunTimeTicks * currentPlaybackPercentage / 100
episode.UserData.PlayedPercentage = currentPlaybackPercentage
this.programDataStore.updateItem(episode)

} else if (urlPathname.includes('PlayedItems')) {
// update the played state of the episode
this.logger.debug('Received PlayedItems');
this.logger.debug('Received PlayedItems')

let itemId: string = extractKeyFromString(urlPathname, 'PlayedItems/');
let changedItem: BaseItem = this.programDataStore.getItemById(itemId);
let itemId: string = extractKeyFromString(urlPathname, 'PlayedItems/')
let changedItem: BaseItem = this.programDataStore.getItemById(itemId)

response.clone().json().then((data) => changedItem.UserData.Played = data["Played"]);
this.programDataStore.updateItem(changedItem);
response.clone().json().then((data) => changedItem.UserData.Played = data["Played"])
this.programDataStore.updateItem(changedItem)

} else if (urlPathname.includes('FavoriteItems')) {
// update the favourite state of the episode
this.logger.debug('Received FavoriteItems');
this.logger.debug('Received FavoriteItems')

let itemId: string = extractKeyFromString(urlPathname, 'FavoriteItems/');
let changedItem: BaseItem = this.programDataStore.getItemById(itemId);

response.clone().json().then((data) => changedItem.UserData.IsFavorite = data["IsFavorite"]);
this.programDataStore.updateItem(changedItem);
this.programDataStore.updateItem(changedItem)

} else if (urlPathname.includes('Items') && url.search.includes('ParentId')) {
this.logger.debug('Received Items with ParentId');
this.logger.debug('Received Items with ParentId')

this.programDataStore.userId = extractKeyFromString(urlPathname, 'Users/', '/');
response.clone().json().then((data: ItemDto): void => this.saveItemData(data));
this.programDataStore.userId = extractKeyFromString(urlPathname, 'Users/', '/')
response.clone().json().then((data: ItemDto): void => this.saveItemData(data))

} else if (urlPathname.includes('Items')) {
this.logger.debug('Received Items without ParentId');
this.logger.debug('Received Items without ParentId')

response.clone().json().then((data: BaseItem): void => {
this.logger.debug('Received single item data -> Setting PlaybackInfo and BoxSet name');

// save the media id of the currently played video
this.programDataStore.activeMediaSourceId = data.Id

// set boxSetName for list title
if (ItemType[data.Type] === ItemType.BoxSet)
this.programDataStore.boxSetName = data.Name;
this.programDataStore.boxSetName = data.Name
});
}

return response;

function extractKeyFromString(searchString: string, startString: string, endString: string = ''): string {
const startIndex: number = searchString.indexOf(startString) + startString.length;
const startIndex: number = searchString.indexOf(startString) + startString.length
if (endString !== '') {
const endIndex: number = searchString.indexOf(endString, startIndex);
return searchString.substring(startIndex, endIndex);
const endIndex: number = searchString.indexOf(endString, startIndex)
return searchString.substring(startIndex, endIndex)
}

return searchString.substring(startIndex);
return searchString.substring(startIndex)
}
};
}

public saveItemData(itemDto: ItemDto): void {
if (this.checkIfDataIsMovieData(itemDto) && itemDto.Items.length > 0) {
this.saveMovieData(itemDto);
this.saveMovieData(itemDto)
return;
}

Expand All @@ -115,60 +115,60 @@ export class DataFetcher {
return itemDto
&& itemDto.Items
&& itemDto.Items.length > 0
&& ItemType[itemDto.Items[0].Type] === ItemType.Movie;
&& ItemType[itemDto.Items[0].Type] === ItemType.Movie
}

public checkIfDataIsEpisodeData(itemDto: ItemDto): boolean {
return itemDto
&& itemDto.Items
&& itemDto.Items.length > 0
&& ItemType[itemDto.Items[0].Type] === ItemType.Episode;
&& ItemType[itemDto.Items[0].Type] === ItemType.Episode
}

public saveMovieData(itemDto: ItemDto): void {
this.programDataStore.type = ItemType.Movie;
this.programDataStore.movies = itemDto.Items;
this.programDataStore.type = ItemType.Movie
this.programDataStore.movies = itemDto.Items
}

public saveEpisodeData(itemDto: ItemDto): void {
this.programDataStore.type = ItemType.Series;
const episodeData: BaseItem[] = itemDto.Items;
this.programDataStore.type = ItemType.Series
const episodeData: BaseItem[] = itemDto.Items

// get all different seasonIds
let seasonIds: Set<string> = new Set<string>(episodeData.map((episode: BaseItem): string => episode.SeasonId))

// group the episodes by seasonId
let group: Record<string, BaseItem[]> = groupBy(episodeData, (episode: BaseItem): string => episode.SeasonId);
let group: Record<string, BaseItem[]> = groupBy(episodeData, (episode: BaseItem): string => episode.SeasonId)

let seasons: Season[] = [];
let iterator: IterableIterator<string> = seasonIds.values();
let value: IteratorResult<string> = iterator.next();
let seasons: Season[] = []
let iterator: IterableIterator<string> = seasonIds.values()
let value: IteratorResult<string> = iterator.next()
while (!value.done) {
let seasonId: string = value.value;
let seasonId: string = value.value
let season: Season = {
seasonId: seasonId,
seasonName: group[seasonId][0].SeasonName,
episodes: group[seasonId]
};
}

season.episodes.sort((a: BaseItem, b: BaseItem): number => a.IndexNumber - b.IndexNumber);
season.episodes.sort((a: BaseItem, b: BaseItem): number => a.IndexNumber - b.IndexNumber)

seasons.push(season);
seasons.push(season)
if (season.episodes.some((episode: BaseItem): boolean => episode.Id === this.programDataStore.activeMediaSourceId))
this.programDataStore.activeSeasonIndex = seasons.length - 1;
this.programDataStore.activeSeasonIndex = seasons.length - 1

value = iterator.next();
value = iterator.next()
}

this.programDataStore.seasons = seasons;
this.programDataStore.seasons = seasons

function groupBy<T>(arr: T[], fn: (item: T) => any): Record<string, T[]> {
return arr.reduce<Record<string, T[]>>((prev: Record<string, T[]>, curr: T): {} => {
const groupKey = fn(curr);
const group: T[] = prev[groupKey] || [];
group.push(curr);
return { ...prev, [groupKey]: group };
}, {});
const groupKey = fn(curr)
const group: T[] = prev[groupKey] || []
group.push(curr)
return { ...prev, [groupKey]: group }
}, {})
}
}
}
2 changes: 1 addition & 1 deletion Namo.Plugin.InPlayerEpisodePreview/build.bat
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
REM Hash tool: https://emn178.github.io/online-tools/md5_checksum.html

REM Flags
set version="1.3.0.0"
set version="1.3.1.0"

REM Create build directory
if not exist ".build" mkdir .build
Expand Down
8 changes: 8 additions & 0 deletions manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,14 @@
"sourceUrl": "https://github.com/Namo2/InPlayerEpisodePreview/releases/download/v1.3.0.0/InPlayerEpisodePreview-1.3.0.0-server.zip",
"checksum": "21e3583d4bb83f3bf61590d0b9dff2d6",
"timestamp": "2024-10-26T12:56:00Z"
},
{
"version": "1.3.1.0",
"changelog": "Fixes issues with the new Jellyfin 10.10.0 release",
"targetAbi": "10.10.0.0",
"sourceUrl": "https://github.com/Namo2/InPlayerEpisodePreview/releases/download/v1.3.1.0/InPlayerEpisodePreview-1.3.1.0-server.zip",
"checksum": "d47bf5f61c4e6abf7d1498cdff91874c",
"timestamp": "2024-10-26T18:34:00Z"
}
]
}
Expand Down

0 comments on commit 52c62bf

Please sign in to comment.