diff --git a/App.tsx b/App.tsx index 827600b..b96c277 100644 --- a/App.tsx +++ b/App.tsx @@ -16,6 +16,7 @@ import CustomNavigationBar from "./src/components/navbar"; import SlotScreen from "./src/screens/feed/slot"; import { createStackNavigator } from "@react-navigation/stack"; import AlbumScreen from "./src/screens/media/album"; +import SmoelScreen from "./src/screens/media/smoel"; import { Item } from "./src/__generated__/media"; import SlidesScreen from "./src/screens/media/slides"; import { useColorScheme } from "react-native"; @@ -41,6 +42,7 @@ export type StackParamList = { Home: undefined; Slot: { slot: number; title: string }; Album: { album: string; title: string }; + Smoel: { smoel: string; title: string }; Slides: { items: Item[]; item: number }; Web: { source: string; title: string }; Search: undefined; @@ -96,6 +98,13 @@ export default function App() { title: route.params.title, })} /> + ({ + title: route.params.title, + })} + /> + this.request({ + path: `/smoelen`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + + /** + * No description + * + * @name GetSmoel + * @summary Get Smoel + * @request GET:/smoelen/{smoel_id} + * @secure + */ + getSmoel: (smoelId: string, params: RequestParams = {}) => + this.request({ + path: `/smoelen/${smoelId}`, + method: "GET", + secure: true, + format: "json", + ...params, + }), + }; } diff --git a/src/auth.tsx b/src/auth.tsx index fff79c8..bd9a117 100644 --- a/src/auth.tsx +++ b/src/auth.tsx @@ -3,9 +3,9 @@ import { jwtDecode } from "jwt-decode"; import * as SecureStore from "expo-secure-store"; import * as AuthSession from "expo-auth-session"; import { Alert, Platform, SafeAreaView, StyleSheet, View } from "react-native"; -import { Button, useTheme, Text } from "react-native-paper"; +import { Button, useTheme, Text, ActivityIndicator } from "react-native-paper"; import * as WebBrowser from "expo-web-browser"; -import { DiscoveryDocument, TokenError } from "expo-auth-session"; +import { DiscoveryDocument } from "expo-auth-session"; import * as Device from "expo-device"; import * as Notifications from "expo-notifications"; import Constants from "expo-constants"; @@ -330,7 +330,7 @@ export function AuthProvider({ children }: { children: JSX.Element }) { backgroundColor: theme.colors.primaryContainer, }} > - Loading... + ))} diff --git a/src/components/media/albums.tsx b/src/components/media/albums.tsx new file mode 100644 index 0000000..697a197 --- /dev/null +++ b/src/components/media/albums.tsx @@ -0,0 +1,34 @@ +import { useAtom } from "jotai"; +import { apiAtom } from "../../stores/media"; +import { AlbumList } from "../../__generated__/media"; +import { useEffect, useState } from "react"; +import { FlatList } from "react-native"; +import Preview from "./preview"; +import { ActivityIndicator } from "react-native-paper"; + +export default function Albums() { + const [albums, setAlbums] = useState(null); + const [api] = useAtom(apiAtom); + + useEffect(() => { + async function getAlbums() { + if (!api) return; + + const { data: albums } = await api.albums.getAlbums(); + setAlbums(albums.sort((a, b) => a.order - b.order)); + } + + getAlbums().then(); + }, [api]); + + if (!albums) return ; + return ( + item.id} + renderItem={({ item }) => } + /> + ); +} diff --git a/src/components/media/preview.tsx b/src/components/media/preview.tsx index 7278d51..36ad690 100644 --- a/src/components/media/preview.tsx +++ b/src/components/media/preview.tsx @@ -1,5 +1,5 @@ -import { AlbumList } from "../../__generated__/media"; -import { Image, StyleSheet, TouchableOpacity } from "react-native"; +import { AlbumList, SmoelAlbumList } from "../../__generated__/media"; +import { Image, TouchableOpacity, StyleSheet } from "react-native"; import { Text } from "react-native-paper"; import { useNavigation } from "@react-navigation/native"; import { NativeStackNavigationProp } from "react-native-screens/native-stack"; @@ -7,16 +7,25 @@ import { StackParamList } from "../../../App"; type NavigationProps = NativeStackNavigationProp; -export default function Preview({ album }: { album: AlbumList }) { +export default function Preview({ + album, + mode, +}: { + album: AlbumList | SmoelAlbumList; + mode: "smoel" | "album"; +}) { const navigation = useNavigation(); + function navigate() { + if (mode === "album") { + navigation.navigate("Album", { album: album.id, title: album.name }); + } else { + navigation.navigate("Smoel", { smoel: album.id, title: album.name }); + } + } + return ( - - navigation.navigate("Album", { album: album.id, title: album.name }) - } - > + {album.name} diff --git a/src/components/media/smoelen.tsx b/src/components/media/smoelen.tsx new file mode 100644 index 0000000..ec79c94 --- /dev/null +++ b/src/components/media/smoelen.tsx @@ -0,0 +1,34 @@ +import { useAtom } from "jotai"; +import { apiAtom } from "../../stores/media"; +import { SmoelAlbumList } from "../../__generated__/media"; +import { useEffect, useState } from "react"; +import { FlatList } from "react-native"; +import { ActivityIndicator } from "react-native-paper"; +import Preview from "./preview"; + +export default function Smoelen() { + const [smoelen, setSmoelen] = useState(null); + const [api] = useAtom(apiAtom); + + useEffect(() => { + async function getSmoelen() { + if (!api) return; + + const { data: albums } = await api.smoelen.getSmoelen(); + setSmoelen(albums); + } + + getSmoelen().then(); + }, [api]); + + if (!smoelen) return ; + return ( + item.id} + renderItem={({ item }) => } + /> + ); +} diff --git a/src/screens/media/album.tsx b/src/screens/media/album.tsx index c1cf5ec..6c3dd94 100644 --- a/src/screens/media/album.tsx +++ b/src/screens/media/album.tsx @@ -11,7 +11,7 @@ import { useAtom } from "jotai"; import { apiAtom } from "../../stores/media"; import { StackScreenProps } from "@react-navigation/stack"; import { StackParamList } from "../../../App"; -import { Appbar, Text } from "react-native-paper"; +import { ActivityIndicator, Appbar } from "react-native-paper"; import { useNavigation } from "@react-navigation/native"; import { NativeStackNavigationProp } from "react-native-screens/native-stack"; import { NativeStackNavigationEventMap } from "react-native-screens/lib/typescript/native-stack/types"; @@ -119,7 +119,7 @@ export default function AlbumScreen({ route }: Props) { navigation.navigate("Slides", { items: album.items, item: image }); } - if (!album) return Loading...; + if (!album) return ; return ( ([]); + const [page, setPage] = useState(Page.ALBUMS); + const theme = useTheme(); useEffect(() => { if (authState.authenticated !== Authed.AUTHENTICATED) { @@ -21,39 +28,32 @@ export default function MediaScreen() { setApi(getApi(token)); }); }, [authState]); - useEffect(() => { - async function getAlbums() { - if (!api) return; - - const { data: albums } = await api.albums.getAlbums(); - setAlbums(albums.sort((a, b) => a.order - b.order)); - } - - getAlbums().then(); - }, [api]); return ( <> - {authState.authenticated === Authed.GUEST && ( - - Je moet eerst inloggen om deze pagina te bekijken - - - )} - {authState.authenticated === Authed.AUTHENTICATED && ( - item.id} - renderItem={({ item }) => } - /> - )} + {page === Page.ALBUMS && } + {page === Page.SMOELEN && } + setPage(page as Page)} + buttons={[ + { + value: Page.ALBUMS, + label: "Albums", + }, + { + value: Page.SMOELEN, + label: "Smoelen ✨", + }, + ]} + /> ); } @@ -67,4 +67,10 @@ const styles = StyleSheet.create({ padding: 20, textAlign: "center", }, + pageSelector: { + position: "absolute", + bottom: 0, + margin: 15, + borderRadius: 50, + }, }); diff --git a/src/screens/media/smoel.tsx b/src/screens/media/smoel.tsx new file mode 100644 index 0000000..a36d062 --- /dev/null +++ b/src/screens/media/smoel.tsx @@ -0,0 +1,61 @@ +import { FlatList, Image, StyleSheet, TouchableOpacity } from "react-native"; +import { StackScreenProps } from "@react-navigation/stack"; +import { StackParamList } from "../../../App"; +import { useEffect, useState } from "react"; +import { useAtom } from "jotai/index"; +import { apiAtom } from "../../stores/media"; +import { SmoelAlbum } from "../../__generated__/media"; +import { ActivityIndicator, Text } from "react-native-paper"; +import { useNavigation } from "@react-navigation/native"; +import { NativeStackNavigationProp } from "react-native-screens/native-stack"; + +type Props = StackScreenProps; +type NavigationProps = NativeStackNavigationProp; + +export default function Smoel({ route }: Props) { + const navigation = useNavigation(); + const [smoel, setSmoel] = useState(); + const [api] = useAtom(apiAtom); + useEffect(() => { + async function getSmoel() { + if (!api) return; + + setSmoel( + await api.smoelen.getSmoel(route.params.smoel).then(({ data }) => data), + ); + } + getSmoel().then(); + }, [api]); + + function openImage(image: number) { + if (!smoel) return; + + navigation.navigate("Slides", { items: smoel.items, item: image }); + } + + if (!smoel) return ; + return ( + item.id} + renderItem={({ item, index }) => ( + openImage(index)}> + + + )} + /> + ); +} + +const styles = StyleSheet.create({ + item: { + flex: 1 / 3, + aspectRatio: 1, + }, + image: { + flex: 1, + resizeMode: "cover", + }, +});