feat: intro page

This commit is contained in:
Fredrik Burmester
2025-01-05 22:17:02 +01:00
parent cad03a3566
commit 58ec915699
6 changed files with 271 additions and 3 deletions

View File

@@ -83,6 +83,14 @@ export default function IndexLayout() {
title: "",
}}
/>
<Stack.Screen
name="intro/page"
options={{
headerShown: false,
title: "",
presentation: "modal",
}}
/>
{Object.entries(nestedTabPageScreenOptions).map(([name, options]) => (
<Stack.Screen key={name} name={name} options={options} />
))}

View File

@@ -23,7 +23,7 @@ import {
getUserViewsApi,
} from "@jellyfin/sdk/lib/utils/api";
import NetInfo from "@react-native-community/netinfo";
import { QueryFunction, useQuery, useQueryClient } from "@tanstack/react-query";
import { QueryFunction, useQuery } from "@tanstack/react-query";
import { useNavigation, useRouter } from "expo-router";
import { useAtomValue } from "jotai";
import { useCallback, useEffect, useMemo, useState } from "react";

View File

@@ -0,0 +1,110 @@
import { Button } from "@/components/Button";
import { Text } from "@/components/common/Text";
import { storage } from "@/utils/mmkv";
import { Feather, Ionicons } from "@expo/vector-icons";
import { Image } from "expo-image";
import { useFocusEffect, useRouter } from "expo-router";
import { useCallback } from "react";
import { TouchableOpacity, View } from "react-native";
export default function page() {
const router = useRouter();
useFocusEffect(
useCallback(() => {
storage.set("hasShownIntro", true);
}, [])
);
return (
<View className="bg-neutral-900 h-full py-32 px-4 space-y-4">
<View>
<Text className="text-3xl font-bold text-center mb-2">
Welcome to Streamyfin
</Text>
<Text className="text-center">
A free and open source client for Jellyfin.
</Text>
</View>
<View>
<Text className="text-lg font-bold">Features</Text>
<Text className="text-xs">
Streamyfin has a bunch of features and integrates with a
wide array of software which you can find in the settings menu, these
include:
</Text>
<View className="flex flex-row items-center mt-4">
<Image
source={require("@/assets/icons/jellyseerr-logo.svg")}
style={{
width: 50,
height: 50,
}}
/>
<View className="shrink ml-2">
<Text className="font-bold mb-1">Jellyseerr</Text>
<Text className="shrink text-xs">
Connect to your Jellyseerr instance and request movies directly in
the app.
</Text>
</View>
</View>
<View className="flex flex-row items-center mt-4">
<View
style={{
width: 50,
height: 50,
}}
className="flex items-center justify-center"
>
<Ionicons name="cloud-download-outline" size={32} color="white" />
</View>
<View className="shrink ml-2">
<Text className="font-bold mb-1">Downloads</Text>
<Text className="shrink text-xs">
Download movies and tv-shows to view offline. Use either the
default method or install the optimize server to download files in
the background.
</Text>
</View>
</View>
<View className="flex flex-row items-center mt-4">
<View
style={{
width: 50,
height: 50,
}}
className="flex items-center justify-center"
>
<Feather name="cast" size={28} color={"white"} />
</View>
<View className="shrink ml-2">
<Text className="font-bold mb-1">Chromecast</Text>
<Text className="shrink text-xs">
Cast movies and tv-shows to your Chromecast devices.
</Text>
</View>
</View>
</View>
<Button
onPress={() => {
router.back();
}}
className="mt-4"
>
Done
</Button>
<TouchableOpacity
onPress={() => {
router.back();
router.push("/settings");
}}
className="mt-4"
>
<Text className="text-purple-600 text-center">Go to settings</Text>
</TouchableOpacity>
</View>
);
}

View File

@@ -18,6 +18,7 @@ import { useNavigation, useRouter } from "expo-router";
import { useEffect } from "react";
import { ScrollView, TouchableOpacity, View } from "react-native";
import { useSafeAreaInsets } from "react-native-safe-area-context";
import { storage } from "@/utils/mmkv";
export default function settings() {
const router = useRouter();
@@ -67,6 +68,15 @@ export default function settings() {
<PluginSettings />
<ListGroup title={"Intro"}>
<ListItem
onPress={() => {
router.push("/intro/page");
}}
title={"Show intro"}
/>
</ListGroup>
<View className="mb-4">
<ListGroup title={"Logs"}>
<ListItem

View File

@@ -1,7 +1,7 @@
import React from "react";
import React, { useCallback, useRef } from "react";
import { Platform } from "react-native";
import { withLayoutContext } from "expo-router";
import { useFocusEffect, useRouter, withLayoutContext } from "expo-router";
import {
createNativeBottomTabNavigator,
@@ -19,6 +19,8 @@ import type {
} from "@react-navigation/native";
import { SystemBars } from "react-native-edge-to-edge";
import { useSettings } from "@/utils/atoms/settings";
import { useAtom, useAtomValue } from "jotai";
import { storage } from "@/utils/mmkv";
export const NativeTabs = withLayoutContext<
BottomTabNavigationOptions,
@@ -29,6 +31,26 @@ export const NativeTabs = withLayoutContext<
export default function TabLayout() {
const [settings] = useSettings();
const router = useRouter();
const hasNavigated = useRef(false);
useFocusEffect(
useCallback(() => {
const hasShownIntro = storage.getBoolean("hasShownIntro");
if (hasShownIntro === false && !hasNavigated.current) {
const timer = setTimeout(() => {
hasNavigated.current = true;
router.push("/intro/page");
storage.set("hasShownIntro", true);
}, 1000);
return () => {
clearTimeout(timer);
};
}
}, [])
);
return (
<>
<SystemBars hidden={false} style="light" />

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 22 KiB