Compare commits

...

4 Commits

Author SHA1 Message Date
Fredrik Burmester
4696671bf5 Merge branch 'develop' into feat/refresh-metadata 2025-11-15 09:08:48 +01:00
Fredrik Burmester
69d744c86f fix(android): update fill color for refresh button based on loading state 2025-11-08 12:38:18 +01:00
Fredrik Burmester
ad1bd72123 feat: add translation support for metadata refresh messages 2025-11-08 12:37:34 +01:00
Fredrik Burmester
b93c56f300 feat: refresh metadata for item 2025-11-08 10:15:06 +01:00
4 changed files with 93 additions and 2 deletions

View File

@@ -35,6 +35,7 @@ import { ItemTechnicalDetails } from "./ItemTechnicalDetails";
import { MediaSourceSheet } from "./MediaSourceSheet"; import { MediaSourceSheet } from "./MediaSourceSheet";
import { MoreMoviesWithActor } from "./MoreMoviesWithActor"; import { MoreMoviesWithActor } from "./MoreMoviesWithActor";
import { PlayInRemoteSessionButton } from "./PlayInRemoteSession"; import { PlayInRemoteSessionButton } from "./PlayInRemoteSession";
import { RefreshMetadata } from "./RefreshMetadata";
import { TrackSheet } from "./TrackSheet"; import { TrackSheet } from "./TrackSheet";
const Chromecast = !Platform.isTV ? require("./Chromecast") : null; const Chromecast = !Platform.isTV ? require("./Chromecast") : null;
@@ -115,7 +116,10 @@ export const ItemContent: React.FC<ItemContentProps> = React.memo(
<DownloadSingleItem item={item} size='large' /> <DownloadSingleItem item={item} size='large' />
)} )}
{user?.Policy?.IsAdministrator && ( {user?.Policy?.IsAdministrator && (
<PlayInRemoteSessionButton item={item} size='large' /> <>
<PlayInRemoteSessionButton item={item} size='large' />
<RefreshMetadata item={item} />
</>
)} )}
<PlayedStatus items={[item]} size='large' /> <PlayedStatus items={[item]} size='large' />
@@ -132,7 +136,10 @@ export const ItemContent: React.FC<ItemContentProps> = React.memo(
<DownloadSingleItem item={item} size='large' /> <DownloadSingleItem item={item} size='large' />
)} )}
{user?.Policy?.IsAdministrator && ( {user?.Policy?.IsAdministrator && (
<PlayInRemoteSessionButton item={item} size='large' /> <>
<PlayInRemoteSessionButton item={item} size='large' />
<RefreshMetadata item={item} />
</>
)} )}
<PlayedStatus items={[item]} size='large' /> <PlayedStatus items={[item]} size='large' />

View File

@@ -0,0 +1,38 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import type { FC } from "react";
import { Platform, View, type ViewProps } from "react-native";
import { RoundButton } from "@/components/RoundButton";
import { useRefreshMetadata } from "@/hooks/useRefreshMetadata";
interface Props extends ViewProps {
item: BaseItemDto;
}
export const RefreshMetadata: FC<Props> = ({ item, ...props }) => {
const { refreshMetadata, isRefreshing } = useRefreshMetadata(item);
if (Platform.OS === "ios") {
return (
<View {...props}>
<RoundButton
size='large'
icon='reload-outline'
onPress={refreshMetadata}
hapticFeedback={!isRefreshing}
/>
</View>
);
}
return (
<View {...props}>
<RoundButton
size='large'
icon='reload-outline'
onPress={refreshMetadata}
hapticFeedback={!isRefreshing}
fillColor={isRefreshing ? "primary" : undefined}
/>
</View>
);
};

View File

@@ -0,0 +1,42 @@
import type { BaseItemDto } from "@jellyfin/sdk/lib/generated-client";
import { getItemRefreshApi } from "@jellyfin/sdk/lib/utils/api";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { useAtom } from "jotai";
import { useTranslation } from "react-i18next";
import { toast } from "sonner-native";
import { apiAtom } from "@/providers/JellyfinProvider";
export const useRefreshMetadata = (item: BaseItemDto) => {
const queryClient = useQueryClient();
const [api] = useAtom(apiAtom);
const { t } = useTranslation();
const type = "item";
const refreshMetadataMutation = useMutation({
mutationFn: async () => {
if (api && item.Id) {
await getItemRefreshApi(api).refreshItem({
itemId: item.Id,
});
}
},
onSuccess: () => {
toast.success(t("metadata.refresh_triggered"));
queryClient.invalidateQueries({ queryKey: [type, item.Id] });
},
onError: (error) => {
console.error("Failed to refresh metadata:", error);
toast.error(t("metadata.refresh_failed"));
},
});
const refreshMetadata = () => {
refreshMetadataMutation.mutate();
};
return {
refreshMetadata,
isRefreshing: refreshMetadataMutation.isPending,
refreshMetadataMutation,
};
};

View File

@@ -528,5 +528,9 @@
"library": "Library", "library": "Library",
"custom_links": "Custom Links", "custom_links": "Custom Links",
"favorites": "Favorites" "favorites": "Favorites"
},
"metadata": {
"refresh_triggered": "Metadata refresh triggered",
"refresh_failed": "Failed to refresh metadata"
} }
} }