feat: update sheet modal

This commit is contained in:
Adrian Castro
2024-03-26 15:43:03 +01:00
parent 5e8422b418
commit 1e975ddce4
4 changed files with 166 additions and 11 deletions

View File

@@ -61,6 +61,7 @@
"react-native-context-menu-view": "^1.14.1", "react-native-context-menu-view": "^1.14.1",
"react-native-gesture-handler": "~2.14.1", "react-native-gesture-handler": "~2.14.1",
"react-native-ios-modal": "^0.1.8", "react-native-ios-modal": "^0.1.8",
"react-native-markdown-display": "^7.0.2",
"react-native-mmkv": "^2.12.2", "react-native-mmkv": "^2.12.2",
"react-native-modal": "^13.0.1", "react-native-modal": "^13.0.1",
"react-native-quick-base64": "^2.0.8", "react-native-quick-base64": "^2.0.8",

View File

@@ -1,6 +1,7 @@
import type { SelectProps } from "tamagui"; import type { SelectProps } from "tamagui";
import React from "react"; import React, { useState } from "react";
import { Platform } from "react-native"; import { Platform } from "react-native";
import Markdown from "react-native-markdown-display";
import * as Application from "expo-application"; import * as Application from "expo-application";
import * as Brightness from "expo-brightness"; import * as Brightness from "expo-brightness";
import * as WebBrowser from "expo-web-browser"; import * as WebBrowser from "expo-web-browser";
@@ -13,6 +14,7 @@ import { useToastController } from "@tamagui/toast";
import { import {
Adapt, Adapt,
Label, Label,
ScrollView,
Select, Select,
Separator, Separator,
Sheet, Sheet,
@@ -44,6 +46,9 @@ export default function SettingsScreen() {
const { gestureControls, setGestureControls, autoPlay, setAutoPlay } = const { gestureControls, setGestureControls, autoPlay, setAutoPlay } =
usePlayerSettingsStore(); usePlayerSettingsStore();
const toastController = useToastController(); const toastController = useToastController();
const [showUpdateSheet, setShowUpdateSheet] = useState(false);
const [updateMarkdownContent, setUpdateMarkdownContent] = useState("");
const [downloadUrl, setDownloadUrl] = useState("");
const handleGestureControlsToggle = async (isEnabled: boolean) => { const handleGestureControlsToggle = async (isEnabled: boolean) => {
if (isEnabled) { if (isEnabled) {
@@ -57,14 +62,17 @@ export default function SettingsScreen() {
}; };
const handleVersionPress = async () => { const handleVersionPress = async () => {
const url = await checkForUpdate(); const res = await checkForUpdate();
if (url) { if (res) {
toastController.show("Update available", { setUpdateMarkdownContent(res.data.body!);
burntOptions: { preset: "none" }, setDownloadUrl(
native: true, res.data.assets.find(
duration: 500, (asset) =>
}); asset.name ===
await WebBrowser.openBrowserAsync(url); `movie-web.${Platform.select({ ios: "ipa", android: "apk" })}`,
)?.browser_download_url ?? "",
);
setShowUpdateSheet(true);
} else { } else {
toastController.show("No updates available", { toastController.show("No updates available", {
burntOptions: { preset: "none" }, burntOptions: { preset: "none" },
@@ -122,10 +130,87 @@ export default function SettingsScreen() {
</XStack> </XStack>
</YStack> </YStack>
</View> </View>
<UpdateSheet
markdownContent={updateMarkdownContent}
open={showUpdateSheet}
setShowUpdateSheet={setShowUpdateSheet}
downloadUrl={downloadUrl}
/>
</ScreenLayout> </ScreenLayout>
); );
} }
export function UpdateSheet({
markdownContent,
open,
setShowUpdateSheet,
downloadUrl,
}: {
markdownContent: string;
open: boolean;
setShowUpdateSheet: (value: boolean) => void;
downloadUrl: string;
}) {
const theme = useTheme();
return (
<Sheet
modal
open={open}
onOpenChange={setShowUpdateSheet}
dismissOnSnapToBottom
dismissOnOverlayPress
animationConfig={{
type: "spring",
damping: 20,
mass: 1.2,
stiffness: 250,
}}
snapPoints={[35]}
>
<Sheet.Handle backgroundColor="$sheetHandle" />
<Sheet.Frame
backgroundColor="$sheetBackground"
padding="$4"
alignItems="center"
justifyContent="center"
>
<ScrollView>
<Markdown
style={{
text: {
color: "white",
},
}}
>
{markdownContent}
</Markdown>
</ScrollView>
<MWButton
type="secondary"
backgroundColor="$sheetItemBackground"
icon={
<MaterialCommunityIcons
name={Platform.select({ ios: "apple", android: "android" })}
size={24}
color={theme.buttonSecondaryText.val}
/>
}
onPress={() => WebBrowser.openBrowserAsync(downloadUrl)}
>
Download
</MWButton>
</Sheet.Frame>
<Sheet.Overlay
animation="lazy"
backgroundColor="rgba(0, 0, 0, 0.8)"
enterStyle={{ opacity: 0 }}
exitStyle={{ opacity: 0 }}
/>
</Sheet>
);
}
export function ThemeSelector(props: SelectProps) { export function ThemeSelector(props: SelectProps) {
const theme = useTheme(); const theme = useTheme();
const themeStore = useThemeStore((s) => s.theme); const themeStore = useThemeStore((s) => s.theme);

View File

@@ -24,7 +24,7 @@ function isVersionHigher(newVersion: string, currentVersion: string): boolean {
return false; return false;
} }
export async function checkForUpdate(): Promise<string | undefined> { export async function checkForUpdate() {
const octokit = new Octokit(); const octokit = new Octokit();
const res = await octokit.repos const res = await octokit.repos
@@ -40,6 +40,6 @@ export async function checkForUpdate(): Promise<string | undefined> {
const currentVersion = Application.nativeApplicationVersion ?? "0.0.0"; const currentVersion = Application.nativeApplicationVersion ?? "0.0.0";
if (isVersionHigher(latestVersion, currentVersion)) { if (isVersionHigher(latestVersion, currentVersion)) {
return res.data.html_url; return res;
} }
} }

69
pnpm-lock.yaml generated
View File

@@ -155,6 +155,9 @@ importers:
react-native-ios-modal: react-native-ios-modal:
specifier: ^0.1.8 specifier: ^0.1.8
version: 0.1.8(react-native@0.73.6)(react@18.2.0) version: 0.1.8(react-native@0.73.6)(react@18.2.0)
react-native-markdown-display:
specifier: ^7.0.2
version: 7.0.2(react-native@0.73.6)(react@18.2.0)
react-native-mmkv: react-native-mmkv:
specifier: ^2.12.2 specifier: ^2.12.2
version: 2.12.2(react-native@0.73.6)(react@18.2.0) version: 2.12.2(react-native@0.73.6)(react@18.2.0)
@@ -6262,6 +6265,10 @@ packages:
engines: {node: '>=10'} engines: {node: '>=10'}
dev: false dev: false
/camelize@1.0.1:
resolution: {integrity: sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==}
dev: false
/caniuse-lite@1.0.30001583: /caniuse-lite@1.0.30001583:
resolution: {integrity: sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==} resolution: {integrity: sha512-acWTYaha8xfhA/Du/z4sNZjHUWjkiuoAi2LM+T/aL+kemKQgPT1xBb/YKjlQ0Qo8gvbHsGNplrEJ+9G3gL7i4Q==}
@@ -6786,6 +6793,11 @@ packages:
engines: {node: '>=8'} engines: {node: '>=8'}
dev: false dev: false
/css-color-keywords@1.0.0:
resolution: {integrity: sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==}
engines: {node: '>=4'}
dev: false
/css-in-js-utils@3.1.0: /css-in-js-utils@3.1.0:
resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==} resolution: {integrity: sha512-fJAcud6B3rRu+KHYk+Bwf+WFL2MDCJJ1XG9x137tJQ0xYxor7XziQtuGFbWNdqrvF4Tk26O3H73nfVqXt/fW1A==}
dependencies: dependencies:
@@ -6802,6 +6814,14 @@ packages:
nth-check: 2.1.1 nth-check: 2.1.1
dev: false dev: false
/css-to-react-native@3.2.0:
resolution: {integrity: sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==}
dependencies:
camelize: 1.0.1
css-color-keywords: 1.0.0
postcss-value-parser: 4.2.0
dev: false
/css-tree@1.1.3: /css-tree@1.1.3:
resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==} resolution: {integrity: sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==}
engines: {node: '>=8.0.0'} engines: {node: '>=8.0.0'}
@@ -7162,6 +7182,10 @@ packages:
once: 1.4.0 once: 1.4.0
dev: false dev: false
/entities@2.0.3:
resolution: {integrity: sha512-MyoZ0jgnLvB2X3Lg5HqpFmn1kybDiIfEQmKzTb5apr51Rb+T3KdmMiqa70T+bhGnyv7bQ6WMj2QMHpGMmlrUYQ==}
dev: false
/entities@4.5.0: /entities@4.5.0:
resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==}
engines: {node: '>=0.12'} engines: {node: '>=0.12'}
@@ -9809,6 +9833,12 @@ packages:
resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==} resolution: {integrity: sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==}
dev: false dev: false
/linkify-it@2.2.0:
resolution: {integrity: sha512-GnAl/knGn+i1U/wjBz3akz2stz+HrHLsxMwHQGofCDfPvlf+gDKN58UtfmUquTY4/MXeE2x7k19KQmeoZi94Iw==}
dependencies:
uc.micro: 1.0.6
dev: false
/locate-path@3.0.0: /locate-path@3.0.0:
resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==} resolution: {integrity: sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==}
engines: {node: '>=6'} engines: {node: '>=6'}
@@ -9947,6 +9977,17 @@ packages:
tmpl: 1.0.5 tmpl: 1.0.5
dev: false dev: false
/markdown-it@10.0.0:
resolution: {integrity: sha512-YWOP1j7UbDNz+TumYP1kpwnP0aEa711cJjrAQrzd0UXlbJfc5aAq0F/PZHjiioqDC1NKgvIMX+o+9Bk7yuM2dg==}
hasBin: true
dependencies:
argparse: 1.0.10
entities: 2.0.3
linkify-it: 2.2.0
mdurl: 1.0.1
uc.micro: 1.0.6
dev: false
/marky@1.2.5: /marky@1.2.5:
resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==} resolution: {integrity: sha512-q9JtQJKjpsVxCRVgQ+WapguSbKC3SQ5HEzFGPAJMStgh3QjCawp00UKv3MTTAArTmGmmPUvllHZoNbZ3gs0I+Q==}
dev: false dev: false
@@ -9991,6 +10032,10 @@ packages:
resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==} resolution: {integrity: sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==}
dev: false dev: false
/mdurl@1.0.1:
resolution: {integrity: sha512-/sKlQJCBYVY9Ers9hqzKou4H6V5UWc/M59TH2dvkt+84itfnq7uFOMLpOiOS4ujvHP4etln18fmIxA5R5fll0g==}
dev: false
/memoize-one@5.2.1: /memoize-one@5.2.1:
resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==} resolution: {integrity: sha512-zYiwtZUcYyXKo/np96AGZAckk+FWWsUdJ3cHGGmld7+AhvcWmQyGCYUh1hc4Q/pkOhb65dQR/pqCyK0cOaHz4Q==}
dev: false dev: false
@@ -11497,6 +11542,12 @@ packages:
- supports-color - supports-color
dev: false dev: false
/react-native-fit-image@1.5.5:
resolution: {integrity: sha512-Wl3Vq2DQzxgsWKuW4USfck9zS7YzhvLNPpkwUUCF90bL32e1a0zOVQ3WsJILJOwzmPdHfzZmWasiiAUNBkhNkg==}
dependencies:
prop-types: 15.8.1
dev: false
/react-native-gesture-handler@2.14.1(react-native@0.73.6)(react@18.2.0): /react-native-gesture-handler@2.14.1(react-native@0.73.6)(react@18.2.0):
resolution: {integrity: sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==} resolution: {integrity: sha512-YiM1BApV4aKeuwsM6O4C2ufwewYEKk6VMXOt0YqEZFMwABBFWhXLySFZYjBSNRU2USGppJbfHP1q1DfFQpKhdA==}
peerDependencies: peerDependencies:
@@ -11522,6 +11573,20 @@ packages:
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0) react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
dev: false dev: false
/react-native-markdown-display@7.0.2(react-native@0.73.6)(react@18.2.0):
resolution: {integrity: sha512-Mn4wotMvMfLAwbX/huMLt202W5DsdpMO/kblk+6eUs55S57VVNni1gzZCh5qpznYLjIQELNh50VIozEfY6fvaQ==}
peerDependencies:
react: '>=16.2.0'
react-native: '>=0.50.4'
dependencies:
css-to-react-native: 3.2.0
markdown-it: 10.0.0
prop-types: 15.8.1
react: 18.2.0
react-native: 0.73.6(@babel/core@7.23.9)(@babel/preset-env@7.23.9)(react@18.2.0)
react-native-fit-image: 1.5.5
dev: false
/react-native-mmkv@2.12.2(react-native@0.73.6)(react@18.2.0): /react-native-mmkv@2.12.2(react-native@0.73.6)(react@18.2.0):
resolution: {integrity: sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg==} resolution: {integrity: sha512-6058Aq0p57chPrUutLGe9fYoiDVDNMU2PKV+lLFUJ3GhoHvUrLdsS1PDSCLr00yqzL4WJQ7TTzH+V8cpyrNcfg==}
peerDependencies: peerDependencies:
@@ -13243,6 +13308,10 @@ packages:
resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==} resolution: {integrity: sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==}
dev: false dev: false
/uc.micro@1.0.6:
resolution: {integrity: sha512-8Y75pvTYkLJW2hWQHXxoqRgV7qb9B+9vFEtidML+7koHUFapnVJAZ6cKs+Qjz5Aw3aZWHMC6u0wJE3At+nSGwA==}
dev: false
/uglify-js@3.17.4: /uglify-js@3.17.4:
resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==}
engines: {node: '>=0.8.0'} engines: {node: '>=0.8.0'}