/*
* Kyoo - A portable and vast media library solution.
* Copyright (c) Kyoo.
*
* See AUTHORS.md and LICENSE file in the project root for full license information.
*
* Kyoo is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* any later version.
*
* Kyoo is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Kyoo. If not, see .
*/
import { type User, queryFn, useAccount } from "@kyoo/models";
import {
Container,
H1,
HR,
Icon,
P,
SubP,
SwitchVariant,
imageBorderRadius,
ts,
} from "@kyoo/primitives";
import { useMutation, useQueryClient } from "@tanstack/react-query";
import { Children, type ReactElement, type ReactNode } from "react";
import { type Falsy, View } from "react-native";
import { percent, px, rem, useYoshiki } from "yoshiki/native";
export const Preference = ({
customIcon,
icon,
label,
description,
children,
...props
}: {
customIcon?: ReactElement | Falsy;
icon: Icon;
label: string | ReactElement;
description: string | ReactElement;
children?: ReactNode;
}) => {
const { css } = useYoshiki();
return (
{customIcon ?? }
{label}
{description}
{children}
);
};
export const SettingsContainer = ({
children,
title,
extra,
extraTop,
...props
}: {
children: ReactElement | (ReactElement | Falsy)[] | Falsy;
title: string;
extra?: ReactElement;
extraTop?: ReactElement;
}) => {
const { css } = useYoshiki();
return (
{title}
{extraTop}
{({ css }) => (
theme.background,
borderRadius: px(imageBorderRadius),
})}
>
{Children.map(children, (x, i) => (
<>
{i !== 0 &&
}
{x}
>
))}
)}
{extra}
);
};
export const useSetting = (setting: Setting) => {
const account = useAccount();
const queryClient = useQueryClient();
const { mutateAsync } = useMutation({
mutationFn: async (update: Partial) =>
await queryFn({
path: ["auth", "me"],
method: "PATCH",
body: { settings: { ...account!.settings, ...update } },
}),
onMutate: async (newSettings) => {
const next = { ...account!, settings: { ...account!.settings, ...newSettings } };
await queryClient.cancelQueries({ queryKey: ["auth", "me"] });
const previous = queryClient.getQueryData(["auth", "me"]);
queryClient.setQueryData(["auth", "me"], next);
return { previous, next };
},
onError: (_, __, context) => {
queryClient.setQueryData(["auth", "me"], context!.previous);
},
onSettled: async () => await queryClient.invalidateQueries({ queryKey: ["auth", "me"] }),
});
if (!account) return null;
return [
account.settings[setting],
async (value: User["settings"][Setting]) => {
await mutateAsync({ [setting]: value });
},
] as const;
};