Merge pull request #430 from streamyfin/feat/refreshsettings

feat: Refresh remote settings
This commit is contained in:
Fredrik Burmester
2025-01-14 16:29:00 +01:00
committed by GitHub
4 changed files with 67 additions and 33 deletions

View File

@@ -59,7 +59,13 @@ export default function index() {
const user = useAtomValue(userAtom); const user = useAtomValue(userAtom);
const [loading, setLoading] = useState(false); const [loading, setLoading] = useState(false);
const [settings, _] = useSettings(); const [
settings,
updateSettings,
pluginSettings,
setPluginSettings,
refreshStreamyfinPluginSettings,
] = useSettings();
const [isConnected, setIsConnected] = useState<boolean | null>(null); const [isConnected, setIsConnected] = useState<boolean | null>(null);
const [loadingRetry, setLoadingRetry] = useState(false); const [loadingRetry, setLoadingRetry] = useState(false);
@@ -110,6 +116,7 @@ export default function index() {
cleanCacheDirectory().catch((e) => cleanCacheDirectory().catch((e) =>
console.error("Something went wrong cleaning cache directory") console.error("Something went wrong cleaning cache directory")
); );
return () => { return () => {
unsubscribe(); unsubscribe();
}; };
@@ -154,6 +161,7 @@ export default function index() {
const refetch = useCallback(async () => { const refetch = useCallback(async () => {
setLoading(true); setLoading(true);
await refreshStreamyfinPluginSettings();
await invalidateCache(); await invalidateCache();
setLoading(false); setLoading(false);
}, []); }, []);
@@ -189,7 +197,7 @@ export default function index() {
); );
let sections: Section[] = []; let sections: Section[] = [];
if (settings?.home === null || settings?.home?.sections === null) { if (!settings?.home || !settings?.home?.sections) {
sections = useMemo(() => { sections = useMemo(() => {
if (!api || !user?.Id) return []; if (!api || !user?.Id) return [];
@@ -305,7 +313,7 @@ export default function index() {
( (
await getItemsApi(api).getItems({ await getItemsApi(api).getItems({
userId: user?.Id, userId: user?.Id,
limit: section.items?.limit || 20, limit: section.items?.limit || 25,
recursive: true, recursive: true,
includeItemTypes: section.items?.includeItemTypes, includeItemTypes: section.items?.includeItemTypes,
sortBy: section.items?.sortBy, sortBy: section.items?.sortBy,

View File

@@ -9,7 +9,7 @@ import * as BackgroundFetch from "expo-background-fetch";
import { useRouter } from "expo-router"; import { useRouter } from "expo-router";
import * as ScreenOrientation from "expo-screen-orientation"; import * as ScreenOrientation from "expo-screen-orientation";
import * as TaskManager from "expo-task-manager"; import * as TaskManager from "expo-task-manager";
import React, {useEffect, useMemo} from "react"; import React, { useEffect, useMemo } from "react";
import { Linking, Switch, TouchableOpacity } from "react-native"; import { Linking, Switch, TouchableOpacity } from "react-native";
import { toast } from "sonner-native"; import { toast } from "sonner-native";
import { Text } from "../common/Text"; import { Text } from "../common/Text";
@@ -52,28 +52,28 @@ export const OtherSettings: React.FC = () => {
/********************** /**********************
*********************/ *********************/
const disabled = useMemo(() => ( const disabled = useMemo(
pluginSettings?.autoRotate?.locked === true && () =>
pluginSettings?.defaultVideoOrientation?.locked === true && pluginSettings?.autoRotate?.locked === true &&
pluginSettings?.safeAreaInControlsEnabled?.locked === true && pluginSettings?.defaultVideoOrientation?.locked === true &&
pluginSettings?.showCustomMenuLinks?.locked === true && pluginSettings?.safeAreaInControlsEnabled?.locked === true &&
pluginSettings?.hiddenLibraries?.locked === true && pluginSettings?.showCustomMenuLinks?.locked === true &&
pluginSettings?.disableHapticFeedback?.locked === true pluginSettings?.hiddenLibraries?.locked === true &&
), [pluginSettings]); pluginSettings?.disableHapticFeedback?.locked === true,
[pluginSettings]
);
const orientations = [ const orientations = [
ScreenOrientation.OrientationLock.DEFAULT, ScreenOrientation.OrientationLock.DEFAULT,
ScreenOrientation.OrientationLock.PORTRAIT_UP, ScreenOrientation.OrientationLock.PORTRAIT_UP,
ScreenOrientation.OrientationLock.LANDSCAPE_LEFT, ScreenOrientation.OrientationLock.LANDSCAPE_LEFT,
ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT ScreenOrientation.OrientationLock.LANDSCAPE_RIGHT,
] ];
if (!settings) return null; if (!settings) return null;
return ( return (
<DisabledSetting <DisabledSetting disabled={disabled}>
disabled={disabled}
>
<ListGroup title="Other" className=""> <ListGroup title="Other" className="">
<ListItem <ListItem
title="Auto rotate" title="Auto rotate"
@@ -82,32 +82,40 @@ export const OtherSettings: React.FC = () => {
<Switch <Switch
value={settings.autoRotate} value={settings.autoRotate}
disabled={pluginSettings?.autoRotate?.locked} disabled={pluginSettings?.autoRotate?.locked}
onValueChange={(value) => updateSettings({autoRotate: value})} onValueChange={(value) => updateSettings({ autoRotate: value })}
/> />
</ListItem> </ListItem>
<ListItem <ListItem
title="Video orientation" title="Video orientation"
disabled={pluginSettings?.defaultVideoOrientation?.locked || settings.autoRotate} disabled={
pluginSettings?.defaultVideoOrientation?.locked ||
settings.autoRotate
}
> >
<Dropdown <Dropdown
data={orientations} data={orientations}
disabled={pluginSettings?.defaultVideoOrientation?.locked || settings.autoRotate} disabled={
keyExtractor={String} pluginSettings?.defaultVideoOrientation?.locked ||
titleExtractor={(item) => settings.autoRotate
ScreenOrientationEnum[item]
} }
keyExtractor={String}
titleExtractor={(item) => ScreenOrientationEnum[item]}
title={ title={
<TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3"> <TouchableOpacity className="flex flex-row items-center justify-between py-3 pl-3">
<Text className="mr-1 text-[#8E8D91]"> <Text className="mr-1 text-[#8E8D91]">
{ScreenOrientationEnum[settings.defaultVideoOrientation]} {ScreenOrientationEnum[settings.defaultVideoOrientation]}
</Text> </Text>
<Ionicons name="chevron-expand-sharp" size={18} color="#5A5960"/> <Ionicons
name="chevron-expand-sharp"
size={18}
color="#5A5960"
/>
</TouchableOpacity> </TouchableOpacity>
} }
label="Orientation" label="Orientation"
onSelected={(defaultVideoOrientation) => onSelected={(defaultVideoOrientation) =>
updateSettings({defaultVideoOrientation}) updateSettings({ defaultVideoOrientation })
} }
/> />
</ListItem> </ListItem>
@@ -120,7 +128,7 @@ export const OtherSettings: React.FC = () => {
value={settings.safeAreaInControlsEnabled} value={settings.safeAreaInControlsEnabled}
disabled={pluginSettings?.safeAreaInControlsEnabled?.locked} disabled={pluginSettings?.safeAreaInControlsEnabled?.locked}
onValueChange={(value) => onValueChange={(value) =>
updateSettings({safeAreaInControlsEnabled: value}) updateSettings({ safeAreaInControlsEnabled: value })
} }
/> />
</ListItem> </ListItem>
@@ -138,7 +146,7 @@ export const OtherSettings: React.FC = () => {
value={settings.showCustomMenuLinks} value={settings.showCustomMenuLinks}
disabled={pluginSettings?.showCustomMenuLinks?.locked} disabled={pluginSettings?.showCustomMenuLinks?.locked}
onValueChange={(value) => onValueChange={(value) =>
updateSettings({showCustomMenuLinks: value}) updateSettings({ showCustomMenuLinks: value })
} }
/> />
</ListItem> </ListItem>
@@ -155,7 +163,7 @@ export const OtherSettings: React.FC = () => {
value={settings.disableHapticFeedback} value={settings.disableHapticFeedback}
disabled={pluginSettings?.disableHapticFeedback?.locked} disabled={pluginSettings?.disableHapticFeedback?.locked}
onValueChange={(disableHapticFeedback) => onValueChange={(disableHapticFeedback) =>
updateSettings({disableHapticFeedback}) updateSettings({ disableHapticFeedback })
} }
/> />
</ListItem> </ListItem>

View File

@@ -174,6 +174,14 @@ export const JellyfinProvider: React.FC<{ children: ReactNode }> = ({
useInterval(pollQuickConnect, isPolling ? 1000 : null); useInterval(pollQuickConnect, isPolling ? 1000 : null);
useEffect(() => {
(async () => {
await refreshStreamyfinPluginSettings();
})();
}, []);
useInterval(refreshStreamyfinPluginSettings, 60 * 5 * 1000); // 5 min
const discoverServers = async (url: string): Promise<Server[]> => { const discoverServers = async (url: string): Promise<Server[]> => {
const servers = await jellyfin?.discovery.getRecommendedServerCandidates( const servers = await jellyfin?.discovery.getRecommendedServerCandidates(
url url

View File

@@ -189,7 +189,14 @@ const loadSettings = (): Settings => {
} }
}; };
const EXCLUDE_FROM_SAVE = ["home"];
const saveSettings = (settings: Settings) => { const saveSettings = (settings: Settings) => {
Object.keys(settings).forEach((key) => {
if (EXCLUDE_FROM_SAVE.includes(key)) {
delete settings[key as keyof Settings];
}
});
const jsonValue = JSON.stringify(settings); const jsonValue = JSON.stringify(settings);
storage.set("settings", jsonValue); storage.set("settings", jsonValue);
}; };
@@ -221,11 +228,13 @@ export const useSettings = () => {
const refreshStreamyfinPluginSettings = useCallback(async () => { const refreshStreamyfinPluginSettings = useCallback(async () => {
if (!api) return; if (!api) return;
const settings = await api const settings = await api.getStreamyfinPluginConfig().then(
.getStreamyfinPluginConfig() ({ data }) => {
.then(({ data }) => data?.settings); writeInfoLog(`Got remote settings`);
return data?.settings;
writeInfoLog(`Got remote settings: ${JSON.stringify(settings)}`); },
(err) => undefined
);
setPluginSettings(settings); setPluginSettings(settings);
return settings; return settings;
@@ -275,6 +284,7 @@ export const useSettings = () => {
if (Object.keys(unlockedPluginDefaults).length > 0) { if (Object.keys(unlockedPluginDefaults).length > 0) {
updateSettings(unlockedPluginDefaults); updateSettings(unlockedPluginDefaults);
} }
return { return {
..._settings, ..._settings,
...overrideSettings, ...overrideSettings,