mirror of
https://github.com/movie-web/native-app.git
synced 2025-09-13 10:23:24 +00:00
Merge pull request #2 from movie-web/setup
Added basic expo skeleton app
This commit is contained in:
@@ -1,8 +1,13 @@
|
||||
# Editor configuration, see http://editorconfig.org
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
charset = utf-8
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
max_line_length = off
|
||||
trim_trailing_whitespace = false
|
||||
|
4
.eslintignore
Normal file
4
.eslintignore
Normal file
@@ -0,0 +1,4 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
/dist
|
||||
/coverage
|
||||
/.nx/cache
|
81
.eslintrc.js
Normal file
81
.eslintrc.js
Normal file
@@ -0,0 +1,81 @@
|
||||
module.exports = {
|
||||
extends: [
|
||||
'airbnb',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:prettier/recommended',
|
||||
],
|
||||
ignorePatterns: [
|
||||
'dist/*',
|
||||
'plugins/*',
|
||||
'tests/*',
|
||||
'/*.cjs',
|
||||
'/*.js',
|
||||
'/**/*.test.ts',
|
||||
'test/*',
|
||||
],
|
||||
parser: '@typescript-eslint/parser',
|
||||
settings: {
|
||||
'import/resolver': {
|
||||
typescript: {
|
||||
project: './tsconfig.json',
|
||||
},
|
||||
},
|
||||
},
|
||||
plugins: ['@typescript-eslint', 'import', 'prettier'],
|
||||
rules: {
|
||||
'no-underscore-dangle': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'no-console': 'off',
|
||||
'@typescript-eslint/no-this-alias': 'off',
|
||||
'import/prefer-default-export': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'no-shadow': 'off',
|
||||
'@typescript-eslint/no-shadow': ['error'],
|
||||
'no-restricted-syntax': 'off',
|
||||
'import/no-unresolved': ['error', { ignore: ['^virtual:'] }],
|
||||
'consistent-return': 'off',
|
||||
'no-continue': 'off',
|
||||
'no-eval': 'off',
|
||||
'no-await-in-loop': 'off',
|
||||
'no-nested-ternary': 'off',
|
||||
'no-param-reassign': ['error', { props: false }],
|
||||
'prefer-destructuring': 'off',
|
||||
'@typescript-eslint/no-unused-vars': ['warn', { argsIgnorePattern: '^_' }],
|
||||
'import/extensions': [
|
||||
'error',
|
||||
'ignorePackages',
|
||||
{
|
||||
ts: 'never',
|
||||
tsx: 'never',
|
||||
},
|
||||
],
|
||||
'import/order': [
|
||||
'error',
|
||||
{
|
||||
groups: [
|
||||
'builtin',
|
||||
'external',
|
||||
'internal',
|
||||
['sibling', 'parent'],
|
||||
'index',
|
||||
'unknown',
|
||||
],
|
||||
'newlines-between': 'always',
|
||||
alphabetize: {
|
||||
order: 'asc',
|
||||
caseInsensitive: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
'sort-imports': [
|
||||
'error',
|
||||
{
|
||||
ignoreCase: false,
|
||||
ignoreDeclarationSort: true,
|
||||
ignoreMemberSort: false,
|
||||
memberSyntaxSortOrder: ['none', 'all', 'multiple', 'single'],
|
||||
allowSeparatedGroups: true,
|
||||
},
|
||||
],
|
||||
},
|
||||
};
|
2
.github/CODEOWNERS
vendored
2
.github/CODEOWNERS
vendored
@@ -1 +1 @@
|
||||
* @movie-web/project-leads
|
||||
* @movie-web/core
|
||||
|
15
.github/SECURITY.md
vendored
Normal file
15
.github/SECURITY.md
vendored
Normal file
@@ -0,0 +1,15 @@
|
||||
# Security Policy
|
||||
|
||||
## Supported Versions
|
||||
|
||||
The movie-web maintainers only support the latest version of movie-web published at https://movie-web.app.
|
||||
This published version is equivalent to the master branch.
|
||||
|
||||
Support is not provided for any forks or mirrors of movie-web.
|
||||
|
||||
## Reporting a Vulnerability
|
||||
|
||||
There are two ways you can contact the movie-web maintainers to report a vulnerability:
|
||||
|
||||
- Email [security@movie-web.app](mailto:security@movie-web.app)
|
||||
- Report the vulnerability in the [movie-web Discord server](https://discord.movie-web.app)
|
6
.github/pull_request_template.md
vendored
Normal file
6
.github/pull_request_template.md
vendored
Normal file
@@ -0,0 +1,6 @@
|
||||
This pull request resolves #XXX
|
||||
|
||||
- [ ] I have read and agreed to the [code of conduct](https://github.com/movie-web/movie-web/blob/dev/.github/CODE_OF_CONDUCT.md).
|
||||
- [ ] I have read and complied with the [contributing guidelines](https://github.com/movie-web/movie-web/blob/dev/.github/CONTRIBUTING.md).
|
||||
- [ ] What I'm implementing was assigned to me and is an [approved issue](https://github.com/movie-web/movie-web/issues?q=is%3Aopen+is%3Aissue+label%3Aapproved). For reference, please take a look at our [GitHub projects](https://github.com/movie-web/movie-web/projects).
|
||||
- [ ] I have tested all of my changes.
|
143
.github/workflows/build-mobile.yml
vendored
Normal file
143
.github/workflows/build-mobile.yml
vendored
Normal file
@@ -0,0 +1,143 @@
|
||||
name: build mobile app
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch:
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
build-android:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 21
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Setup Android SDK
|
||||
uses: android-actions/setup-android@v3
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build native Android modules
|
||||
run: pnpm exec nx run mobile:prebuild --platform=android
|
||||
|
||||
- name: Build Android app
|
||||
run: cd apps/mobile/android && ./gradlew assembleRelease
|
||||
|
||||
- name: Rename apk
|
||||
run: mv apps/mobile/android/app/build/outputs/apk/release/app-release.apk apps/mobile/android/app/build/outputs/apk/release/movie-web.apk
|
||||
|
||||
- name: Upload movie-web.apk as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: apk
|
||||
path: ./apps/mobile/android/app/build/outputs/apk/release/movie-web.apk
|
||||
|
||||
build-ios:
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Xcode Select Version
|
||||
uses: maxim-lobanov/setup-xcode@v1
|
||||
with:
|
||||
xcode-version: '15.1.0'
|
||||
|
||||
- name: Install Node.js
|
||||
uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 21
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
name: Install pnpm
|
||||
with:
|
||||
version: 8
|
||||
run_install: false
|
||||
|
||||
- name: Install dependencies
|
||||
run: pnpm install
|
||||
|
||||
- name: Build native iOS modules
|
||||
run: pnpm exec nx run mobile:prebuild --platform=ios
|
||||
|
||||
- name: Build iOS app
|
||||
run: cd apps/mobile/ios && xcodebuild archive -workspace movieweb.xcworkspace -scheme "movieweb" -sdk iphoneos -configuration "Release" -archivePath "build/app.xcarchive" -destination generic/platform=iOS CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||
|
||||
- name: Export .ipa from .xcarchive
|
||||
run: |
|
||||
mv apps/mobile/ios/build/app.xcarchive/Products/Applications apps/mobile/ios/build/app.xcarchive/Products/Payload
|
||||
cd apps/mobile/ios/build/app.xcarchive/Products
|
||||
zip -r ../../movie-web.ipa Payload
|
||||
|
||||
- name: Upload movie-web.ipa as artifact
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: ipa
|
||||
path: ./apps/mobile/ios/build/movie-web.ipa
|
||||
|
||||
release-app:
|
||||
runs-on: ubuntu-latest
|
||||
needs: [build-android, build-ios]
|
||||
if: github.ref == 'refs/heads/master'
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Automated Version Bump
|
||||
uses: phips28/gh-action-bump-version@v10.1.1
|
||||
with:
|
||||
skip-tag: 'true'
|
||||
commit-message: 'chore: bump version to {{version}} [skip ci]'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
PACKAGEJSON_DIR: 'apps/mobile'
|
||||
|
||||
- name: Download build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
merge-multiple: true
|
||||
|
||||
- name: Get package version
|
||||
id: package-version
|
||||
uses: martinbeentjes/npm-get-version-action@v1.3.1
|
||||
with:
|
||||
path: apps/mobile
|
||||
|
||||
- name: Create GitHub Release
|
||||
uses: softprops/action-gh-release@v1
|
||||
with:
|
||||
tag_name: v${{ steps.package-version.outputs.current-version }}
|
||||
files: |
|
||||
movie-web.apk
|
||||
movie-web.ipa
|
||||
fail_on_unmatched_files: true
|
||||
token: ${{ env.GITHUB_TOKEN }}
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
59
.gitignore
vendored
Normal file
59
.gitignore
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
# See http://help.github.com/ignore-files/ for more about ignoring files.
|
||||
|
||||
# compiled output
|
||||
dist
|
||||
tmp
|
||||
/out-tsc
|
||||
|
||||
# dependencies
|
||||
node_modules
|
||||
|
||||
# IDEs and editors
|
||||
/.idea
|
||||
.project
|
||||
.classpath
|
||||
.c9/
|
||||
*.launch
|
||||
.settings/
|
||||
*.sublime-workspace
|
||||
|
||||
# IDE - VSCode
|
||||
.vscode/*
|
||||
!.vscode/settings.json
|
||||
!.vscode/tasks.json
|
||||
!.vscode/launch.json
|
||||
!.vscode/extensions.json
|
||||
|
||||
# misc
|
||||
/.sass-cache
|
||||
/connect.lock
|
||||
/coverage
|
||||
/libpeerconnection.log
|
||||
npm-debug.log
|
||||
yarn-error.log
|
||||
testem.log
|
||||
/typings
|
||||
|
||||
# System Files
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
.nx/cache
|
||||
|
||||
# Expo
|
||||
node_modules/
|
||||
.expo/
|
||||
.yarn/
|
||||
dist/
|
||||
npm-debug.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
*.orig.*
|
||||
web-build/
|
||||
cache/
|
||||
|
||||
|
||||
apps/mobile-e2e/artifacts
|
3
.npmrc
Normal file
3
.npmrc
Normal file
@@ -0,0 +1,3 @@
|
||||
strict-peer-dependencies=false
|
||||
auto-install-peers=true
|
||||
node-linker=hoisted
|
4
.prettierignore
Normal file
4
.prettierignore
Normal file
@@ -0,0 +1,4 @@
|
||||
# Add files here to ignore them from prettier formatting
|
||||
/dist
|
||||
/coverage
|
||||
/.nx/cache
|
3
.prettierrc
Normal file
3
.prettierrc
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"singleQuote": true
|
||||
}
|
8
.vscode/extensions.json
vendored
Normal file
8
.vscode/extensions.json
vendored
Normal file
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"recommendations": [
|
||||
"dbaeumer.vscode-eslint",
|
||||
"editorconfig.editorconfig",
|
||||
"esbenp.prettier-vscode",
|
||||
"firsttris.vscode-jest-runner"
|
||||
]
|
||||
}
|
11
.vscode/settings.json
vendored
Normal file
11
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"editor.formatOnSave": true,
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint",
|
||||
"eslint.format.enable": true,
|
||||
"[json]": {
|
||||
"editor.defaultFormatter": "esbenp.prettier-vscode"
|
||||
},
|
||||
"[typescriptreact]": {
|
||||
"editor.defaultFormatter": "dbaeumer.vscode-eslint"
|
||||
}
|
||||
}
|
72
README.md
72
README.md
@@ -1,6 +1,70 @@
|
||||
# native-app
|
||||
# movie-web native-app
|
||||
|
||||
The native app version of movie-web
|
||||
Native-app for movie-web.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This is work in progress, not even remotely close to being ready for use.
|
||||
## Getting started
|
||||
|
||||
```bash
|
||||
pnpm install
|
||||
|
||||
// Having nx installed globally is recommended
|
||||
pnpm install -g nx
|
||||
|
||||
// If you don't want nx installed globally, you can use the following command
|
||||
(pnpm exec or npx) nx <command>
|
||||
```
|
||||
|
||||
## Running tasks
|
||||
|
||||
To execute tasks with Nx use the following syntax:
|
||||
|
||||
```bash
|
||||
nx <target> <project> <...options>
|
||||
```
|
||||
|
||||
For example, to run the mobile app:
|
||||
|
||||
### Android
|
||||
|
||||
```bash
|
||||
nx run mobile:android
|
||||
```
|
||||
|
||||
### iOS
|
||||
|
||||
```bash
|
||||
nx run mobile:ios
|
||||
```
|
||||
|
||||
## Building archives
|
||||
|
||||
### Android .apk
|
||||
|
||||
```bash
|
||||
nx run mobile:prebuild --platform=android
|
||||
cd apps/mobile/android && ./gradlew assembleRelease
|
||||
```
|
||||
|
||||
### iOS .app
|
||||
|
||||
#### Real device
|
||||
|
||||
```bash
|
||||
nx run mobile:prebuild --platform=ios
|
||||
cd apps/mobile/ios && xcodebuild archive -workspace movieweb.xcworkspace -scheme "movieweb" -sdk iphoneos -configuration "Release" -archivePath "build/app.xcarchive" -destination generic/platform=iOS CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||
```
|
||||
|
||||
#### Simulator
|
||||
|
||||
```bash
|
||||
nx run mobile:prebuild --platform=ios
|
||||
cd apps/mobile/ios && xcodebuild archive -workspace movieweb.xcworkspace -scheme "movieweb" -sdk iphonesimulator -configuration "Release" -archivePath "build/app.xcarchive" -destination "generic/platform=iOS Simulator" CODE_SIGN_IDENTITY="" CODE_SIGNING_REQUIRED=NO CODE_SIGNING_ALLOWED=NO
|
||||
```
|
||||
|
||||
## Repository information
|
||||
|
||||
This project uses Nx to manage the monorepo. For more information about Nx, visit [nx.dev](https://nx.dev).
|
||||
|
||||
### Mobile app
|
||||
|
||||
The mobile app is built with React Native and Expo. For more information about Expo, visit [expo.io](https://expo.io).
|
||||
|
11
apps/mobile-e2e/.babelrc
Normal file
11
apps/mobile-e2e/.babelrc
Normal file
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"presets": [
|
||||
[
|
||||
"@nx/react/babel",
|
||||
{
|
||||
"runtime": "automatic",
|
||||
},
|
||||
],
|
||||
],
|
||||
"plugins": [],
|
||||
}
|
89
apps/mobile-e2e/.detoxrc.json
Normal file
89
apps/mobile-e2e/.detoxrc.json
Normal file
@@ -0,0 +1,89 @@
|
||||
{
|
||||
"testRunner": {
|
||||
"args": {
|
||||
"$0": "jest",
|
||||
"config": "./jest.config.json"
|
||||
},
|
||||
"jest": {
|
||||
"setupTimeout": 120000
|
||||
}
|
||||
},
|
||||
"apps": {
|
||||
"ios.debug": {
|
||||
"type": "ios.app",
|
||||
"build": "cd ../../apps/mobile/ios && xcodebuild -workspace movieweb.xcworkspace -scheme movieweb -configuration Debug -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
|
||||
"binaryPath": "../../apps/mobile/ios/build/Build/Products/Debug-iphonesimulator/movieweb.app"
|
||||
},
|
||||
"ios.release": {
|
||||
"type": "ios.app",
|
||||
"build": "cd ../../apps/mobile/ios && xcodebuild -workspace movieweb.xcworkspace -scheme movieweb -configuration Release -sdk iphonesimulator -destination 'platform=iOS Simulator,name=iPhone 14' -derivedDataPath ./build -quiet",
|
||||
"binaryPath": "../../apps/mobile/ios/build/Build/Products/Release-iphonesimulator/movieweb.app"
|
||||
},
|
||||
|
||||
"ios.local": {
|
||||
"type": "ios.app",
|
||||
"build": "pnpm exec nx run mobile:build --platform ios --profile preview --wait --local --no-interactive --output=../../apps/mobile/dist/movieweb.tar.gz",
|
||||
"binaryPath": "../../apps/mobile/dist/movieweb.app"
|
||||
},
|
||||
|
||||
"android.debug": {
|
||||
"type": "android.apk",
|
||||
"build": "cd ../../apps/mobile/android && ./gradlew assembleDebug assembleAndroidTest -DtestBuildType=debug",
|
||||
"binaryPath": "../../apps/mobile/android/app/build/outputs/apk/debug/app-debug.apk"
|
||||
},
|
||||
"android.release": {
|
||||
"type": "android.apk",
|
||||
"build": "cd ../../apps/mobile/android && ./gradlew assembleRelease assembleAndroidTest -DtestBuildType=release",
|
||||
"binaryPath": "../../apps/mobile/android/app/build/outputs/apk/release/app-release.apk"
|
||||
},
|
||||
|
||||
"android.local": {
|
||||
"type": "android.apk",
|
||||
"build": "pnpm exec nx run mobile:build --platform android --profile preview --wait --local --no-interactive --output=../../apps/mobile/dist/movieweb.apk",
|
||||
"binaryPath": "../../apps/mobile/dist/movieweb.apk"
|
||||
}
|
||||
},
|
||||
"devices": {
|
||||
"simulator": {
|
||||
"type": "ios.simulator",
|
||||
"device": {
|
||||
"type": "iPhone 14"
|
||||
}
|
||||
},
|
||||
"emulator": {
|
||||
"type": "android.emulator",
|
||||
"device": {
|
||||
"avdName": "Pixel_4a_API_30"
|
||||
}
|
||||
}
|
||||
},
|
||||
"configurations": {
|
||||
"ios.sim.release": {
|
||||
"device": "simulator",
|
||||
"app": "ios.release"
|
||||
},
|
||||
"ios.sim.debug": {
|
||||
"device": "simulator",
|
||||
"app": "ios.debug"
|
||||
},
|
||||
|
||||
"ios.sim.local": {
|
||||
"device": "simulator",
|
||||
"app": "ios.local"
|
||||
},
|
||||
|
||||
"android.emu.release": {
|
||||
"device": "emulator",
|
||||
"app": "android.release"
|
||||
},
|
||||
"android.emu.debug": {
|
||||
"device": "emulator",
|
||||
"app": "android.debug"
|
||||
},
|
||||
|
||||
"android.emu.local": {
|
||||
"device": "emulator",
|
||||
"app": "android.local"
|
||||
}
|
||||
}
|
||||
}
|
18
apps/mobile-e2e/.eslintrc.json
Normal file
18
apps/mobile-e2e/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.js"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
22
apps/mobile-e2e/jest.config.json
Normal file
22
apps/mobile-e2e/jest.config.json
Normal file
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"preset": "../../jest.preset",
|
||||
"rootDir": ".",
|
||||
"testMatch": [
|
||||
"<rootDir>/src/**/*.test.ts?(x)",
|
||||
"<rootDir>/src/**/*.spec.ts?(x)"
|
||||
],
|
||||
"testTimeout": 120000,
|
||||
"maxWorkers": 1,
|
||||
"globalSetup": "detox/runners/jest/globalSetup",
|
||||
"globalTeardown": "detox/runners/jest/globalTeardown",
|
||||
"reporters": ["detox/runners/jest/reporter"],
|
||||
"testEnvironment": "detox/runners/jest/testEnvironment",
|
||||
"verbose": true,
|
||||
"setupFilesAfterEnv": ["<rootDir>/test-setup.ts"],
|
||||
"transform": {
|
||||
"^.+\\.(ts|js|html)$": [
|
||||
"ts-jest",
|
||||
{ "tsconfig": "<rootDir>/tsconfig.e2e.json" }
|
||||
]
|
||||
}
|
||||
}
|
76
apps/mobile-e2e/project.json
Normal file
76
apps/mobile-e2e/project.json
Normal file
@@ -0,0 +1,76 @@
|
||||
{
|
||||
"name": "mobile-e2e",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/mobile-e2e/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"build-ios": {
|
||||
"executor": "@nx/detox:build",
|
||||
"options": {
|
||||
"detoxConfiguration": "ios.sim.local"
|
||||
},
|
||||
"configurations": {
|
||||
"bare": {
|
||||
"detoxConfiguration": "ios.sim.debug"
|
||||
},
|
||||
"production": {
|
||||
"detoxConfiguration": "ios.sim.release"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-ios": {
|
||||
"executor": "@nx/detox:test",
|
||||
"options": {
|
||||
"detoxConfiguration": "ios.sim.local",
|
||||
"buildTarget": "mobile-e2e:build-ios"
|
||||
},
|
||||
"configurations": {
|
||||
"bare": {
|
||||
"detoxConfiguration": "ios.sim.debug",
|
||||
"buildTarget": "mobile-e2e:build-ios:bare"
|
||||
},
|
||||
"production": {
|
||||
"detoxConfiguration": "ios.sim.release",
|
||||
"buildTarget": "mobile-e2e:build-ios:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"build-android": {
|
||||
"executor": "@nx/detox:build",
|
||||
"options": {
|
||||
"detoxConfiguration": "android.emu.local"
|
||||
},
|
||||
"configurations": {
|
||||
"bare": {
|
||||
"detoxConfiguration": "android.emu.debug"
|
||||
},
|
||||
"production": {
|
||||
"detoxConfiguration": "android.emu.release"
|
||||
}
|
||||
}
|
||||
},
|
||||
"test-android": {
|
||||
"executor": "@nx/detox:test",
|
||||
"options": {
|
||||
"detoxConfiguration": "android.emu.local",
|
||||
"buildTarget": "mobile-e2e:build-android"
|
||||
},
|
||||
"configurations": {
|
||||
"bare": {
|
||||
"detoxConfiguration": "android.emu.debug",
|
||||
"buildTarget": "mobile-e2e:build-android:bare"
|
||||
},
|
||||
"production": {
|
||||
"detoxConfiguration": "android.emu.release",
|
||||
"buildTarget": "mobile-e2e:build-android:production"
|
||||
}
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"]
|
||||
}
|
||||
},
|
||||
"tags": [],
|
||||
"implicitDependencies": ["mobile"]
|
||||
}
|
11
apps/mobile-e2e/src/app.spec.ts
Normal file
11
apps/mobile-e2e/src/app.spec.ts
Normal file
@@ -0,0 +1,11 @@
|
||||
import { device, element, by, expect } from 'detox';
|
||||
|
||||
describe('movieweb', () => {
|
||||
beforeEach(async () => {
|
||||
await device.reloadReactNative();
|
||||
});
|
||||
|
||||
it('should display welcome message', async () => {
|
||||
await expect(element(by.id('heading'))).toHaveText('Welcome movie-web 👋');
|
||||
});
|
||||
});
|
5
apps/mobile-e2e/test-setup.ts
Normal file
5
apps/mobile-e2e/test-setup.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { device } from 'detox';
|
||||
|
||||
beforeAll(async () => {
|
||||
await device.launchApp();
|
||||
});
|
10
apps/mobile-e2e/tsconfig.e2e.json
Normal file
10
apps/mobile-e2e/tsconfig.e2e.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"sourceMap": false,
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"allowJs": true,
|
||||
"types": ["node", "jest", "detox"]
|
||||
},
|
||||
"include": ["src/**/*.ts", "src/**/*.js"]
|
||||
}
|
10
apps/mobile-e2e/tsconfig.json
Normal file
10
apps/mobile-e2e/tsconfig.json
Normal file
@@ -0,0 +1,10 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"files": [],
|
||||
"include": [],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.e2e.json"
|
||||
}
|
||||
]
|
||||
}
|
31
apps/mobile/.eslintrc.js
Normal file
31
apps/mobile/.eslintrc.js
Normal file
@@ -0,0 +1,31 @@
|
||||
module.exports = {
|
||||
extends: ['../../.eslintrc.js'],
|
||||
ignorePatterns: ['/*.js', '/*.d.ts'],
|
||||
overrides: [
|
||||
{
|
||||
files: ['*.ts', '*.tsx', '*.js', '*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['*.ts', '*.tsx'],
|
||||
rules: {},
|
||||
},
|
||||
{
|
||||
files: ['*.js', '*.jsx'],
|
||||
rules: {},
|
||||
},
|
||||
],
|
||||
rules: {
|
||||
'react/jsx-uses-react': 'off',
|
||||
'react/react-in-jsx-scope': 'off',
|
||||
'react/require-default-props': 'off',
|
||||
'react/destructuring-assignment': 'off',
|
||||
'react/jsx-filename-extension': [
|
||||
'error',
|
||||
{ extensions: ['.js', '.tsx', '.jsx'] },
|
||||
],
|
||||
'react/jsx-props-no-spreading': 'off',
|
||||
'react/no-unstable-nested-components': 'off',
|
||||
'no-use-before-define': 'off',
|
||||
},
|
||||
};
|
18
apps/mobile/.eslintrc.json
Normal file
18
apps/mobile/.eslintrc.json
Normal file
@@ -0,0 +1,18 @@
|
||||
{
|
||||
"extends": ["../../.eslintrc.js"],
|
||||
"ignorePatterns": ["!**/*"],
|
||||
"overrides": [
|
||||
{
|
||||
"files": ["*.ts", "*.tsx", "*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.ts", "*.tsx"],
|
||||
"rules": {}
|
||||
},
|
||||
{
|
||||
"files": ["*.js", "*.jsx"],
|
||||
"rules": {}
|
||||
}
|
||||
]
|
||||
}
|
44
apps/mobile/.gitignore
vendored
Normal file
44
apps/mobile/.gitignore
vendored
Normal file
@@ -0,0 +1,44 @@
|
||||
# Learn more https://docs.github.com/en/get-started/getting-started-with-git/ignoring-files
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# Expo
|
||||
.expo/
|
||||
dist/
|
||||
web-build/
|
||||
android/
|
||||
ios/
|
||||
|
||||
# Native
|
||||
*.orig.*
|
||||
*.jks
|
||||
*.p8
|
||||
*.p12
|
||||
*.key
|
||||
*.mobileprovision
|
||||
|
||||
# Metro
|
||||
.metro-health-check*
|
||||
|
||||
# debug
|
||||
npm-debug.*
|
||||
yarn-debug.*
|
||||
yarn-error.*
|
||||
|
||||
# macOS
|
||||
.DS_Store
|
||||
*.pem
|
||||
|
||||
# local env files
|
||||
.env*.local
|
||||
|
||||
# typescript
|
||||
*.tsbuildinfo
|
||||
|
||||
|
||||
# @generated expo-cli sync-2b81b286409207a5da26e14c78851eb30d8ccbdb
|
||||
# The following patterns were generated by expo-cli
|
||||
|
||||
expo-env.d.ts
|
||||
# @end expo-cli
|
@@ -1 +0,0 @@
|
||||
This will be the folder the mobile native app.
|
53
apps/mobile/app.json
Normal file
53
apps/mobile/app.json
Normal file
@@ -0,0 +1,53 @@
|
||||
{
|
||||
"expo": {
|
||||
"name": "movie-web",
|
||||
"slug": "mw-mobile",
|
||||
"version": "1.0.0",
|
||||
"orientation": "portrait",
|
||||
"scheme":"dev.movieweb.app",
|
||||
"icon": "./assets/images/icon.png",
|
||||
"splash": {
|
||||
"image": "./assets/images/splash.png",
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"jsEngine": "jsc",
|
||||
"updates": {
|
||||
"fallbackToCacheTimeout": 0
|
||||
},
|
||||
"assetBundlePatterns": [
|
||||
"**/*"
|
||||
],
|
||||
"ios": {
|
||||
"supportsTablet": true,
|
||||
"bundleIdentifier": "dev.movieweb.app"
|
||||
},
|
||||
"android": {
|
||||
"adaptiveIcon": {
|
||||
"foregroundImage": "./assets/images/adaptive-icon.png",
|
||||
"backgroundColor": "#FFFFFF"
|
||||
},
|
||||
"package": "dev.movieweb.app"
|
||||
},
|
||||
"web": {
|
||||
"favicon": "./assets/images/favicon.png",
|
||||
"bundler": "metro"
|
||||
},
|
||||
"plugins": [
|
||||
"expo-router",
|
||||
[
|
||||
"@config-plugins/detox",
|
||||
{
|
||||
"skipProguard": false,
|
||||
"subdomains": [
|
||||
"10.0.2.2",
|
||||
"localhost"
|
||||
]
|
||||
}
|
||||
]
|
||||
],
|
||||
"experiments": {
|
||||
"typedRoutes": true
|
||||
}
|
||||
}
|
||||
}
|
56
apps/mobile/app/(tabs)/_layout.tsx
Normal file
56
apps/mobile/app/(tabs)/_layout.tsx
Normal file
@@ -0,0 +1,56 @@
|
||||
import FontAwesome from '@expo/vector-icons/FontAwesome';
|
||||
import { Link, Tabs } from 'expo-router';
|
||||
import { Pressable, useColorScheme } from 'react-native';
|
||||
|
||||
import Colors from '../../constants/Colors';
|
||||
|
||||
/**
|
||||
* You can explore the built-in icon families and icons on the web at https://icons.expo.fyi/
|
||||
*/
|
||||
function TabBarIcon(props: {
|
||||
name: React.ComponentProps<typeof FontAwesome>['name'];
|
||||
color: string;
|
||||
}) {
|
||||
return <FontAwesome size={28} style={{ marginBottom: -3 }} {...props} />;
|
||||
}
|
||||
|
||||
export default function TabLayout() {
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
return (
|
||||
<Tabs
|
||||
screenOptions={{
|
||||
tabBarActiveTintColor: Colors[colorScheme ?? 'light'].tint,
|
||||
}}
|
||||
>
|
||||
<Tabs.Screen
|
||||
name="index"
|
||||
options={{
|
||||
title: 'Tab One',
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="code" color={color} />,
|
||||
headerRight: () => (
|
||||
<Link href="/modal" asChild>
|
||||
<Pressable>
|
||||
{({ pressed }) => (
|
||||
<FontAwesome
|
||||
name="info-circle"
|
||||
size={25}
|
||||
color={Colors[colorScheme ?? 'light'].text}
|
||||
style={{ marginRight: 15, opacity: pressed ? 0.5 : 1 }}
|
||||
/>
|
||||
)}
|
||||
</Pressable>
|
||||
</Link>
|
||||
),
|
||||
}}
|
||||
/>
|
||||
<Tabs.Screen
|
||||
name="two"
|
||||
options={{
|
||||
title: 'Tab Two',
|
||||
tabBarIcon: ({ color }) => <TabBarIcon name="code" color={color} />,
|
||||
}}
|
||||
/>
|
||||
</Tabs>
|
||||
);
|
||||
}
|
35
apps/mobile/app/(tabs)/index.tsx
Normal file
35
apps/mobile/app/(tabs)/index.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import EditScreenInfo from '../../components/EditScreenInfo';
|
||||
import { Text, View } from '../../components/Themed';
|
||||
|
||||
export default function TabOneScreen() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Tab One</Text>
|
||||
<View
|
||||
style={styles.separator}
|
||||
lightColor="#eee"
|
||||
darkColor="rgba(255,255,255,0.1)"
|
||||
/>
|
||||
<EditScreenInfo path="app/(tabs)/index.tsx" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
separator: {
|
||||
marginVertical: 30,
|
||||
height: 1,
|
||||
width: '80%',
|
||||
},
|
||||
});
|
35
apps/mobile/app/(tabs)/two.tsx
Normal file
35
apps/mobile/app/(tabs)/two.tsx
Normal file
@@ -0,0 +1,35 @@
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import EditScreenInfo from '../../components/EditScreenInfo';
|
||||
import { Text, View } from '../../components/Themed';
|
||||
|
||||
export default function TabTwoScreen() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Tab Two</Text>
|
||||
<View
|
||||
style={styles.separator}
|
||||
lightColor="#eee"
|
||||
darkColor="rgba(255,255,255,0.1)"
|
||||
/>
|
||||
<EditScreenInfo path="app/(tabs)/two.tsx" />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
separator: {
|
||||
marginVertical: 30,
|
||||
height: 1,
|
||||
width: '80%',
|
||||
},
|
||||
});
|
46
apps/mobile/app/+html.tsx
Normal file
46
apps/mobile/app/+html.tsx
Normal file
@@ -0,0 +1,46 @@
|
||||
import { ScrollViewStyleReset } from 'expo-router/html';
|
||||
|
||||
// This file is web-only and used to configure the root HTML for every
|
||||
// web page during static rendering.
|
||||
// The contents of this function only run in Node.js environments and
|
||||
// do not have access to the DOM or browser APIs.
|
||||
export default function Root({ children }: { children: React.ReactNode }) {
|
||||
return (
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charSet="utf-8" />
|
||||
<meta httpEquiv="X-UA-Compatible" content="IE=edge" />
|
||||
|
||||
{/*
|
||||
This viewport disables scaling which makes the mobile website act more like a native app.
|
||||
However this does reduce built-in accessibility. If you want to enable scaling, use this instead:
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, viewport-fit=cover" />
|
||||
*/}
|
||||
<meta
|
||||
name="viewport"
|
||||
content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1.00001,viewport-fit=cover"
|
||||
/>
|
||||
{/*
|
||||
Disable body scrolling on web. This makes ScrollView components work closer to how they do on native.
|
||||
However, body scrolling is often nice to have for mobile web. If you want to enable it, remove this line.
|
||||
*/}
|
||||
<ScrollViewStyleReset />
|
||||
|
||||
{/* Using raw CSS styles as an escape-hatch to ensure the background color never flickers in dark-mode. */}
|
||||
<style dangerouslySetInnerHTML={{ __html: responsiveBackground }} />
|
||||
{/* Add any additional <head> elements that you want globally available on web... */}
|
||||
</head>
|
||||
<body>{children}</body>
|
||||
</html>
|
||||
);
|
||||
}
|
||||
|
||||
const responsiveBackground = `
|
||||
body {
|
||||
background-color: #fff;
|
||||
}
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body {
|
||||
background-color: #000;
|
||||
}
|
||||
}`;
|
40
apps/mobile/app/[...missing].tsx
Normal file
40
apps/mobile/app/[...missing].tsx
Normal file
@@ -0,0 +1,40 @@
|
||||
import { Link, Stack } from 'expo-router';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { Text, View } from '../components/Themed';
|
||||
|
||||
export default function NotFoundScreen() {
|
||||
return (
|
||||
<>
|
||||
<Stack.Screen options={{ title: 'Oops!' }} />
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>This screen doesn't exist.</Text>
|
||||
|
||||
<Link href="/" style={styles.link}>
|
||||
<Text style={styles.linkText}>Go to home screen!</Text>
|
||||
</Link>
|
||||
</View>
|
||||
</>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
padding: 20,
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
link: {
|
||||
marginTop: 15,
|
||||
paddingVertical: 15,
|
||||
},
|
||||
linkText: {
|
||||
fontSize: 14,
|
||||
color: '#2e78b7',
|
||||
},
|
||||
});
|
62
apps/mobile/app/_layout.tsx
Normal file
62
apps/mobile/app/_layout.tsx
Normal file
@@ -0,0 +1,62 @@
|
||||
import FontAwesome from '@expo/vector-icons/FontAwesome';
|
||||
import {
|
||||
DarkTheme,
|
||||
DefaultTheme,
|
||||
ThemeProvider,
|
||||
} from '@react-navigation/native';
|
||||
import { useFonts } from 'expo-font';
|
||||
import { SplashScreen, Stack } from 'expo-router';
|
||||
import { useEffect } from 'react';
|
||||
import { useColorScheme } from 'react-native';
|
||||
|
||||
export {
|
||||
// Catch any errors thrown by the Layout component.
|
||||
ErrorBoundary,
|
||||
} from 'expo-router';
|
||||
|
||||
// eslint-disable-next-line camelcase
|
||||
export const unstable_settings = {
|
||||
// Ensure that reloading on `/modal` keeps a back button present.
|
||||
initialRouteName: '(tabs)/index',
|
||||
};
|
||||
|
||||
// Prevent the splash screen from auto-hiding before asset loading is complete.
|
||||
SplashScreen.preventAutoHideAsync();
|
||||
|
||||
export default function RootLayout() {
|
||||
const [loaded, error] = useFonts({
|
||||
// eslint-disable-next-line global-require
|
||||
SpaceMono: require('../assets/fonts/SpaceMono-Regular.ttf'),
|
||||
...FontAwesome.font,
|
||||
});
|
||||
|
||||
// Expo Router uses Error Boundaries to catch errors in the navigation tree.
|
||||
useEffect(() => {
|
||||
if (error) throw error;
|
||||
}, [error]);
|
||||
|
||||
useEffect(() => {
|
||||
if (loaded) {
|
||||
SplashScreen.hideAsync();
|
||||
}
|
||||
}, [loaded]);
|
||||
|
||||
if (!loaded) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return <RootLayoutNav />;
|
||||
}
|
||||
|
||||
function RootLayoutNav() {
|
||||
const colorScheme = useColorScheme();
|
||||
|
||||
return (
|
||||
<ThemeProvider value={colorScheme === 'dark' ? DarkTheme : DefaultTheme}>
|
||||
<Stack>
|
||||
<Stack.Screen name="(tabs)" options={{ headerShown: false }} />
|
||||
<Stack.Screen name="modal" options={{ presentation: 'modal' }} />
|
||||
</Stack>
|
||||
</ThemeProvider>
|
||||
);
|
||||
}
|
39
apps/mobile/app/modal.tsx
Normal file
39
apps/mobile/app/modal.tsx
Normal file
@@ -0,0 +1,39 @@
|
||||
import { StatusBar } from 'expo-status-bar';
|
||||
import { Platform, StyleSheet } from 'react-native';
|
||||
|
||||
import EditScreenInfo from '../components/EditScreenInfo';
|
||||
import { Text, View } from '../components/Themed';
|
||||
|
||||
export default function ModalScreen() {
|
||||
return (
|
||||
<View style={styles.container}>
|
||||
<Text style={styles.title}>Modal</Text>
|
||||
<View
|
||||
style={styles.separator}
|
||||
lightColor="#eee"
|
||||
darkColor="rgba(255,255,255,0.1)"
|
||||
/>
|
||||
<EditScreenInfo path="app/modal.tsx" />
|
||||
|
||||
{/* Use a light status bar on iOS to account for the black space above the modal */}
|
||||
<StatusBar style={Platform.OS === 'ios' ? 'light' : 'auto'} />
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
alignItems: 'center',
|
||||
justifyContent: 'center',
|
||||
},
|
||||
title: {
|
||||
fontSize: 20,
|
||||
fontWeight: 'bold',
|
||||
},
|
||||
separator: {
|
||||
marginVertical: 30,
|
||||
height: 1,
|
||||
width: '80%',
|
||||
},
|
||||
});
|
BIN
apps/mobile/assets/fonts/SpaceMono-Regular.ttf
Normal file
BIN
apps/mobile/assets/fonts/SpaceMono-Regular.ttf
Normal file
Binary file not shown.
BIN
apps/mobile/assets/images/adaptive-icon.png
Normal file
BIN
apps/mobile/assets/images/adaptive-icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 17 KiB |
BIN
apps/mobile/assets/images/favicon.png
Normal file
BIN
apps/mobile/assets/images/favicon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.4 KiB |
BIN
apps/mobile/assets/images/icon.png
Normal file
BIN
apps/mobile/assets/images/icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 22 KiB |
BIN
apps/mobile/assets/images/splash.png
Normal file
BIN
apps/mobile/assets/images/splash.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 46 KiB |
10
apps/mobile/babel.config.js
Normal file
10
apps/mobile/babel.config.js
Normal file
@@ -0,0 +1,10 @@
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ['babel-preset-expo'],
|
||||
plugins: [
|
||||
// Required for expo-router
|
||||
'expo-router/babel',
|
||||
],
|
||||
};
|
||||
};
|
82
apps/mobile/components/EditScreenInfo.tsx
Normal file
82
apps/mobile/components/EditScreenInfo.tsx
Normal file
@@ -0,0 +1,82 @@
|
||||
import React from 'react';
|
||||
import { StyleSheet } from 'react-native';
|
||||
|
||||
import { ExternalLink } from './ExternalLink';
|
||||
import { MonoText } from './StyledText';
|
||||
import { Text, View } from './Themed';
|
||||
import Colors from '../constants/Colors';
|
||||
|
||||
export default function EditScreenInfo({ path }: { path: string }) {
|
||||
return (
|
||||
<View>
|
||||
<View style={styles.getStartedContainer}>
|
||||
<Text
|
||||
style={styles.getStartedText}
|
||||
lightColor="rgba(0,0,0,0.8)"
|
||||
darkColor="rgba(255,255,255,0.8)"
|
||||
>
|
||||
Open up the code for this screen:
|
||||
</Text>
|
||||
|
||||
<View
|
||||
style={[styles.codeHighlightContainer, styles.homeScreenFilename]}
|
||||
darkColor="rgba(255,255,255,0.05)"
|
||||
lightColor="rgba(0,0,0,0.05)"
|
||||
>
|
||||
<MonoText>{path}</MonoText>
|
||||
</View>
|
||||
|
||||
<Text
|
||||
style={styles.getStartedText}
|
||||
lightColor="rgba(0,0,0,0.8)"
|
||||
darkColor="rgba(255,255,255,0.8)"
|
||||
>
|
||||
Change any of the text, save the file, and your app will automatically
|
||||
update.
|
||||
</Text>
|
||||
</View>
|
||||
|
||||
<View style={styles.helpContainer}>
|
||||
<ExternalLink
|
||||
style={styles.helpLink}
|
||||
href="https://docs.expo.io/get-started/create-a-new-app/#opening-the-app-on-your-phonetablet"
|
||||
>
|
||||
<Text style={styles.helpLinkText} lightColor={Colors.light.tint}>
|
||||
Tap here if your app doesn't automatically update after making
|
||||
changes
|
||||
</Text>
|
||||
</ExternalLink>
|
||||
</View>
|
||||
</View>
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
getStartedContainer: {
|
||||
alignItems: 'center',
|
||||
marginHorizontal: 50,
|
||||
},
|
||||
homeScreenFilename: {
|
||||
marginVertical: 7,
|
||||
},
|
||||
codeHighlightContainer: {
|
||||
borderRadius: 3,
|
||||
paddingHorizontal: 4,
|
||||
},
|
||||
getStartedText: {
|
||||
fontSize: 17,
|
||||
lineHeight: 24,
|
||||
textAlign: 'center',
|
||||
},
|
||||
helpContainer: {
|
||||
marginTop: 15,
|
||||
marginHorizontal: 20,
|
||||
alignItems: 'center',
|
||||
},
|
||||
helpLink: {
|
||||
paddingVertical: 15,
|
||||
},
|
||||
helpLinkText: {
|
||||
textAlign: 'center',
|
||||
},
|
||||
});
|
28
apps/mobile/components/ExternalLink.tsx
Normal file
28
apps/mobile/components/ExternalLink.tsx
Normal file
@@ -0,0 +1,28 @@
|
||||
import { Link } from 'expo-router';
|
||||
import * as WebBrowser from 'expo-web-browser';
|
||||
import React from 'react';
|
||||
import { Platform } from 'react-native';
|
||||
|
||||
export function ExternalLink(
|
||||
props: Omit<React.ComponentProps<typeof Link>, 'href'> & { href: string },
|
||||
) {
|
||||
return (
|
||||
<Link
|
||||
hrefAttrs={{
|
||||
// On web, launch the link in a new tab.
|
||||
target: '_blank',
|
||||
}}
|
||||
{...props}
|
||||
// @ts-expect-error: External URLs are not typed.
|
||||
href={props.href}
|
||||
onPress={(e) => {
|
||||
if (Platform.OS !== 'web') {
|
||||
// Prevent the default behavior of linking to the default browser on native.
|
||||
e.preventDefault();
|
||||
// Open the link in an in-app browser.
|
||||
WebBrowser.openBrowserAsync(props.href as string);
|
||||
}
|
||||
}}
|
||||
/>
|
||||
);
|
||||
}
|
5
apps/mobile/components/StyledText.tsx
Normal file
5
apps/mobile/components/StyledText.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { Text, TextProps } from './Themed';
|
||||
|
||||
export function MonoText(props: TextProps) {
|
||||
return <Text {...props} style={[props.style, { fontFamily: 'SpaceMono' }]} />;
|
||||
}
|
50
apps/mobile/components/Themed.tsx
Normal file
50
apps/mobile/components/Themed.tsx
Normal file
@@ -0,0 +1,50 @@
|
||||
/**
|
||||
* Learn more about Light and Dark modes:
|
||||
* https://docs.expo.io/guides/color-schemes/
|
||||
*/
|
||||
|
||||
import {
|
||||
Text as DefaultText,
|
||||
View as DefaultView,
|
||||
useColorScheme,
|
||||
} from 'react-native';
|
||||
|
||||
import Colors from '../constants/Colors';
|
||||
|
||||
type ThemeProps = {
|
||||
lightColor?: string;
|
||||
darkColor?: string;
|
||||
};
|
||||
|
||||
export type TextProps = ThemeProps & DefaultText['props'];
|
||||
export type ViewProps = ThemeProps & DefaultView['props'];
|
||||
|
||||
export function useThemeColor(
|
||||
props: { light?: string; dark?: string },
|
||||
colorName: keyof typeof Colors.light & keyof typeof Colors.dark,
|
||||
) {
|
||||
const theme = useColorScheme() ?? 'light';
|
||||
const colorFromProps = props[theme];
|
||||
|
||||
if (colorFromProps) {
|
||||
return colorFromProps;
|
||||
}
|
||||
return Colors[theme][colorName];
|
||||
}
|
||||
|
||||
export function Text(props: TextProps) {
|
||||
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||
const color = useThemeColor({ light: lightColor, dark: darkColor }, 'text');
|
||||
|
||||
return <DefaultText style={[{ color }, style]} {...otherProps} />;
|
||||
}
|
||||
|
||||
export function View(props: ViewProps) {
|
||||
const { style, lightColor, darkColor, ...otherProps } = props;
|
||||
const backgroundColor = useThemeColor(
|
||||
{ light: lightColor, dark: darkColor },
|
||||
'background',
|
||||
);
|
||||
|
||||
return <DefaultView style={[{ backgroundColor }, style]} {...otherProps} />;
|
||||
}
|
19
apps/mobile/constants/Colors.ts
Normal file
19
apps/mobile/constants/Colors.ts
Normal file
@@ -0,0 +1,19 @@
|
||||
const tintColorLight = '#2f95dc';
|
||||
const tintColorDark = '#fff';
|
||||
|
||||
export default {
|
||||
light: {
|
||||
text: '#000',
|
||||
background: '#fff',
|
||||
tint: tintColorLight,
|
||||
tabIconDefault: '#ccc',
|
||||
tabIconSelected: tintColorLight,
|
||||
},
|
||||
dark: {
|
||||
text: '#fff',
|
||||
background: '#000',
|
||||
tint: tintColorDark,
|
||||
tabIconDefault: '#ccc',
|
||||
tabIconSelected: tintColorDark,
|
||||
},
|
||||
};
|
28
apps/mobile/eas.json
Normal file
28
apps/mobile/eas.json
Normal file
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"build": {
|
||||
"production": {
|
||||
"android": {
|
||||
"buildType": "app-bundle"
|
||||
}
|
||||
},
|
||||
"development": {
|
||||
"developmentClient": true,
|
||||
"distribution": "internal"
|
||||
},
|
||||
"preview": {
|
||||
"distribution": "internal",
|
||||
"ios": {
|
||||
"simulator": true
|
||||
},
|
||||
"android": {
|
||||
"buildType": "apk"
|
||||
}
|
||||
}
|
||||
},
|
||||
"submit": {
|
||||
"production": {}
|
||||
},
|
||||
"cli": {
|
||||
"version": ">= 5.2.0"
|
||||
}
|
||||
}
|
13
apps/mobile/jest.config.ts
Normal file
13
apps/mobile/jest.config.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
module.exports = {
|
||||
displayName: 'mobile',
|
||||
resolver: '@nx/jest/plugins/resolver',
|
||||
preset: 'jest-expo',
|
||||
transformIgnorePatterns: [
|
||||
'node_modules/(?!((jest-)?react-native|@react-native(-community)?)|expo(nent)?|@expo(nent)?/.*|@expo-google-fonts/.*|react-navigation|@react-navigation/.*|@unimodules/.*|unimodules|sentry-expo|native-base|react-native-svg)',
|
||||
],
|
||||
moduleFileExtensions: ['ts', 'js', 'html', 'tsx', 'jsx'],
|
||||
setupFilesAfterEnv: ['<rootDir>/test-setup.ts'],
|
||||
moduleNameMapper: {
|
||||
'\\.svg$': '@nx/expo/plugins/jest/svg-mock',
|
||||
},
|
||||
};
|
36
apps/mobile/metro.config.js
Normal file
36
apps/mobile/metro.config.js
Normal file
@@ -0,0 +1,36 @@
|
||||
const { withNxMetro } = require('@nx/expo');
|
||||
const { getDefaultConfig } = require('@expo/metro-config');
|
||||
const { mergeConfig } = require('metro-config');
|
||||
const exclusionList = require('metro-config/src/defaults/exclusionList');
|
||||
|
||||
const defaultConfig = getDefaultConfig(__dirname);
|
||||
const { assetExts, sourceExts } = defaultConfig.resolver;
|
||||
|
||||
/**
|
||||
* Metro configuration
|
||||
* https://facebook.github.io/metro/docs/configuration
|
||||
*
|
||||
* @type {import('metro-config').MetroConfig}
|
||||
*/
|
||||
const customConfig = {
|
||||
transformer: {
|
||||
babelTransformerPath: require.resolve('react-native-svg-transformer'),
|
||||
},
|
||||
resolver: {
|
||||
assetExts: assetExts.filter((ext) => ext !== 'svg'),
|
||||
sourceExts: [...sourceExts, 'svg'],
|
||||
blockList: exclusionList([/^(?!.*node_modules).*\/dist\/.*/]),
|
||||
// unstable_enableSymlinks: true,
|
||||
// unstable_enablePackageExports: true,
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = withNxMetro(mergeConfig(defaultConfig, customConfig), {
|
||||
// Change this to true to see debugging info.
|
||||
// Useful if you have issues resolving modules
|
||||
debug: false,
|
||||
// all the file extensions used for imports other than 'ts', 'tsx', 'js', 'jsx', 'json'
|
||||
extensions: [],
|
||||
// Specify folders to watch, in addition to Nx defaults (workspace libraries and node_modules)
|
||||
watchFolders: [],
|
||||
});
|
65
apps/mobile/package.json
Normal file
65
apps/mobile/package.json
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
"name": "mobile",
|
||||
"main": "expo-router/entry",
|
||||
"version": "1.0.0",
|
||||
"jest": {
|
||||
"preset": "jest-expo"
|
||||
},
|
||||
"private": true,
|
||||
"dependencies": {
|
||||
"@babel/core": "*",
|
||||
"@expo/metro-config": "*",
|
||||
"@expo/vector-icons": "^13.0.0",
|
||||
"@nx/expo": "*",
|
||||
"@react-navigation/native": "^6.1.9",
|
||||
"@testing-library/jest-native": "*",
|
||||
"@testing-library/react-native": "*",
|
||||
"expo": "*",
|
||||
"expo-font": "^11.4.0",
|
||||
"expo-linking": "^6.0.0",
|
||||
"expo-router": "^2.0.14",
|
||||
"expo-splash-screen": "~0.20.5",
|
||||
"expo-status-bar": "*",
|
||||
"expo-system-ui": "^2.6.0",
|
||||
"expo-web-browser": "^12.5.0",
|
||||
"metro-config": "*",
|
||||
"pod-install": "*",
|
||||
"react": "*",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native": "*",
|
||||
"react-native-gesture-handler": "^2.14.1",
|
||||
"react-native-safe-area-context": "^4.8.2",
|
||||
"react-native-screens": "^3.29.0",
|
||||
"react-native-svg": "*",
|
||||
"react-native-svg-transformer": "*",
|
||||
"react-native-web": "^0.19.10"
|
||||
},
|
||||
"scripts": {
|
||||
"eas-build-pre-install": "cd ../../ && node tools/scripts/eas-build-pre-install.mjs . apps/mobile && cp pnpm-lock.yaml apps/mobile",
|
||||
"eas-build-post-install": "cd ../../ && node tools/scripts/eas-build-post-install.mjs . apps/mobile",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"test": "jest --watchAll",
|
||||
"lint": "eslint . --ext .js,.jsx,.ts,.tsx",
|
||||
"format": "prettier --write ."
|
||||
},
|
||||
"devDependencies": {
|
||||
"@babel/core": "^7.20.0",
|
||||
"@rnx-kit/metro-config": "^1.3.14",
|
||||
"@rnx-kit/metro-resolver-symlinks": "^0.1.34",
|
||||
"@types/react": "18.0.28",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"jest": "^29.4.1",
|
||||
"jest-expo": "~49.0.0",
|
||||
"pod-install": "^0.1.39",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"typescript": "~5.2.2"
|
||||
},
|
||||
"overrides": {
|
||||
"react-refresh": "~0.14.0"
|
||||
},
|
||||
"resolutions": {
|
||||
"react-refresh": "~0.14.0"
|
||||
}
|
||||
}
|
94
apps/mobile/project.json
Normal file
94
apps/mobile/project.json
Normal file
@@ -0,0 +1,94 @@
|
||||
{
|
||||
"name": "mobile",
|
||||
"$schema": "../../node_modules/nx/schemas/project-schema.json",
|
||||
"sourceRoot": "apps/mobile/src",
|
||||
"projectType": "application",
|
||||
"targets": {
|
||||
"start": {
|
||||
"executor": "@nx/expo:start",
|
||||
"dependsOn": ["ensure-symlink", "sync-deps"],
|
||||
"options": {
|
||||
"port": 8081
|
||||
}
|
||||
},
|
||||
"serve": {
|
||||
"executor": "nx:run-commands",
|
||||
"options": {
|
||||
"command": "nx start mobile"
|
||||
}
|
||||
},
|
||||
"run-ios": {
|
||||
"executor": "@nx/expo:run",
|
||||
"dependsOn": ["ensure-symlink", "sync-deps"],
|
||||
"options": {
|
||||
"platform": "ios"
|
||||
}
|
||||
},
|
||||
"run-android": {
|
||||
"executor": "@nx/expo:run",
|
||||
"dependsOn": ["ensure-symlink", "sync-deps"],
|
||||
"options": {
|
||||
"platform": "android"
|
||||
}
|
||||
},
|
||||
"build": {
|
||||
"executor": "@nx/expo:build",
|
||||
"options": {}
|
||||
},
|
||||
"submit": {
|
||||
"executor": "@nx/expo:submit",
|
||||
"options": {}
|
||||
},
|
||||
"build-list": {
|
||||
"executor": "@nx/expo:build-list",
|
||||
"options": {}
|
||||
},
|
||||
"sync-deps": {
|
||||
"executor": "@nx/expo:sync-deps",
|
||||
"options": {}
|
||||
},
|
||||
"ensure-symlink": {
|
||||
"executor": "@nx/expo:ensure-symlink",
|
||||
"options": {}
|
||||
},
|
||||
"prebuild": {
|
||||
"executor": "@nx/expo:prebuild",
|
||||
"dependsOn": ["ensure-symlink", "sync-deps"],
|
||||
"options": {}
|
||||
},
|
||||
"install": {
|
||||
"executor": "@nx/expo:install",
|
||||
"options": {}
|
||||
},
|
||||
"update": {
|
||||
"executor": "@nx/expo:update",
|
||||
"options": {}
|
||||
},
|
||||
"export": {
|
||||
"executor": "@nx/expo:export",
|
||||
"dependsOn": ["ensure-symlink", "sync-deps"],
|
||||
"options": {
|
||||
"platform": "all",
|
||||
"outputDir": "../../dist/apps/mobile"
|
||||
}
|
||||
},
|
||||
"export-web": {
|
||||
"executor": "@nx/expo:export",
|
||||
"options": {
|
||||
"bundler": "metro"
|
||||
}
|
||||
},
|
||||
"lint": {
|
||||
"executor": "@nx/eslint:lint",
|
||||
"outputs": ["{options.outputFile}"]
|
||||
},
|
||||
"test": {
|
||||
"executor": "@nx/jest:jest",
|
||||
"outputs": ["{workspaceRoot}/coverage/{projectRoot}"],
|
||||
"options": {
|
||||
"jestConfig": "apps/mobile/jest.config.ts"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": []
|
||||
}
|
1
apps/mobile/test-setup.ts
Normal file
1
apps/mobile/test-setup.ts
Normal file
@@ -0,0 +1 @@
|
||||
import '@testing-library/jest-native/extend-expect';
|
15
apps/mobile/tsconfig.app.json
Normal file
15
apps/mobile/tsconfig.app.json
Normal file
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"types": ["node"]
|
||||
},
|
||||
"files": ["../../node_modules/@nx/expo/typings/svg.d.ts"],
|
||||
"exclude": [
|
||||
"jest.config.ts",
|
||||
"**/*.spec.ts",
|
||||
"**/*.spec.tsx",
|
||||
"test-setup.ts"
|
||||
],
|
||||
"include": ["**/*.ts", "**/*.tsx", "**/*.js", "**/*.jsx"]
|
||||
}
|
29
apps/mobile/tsconfig.json
Normal file
29
apps/mobile/tsconfig.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"extends": "../../tsconfig.base.json",
|
||||
"compilerOptions": {
|
||||
"allowSyntheticDefaultImports": true,
|
||||
"jsx": "react-native",
|
||||
"lib": [
|
||||
"dom",
|
||||
"esnext"
|
||||
],
|
||||
"moduleResolution": "node",
|
||||
"skipLibCheck": true,
|
||||
"resolveJsonModule": true,
|
||||
"strict": true,
|
||||
"declaration": true
|
||||
},
|
||||
"files": [],
|
||||
"include": [
|
||||
".expo/types/**/*.ts",
|
||||
"expo-env.d.ts"
|
||||
],
|
||||
"references": [
|
||||
{
|
||||
"path": "./tsconfig.app.json"
|
||||
},
|
||||
{
|
||||
"path": "./tsconfig.spec.json"
|
||||
}
|
||||
]
|
||||
}
|
20
apps/mobile/tsconfig.spec.json
Normal file
20
apps/mobile/tsconfig.spec.json
Normal file
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../../dist/out-tsc",
|
||||
"module": "commonjs",
|
||||
"types": ["jest", "node"]
|
||||
},
|
||||
"include": [
|
||||
"jest.config.ts",
|
||||
"src/**/*.test.ts",
|
||||
"src/**/*.spec.ts",
|
||||
"src/**/*.test.tsx",
|
||||
"src/**/*.spec.tsx",
|
||||
"src/**/*.test.js",
|
||||
"src/**/*.spec.js",
|
||||
"src/**/*.test.jsx",
|
||||
"src/**/*.spec.jsx",
|
||||
"src/**/*.d.ts"
|
||||
]
|
||||
}
|
3
babel.config.json
Normal file
3
babel.config.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"babelrcRoots": ["*"]
|
||||
}
|
5
jest.config.ts
Normal file
5
jest.config.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import { getJestProjects } from '@nx/jest';
|
||||
|
||||
export default {
|
||||
projects: getJestProjects(),
|
||||
};
|
3
jest.preset.js
Normal file
3
jest.preset.js
Normal file
@@ -0,0 +1,3 @@
|
||||
const nxPreset = require('@nx/jest/preset').default;
|
||||
|
||||
module.exports = { ...nxPreset };
|
41
nx.json
Normal file
41
nx.json
Normal file
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "./node_modules/nx/schemas/nx-schema.json",
|
||||
"affected": {
|
||||
"defaultBase": "master"
|
||||
},
|
||||
"targetDefaults": {
|
||||
"build": {
|
||||
"cache": true,
|
||||
"dependsOn": ["^build"],
|
||||
"inputs": ["production", "^production"]
|
||||
},
|
||||
"lint": {
|
||||
"cache": true
|
||||
},
|
||||
"@nx/jest:jest": {
|
||||
"cache": true,
|
||||
"inputs": ["default", "^production", "{workspaceRoot}/jest.preset.js"],
|
||||
"options": {
|
||||
"passWithNoTests": true
|
||||
},
|
||||
"configurations": {
|
||||
"ci": {
|
||||
"ci": true,
|
||||
"codeCoverage": true
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"namedInputs": {
|
||||
"default": ["{projectRoot}/**/*", "sharedGlobals"],
|
||||
"production": [
|
||||
"default",
|
||||
"!{projectRoot}/**/?(*.)+(spec|test).[jt]s?(x)?(.snap)",
|
||||
"!{projectRoot}/tsconfig.spec.json",
|
||||
"!{projectRoot}/jest.config.[jt]s",
|
||||
"!{projectRoot}/src/test-setup.[jt]s",
|
||||
"!{projectRoot}/test-setup.[jt]s"
|
||||
],
|
||||
"sharedGlobals": []
|
||||
}
|
||||
}
|
64
package.json
Normal file
64
package.json
Normal file
@@ -0,0 +1,64 @@
|
||||
{
|
||||
"name": "@movie-web/native-app",
|
||||
"version": "0.0.0",
|
||||
"license": "MIT",
|
||||
"scripts": {},
|
||||
"private": true,
|
||||
"devDependencies": {
|
||||
"@config-plugins/detox": "~6.0.0",
|
||||
"@expo/cli": "~0.10.13",
|
||||
"@nx/detox": "17.2.8",
|
||||
"@nx/expo": "17.2.8",
|
||||
"@nx/jest": "17.2.8",
|
||||
"@nx/js": "17.2.8",
|
||||
"@nx/workspace": "17.2.8",
|
||||
"@swc-node/register": "~1.6.8",
|
||||
"@swc/core": "~1.3.102",
|
||||
"@testing-library/jest-dom": "5.16.5",
|
||||
"@testing-library/jest-native": "~5.4.3",
|
||||
"@testing-library/react-native": "~12.3.0",
|
||||
"@types/jest": "^29.4.0",
|
||||
"@types/node": "18.16.9",
|
||||
"@types/react": "18.0.28",
|
||||
"@typescript-eslint/eslint-plugin": "^6.18.1",
|
||||
"@typescript-eslint/parser": "^6.18.1",
|
||||
"babel-jest": "^29.4.1",
|
||||
"babel-preset-expo": "~9.5.2",
|
||||
"detox": "^20.11.1",
|
||||
"eas-cli": "~5.2.0",
|
||||
"eslint": "^8.56.0",
|
||||
"eslint-config-airbnb": "^19.0.4",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-import-resolver-typescript": "^3.6.1",
|
||||
"eslint-plugin-import": "^2.29.1",
|
||||
"eslint-plugin-jsx-a11y": "6.7.1",
|
||||
"eslint-plugin-prettier": "^5.1.3",
|
||||
"eslint-plugin-react": "7.32.2",
|
||||
"eslint-plugin-react-hooks": "4.6.0",
|
||||
"jest": "^29.4.1",
|
||||
"jest-circus": "^29.4.1",
|
||||
"jest-environment-jsdom": "^29.4.1",
|
||||
"jest-expo": "~49.0.0",
|
||||
"metro": "0.76.8",
|
||||
"metro-resolver": "0.76.8",
|
||||
"nx": "17.2.8",
|
||||
"prettier": "^3.0.3",
|
||||
"react-test-renderer": "18.2.0",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-node": "10.9.1",
|
||||
"typescript": "~5.2.2"
|
||||
},
|
||||
"dependencies": {
|
||||
"@expo/metro-config": "~0.10.7",
|
||||
"expo": "49.0.16",
|
||||
"expo-splash-screen": "~0.20.5",
|
||||
"expo-status-bar": "~1.6.0",
|
||||
"react": "18.2.0",
|
||||
"react-dom": "18.2.0",
|
||||
"react-native": "0.72.6",
|
||||
"react-native-svg": "13.9.0",
|
||||
"react-native-svg-transformer": "1.3.0",
|
||||
"react-native-web": "~0.19.9",
|
||||
"tslib": "^2.3.0"
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
This will be the folder that holds the common library
|
14515
pnpm-lock.yaml
generated
Normal file
14515
pnpm-lock.yaml
generated
Normal file
File diff suppressed because it is too large
Load Diff
3
pnpm-workspace.yaml
Normal file
3
pnpm-workspace.yaml
Normal file
@@ -0,0 +1,3 @@
|
||||
packages:
|
||||
- packages/*
|
||||
- apps/*
|
28
tools/scripts/eas-build-post-install.mjs
Normal file
28
tools/scripts/eas-build-post-install.mjs
Normal file
@@ -0,0 +1,28 @@
|
||||
/**
|
||||
* This script is used to patch the '@nx/expo' package to work with EAS Build.
|
||||
* It is run as a eas-build-post-install script in the 'package.json' of expo app.
|
||||
* It is executed as 'node tools/scripts/eas-build-post-install.mjs <workspace root> <project root>'
|
||||
* It will create a symlink from the project's node_modules to the workspace's node_modules.
|
||||
*/
|
||||
|
||||
import { symlink, existsSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const [workspaceRoot, projectRoot] = process.argv.slice(2);
|
||||
|
||||
if (existsSync(join(workspaceRoot, 'node_modules'))) {
|
||||
console.log('Symlink already exists');
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
symlink(
|
||||
join(projectRoot, 'node_modules'),
|
||||
join(workspaceRoot, 'node_modules'),
|
||||
'dir',
|
||||
(err) => {
|
||||
if (err) console.log(err);
|
||||
else {
|
||||
console.log('Symlink created');
|
||||
}
|
||||
},
|
||||
);
|
33
tools/scripts/eas-build-pre-install.mjs
Normal file
33
tools/scripts/eas-build-pre-install.mjs
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* This script is used to patch the '@nx/expo' package to work with EAS Build.
|
||||
* It is run as the eas-build-pre-install script in the 'package.json' of expo app.
|
||||
* It is executed as 'node tools/scripts/eas-build-pre-install.mjs <workspace root> <project root>'
|
||||
* It will copy the dependencies and devDependencies from the workspace package.json to project's package.json.
|
||||
* This is needed because EAS Build does the install in project's directory and not workspace's directory.
|
||||
*/
|
||||
import { readFileSync, writeFileSync } from 'fs';
|
||||
import { join } from 'path';
|
||||
|
||||
const [workspaceRoot, projectRoot] = process.argv.slice(2);
|
||||
if (!workspaceRoot) {
|
||||
throw new Error('Missing workspace root');
|
||||
}
|
||||
if (!projectRoot) {
|
||||
throw new Error('Missing project root');
|
||||
}
|
||||
try {
|
||||
const workspacePackage = JSON.parse(
|
||||
readFileSync(join(workspaceRoot, 'package.json')).toString(),
|
||||
);
|
||||
const projectPackage = JSON.parse(
|
||||
readFileSync(join(projectRoot, 'package.json')).toString(),
|
||||
);
|
||||
projectPackage.dependencies = workspacePackage.dependencies;
|
||||
projectPackage.devDependencies = workspacePackage.devDependencies;
|
||||
writeFileSync(
|
||||
join(projectRoot, 'package.json'),
|
||||
JSON.stringify(projectPackage, null, 2),
|
||||
);
|
||||
} catch (e) {
|
||||
console.error('Error reading package.json file', e);
|
||||
}
|
19
tsconfig.base.json
Normal file
19
tsconfig.base.json
Normal file
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"rootDir": ".",
|
||||
"sourceMap": true,
|
||||
"declaration": false,
|
||||
"moduleResolution": "node",
|
||||
"emitDecoratorMetadata": true,
|
||||
"experimentalDecorators": true,
|
||||
"importHelpers": true,
|
||||
"target": "es2015",
|
||||
"module": "esnext",
|
||||
"lib": ["es2020", "dom"],
|
||||
"skipLibCheck": true,
|
||||
"skipDefaultLibCheck": true,
|
||||
"baseUrl": ".",
|
||||
"paths": {}
|
||||
},
|
||||
"exclude": ["node_modules", "tmp"]
|
||||
}
|
Reference in New Issue
Block a user