Close
This commit is contained in:
parent
82069f3bef
commit
85b1cb8759
@ -1,10 +1,15 @@
|
||||
rootProject.name = 'Railbird'
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('expo/package.json')"].execute(null, rootDir).text.trim(), "../scripts/autolinking.gradle");
|
||||
|
||||
useExpoModules()
|
||||
|
||||
apply from: new File(["node", "--print", "require.resolve('@react-native-community/cli-platform-android/package.json')"].execute(null, rootDir).text.trim(), "../native_modules.gradle");
|
||||
|
||||
applyNativeModulesSettingsGradle(settings)
|
||||
|
||||
include ':app'
|
||||
includeBuild(new File(["node", "--print", "require.resolve('@react-native/gradle-plugin/package.json')"].execute(null, rootDir).text.trim()).getParentFile())
|
||||
|
||||
include ':react-native-vision-camera'
|
||||
project(':react-native-vision-camera').projectDir = new File(rootProject.projectDir, '../react-native-vision-camera/package/android')
|
||||
|
4
app.json
4
app.json
@ -11,9 +11,7 @@
|
||||
"resizeMode": "contain",
|
||||
"backgroundColor": "#ffffff"
|
||||
},
|
||||
"assetBundlePatterns": [
|
||||
"**/*"
|
||||
],
|
||||
"assetBundlePatterns": ["**/*"],
|
||||
"plugins": [
|
||||
"@react-native-firebase/app",
|
||||
"@react-native-firebase/auth",
|
||||
|
@ -1,16 +1,34 @@
|
||||
module.exports = function(api) {
|
||||
const path = require("path");
|
||||
const pak = require("./react-native-vision-camera/package/package.json");
|
||||
|
||||
module.exports = function (api) {
|
||||
api.cache(true);
|
||||
return {
|
||||
presets: ["babel-preset-expo"],
|
||||
plugins: [
|
||||
["module:react-native-dotenv", {
|
||||
"moduleName": "@env",
|
||||
"path": ".env",
|
||||
"safe": false,
|
||||
"allowUndefined": true,
|
||||
"verbose": false,
|
||||
}],
|
||||
'react-native-reanimated/plugin',
|
||||
[
|
||||
"module:react-native-dotenv",
|
||||
{
|
||||
moduleName: "@env",
|
||||
path: ".env",
|
||||
safe: false,
|
||||
allowUndefined: true,
|
||||
verbose: false,
|
||||
},
|
||||
],
|
||||
"react-native-reanimated/plugin",
|
||||
[
|
||||
"module-resolver",
|
||||
{
|
||||
alias: {
|
||||
[pak.name]: path.join(
|
||||
__dirname,
|
||||
"./react-native-vision-camera/package",
|
||||
pak.source,
|
||||
),
|
||||
},
|
||||
},
|
||||
],
|
||||
],
|
||||
};
|
||||
};
|
||||
|
@ -1,57 +1,68 @@
|
||||
import React, { useCallback, useRef, useState } from 'react'
|
||||
import { Button, StyleSheet, Text, View } from 'react-native'
|
||||
import { Camera, useCameraPermission, useCameraDevice, useCameraFormat, PhotoFile, VideoFile, CameraRuntimeError, Orientation } from 'react-native-vision-camera'
|
||||
import { RecordingButton } from './capture-button'
|
||||
import { useIsForeground } from './is-foreground'
|
||||
import React, { useCallback, useRef, useState } from "react";
|
||||
import { Button, StyleSheet, Text, View } from "react-native";
|
||||
import {
|
||||
Camera,
|
||||
useCameraPermission,
|
||||
useCameraDevice,
|
||||
useCameraFormat,
|
||||
PhotoFile,
|
||||
VideoFile,
|
||||
CameraRuntimeError,
|
||||
Orientation,
|
||||
} from "react-native-vision-camera";
|
||||
import { RecordingButton } from "./capture-button";
|
||||
import { useIsForeground } from "./is-foreground";
|
||||
|
||||
export default function CameraScreen(): React.ReactElement {
|
||||
const camera = useRef<Camera>(null)
|
||||
const { hasPermission, requestPermission } = useCameraPermission()
|
||||
const [isCameraInitialized, setIsCameraInitialized] = useState<boolean>(false)
|
||||
const camera = useRef<Camera>(null);
|
||||
const { hasPermission, requestPermission } = useCameraPermission();
|
||||
const [isCameraInitialized, setIsCameraInitialized] =
|
||||
useState<boolean>(false);
|
||||
|
||||
const isForeground: boolean = useIsForeground()
|
||||
const isActive: boolean = isForeground // Should be combined with isFocused hook
|
||||
const isForeground: boolean = useIsForeground();
|
||||
const isActive: boolean = isForeground; // Should be combined with isFocused hook
|
||||
|
||||
const onError = useCallback((error: CameraRuntimeError) => {
|
||||
console.error(error)
|
||||
}, [])
|
||||
console.error(error);
|
||||
}, []);
|
||||
|
||||
const onInitialized = useCallback(() => {
|
||||
console.log('Camera initialized!')
|
||||
setIsCameraInitialized(true)
|
||||
}, [])
|
||||
console.log("Camera initialized!");
|
||||
setIsCameraInitialized(true);
|
||||
}, []);
|
||||
|
||||
const onMediaCaptured = useCallback(
|
||||
(media: PhotoFile | VideoFile) => {
|
||||
console.log(`Media captured! ${JSON.stringify(media)}`)
|
||||
},
|
||||
[],
|
||||
)
|
||||
const onMediaCaptured = useCallback((media: PhotoFile | VideoFile) => {
|
||||
console.log(`Media captured! ${JSON.stringify(media)}`);
|
||||
}, []);
|
||||
|
||||
if (!hasPermission) {
|
||||
requestPermission()
|
||||
requestPermission();
|
||||
// Error handling in case they refuse to give permission
|
||||
}
|
||||
|
||||
const device = useCameraDevice('back')
|
||||
const device = useCameraDevice("back");
|
||||
const format = useCameraFormat(device, [
|
||||
{ videoResolution: { width: 3048, height: 2160 } },
|
||||
{ fps: 60 }
|
||||
]) // this sets as a target
|
||||
{ fps: 60 },
|
||||
]); // this sets as a target
|
||||
|
||||
//Orientation detection
|
||||
const [orientation, setOrientation] = useState<Orientation>('portrait');
|
||||
const [orientation, setOrientation] = useState<Orientation>("portrait");
|
||||
|
||||
const toggleOrientation = () => {
|
||||
setOrientation(currentOrientation =>
|
||||
currentOrientation === 'landscape-left' ? 'portrait' : 'landscape-left' // Can adjust this and the type to match what we want
|
||||
setOrientation(
|
||||
(currentOrientation) =>
|
||||
currentOrientation === "landscape-left" ? "portrait" : "landscape-left", // Can adjust this and the type to match what we want
|
||||
);
|
||||
};
|
||||
|
||||
if (device === null) {
|
||||
return <Text>Camera not available. Does user have permissions: {hasPermission}</Text>
|
||||
return (
|
||||
<Text>
|
||||
Camera not available. Does user have permissions: {hasPermission}
|
||||
</Text>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
hasPermission && (
|
||||
<View style={styles.container}>
|
||||
@ -67,12 +78,22 @@ export default function CameraScreen(): React.ReactElement {
|
||||
isActive={isActive}
|
||||
/>
|
||||
<RecordingButton
|
||||
style={[styles.captureButton, orientation === 'portrait' ? styles.portrait : styles.landscape ]}
|
||||
style={[
|
||||
styles.captureButton,
|
||||
orientation === "portrait" ? styles.portrait : styles.landscape,
|
||||
]}
|
||||
camera={camera}
|
||||
onMediaCaptured={onMediaCaptured}
|
||||
enabled={isCameraInitialized}
|
||||
/>
|
||||
<View style={[styles.button, orientation === 'portrait' ? styles.togglePortrait : styles.toggleLandscape ]}>
|
||||
<View
|
||||
style={[
|
||||
styles.button,
|
||||
orientation === "portrait"
|
||||
? styles.togglePortrait
|
||||
: styles.toggleLandscape,
|
||||
]}
|
||||
>
|
||||
<Button
|
||||
title="Toggle Orientation"
|
||||
onPress={toggleOrientation}
|
||||
@ -82,35 +103,35 @@ export default function CameraScreen(): React.ReactElement {
|
||||
</View>
|
||||
</View>
|
||||
)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
const styles = StyleSheet.create({
|
||||
container: {
|
||||
flex: 1,
|
||||
backgroundColor: 'black',
|
||||
backgroundColor: "black",
|
||||
},
|
||||
captureButton: {
|
||||
position: 'absolute',
|
||||
alignSelf: 'center',
|
||||
position: "absolute",
|
||||
alignSelf: "center",
|
||||
},
|
||||
button: {
|
||||
position: 'absolute',
|
||||
alignSelf: 'center',
|
||||
position: "absolute",
|
||||
alignSelf: "center",
|
||||
},
|
||||
togglePortrait: {
|
||||
bottom: 110, // needs refined
|
||||
},
|
||||
toggleLandscape: {
|
||||
transform: [{ rotate: '90deg' }],
|
||||
bottom: '43%', // Should come from SafeAreaProvider, hardcoded right now, should roughly appear above the button
|
||||
left: 50 // needs refined
|
||||
transform: [{ rotate: "90deg" }],
|
||||
bottom: "43%", // Should come from SafeAreaProvider, hardcoded right now, should roughly appear above the button
|
||||
left: 50, // needs refined
|
||||
},
|
||||
portrait: {
|
||||
bottom: 20 // needs refined
|
||||
bottom: 20, // needs refined
|
||||
},
|
||||
landscape: {
|
||||
bottom: '40%', // Should come from SafeAreaProvider
|
||||
left: 20 // needs refined
|
||||
}
|
||||
})
|
||||
bottom: "40%", // Should come from SafeAreaProvider
|
||||
left: 20, // needs refined
|
||||
},
|
||||
});
|
||||
|
26
flake.nix
26
flake.nix
@ -11,17 +11,23 @@
|
||||
url = "github:tadfisher/android-nixpkgs";
|
||||
};
|
||||
};
|
||||
outputs = { self, nixpkgs, flake-utils, gitignore, android-nixpkgs, ... }:
|
||||
flake-utils.lib.eachDefaultSystem (system:
|
||||
let
|
||||
pkgs = import nixpkgs { inherit system; };
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
flake-utils,
|
||||
gitignore,
|
||||
android-nixpkgs,
|
||||
...
|
||||
}:
|
||||
flake-utils.lib.eachDefaultSystem (system: let
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
nodejs = pkgs.nodejs-18_x;
|
||||
# NOTE: this does not work
|
||||
appBuild = pkgs.stdenv.mkDerivation {
|
||||
name = "example-ts-node";
|
||||
version = "0.1.0";
|
||||
src = gitignore.lib.gitignoreSource ./.; # uses the gitignore in the repo to only copy files git would see
|
||||
buildInputs = [ nodejs ];
|
||||
buildInputs = [nodejs];
|
||||
# https://nixos.org/manual/nixpkgs/stable/#sec-stdenv-phases
|
||||
buildPhase = ''
|
||||
# each phase has pre/postHooks. When you make your own phase be sure to still call the hooks
|
||||
@ -38,7 +44,8 @@
|
||||
runHook postInstall
|
||||
'';
|
||||
};
|
||||
android-sdk = android-nixpkgs.sdk.${system} (sdkPkgs: with sdkPkgs; [
|
||||
android-sdk = android-nixpkgs.sdk.${system} (sdkPkgs:
|
||||
with sdkPkgs; [
|
||||
cmdline-tools-latest
|
||||
build-tools-30-0-3
|
||||
build-tools-33-0-0
|
||||
@ -50,15 +57,16 @@
|
||||
system-images-android-33-google-apis-x86-64
|
||||
system-images-android-34-google-apis-x86-64
|
||||
]);
|
||||
in with pkgs; {
|
||||
in
|
||||
with pkgs; {
|
||||
defaultPackage = appBuild;
|
||||
devShell = mkShell {
|
||||
buildInputs = [ nodejs yarn watchman gradle_7 alejandra nodePackages.prettier ];
|
||||
buildInputs = [nodejs yarn watchman gradle_7 alejandra nodePackages.prettier];
|
||||
ANDROID_SDK_BIN = android-sdk;
|
||||
shellHook = ''
|
||||
export JAVA_HOME=${pkgs.jdk17.home}
|
||||
source ${android-sdk.out}/nix-support/setup-hook
|
||||
export PATH=${android-sdk}/bin:$PATH
|
||||
export PATH=${android-sdk}/bin:${android-sdk}/share/android-sdk/build-tools/33.0.0/:$PATH
|
||||
ORG_GRADLE_PROJECT_ANDROID_HOME="$ANDROID_HOME"
|
||||
'';
|
||||
};
|
||||
|
@ -384,7 +384,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_DEBUG";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ai.railbird.railbird;
|
||||
PRODUCT_NAME = Railbird;
|
||||
PRODUCT_NAME = "Railbird";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Railbird/Railbird-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@ -419,7 +419,7 @@
|
||||
);
|
||||
OTHER_SWIFT_FLAGS = "$(inherited) -D EXPO_CONFIGURATION_RELEASE";
|
||||
PRODUCT_BUNDLE_IDENTIFIER = ai.railbird.railbird;
|
||||
PRODUCT_NAME = Railbird;
|
||||
PRODUCT_NAME = "Railbird";
|
||||
PROVISIONING_PROFILE_SPECIFIER = "";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Railbird/Railbird-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
|
@ -1,7 +1,53 @@
|
||||
// Learn more https://docs.expo.io/guides/customizing-metro
|
||||
const { getDefaultConfig } = require('expo/metro-config');
|
||||
const { getDefaultConfig } = require("expo/metro-config");
|
||||
const { mergeConfig } = require("@react-native/metro-config");
|
||||
const path = require("path");
|
||||
const escape = require("escape-string-regexp");
|
||||
const exclusionList = require("metro-config/src/defaults/exclusionList");
|
||||
const pak = require("./react-native-vision-camera/package/package.json");
|
||||
|
||||
/** @type {import('expo/metro-config').MetroConfig} */
|
||||
const config = getDefaultConfig(__dirname);
|
||||
const root = path.resolve(__dirname, "./react-native-vision-camera/package");
|
||||
const modules = Object.keys({ ...pak.peerDependencies });
|
||||
const localPackagePath = path.resolve(
|
||||
__dirname,
|
||||
"./react-native-vision-camera/package/src/index",
|
||||
);
|
||||
|
||||
module.exports = config;
|
||||
/**
|
||||
* Metro configuration
|
||||
* https://facebook.github.io/metro/docs/configuration
|
||||
*
|
||||
* @type {import('metro-config').MetroConfig}
|
||||
*/
|
||||
const config = {
|
||||
watchFolders: [root],
|
||||
|
||||
// We need to make sure that only one version is loaded for peerDependencies
|
||||
// So we block them at the root, and alias them to the versions in example's node_modules
|
||||
resolver: {
|
||||
blacklistRE: exclusionList(
|
||||
modules.map(
|
||||
(m) =>
|
||||
new RegExp(`^${escape(path.join(root, "node_modules", m))}\\/.*$`),
|
||||
),
|
||||
),
|
||||
|
||||
extraNodeModules: modules.reduce(
|
||||
(acc, name) => {
|
||||
acc[name] = path.join(__dirname, "node_modules", name);
|
||||
return acc;
|
||||
},
|
||||
{ "react-native-vision-camera": localPackagePath },
|
||||
),
|
||||
},
|
||||
|
||||
transformer: {
|
||||
getTransformOptions: async () => ({
|
||||
transform: {
|
||||
experimentalImportSupport: false,
|
||||
inlineRequires: true,
|
||||
},
|
||||
}),
|
||||
},
|
||||
};
|
||||
|
||||
module.exports = mergeConfig(getDefaultConfig(__dirname), config);
|
||||
|
@ -4,8 +4,8 @@
|
||||
"main": "node_modules/expo/AppEntry.js",
|
||||
"scripts": {
|
||||
"start": "cp .env.development .env && expo start",
|
||||
"android": "expo start --android",
|
||||
"ios": "expo start --ios",
|
||||
"android": "expo run:android",
|
||||
"ios": "expo run:ios",
|
||||
"run:android": "expo run:android",
|
||||
"run:ios": "expo run:ios",
|
||||
"web": "expo start --web",
|
||||
@ -54,8 +54,10 @@
|
||||
"@babel/core": "^7.20.0",
|
||||
"@testing-library/jest-native": "^5.4.3",
|
||||
"@testing-library/react-native": "^12.4.3",
|
||||
"@react-native/metro-config": "^0.72.9",
|
||||
"@types/d3-path": "^3.0.2",
|
||||
"@types/jest": "^29.5.11",
|
||||
"metro-react-native-babel-preset": "^0.77.0",
|
||||
"@types/react-native-svg-charts": "^5.0.16",
|
||||
"eslint-config-prettier": "^9.1.0"
|
||||
},
|
||||
|
@ -1,10 +1,32 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"allowJs": false,
|
||||
"allowUnreachableCode": false,
|
||||
"allowUnusedLabels": false,
|
||||
"esModuleInterop": true,
|
||||
"forceConsistentCasingInFileNames": true,
|
||||
"jsx": "react-native",
|
||||
"lib": ["esnext"],
|
||||
"module": "esnext",
|
||||
"moduleResolution": "node",
|
||||
"noFallthroughCasesInSwitch": true,
|
||||
"noImplicitReturns": true,
|
||||
"noStrictGenericChecks": false,
|
||||
"noUnusedLocals": true,
|
||||
"noUnusedParameters": true,
|
||||
"noUncheckedIndexedAccess": true,
|
||||
"resolveJsonModule": true,
|
||||
"skipLibCheck": true,
|
||||
"strict": true,
|
||||
"target": "esnext",
|
||||
"outDir": "lib",
|
||||
"paths": {
|
||||
"react-native-vision-camera": [
|
||||
"./react-native-vision-camera/package/src/index"
|
||||
]
|
||||
}
|
||||
},
|
||||
"extends": "expo/tsconfig.base"
|
||||
"include": ["react-native-vision-camera/package/src", "."],
|
||||
"exclude": ["node_modules"],
|
||||
"extends": ["expo/tsconfig.base"]
|
||||
}
|
||||
|
55
yarn.lock
55
yarn.lock
@ -2487,6 +2487,16 @@
|
||||
hermes-parser "0.15.0"
|
||||
nullthrows "^1.1.1"
|
||||
|
||||
"@react-native/metro-config@^0.72.9":
|
||||
version "0.72.11"
|
||||
resolved "https://registry.yarnpkg.com/@react-native/metro-config/-/metro-config-0.72.11.tgz#c775a22fbb138cedd4513ca46c06bfd6a9dad316"
|
||||
integrity sha512-661EyQnDdVelyc0qP/ew7kKkGAh6N6KlkuPLC2SQ8sxaXskVU6fSuNlpLW4bUTBUDFKG8gEOU2hp6rzk4wQnGQ==
|
||||
dependencies:
|
||||
"@react-native/js-polyfills" "^0.72.1"
|
||||
metro-config "0.76.8"
|
||||
metro-react-native-babel-transformer "0.76.8"
|
||||
metro-runtime "0.76.8"
|
||||
|
||||
"@react-native/normalize-color@^2.0.0":
|
||||
version "2.1.0"
|
||||
resolved "https://registry.yarnpkg.com/@react-native/normalize-color/-/normalize-color-2.1.0.tgz#939b87a9849e81687d3640c5efa2a486ac266f91"
|
||||
@ -7214,6 +7224,51 @@ metro-react-native-babel-preset@0.76.8:
|
||||
babel-plugin-transform-flow-enums "^0.0.2"
|
||||
react-refresh "^0.4.0"
|
||||
|
||||
metro-react-native-babel-preset@^0.77.0:
|
||||
version "0.77.0"
|
||||
resolved "https://registry.yarnpkg.com/metro-react-native-babel-preset/-/metro-react-native-babel-preset-0.77.0.tgz#47457eca8e36b77156afbe790247a70dbb40faaa"
|
||||
integrity sha512-HPPD+bTxADtoE4y/4t1txgTQ1LVR6imOBy7RMHUsqMVTbekoi8Ph5YI9vKX2VMPtVWeFt0w9YnCSLPa76GcXsA==
|
||||
dependencies:
|
||||
"@babel/core" "^7.20.0"
|
||||
"@babel/plugin-proposal-async-generator-functions" "^7.0.0"
|
||||
"@babel/plugin-proposal-class-properties" "^7.18.0"
|
||||
"@babel/plugin-proposal-export-default-from" "^7.0.0"
|
||||
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.18.0"
|
||||
"@babel/plugin-proposal-numeric-separator" "^7.0.0"
|
||||
"@babel/plugin-proposal-object-rest-spread" "^7.20.0"
|
||||
"@babel/plugin-proposal-optional-catch-binding" "^7.0.0"
|
||||
"@babel/plugin-proposal-optional-chaining" "^7.20.0"
|
||||
"@babel/plugin-syntax-dynamic-import" "^7.8.0"
|
||||
"@babel/plugin-syntax-export-default-from" "^7.0.0"
|
||||
"@babel/plugin-syntax-flow" "^7.18.0"
|
||||
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.0.0"
|
||||
"@babel/plugin-syntax-optional-chaining" "^7.0.0"
|
||||
"@babel/plugin-transform-arrow-functions" "^7.0.0"
|
||||
"@babel/plugin-transform-async-to-generator" "^7.20.0"
|
||||
"@babel/plugin-transform-block-scoping" "^7.0.0"
|
||||
"@babel/plugin-transform-classes" "^7.0.0"
|
||||
"@babel/plugin-transform-computed-properties" "^7.0.0"
|
||||
"@babel/plugin-transform-destructuring" "^7.20.0"
|
||||
"@babel/plugin-transform-flow-strip-types" "^7.20.0"
|
||||
"@babel/plugin-transform-function-name" "^7.0.0"
|
||||
"@babel/plugin-transform-literals" "^7.0.0"
|
||||
"@babel/plugin-transform-modules-commonjs" "^7.0.0"
|
||||
"@babel/plugin-transform-named-capturing-groups-regex" "^7.0.0"
|
||||
"@babel/plugin-transform-parameters" "^7.0.0"
|
||||
"@babel/plugin-transform-react-display-name" "^7.0.0"
|
||||
"@babel/plugin-transform-react-jsx" "^7.0.0"
|
||||
"@babel/plugin-transform-react-jsx-self" "^7.0.0"
|
||||
"@babel/plugin-transform-react-jsx-source" "^7.0.0"
|
||||
"@babel/plugin-transform-runtime" "^7.0.0"
|
||||
"@babel/plugin-transform-shorthand-properties" "^7.0.0"
|
||||
"@babel/plugin-transform-spread" "^7.0.0"
|
||||
"@babel/plugin-transform-sticky-regex" "^7.0.0"
|
||||
"@babel/plugin-transform-typescript" "^7.5.0"
|
||||
"@babel/plugin-transform-unicode-regex" "^7.0.0"
|
||||
"@babel/template" "^7.0.0"
|
||||
babel-plugin-transform-flow-enums "^0.0.2"
|
||||
react-refresh "^0.4.0"
|
||||
|
||||
metro-react-native-babel-transformer@0.76.8:
|
||||
version "0.76.8"
|
||||
resolved "https://registry.yarnpkg.com/metro-react-native-babel-transformer/-/metro-react-native-babel-transformer-0.76.8.tgz#c3a98e1f4cd5faf1e21eba8e004b94a90c4db69b"
|
||||
|
Loading…
Reference in New Issue
Block a user