Skip to content

Commit

Permalink
Merge pull request #85 from mykhailodanilenko/feature/docs-setup
Browse files Browse the repository at this point in the history
Setup documentation
  • Loading branch information
mykhailodanilenko authored Jun 27, 2024
2 parents 43c86b2 + e1d2738 commit 793f7e0
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 0 deletions.
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,7 @@ When a improvement is ready to be contributed in a pull request, please review t
4. Ensure that the changes adhere to the project code style and formatting rules by running `npx eslint .` and `npx prettier --check ../` from the `./OwnTube.tv/` directory (without errors/warnings)
5. Include links and illustrations in your pull request to make it easy to review
6. Request a review by @ar9708, @OGTor, @tryklick and @mblomdahl

## Documentation

Refer to [documentation](docs/index.md) for additional info.
4 changes: 4 additions & 0 deletions docs/index.md
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.
80 changes: 80 additions & 0 deletions docs/structure.md
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.
55 changes: 55 additions & 0 deletions docs/tech.md
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.

0 comments on commit 793f7e0

Please sign in to comment.