-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #85 from mykhailodanilenko/feature/docs-setup
Setup documentation
- Loading branch information
Showing
4 changed files
with
143 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,4 @@ | ||
### Introduction ### | ||
|
||
This is an overview of the OwnTube.tv client, specifically the frontend part of it. This document will guide you through | ||
the [project folder structure](structure.md), [the technologies used](tech.md), reasoning behind some of the decisions made. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
## Folder structure | ||
|
||
For convenience, we will consider all folder names prefixed by `./OwnTube.tv/` | ||
|
||
### 📁`/__mocks__/`: | ||
|
||
This is a utility folder where you can put mocks for modules that you are sure will be used in all tests across the app. | ||
|
||
File structure: `/__mocks__/<moduleName>/<fileToMockName>.js` | ||
|
||
This is quite handy for react-native projects as some native modules will never render in a test renderer (e.g. *Camera*). | ||
Some libraries have instructions for creating such mock files. | ||
|
||
Alternative: 1 large `jest.setup.js` file with all the mocks. | ||
|
||
### 📁`/api/`: | ||
|
||
The 2 base structures working with the PeerTube API are contained in `peertubeVideosApi.ts` and `queries.ts`. | ||
|
||
`peertubeVideosApi.ts` contains the Axios instance and data fetching methods. There are predefined base query params and logic for response transformation. | ||
However please note that the instance URL is obtained from request params to support choosing the peertube instance to fetch from. | ||
|
||
`queries.ts` contains React hooks that wrap around the data fetching functions and handle things like loading state, refetching, cache invalidation through the use of `tanstack-query` (formerly `react-query`) library. | ||
|
||
The tests covering these files can be found in the `/api/tests/` folder. | ||
|
||
### 📁`/app/`: | ||
|
||
This directory's structure is static and determined by the `expo-router` package guidelines. | ||
More insight on why expo-router is used can be found further in the document, and more information on the file structure can be found here: https://docs.expo.dev/router/create-pages/ | ||
|
||
The route structure is as follows: | ||
|
||
`(home)/<screen>` where `(home)` is the base path and the 2 available screens - `/settings` and `/video` are separate routes. | ||
There is also a file for the `(home)/index` route which corresponds to the home page (`/`). | ||
|
||
Each route has a `backend` parameter and the `/video` route additionally has `id` and `timestamp` params used for video playback. | ||
All the routes come together in the `_layout.tsx` file which exports the app navigation. | ||
The reasoning behind the inclusion of the `+html.tsx` file will be discussed further in the document. | ||
|
||
### 📁`/assets/`: | ||
|
||
Contains logos and test data jsons, only the files put in this folder will be included in the build. | ||
|
||
### 📁`/components/`: | ||
|
||
A base folder for React components used in the app, the `/shared/` folder contains base component like "button" or "spacer". | ||
Some of the components that require a lot of supporting files (styles, tests etc.) are placed in a single folder, | ||
while most consist of 1 file which contains the styles (if any) and the component code. | ||
|
||
### 📁`/contexts/`: | ||
|
||
This folder contains setup files for information that should be available across the whole app - one is a color context used | ||
for theme switching and the other is the `AppConfigContext` which is used for technical information like settings or | ||
device capability info. | ||
|
||
### 📁`/hooks/`: | ||
|
||
Each file in this folder contains a React hook and if available, a file with the same name with a `.test.ts` extension. | ||
|
||
### 📁`/layouts/`: | ||
|
||
Contains layout components, currently having only one - a `<Screen />` that wraps app screens. | ||
|
||
### 📁`/patches/`: | ||
|
||
Contains patches used by the `patch-package` package. Best to keep this folder temporary. | ||
|
||
### 📁`/screens/`: | ||
|
||
This folder contains screen components which are imported into the route files in the `/app/` folder. Mostly these screens | ||
consist of components from the `/components/` folder. | ||
|
||
### 📁`/theme/`: | ||
|
||
Contains stylistic values and variables, such as colors or typography, however currently the app is mostly using the built-ins from `react-navigation` (a dependency of `expo-router`) | ||
|
||
### 📁`/utils/`: | ||
|
||
Here you can find various utilities used across the app, such as time formatting or working with async storage, test setup helpers etc. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
## Technologies used | ||
|
||
### Framework 🖼️ | ||
|
||
This app uses Expo which is a framework of React Native which simplifies the DX drastically for a lot of use cases. | ||
|
||
### Data Fetching ⬇️ | ||
|
||
The project uses `tanstack-query` library for its simplified data handling, automatic background refetching, and performance optimization | ||
through built-in caching. Its powerful DevTools and flexibility in supporting various use cases enhance our development | ||
efficiency, while an active community ensures we stay updated with the best practices. | ||
|
||
### Navigation 🧭 | ||
|
||
A significant majority of React Native projects use the `react-navigation` navigation library. This project, however, uses | ||
a file-based routing solution built on top of it by Expo, called `expo-router`. Expo-router comes with some additional features, | ||
such as deploying your application on the web in 3 different ways ('static', 'single' and 'server'). | ||
|
||
The 'static' export is what allows us to deploy the app to GitHub pages as a set of html files (hence the name "static"). | ||
This allows us to refresh the page without 404 errors unlike a "single" export (which would be the only option if we didn't use `expo-router`). | ||
However, there is currently a problem that comes up when deploying the app to GH Pages, which was patched in the `/patches/` folder. Currently, an issue | ||
in the Expo Github repo is created and assigned to a team member there. | ||
|
||
Each page is navigated to with a `backend` param so that the chosen instance link is determined by the URL and not the internal memory state. | ||
For example, if the user has `foo.bar` chosen in settings and gets a link to `owntube.tv/video?backend=bar.baz&id=123`, then they will watch a video from `bar.baz` that they were sent. | ||
|
||
The video page also has params such as `id` (the video uuid) and `timestamp` (the time when we want the video to start from when the link is opened) | ||
|
||
The settings page has only the `backend` param and uses it to show the currently selected instance, when the user select a new one they are "navigated" to the same page with a different `backend` param. | ||
|
||
### Video playback 📼 | ||
|
||
The turnkey solution for Expo apps is expo-video. However, this library is still in beta state and is considered unsupported | ||
on TV devices. So, the OwnTube.tv client uses an older `expo-av` library. | ||
|
||
A PeerTube instance outputs two variants when a video is fetched - either an mp4 video file, or an HLS streaming playlist, | ||
or both. However, not all videos have both, so we need to be able to play both variants. | ||
|
||
HLS is a technology which is not supported natively on desktop browsers except for Safari. Thus, we need a custom solution to support Chrome and FF. | ||
The `video.js` library includes the `hls.js` library which is used by PeerTube on the frontend in their custom peer-to-peer loader. However this custom loader is not | ||
necessary for the current needs of OwnTube.tv. | ||
In our case, a platform-specific component is used for the Web platform (React Native is able to determine where it is running and will supply the specific component). | ||
Through video.js we are converting the hls stream into a stream of mp4 chunks which are readable in any browser on the fly using ffmpeg, thus enabling the hls playback. | ||
|
||
The video controls are overlaid above the video player, this way the experience is unified regardless of the platform. | ||
You can skip 10 seconds in each direction, seek through the video, play/pause, mute. | ||
|
||
### Testing | ||
|
||
Jest is used throughout the app for testing, both for component tests and unit tests. For testing React components, the | ||
`@testing-library/react-native` package is used, which allows us to test components as real functioning entities, | ||
with state changes, user interactions etc. which in turn allows us to write tests similar to integration tests (e.g. user | ||
clicks X button and sees Y result). | ||
|
||
Data fetching is tested against a real peertube nightly instance, without mocking the API response. |