diff --git a/.expo/README.md b/.expo/README.md new file mode 100644 index 0000000..f7eb5fe --- /dev/null +++ b/.expo/README.md @@ -0,0 +1,8 @@ +> Why do I have a folder named ".expo" in my project? +The ".expo" folder is created when an Expo project is started using "expo start" command. +> What do the files contain? +- "devices.json": contains information about devices that have recently opened this project. This is used to populate the "Development sessions" list in your development builds. +- "settings.json": contains the server configuration that is used to serve the application manifest. +> Should I commit the ".expo" folder? +No, you should not share the ".expo" folder. It does not contain any information that is relevant for other developers working on the project, it is specific to your machine. +Upon project creation, the ".expo" folder is already added to your ".gitignore" file. diff --git a/.expo/devices.json b/.expo/devices.json new file mode 100644 index 0000000..5efff6c --- /dev/null +++ b/.expo/devices.json @@ -0,0 +1,3 @@ +{ + "devices": [] +} diff --git a/.expo/types/router.d.ts b/.expo/types/router.d.ts new file mode 100644 index 0000000..f0286a7 --- /dev/null +++ b/.expo/types/router.d.ts @@ -0,0 +1,357 @@ +/* eslint-disable */ +import type { ReactNode } from 'react'; +import type { TextProps, GestureResponderEvent } from 'react-native'; + +export namespace ExpoRouter { + type StaticRoutes = `/` | `/(auth)` | `/(tabs)` | `/_sitemap` | `/home` | `/profile` | `/search` | `/sign-in` | `/sign-up`; + type DynamicRoutes = `/search/${SingleRoutePart}`; + type DynamicRouteTemplate = `/search/[query]`; + + export type RelativePathString = `./${string}` | `../${string}` | '..'; + export type AbsoluteRoute = DynamicRouteTemplate | StaticRoutes; + export type ExternalPathString = `${string}:${string}`; + export type ExpoRouterRoutes = DynamicRouteTemplate | StaticRoutes | RelativePathString; + export type AllRoutes = ExpoRouterRoutes | ExternalPathString; + + /**************** + * Route Utils * + ****************/ + type SearchOrHash = `?${string}` | `#${string}`; + export type UnknownInputParams = Record< + string, + string | number | undefined | null | (string | number)[] + >; + type UnknownOutputParams = Record; + + /** + * Return only the RoutePart of a string. If the string has multiple parts return never + * + * string | type + * ---------|------ + * 123 | 123 + * /123/abc | never + * 123?abc | never + * ./123 | never + * /123 | never + * 123/../ | never + */ + type SingleRoutePart = S extends `${string}/${string}` + ? never + : S extends `${string}${SearchOrHash}` + ? never + : S extends '' + ? never + : S extends `(${string})` + ? never + : S extends `[${string}]` + ? never + : S; + + /** + * Return only the CatchAll router part. If the string has search parameters or a hash return never + */ + type CatchAllRoutePart = S extends `${string}${SearchOrHash}` + ? never + : S extends '' + ? never + : S extends `${string}(${string})${string}` + ? never + : S extends `${string}[${string}]${string}` + ? never + : S; + + /** + * Return the name of a route parameter + * '[test]' -> 'test' + * 'test' -> never + * '[...test]' -> '...test' + */ + type IsParameter = Part extends `[${infer ParamName}]` ? ParamName : never; + + /** + * Return a union of all raw parameter names. If there are no names return never + * + * This differs from ParameterNames as it returns the `...` for catch all parameters + * + * /[test] -> 'test' + * /[abc]/[...def] -> 'abc'|'...def' + */ + type ParameterNames = Path extends `${infer PartA}/${infer PartB}` + ? IsParameter | ParameterNames + : IsParameter; + + /** + * Returns all segments of a route. + * + * /(group)/123/abc/[id]/[...rest] -> ['(group)', '123', 'abc', '[id]', '[...rest]' + */ + type RouteSegments = Path extends `${infer PartA}/${infer PartB}` + ? PartA extends '' | '.' + ? [...RouteSegments] + : [PartA, ...RouteSegments] + : Path extends '' + ? [] + : [Path]; + + type AllUngroupedRoutes = Path extends `(${infer PartA})/${infer PartB}` + ? `(${PartA})/${AllUngroupedRoutes}` | AllUngroupedRoutes + : Path; + + /** + * Returns a Record of the routes parameters as strings and CatchAll parameters + * + * There are two versions, input and output, as you can input 'string | number' but + * the output will always be 'string' + * + * /[id]/[...rest] -> { id: string, rest: string[] } + * /no-params -> {} + */ + export type InputRouteParams = { + [Key in ParameterNames as Key extends `...${infer Name}` + ? Name + : Key]: Key extends `...${string}` ? (string | number)[] : string | number; + } & UnknownInputParams; + + type OutputRouteParams = { + [Key in ParameterNames as Key extends `...${infer Name}` + ? Name + : Key]: Key extends `...${string}` ? string[] : string; + } & UnknownOutputParams; + + /** + * Returns the search parameters for a route. + */ + export type SearchParams = T extends DynamicRouteTemplate + ? OutputRouteParams + : T extends StaticRoutes + ? never + : UnknownOutputParams; + + /********* + * Href * + *********/ + + /** + * The main routing type for Expo Router. Includes all available routes with strongly typed parameters. + * + * Allows for static routes, relative paths, external paths, dynamic routes, and the dynamic route provided as a static string + */ + export type Href = + | StringRouteToType | RelativePathString | ExternalPathString> + | DynamicRouteTemplateToString + | DynamicRouteObject< + StaticRoutes | RelativePathString | ExternalPathString | DynamicRouteTemplate + >; + + type StringRouteToType = + | T + | `${T}${SearchOrHash}` + | { pathname: T; params?: UnknownInputParams | never }; + + type DynamicRouteTemplateToString = Path extends `${infer PartA}/${infer PartB}` + ? `${PartA extends `[${string}]` ? string : PartA}/${DynamicRouteTemplateToString}` + : Path extends `[${string}]` + ? string + : Path; + + type DynamicRouteObject = T extends DynamicRouteTemplate + ? { + pathname: T; + params: InputRouteParams; + } + : never; + + type IsStaticRoute = + | StaticRoutes + | RelativePathString + | ExternalPathString + | (T extends DynamicRoutes ? T : never); + + /*********************** + * Expo Router Exports * + ***********************/ + + export type Router = { + /** Go back in the history. */ + back: () => void; + /** If there's history that supports invoking the `back` function. */ + canGoBack: () => boolean; + /** Navigate to the provided href using a push operation if possible. */ + push: (href: Href) => void; + /** Navigate to the provided href. */ + navigate: (href: Href) => void; + /** Navigate to route without appending to the history. */ + replace: (href: Href) => void; + /** Navigate to a screen with a stack lower than the current screen. Using the provided count if possible, otherwise 1. */ + dismiss: (count?: number) => void; + /** Navigate to first screen within the lowest stack. */ + dismissAll: () => void; + /** If there's history that supports invoking the `dismiss` and `dismissAll` function. */ + canDismiss: () => boolean; + /** Update the current route query params. */ + setParams: ( + params?: T extends '' ? Record : InputRouteParams + ) => void; + }; + + /** The imperative router. */ + export declare const router: Router; + + /************ + * * + ************/ + export interface WebAnchorProps { + /** + * **Web only:** Specifies where to open the `href`. + * + * - **_self**: the current tab. + * - **_blank**: opens in a new tab or window. + * - **_parent**: opens in the parent browsing context. If no parent, defaults to **_self**. + * - **_top**: opens in the highest browsing context ancestor. If no ancestors, defaults to **_self**. + * + * This property is passed to the underlying anchor (``) tag. + * + * @default '_self' + * + * @example + * Go to Expo in new tab + */ + target?: '_self' | '_blank' | '_parent' | '_top' | (string & object); + + /** + * **Web only:** Specifies the relationship between the `href` and the current route. + * + * Common values: + * - **nofollow**: Indicates to search engines that they should not follow the `href`. This is often used for user-generated content or links that should not influence search engine rankings. + * - **noopener**: Suggests that the `href` should not have access to the opening window's `window.opener` object, which is a security measure to prevent potentially harmful behavior in cases of links that open new tabs or windows. + * - **noreferrer**: Requests that the browser not send the `Referer` HTTP header when navigating to the `href`. This can enhance user privacy. + * + * The `rel` property is primarily used for informational and instructive purposes, helping browsers and web + * crawlers make better decisions about how to handle and interpret the links on a web page. It is important + * to use appropriate `rel` values to ensure that links behave as intended and adhere to best practices for web + * development and SEO (Search Engine Optimization). + * + * This property is passed to the underlying anchor (``) tag. + * + * @example + * Go to Expo + */ + rel?: string; + + /** + * **Web only:** Specifies that the `href` should be downloaded when the user clicks on the link, + * instead of navigating to it. It is typically used for links that point to files that the user should download, + * such as PDFs, images, documents, etc. + * + * The value of the `download` property, which represents the filename for the downloaded file. + * This property is passed to the underlying anchor (``) tag. + * + * @example + * Download image + */ + download?: string; + } + + export interface LinkProps extends Omit, WebAnchorProps { + /** Path to route to. */ + href: Href; + + // TODO(EvanBacon): This may need to be extracted for React Native style support. + /** Forward props to child component. Useful for custom buttons. */ + asChild?: boolean; + + /** Should replace the current route without adding to the history. */ + replace?: boolean; + /** Should push the current route */ + push?: boolean; + + /** On web, this sets the HTML `class` directly. On native, this can be used with CSS interop tools like Nativewind. */ + className?: string; + + onPress?: (e: React.MouseEvent | GestureResponderEvent) => void; + } + + export interface LinkComponent { + (props: React.PropsWithChildren): JSX.Element; + /** Helper method to resolve an Href object into a string. */ + resolveHref: (href: Href) => string; + } + + /** + * Component to render link to another route using a path. + * Uses an anchor tag on the web. + * + * @param props.href Absolute path to route (e.g. \`/feeds/hot\`). + * @param props.replace Should replace the current route without adding to the history. + * @param props.asChild Forward props to child component. Useful for custom buttons. + * @param props.children Child elements to render the content. + * @param props.className On web, this sets the HTML \`class\` directly. On native, this can be used with CSS interop tools like Nativewind. + */ + export declare const Link: LinkComponent; + + /** Redirects to the href as soon as the component is mounted. */ + export declare const Redirect: (props: React.PropsWithChildren<{ href: Href }>) => ReactNode; + export type Redirect = typeof Redirect; + + /** + * Hooks + */ + + export declare function useRouter(): Router; + type useRouter = typeof useRouter; + + /** + * Returns the URL search parameters for the contextually focused route. e.g. \`/acme?foo=bar\` -> \`{ foo: "bar" }\`. + * This is useful for stacks where you may push a new screen that changes the query parameters. + * + * To observe updates even when the invoking route is not focused, use \`useGlobalSearchParams()\`. + * @see \`useGlobalSearchParams\` + */ + export declare function useLocalSearchParams< + TParams extends AllRoutes | UnknownOutputParams = UnknownOutputParams, + >(): TParams extends AllRoutes ? SearchParams : TParams; + type useLocalSearchParams = typeof useLocalSearchParams; + + export declare function useSearchParams< + TParams extends AllRoutes | UnknownOutputParams = UnknownOutputParams, + >(): TParams extends AllRoutes ? SearchParams : TParams; + type useSearchParams = typeof useSearchParams; + + /** + * Get the globally selected query parameters, including dynamic path segments. This function will update even when the route is not focused. + * Useful for analytics or other background operations that don't draw to the screen. + * + * When querying search params in a stack, opt-towards using \`useLocalSearchParams\` as these will only + * update when the route is focused. + * + * @see \`useLocalSearchParams\` + */ + export declare function useGlobalSearchParams< + T extends AllRoutes | UnknownOutputParams = UnknownOutputParams, + >(): T extends AllRoutes ? SearchParams : T; + type useGlobalSearchParams = typeof useGlobalSearchParams; + + /** + * Get a list of selected file segments for the currently selected route. Segments are not normalized, so they will be the same as the file path. e.g. /[id]?id=normal -> ["[id]"] + * + * \`useSegments\` can be typed using an abstract. + * Consider the following file structure, and strictly typed \`useSegments\` function: + * + * \`\`\`md + * - app + * - [user] + * - index.js + * - followers.js + * - settings.js + * \`\`\` + * This can be strictly typed using the following abstract: + * + * \`\`\`ts + * const [first, second] = useSegments<['settings'] | ['[user]'] | ['[user]', 'followers']>() + * \`\`\` + */ + export declare function useSegments< + T extends AbsoluteRoute | RouteSegments | RelativePathString, + >(): T extends AbsoluteRoute ? RouteSegments : T extends string ? string[] : T; + type useSegments = typeof useSegments; +} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..620ca05 --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +.DS_Store +node_modules + +# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb +# The following patterns were generated by expo-cli + +expo-env.d.ts +# @end expo-cli \ No newline at end of file diff --git a/README.md b/README.md new file mode 100644 index 0000000..cd4feb8 --- /dev/null +++ b/README.md @@ -0,0 +1,50 @@ +# Welcome to your Expo app 👋 + +This is an [Expo](https://expo.dev) project created with [`create-expo-app`](https://www.npmjs.com/package/create-expo-app). + +## Get started + +1. Install dependencies + + ```bash + npm install + ``` + +2. Start the app + + ```bash + npx expo start + ``` + +In the output, you'll find options to open the app in a + +- [development build](https://docs.expo.dev/develop/development-builds/introduction/) +- [Android emulator](https://docs.expo.dev/workflow/android-studio-emulator/) +- [iOS simulator](https://docs.expo.dev/workflow/ios-simulator/) +- [Expo Go](https://expo.dev/go), a limited sandbox for trying out app development with Expo + +You can start developing by editing the files inside the **app** directory. This project uses [file-based routing](https://docs.expo.dev/router/introduction). + +## Get a fresh project + +When you're ready, run: + +```bash +npm run reset-project +``` + +This command will move the starter code to the **app-example** directory and create a blank **app** directory where you can start developing. + +## Learn more + +To learn more about developing your project with Expo, look at the following resources: + +- [Expo documentation](https://docs.expo.dev/): Learn fundamentals, or go into advanced topics with our [guides](https://docs.expo.dev/guides). +- [Learn Expo tutorial](https://docs.expo.dev/tutorial/introduction/): Follow a step-by-step tutorial where you'll create a project that runs on Android, iOS, and the web. + +## Join the community + +Join our community of developers creating universal apps. + +- [Expo on GitHub](https://github.com/expo/expo): View our open source platform and contribute. +- [Discord community](https://chat.expo.dev): Chat with Expo users and ask questions. diff --git a/app.json b/app.json new file mode 100644 index 0000000..158facd --- /dev/null +++ b/app.json @@ -0,0 +1,37 @@ +{ + "expo": { + "name": "Boombox", + "slug": "boombox", + "version": "1.0.0", + "orientation": "portrait", + "icon": "./assets/images/icon.png", + "scheme": "boombox", + "userInterfaceStyle": "automatic", + "splash": { + "image": "./assets/images/splash.png", + "resizeMode": "contain", + "backgroundColor": "#ffffff" + }, + "ios": { + "supportsTablet": true, + "package": "com.mathiszerari.boombox" + }, + "android": { + "adaptiveIcon": { + "foregroundImage": "./assets/images/adaptive-icon.png", + "backgroundColor": "#ffffff" + } + }, + "web": { + "bundler": "metro", + "output": "static", + "favicon": "./assets/images/favicon.png" + }, + "plugins": [ + "expo-router" + ], + "experiments": { + "typedRoutes": true + } + } +} diff --git a/app/(auth)/_layout.jsx b/app/(auth)/_layout.jsx new file mode 100644 index 0000000..18d5a3a --- /dev/null +++ b/app/(auth)/_layout.jsx @@ -0,0 +1,22 @@ +import React from 'react' +import { Stack } from 'expo-router' +import { StatusBar } from 'expo-status-bar' + +const AuthLayout = () => { + return ( + <> + + + + + +