mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 14:53:24 +00:00
improved settings design
This commit is contained in:
@@ -11,12 +11,13 @@ import {
|
|||||||
MaterialIcons,
|
MaterialIcons,
|
||||||
} from "@expo/vector-icons";
|
} from "@expo/vector-icons";
|
||||||
import { useToastController } from "@tamagui/toast";
|
import { useToastController } from "@tamagui/toast";
|
||||||
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import {
|
import {
|
||||||
Adapt,
|
Adapt,
|
||||||
ScrollView,
|
ScrollView,
|
||||||
Select,
|
Select,
|
||||||
Separator,
|
|
||||||
Sheet,
|
Sheet,
|
||||||
|
Spinner,
|
||||||
Text,
|
Text,
|
||||||
useTheme,
|
useTheme,
|
||||||
View,
|
View,
|
||||||
@@ -28,6 +29,7 @@ import type { ThemeStoreOption } from "~/stores/theme";
|
|||||||
import ScreenLayout from "~/components/layout/ScreenLayout";
|
import ScreenLayout from "~/components/layout/ScreenLayout";
|
||||||
import { MWButton } from "~/components/ui/Button";
|
import { MWButton } from "~/components/ui/Button";
|
||||||
import { MWSelect } from "~/components/ui/Select";
|
import { MWSelect } from "~/components/ui/Select";
|
||||||
|
import { MWSeparator } from "~/components/ui/Separator";
|
||||||
import { MWSwitch } from "~/components/ui/Switch";
|
import { MWSwitch } from "~/components/ui/Switch";
|
||||||
import { checkForUpdate } from "~/lib/update";
|
import { checkForUpdate } from "~/lib/update";
|
||||||
import { usePlayerSettingsStore } from "~/stores/settings";
|
import { usePlayerSettingsStore } from "~/stores/settings";
|
||||||
@@ -50,6 +52,30 @@ export default function SettingsScreen() {
|
|||||||
const [updateMarkdownContent, setUpdateMarkdownContent] = useState("");
|
const [updateMarkdownContent, setUpdateMarkdownContent] = useState("");
|
||||||
const [downloadUrl, setDownloadUrl] = useState("");
|
const [downloadUrl, setDownloadUrl] = useState("");
|
||||||
|
|
||||||
|
const mutation = useMutation({
|
||||||
|
mutationKey: ["checkForUpdate"],
|
||||||
|
mutationFn: checkForUpdate,
|
||||||
|
onSuccess: (res) => {
|
||||||
|
if (res) {
|
||||||
|
setUpdateMarkdownContent(res.data.body!);
|
||||||
|
setDownloadUrl(
|
||||||
|
res.data.assets.find(
|
||||||
|
(asset) =>
|
||||||
|
asset.name ===
|
||||||
|
`movie-web.${Platform.select({ ios: "ipa", android: "apk" })}`,
|
||||||
|
)?.browser_download_url ?? "",
|
||||||
|
);
|
||||||
|
setShowUpdateSheet(true);
|
||||||
|
} else {
|
||||||
|
toastController.show("No updates available", {
|
||||||
|
burntOptions: { preset: "none" },
|
||||||
|
native: true,
|
||||||
|
duration: 500,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
const handleGestureControlsToggle = async (isEnabled: boolean) => {
|
const handleGestureControlsToggle = async (isEnabled: boolean) => {
|
||||||
if (isEnabled) {
|
if (isEnabled) {
|
||||||
const { status } = await Brightness.requestPermissionsAsync();
|
const { status } = await Brightness.requestPermissionsAsync();
|
||||||
@@ -61,32 +87,90 @@ export default function SettingsScreen() {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const handleVersionPress = async () => {
|
|
||||||
const res = await checkForUpdate();
|
|
||||||
if (res) {
|
|
||||||
setUpdateMarkdownContent(res.data.body!);
|
|
||||||
setDownloadUrl(
|
|
||||||
res.data.assets.find(
|
|
||||||
(asset) =>
|
|
||||||
asset.name ===
|
|
||||||
`movie-web.${Platform.select({ ios: "ipa", android: "apk" })}`,
|
|
||||||
)?.browser_download_url ?? "",
|
|
||||||
);
|
|
||||||
setShowUpdateSheet(true);
|
|
||||||
} else {
|
|
||||||
toastController.show("No updates available", {
|
|
||||||
burntOptions: { preset: "none" },
|
|
||||||
native: true,
|
|
||||||
duration: 500,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<ScreenLayout>
|
<ScreenLayout>
|
||||||
<View padding={4}>
|
<View padding={4}>
|
||||||
<YStack gap={4}>
|
<YStack gap="$8">
|
||||||
<XStack width={200} alignItems="center" gap="$4">
|
<YStack gap="$4">
|
||||||
|
<Text fontSize="$9" fontWeight="$semibold">
|
||||||
|
Appearance
|
||||||
|
</Text>
|
||||||
|
<MWSeparator />
|
||||||
|
<YStack gap="$2">
|
||||||
|
<XStack gap="$4" alignItems="center">
|
||||||
|
<Text fontWeight="$semibold" flexGrow={1}>
|
||||||
|
Theme
|
||||||
|
</Text>
|
||||||
|
<ThemeSelector />
|
||||||
|
</XStack>
|
||||||
|
</YStack>
|
||||||
|
</YStack>
|
||||||
|
|
||||||
|
<YStack gap="$4">
|
||||||
|
<Text fontSize="$9" fontWeight="$semibold">
|
||||||
|
Player
|
||||||
|
</Text>
|
||||||
|
<MWSeparator />
|
||||||
|
<YStack gap="$2">
|
||||||
|
<XStack gap="$4" alignItems="center">
|
||||||
|
<Text fontWeight="$semibold" flexGrow={1}>
|
||||||
|
Gesture controls
|
||||||
|
</Text>
|
||||||
|
<MWSwitch
|
||||||
|
checked={gestureControls}
|
||||||
|
onCheckedChange={handleGestureControlsToggle}
|
||||||
|
>
|
||||||
|
<MWSwitch.Thumb animation="quicker" />
|
||||||
|
</MWSwitch>
|
||||||
|
</XStack>
|
||||||
|
<XStack gap="$4" alignItems="center">
|
||||||
|
<Text fontWeight="$semibold" flexGrow={1}>
|
||||||
|
Autoplay
|
||||||
|
</Text>
|
||||||
|
<MWSwitch checked={autoPlay} onCheckedChange={setAutoPlay}>
|
||||||
|
<MWSwitch.Thumb animation="quicker" />
|
||||||
|
</MWSwitch>
|
||||||
|
</XStack>
|
||||||
|
</YStack>
|
||||||
|
</YStack>
|
||||||
|
|
||||||
|
<YStack gap="$4">
|
||||||
|
<Text fontSize="$9" fontWeight="$semibold">
|
||||||
|
App
|
||||||
|
</Text>
|
||||||
|
<MWSeparator />
|
||||||
|
<YStack gap="$2">
|
||||||
|
<XStack gap="$4" alignItems="center">
|
||||||
|
<Text fontWeight="$semibold" flexGrow={1}>
|
||||||
|
Version v{Application.nativeApplicationVersion}
|
||||||
|
</Text>
|
||||||
|
<MWButton
|
||||||
|
type="secondary"
|
||||||
|
backgroundColor="$sheetItemBackground"
|
||||||
|
icon={
|
||||||
|
<MaterialCommunityIcons
|
||||||
|
name={Platform.select({
|
||||||
|
ios: "apple",
|
||||||
|
android: "android",
|
||||||
|
})}
|
||||||
|
size={24}
|
||||||
|
color={theme.buttonSecondaryText.val}
|
||||||
|
/>
|
||||||
|
}
|
||||||
|
iconAfter={
|
||||||
|
<>{mutation.isPending && <Spinner color="$purple200" />}</>
|
||||||
|
}
|
||||||
|
disabled={mutation.isPending}
|
||||||
|
onPress={() => mutation.mutate()}
|
||||||
|
animation="quicker"
|
||||||
|
>
|
||||||
|
Update
|
||||||
|
</MWButton>
|
||||||
|
</XStack>
|
||||||
|
</YStack>
|
||||||
|
</YStack>
|
||||||
|
|
||||||
|
{/* <XStack width={200} alignItems="center" gap="$4">
|
||||||
<Text minWidth={110}>Theme</Text>
|
<Text minWidth={110}>Theme</Text>
|
||||||
<Separator minHeight={20} vertical />
|
<Separator minHeight={20} vertical />
|
||||||
<ThemeSelector />
|
<ThemeSelector />
|
||||||
@@ -125,7 +209,7 @@ export default function SettingsScreen() {
|
|||||||
>
|
>
|
||||||
Update
|
Update
|
||||||
</MWButton>
|
</MWButton>
|
||||||
</XStack>
|
</XStack> */}
|
||||||
</YStack>
|
</YStack>
|
||||||
</View>
|
</View>
|
||||||
<UpdateSheet
|
<UpdateSheet
|
||||||
|
@@ -2,6 +2,7 @@ import type { LanguageCode } from "iso-639-1";
|
|||||||
import type { ContentCaption } from "subsrt-ts/dist/types/handler";
|
import type { ContentCaption } from "subsrt-ts/dist/types/handler";
|
||||||
import { useState } from "react";
|
import { useState } from "react";
|
||||||
import { MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
|
import { MaterialCommunityIcons, MaterialIcons } from "@expo/vector-icons";
|
||||||
|
import { useToastController } from "@tamagui/toast";
|
||||||
import { useMutation } from "@tanstack/react-query";
|
import { useMutation } from "@tanstack/react-query";
|
||||||
import { parse } from "subsrt-ts";
|
import { parse } from "subsrt-ts";
|
||||||
import { Spinner, useTheme, View } from "tamagui";
|
import { Spinner, useTheme, View } from "tamagui";
|
||||||
@@ -34,6 +35,7 @@ const parseCaption = async (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const CaptionsSelector = () => {
|
export const CaptionsSelector = () => {
|
||||||
|
const toast = useToastController();
|
||||||
const theme = useTheme();
|
const theme = useTheme();
|
||||||
const [open, setOpen] = useState(false);
|
const [open, setOpen] = useState(false);
|
||||||
const captions = usePlayerStore(
|
const captions = usePlayerStore(
|
||||||
@@ -94,6 +96,13 @@ export const CaptionsSelector = () => {
|
|||||||
color="$playerSettingsUnactiveText"
|
color="$playerSettingsUnactiveText"
|
||||||
fontWeight="bold"
|
fontWeight="bold"
|
||||||
chromeless
|
chromeless
|
||||||
|
onPress={() => {
|
||||||
|
toast.show("Work in progress", {
|
||||||
|
burntOptions: { preset: "none" },
|
||||||
|
native: true,
|
||||||
|
duration: 500,
|
||||||
|
});
|
||||||
|
}}
|
||||||
>
|
>
|
||||||
Customize
|
Customize
|
||||||
</MWButton>
|
</MWButton>
|
||||||
|
14
apps/expo/src/components/ui/Separator.tsx
Normal file
14
apps/expo/src/components/ui/Separator.tsx
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
import { Separator, styled } from "tamagui";
|
||||||
|
|
||||||
|
export const MWSeparator = styled(Separator, {
|
||||||
|
variants: {
|
||||||
|
type: {
|
||||||
|
settings: {
|
||||||
|
borderColor: "$shade300",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
defaultVariants: {
|
||||||
|
type: "settings",
|
||||||
|
},
|
||||||
|
});
|
@@ -29,7 +29,7 @@
|
|||||||
},
|
},
|
||||||
"prettier": "@movie-web/prettier-config",
|
"prettier": "@movie-web/prettier-config",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@movie-web/providers": "^2.2.4",
|
"@movie-web/providers": "^2.2.7",
|
||||||
"parse-hls": "^1.0.7",
|
"parse-hls": "^1.0.7",
|
||||||
"srt-webvtt": "^2.0.0",
|
"srt-webvtt": "^2.0.0",
|
||||||
"tmdb-ts": "^1.6.1"
|
"tmdb-ts": "^1.6.1"
|
||||||
|
47
pnpm-lock.yaml
generated
47
pnpm-lock.yaml
generated
@@ -265,8 +265,8 @@ importers:
|
|||||||
packages/provider-utils:
|
packages/provider-utils:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@movie-web/providers':
|
'@movie-web/providers':
|
||||||
specifier: ^2.2.4
|
specifier: ^2.2.7
|
||||||
version: 2.2.4
|
version: 2.2.7
|
||||||
parse-hls:
|
parse-hls:
|
||||||
specifier: ^1.0.7
|
specifier: ^1.0.7
|
||||||
version: 1.0.7
|
version: 1.0.7
|
||||||
@@ -2894,8 +2894,9 @@ packages:
|
|||||||
tslib: 2.6.2
|
tslib: 2.6.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@movie-web/providers@2.2.4:
|
/@movie-web/providers@2.2.7:
|
||||||
resolution: {integrity: sha512-c10ffR7/oPMbVwpD+Lw0/k5jvx51NbywGJtogzRjeXqDr01o5+pitPeN1qSGaqTg5FBlipn7NSesrd+cczDDQw==}
|
resolution: {integrity: sha512-XwU1IkXrF7e99JtC5Tna00/yuRECqEyBo8bhTtVE6ZFLYj3YQXVm2sdHjcyerjbyAsXvKGeikWEkrvHofTUjDA==}
|
||||||
|
requiresBuild: true
|
||||||
dependencies:
|
dependencies:
|
||||||
cheerio: 1.0.0-rc.12
|
cheerio: 1.0.0-rc.12
|
||||||
cookie: 0.6.0
|
cookie: 0.6.0
|
||||||
@@ -2903,11 +2904,9 @@ packages:
|
|||||||
form-data: 4.0.0
|
form-data: 4.0.0
|
||||||
iso-639-1: 3.1.2
|
iso-639-1: 3.1.2
|
||||||
nanoid: 3.3.7
|
nanoid: 3.3.7
|
||||||
node-fetch: 2.7.0
|
node-fetch: 3.3.2
|
||||||
set-cookie-parser: 2.6.0
|
set-cookie-parser: 2.6.0
|
||||||
unpacker: 1.0.1
|
unpacker: 1.0.1
|
||||||
transitivePeerDependencies:
|
|
||||||
- encoding
|
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/@nodelib/fs.scandir@2.1.5:
|
/@nodelib/fs.scandir@2.1.5:
|
||||||
@@ -6890,6 +6889,11 @@ packages:
|
|||||||
engines: {node: '>= 6'}
|
engines: {node: '>= 6'}
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/data-uri-to-buffer@4.0.1:
|
||||||
|
resolution: {integrity: sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==}
|
||||||
|
engines: {node: '>= 12'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/data-uri-to-buffer@6.0.1:
|
/data-uri-to-buffer@6.0.1:
|
||||||
resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==}
|
resolution: {integrity: sha512-MZd3VlchQkp8rdend6vrx7MmVDJzSNTBvghvKjirLkD+WTChA3KUf0jkE68Q4UyctNqI11zZO9/x2Yx+ub5Cvg==}
|
||||||
engines: {node: '>= 14'}
|
engines: {node: '>= 14'}
|
||||||
@@ -8118,6 +8122,14 @@ packages:
|
|||||||
- encoding
|
- encoding
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/fetch-blob@3.2.0:
|
||||||
|
resolution: {integrity: sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==}
|
||||||
|
engines: {node: ^12.20 || >= 14.13}
|
||||||
|
dependencies:
|
||||||
|
node-domexception: 1.0.0
|
||||||
|
web-streams-polyfill: 3.3.2
|
||||||
|
dev: false
|
||||||
|
|
||||||
/fetch-retry@4.1.1:
|
/fetch-retry@4.1.1:
|
||||||
resolution: {integrity: sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==}
|
resolution: {integrity: sha512-e6eB7zN6UBSwGVwrbWVH+gdLnkW9WwHhmq2YDK1Sh30pzx1onRVGBvogTlUeWxwTa+L86NYdo4hFkh7O8ZjSnA==}
|
||||||
dev: false
|
dev: false
|
||||||
@@ -8288,6 +8300,13 @@ packages:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/formdata-polyfill@4.0.10:
|
||||||
|
resolution: {integrity: sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==}
|
||||||
|
engines: {node: '>=12.20.0'}
|
||||||
|
dependencies:
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
dev: false
|
||||||
|
|
||||||
/framer-motion@6.5.1(react-dom@18.2.0)(react@18.2.0):
|
/framer-motion@6.5.1(react-dom@18.2.0)(react@18.2.0):
|
||||||
resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==}
|
resolution: {integrity: sha512-o1BGqqposwi7cgDrtg0dNONhkmPsUFDaLcKXigzuTFC5x58mE8iyTazxSudFzmT6MEyJKfjjU8ItoMe3W+3fiw==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -10465,6 +10484,11 @@ packages:
|
|||||||
minimatch: 3.1.2
|
minimatch: 3.1.2
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-domexception@1.0.0:
|
||||||
|
resolution: {integrity: sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==}
|
||||||
|
engines: {node: '>=10.5.0'}
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-fetch@2.7.0:
|
/node-fetch@2.7.0:
|
||||||
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
resolution: {integrity: sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==}
|
||||||
engines: {node: 4.x || >=6.0.0}
|
engines: {node: 4.x || >=6.0.0}
|
||||||
@@ -10477,6 +10501,15 @@ packages:
|
|||||||
whatwg-url: 5.0.0
|
whatwg-url: 5.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
|
/node-fetch@3.3.2:
|
||||||
|
resolution: {integrity: sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==}
|
||||||
|
engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
data-uri-to-buffer: 4.0.1
|
||||||
|
fetch-blob: 3.2.0
|
||||||
|
formdata-polyfill: 4.0.10
|
||||||
|
dev: false
|
||||||
|
|
||||||
/node-forge@1.3.1:
|
/node-forge@1.3.1:
|
||||||
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
|
resolution: {integrity: sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==}
|
||||||
engines: {node: '>= 6.13.0'}
|
engines: {node: '>= 6.13.0'}
|
||||||
|
Reference in New Issue
Block a user