diff --git a/.github/workflows/buildAndTest.yaml b/.github/workflows/buildAndTest.yaml
index b1cc75c2232..672b286f46e 100644
--- a/.github/workflows/buildAndTest.yaml
+++ b/.github/workflows/buildAndTest.yaml
@@ -19,9 +19,9 @@ jobs:
build:
runs-on: macos-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v6
- name: Set up JDK 17
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
diff --git a/.github/workflows/kotlin_checker.yml b/.github/workflows/kotlin_checker.yml
index 0bbc9703ef3..7b1bbb8041e 100644
--- a/.github/workflows/kotlin_checker.yml
+++ b/.github/workflows/kotlin_checker.yml
@@ -4,14 +4,15 @@ jobs:
build:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v1
+ - uses: actions/checkout@v6
+ with:
+ fetch-depth: 0
- name: Setup ruby
uses: ruby/setup-ruby@v1
with:
ruby-version: "3.0"
- architecture: "x64"
- name: Setup JDK
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: "17"
distribution: "temurin"
diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml
index f7c487e9b48..8de75a6e6ff 100644
--- a/.github/workflows/release.yaml
+++ b/.github/workflows/release.yaml
@@ -9,17 +9,17 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout main
- uses: actions/checkout@v3
+ uses: actions/checkout@v6
with:
path: main
ref: ${{ github.event.release.tag_name }}
- name: Checkout gh-pages
- uses: actions/checkout@v3
+ uses: actions/checkout@v6
with:
path: gh-pages
ref: gh-pages
- name: Set up JDK 17
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: "17"
distribution: "temurin"
diff --git a/.github/workflows/test-flutter.yaml b/.github/workflows/test-flutter.yaml
index 8f4091f9958..f70196516d4 100644
--- a/.github/workflows/test-flutter.yaml
+++ b/.github/workflows/test-flutter.yaml
@@ -11,7 +11,7 @@ jobs:
build:
runs-on: macos-latest
steps:
- - uses: actions/checkout@v4
+ - uses: actions/checkout@v6
- name: flutter
uses: subosito/flutter-action@v2
with:
diff --git a/.github/workflows/test-kmp.yaml b/.github/workflows/test-kmp.yaml
index 71bbf96e6f3..b1d41272463 100644
--- a/.github/workflows/test-kmp.yaml
+++ b/.github/workflows/test-kmp.yaml
@@ -11,9 +11,9 @@ jobs:
build:
runs-on: macos-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v6
- name: Set up JDK 17
- uses: actions/setup-java@v3
+ uses: actions/setup-java@v5
with:
java-version: '17'
distribution: 'temurin'
diff --git a/.github/workflows/test-rn.yaml b/.github/workflows/test-rn.yaml
index 07bfd1e32e6..d0377995cde 100644
--- a/.github/workflows/test-rn.yaml
+++ b/.github/workflows/test-rn.yaml
@@ -11,11 +11,11 @@ jobs:
build:
runs-on: macos-latest
steps:
- - uses: actions/checkout@v3
+ - uses: actions/checkout@v6
- name: Use Node.js
- uses: actions/setup-node@v3
+ uses: actions/setup-node@v6
with:
- node-version: '18.x'
+ node-version: '22.x'
- name: test-rn
run: |
cd ./react-native
diff --git a/README.md b/README.md
index 2e5b4745ecb..431a69a4a59 100644
--- a/README.md
+++ b/README.md
@@ -6,7 +6,7 @@
[](https://kotlinlang.org)
[](https://kotlinlang.org)
[](https://ricohapi.github.io/theta-client/)
-[](https://ricohapi.github.io/theta-client/)
+[](https://ricohapi.github.io/theta-client/)
This library provides a way to control RICOH THETA using [RICOH THETA API v2.1](https://github.com/ricohapi/theta-api-specs/tree/main/theta-web-api-v2.1).
@@ -23,6 +23,14 @@ Your app can perform the following actions:
* React Native
* Flutter
+##### React Native
+
+| Version | React Native | Legacy Architecture | New Architecture |
+|------------|------------|---------------------|------------------|
+| 1.14.0 or later | 0.78.2 | Not supported | Supported |
+| 1.13.1 or earlier | 0.71.19 | Supported | Not supported |
+
+
## Supported Models
* THETA X
* THETA Z1
@@ -78,5 +86,3 @@ Using this verification tool, you can select and send a command with its paramet
[MIT License](LICENSE)
-## Useful guides
-* [THETA SDK docs | help](https://theta360developers.github.io/sdk/)
diff --git a/demos/demo-android/app/build.gradle b/demos/demo-android/app/build.gradle
index 284441a17a2..b92b12e8bf0 100755
--- a/demos/demo-android/app/build.gradle
+++ b/demos/demo-android/app/build.gradle
@@ -76,7 +76,7 @@ dependencies {
implementation 'com.jakewharton.timber:timber:5.0.1'
implementation 'io.coil-kt:coil-compose:2.2.2'
implementation "io.ktor:ktor-client-cio:$ktor_version"
- implementation "com.ricoh360.thetaclient:theta-client:1.13.2"
+ implementation "com.ricoh360.thetaclient:theta-client:1.14.0"
testImplementation 'org.junit.jupiter:junit-jupiter:5.9.0'
testImplementation "org.jetbrains.kotlinx:kotlinx-coroutines-test:$coroutines_version"
diff --git a/demos/demo-ios/Podfile b/demos/demo-ios/Podfile
index c365e40458a..4f3679c5480 100644
--- a/demos/demo-ios/Podfile
+++ b/demos/demo-ios/Podfile
@@ -7,5 +7,5 @@ target 'SdkSample' do
use_frameworks!
# Pods for SdkSample
- pod 'THETAClient', '1.13.2'
+ pod 'THETAClient', '1.14.0'
end
diff --git a/demos/demo-react-native/.buckconfig b/demos/demo-react-native/.buckconfig
deleted file mode 100644
index 934256cb29d..00000000000
--- a/demos/demo-react-native/.buckconfig
+++ /dev/null
@@ -1,6 +0,0 @@
-
-[android]
- target = Google Inc.:Google APIs:23
-
-[maven_repositories]
- central = https://repo1.maven.org/maven2
diff --git a/demos/demo-react-native/.eslintignore b/demos/demo-react-native/.eslintignore
new file mode 100644
index 00000000000..92f213efe28
--- /dev/null
+++ b/demos/demo-react-native/.eslintignore
@@ -0,0 +1,13 @@
+node_modules/
+android/
+ios/
+build/
+.bundle/
+dist/
+vendor/
+coverage/
+web/
+*.bundle.*
+.git/
+*.lock
+Gemfile*
diff --git a/demos/demo-react-native/.eslintrc.js b/demos/demo-react-native/.eslintrc.js
index 1f10b3ae487..187894b6af2 100644
--- a/demos/demo-react-native/.eslintrc.js
+++ b/demos/demo-react-native/.eslintrc.js
@@ -1,17 +1,4 @@
module.exports = {
root: true,
- extends: '@react-native-community',
- parser: '@typescript-eslint/parser',
- plugins: ['@typescript-eslint'],
- overrides: [
- {
- files: ['*.ts', '*.tsx'],
- rules: {
- '@typescript-eslint/no-shadow': ['error'],
- 'no-shadow': 'off',
- 'no-undef': 'off',
- },
- },
- ],
- ignorePatterns: ['marzipano.js'],
+ extends: '@react-native',
};
diff --git a/demos/demo-react-native/.gitignore b/demos/demo-react-native/.gitignore
index 0efef7b48e3..de99955957c 100644
--- a/demos/demo-react-native/.gitignore
+++ b/demos/demo-react-native/.gitignore
@@ -20,7 +20,7 @@ DerivedData
*.hmap
*.ipa
*.xcuserstate
-ios/.xcode.env.local
+**/.xcode.env.local
# Android/IntelliJ
#
@@ -31,6 +31,9 @@ local.properties
*.iml
*.hprof
.cxx/
+*.keystore
+!debug.keystore
+.kotlin/
# node.js
#
@@ -38,12 +41,6 @@ node_modules/
npm-debug.log
yarn-error.log
-# BUCK
-buck-out/
-\.buckd/
-*.keystore
-!debug.keystore
-
# fastlane
#
# It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the
@@ -60,8 +57,19 @@ buck-out/
*.jsbundle
# Ruby / CocoaPods
-/ios/Pods/
+**/Pods/
/vendor/bundle/
-# live preview
-marzipano.js
+# Temporary files created by Metro to check the health of the file watcher
+.metro-health-check*
+
+# testing
+/coverage
+
+# Yarn
+.yarn/*
+!.yarn/patches
+!.yarn/plugins
+!.yarn/releases
+!.yarn/sdks
+!.yarn/versions
diff --git a/demos/demo-react-native/.node-version b/demos/demo-react-native/.node-version
deleted file mode 100644
index b6a7d89c68e..00000000000
--- a/demos/demo-react-native/.node-version
+++ /dev/null
@@ -1 +0,0 @@
-16
diff --git a/demos/demo-react-native/.ruby-version b/demos/demo-react-native/.ruby-version
deleted file mode 100644
index a603bb50a29..00000000000
--- a/demos/demo-react-native/.ruby-version
+++ /dev/null
@@ -1 +0,0 @@
-2.7.5
diff --git a/demos/demo-react-native/.watchmanconfig b/demos/demo-react-native/.watchmanconfig
index 9e26dfeeb6e..0967ef424bc 100644
--- a/demos/demo-react-native/.watchmanconfig
+++ b/demos/demo-react-native/.watchmanconfig
@@ -1 +1 @@
-{}
\ No newline at end of file
+{}
diff --git a/demos/demo-react-native/Gemfile b/demos/demo-react-native/Gemfile
index 5efda89f452..10789062b6e 100644
--- a/demos/demo-react-native/Gemfile
+++ b/demos/demo-react-native/Gemfile
@@ -1,6 +1,6 @@
source 'https://rubygems.org'
# You may use http://rbenv.org/ or https://rvm.io/ to install and use this version
-ruby '2.7.5'
+ruby '>= 3.0'
gem 'cocoapods', '~> 1.11', '>= 1.11.2'
diff --git a/demos/demo-react-native/Gemfile.lock b/demos/demo-react-native/Gemfile.lock
index a83e9963f7f..d2c05b7ccec 100644
--- a/demos/demo-react-native/Gemfile.lock
+++ b/demos/demo-react-native/Gemfile.lock
@@ -1,26 +1,35 @@
GEM
remote: https://rubygems.org/
specs:
- CFPropertyList (3.0.6)
- rexml
- activesupport (7.0.4.3)
- concurrent-ruby (~> 1.0, >= 1.0.2)
+ CFPropertyList (3.0.9)
+ activesupport (7.2.3)
+ base64
+ benchmark (>= 0.3)
+ bigdecimal
+ concurrent-ruby (~> 1.0, >= 1.3.1)
+ connection_pool (>= 2.2.5)
+ drb
i18n (>= 1.6, < 2)
+ logger (>= 1.4.2)
minitest (>= 5.1)
- tzinfo (~> 2.0)
- addressable (2.8.4)
- public_suffix (>= 2.0.2, < 6.0)
+ securerandom (>= 0.3)
+ tzinfo (~> 2.0, >= 2.0.5)
+ addressable (2.8.9)
+ public_suffix (>= 2.0.2, < 8.0)
algoliasearch (1.27.5)
httpclient (~> 2.8, >= 2.8.3)
json (>= 1.5.1)
atomos (0.1.3)
+ base64 (0.3.0)
+ benchmark (0.5.0)
+ bigdecimal (4.0.1)
claide (1.1.0)
- cocoapods (1.12.1)
+ cocoapods (1.16.2)
addressable (~> 2.8)
claide (>= 1.0.2, < 2.0)
- cocoapods-core (= 1.12.1)
+ cocoapods-core (= 1.16.2)
cocoapods-deintegrate (>= 1.0.3, < 2.0)
- cocoapods-downloader (>= 1.6.0, < 2.0)
+ cocoapods-downloader (>= 2.1, < 3.0)
cocoapods-plugins (>= 1.0.0, < 2.0)
cocoapods-search (>= 1.0.0, < 2.0)
cocoapods-trunk (>= 1.6.0, < 2.0)
@@ -32,8 +41,8 @@ GEM
molinillo (~> 0.8.0)
nap (~> 1.0)
ruby-macho (>= 2.3.0, < 3.0)
- xcodeproj (>= 1.21.0, < 2.0)
- cocoapods-core (1.12.1)
+ xcodeproj (>= 1.27.0, < 2.0)
+ cocoapods-core (1.16.2)
activesupport (>= 5.0, < 8)
addressable (~> 2.8)
algoliasearch (~> 1.0)
@@ -44,7 +53,7 @@ GEM
public_suffix (~> 4.0)
typhoeus (~> 1.0)
cocoapods-deintegrate (1.0.5)
- cocoapods-downloader (1.6.3)
+ cocoapods-downloader (2.1)
cocoapods-plugins (1.0.0)
nap
cocoapods-search (1.0.1)
@@ -53,37 +62,43 @@ GEM
netrc (~> 0.11)
cocoapods-try (1.2.0)
colored2 (3.1.2)
- concurrent-ruby (1.2.2)
+ concurrent-ruby (1.3.6)
+ connection_pool (2.5.5)
+ drb (2.2.3)
escape (0.0.4)
- ethon (0.16.0)
+ ethon (0.15.0)
ffi (>= 1.15.0)
- ffi (1.15.5)
+ ffi (1.17.3)
fourflusher (2.3.1)
fuzzy_match (2.0.4)
gh_inspector (1.1.3)
- httpclient (2.8.3)
- i18n (1.13.0)
+ httpclient (2.9.0)
+ mutex_m
+ i18n (1.14.8)
concurrent-ruby (~> 1.0)
- json (2.6.3)
- minitest (5.18.0)
+ json (2.18.1)
+ logger (1.7.0)
+ minitest (5.27.0)
molinillo (0.8.0)
- nanaimo (0.3.0)
+ mutex_m (0.3.0)
+ nanaimo (0.4.0)
nap (1.1.0)
netrc (0.11.0)
public_suffix (4.0.7)
- rexml (3.2.5)
+ rexml (3.4.4)
ruby-macho (2.5.1)
- typhoeus (1.4.0)
- ethon (>= 0.9.0)
+ securerandom (0.4.1)
+ typhoeus (1.5.0)
+ ethon (>= 0.9.0, < 0.16.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
- xcodeproj (1.22.0)
+ xcodeproj (1.27.0)
CFPropertyList (>= 2.3.3, < 4.0)
atomos (~> 0.1.3)
claide (>= 1.0.2, < 2.0)
colored2 (~> 3.1)
- nanaimo (~> 0.3.0)
- rexml (~> 3.2.4)
+ nanaimo (~> 0.4.0)
+ rexml (>= 3.3.6, < 4.0)
PLATFORMS
ruby
@@ -92,7 +107,7 @@ DEPENDENCIES
cocoapods (~> 1.11, >= 1.11.2)
RUBY VERSION
- ruby 2.7.5p203
+ ruby 3.1.3p185
BUNDLED WITH
- 2.4.10
+ 2.3.26
diff --git a/demos/demo-react-native/__tests__/App-test.tsx b/demos/demo-react-native/__tests__/App-test.tsx
deleted file mode 100644
index 178476699b6..00000000000
--- a/demos/demo-react-native/__tests__/App-test.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-/**
- * @format
- */
-
-import 'react-native';
-import React from 'react';
-import App from '../App';
-
-// Note: test renderer must be required after react-native.
-import renderer from 'react-test-renderer';
-
-it('renders correctly', () => {
- renderer.create( );
-});
diff --git a/demos/demo-react-native/android/app/_BUCK b/demos/demo-react-native/android/app/_BUCK
deleted file mode 100644
index 148354dc922..00000000000
--- a/demos/demo-react-native/android/app/_BUCK
+++ /dev/null
@@ -1,55 +0,0 @@
-# To learn about Buck see [Docs](https://buckbuild.com/).
-# To run your application with Buck:
-# - install Buck
-# - `npm start` - to start the packager
-# - `cd android`
-# - `keytool -genkey -v -keystore keystores/debug.keystore -storepass android -alias androiddebugkey -keypass android -dname "CN=Android Debug,O=Android,C=US"`
-# - `./gradlew :app:copyDownloadableDepsToLibs` - make all Gradle compile dependencies available to Buck
-# - `buck install -r android/app` - compile, install and run application
-#
-
-load(":build_defs.bzl", "create_aar_targets", "create_jar_targets")
-
-lib_deps = []
-
-create_aar_targets(glob(["libs/*.aar"]))
-
-create_jar_targets(glob(["libs/*.jar"]))
-
-android_library(
- name = "all-libs",
- exported_deps = lib_deps,
-)
-
-android_library(
- name = "app-code",
- srcs = glob([
- "src/main/java/**/*.java",
- ]),
- deps = [
- ":all-libs",
- ":build_config",
- ":res",
- ],
-)
-
-android_build_config(
- name = "build_config",
- package = "com.demoreactnative",
-)
-
-android_resource(
- name = "res",
- package = "com.demoreactnative",
- res = "src/main/res",
-)
-
-android_binary(
- name = "app",
- keystore = "//android/keystores:debug",
- manifest = "src/main/AndroidManifest.xml",
- package_type = "debug",
- deps = [
- ":app-code",
- ],
-)
diff --git a/demos/demo-react-native/android/app/build.gradle b/demos/demo-react-native/android/app/build.gradle
index 9c95436efcf..66307d098e5 100644
--- a/demos/demo-react-native/android/app/build.gradle
+++ b/demos/demo-react-native/android/app/build.gradle
@@ -1,216 +1,89 @@
apply plugin: "com.android.application"
+apply plugin: "org.jetbrains.kotlin.android"
apply plugin: "com.facebook.react"
-import com.android.build.OutputFile
-
-/**
- * The react.gradle file registers a task for each build variant (e.g. bundleDebugJsAndAssets
- * and bundleReleaseJsAndAssets).
- * These basically call `react-native bundle` with the correct arguments during the Android build
- * cycle. By default, bundleDebugJsAndAssets is skipped, as in debug/dev mode we prefer to load the
- * bundle directly from the development server. Below you can see all the possible configurations
- * and their defaults. If you decide to add a configuration block, make sure to add it before the
- * `apply from: "../../node_modules/react-native/react.gradle"` line.
- *
- * project.ext.react = [
- * // the name of the generated asset file containing your JS bundle
- * bundleAssetName: "index.android.bundle",
- *
- * // the entry file for bundle generation. If none specified and
- * // "index.android.js" exists, it will be used. Otherwise "index.js" is
- * // default. Can be overridden with ENTRY_FILE environment variable.
- * entryFile: "index.android.js",
- *
- * // https://reactnative.dev/docs/performance#enable-the-ram-format
- * bundleCommand: "ram-bundle",
- *
- * // whether to bundle JS and assets in debug mode
- * bundleInDebug: false,
- *
- * // whether to bundle JS and assets in release mode
- * bundleInRelease: true,
- *
- * // whether to bundle JS and assets in another build variant (if configured).
- * // See http://tools.android.com/tech-docs/new-build-system/user-guide#TOC-Build-Variants
- * // The configuration property can be in the following formats
- * // 'bundleIn${productFlavor}${buildType}'
- * // 'bundleIn${buildType}'
- * // bundleInFreeDebug: true,
- * // bundleInPaidRelease: true,
- * // bundleInBeta: true,
- *
- * // whether to disable dev mode in custom build variants (by default only disabled in release)
- * // for example: to disable dev mode in the staging build type (if configured)
- * devDisabledInStaging: true,
- * // The configuration property can be in the following formats
- * // 'devDisabledIn${productFlavor}${buildType}'
- * // 'devDisabledIn${buildType}'
- *
- * // the root of your project, i.e. where "package.json" lives
- * root: "../../",
- *
- * // where to put the JS bundle asset in debug mode
- * jsBundleDirDebug: "$buildDir/intermediates/assets/debug",
- *
- * // where to put the JS bundle asset in release mode
- * jsBundleDirRelease: "$buildDir/intermediates/assets/release",
- *
- * // where to put drawable resources / React Native assets, e.g. the ones you use via
- * // require('./image.png')), in debug mode
- * resourcesDirDebug: "$buildDir/intermediates/res/merged/debug",
- *
- * // where to put drawable resources / React Native assets, e.g. the ones you use via
- * // require('./image.png')), in release mode
- * resourcesDirRelease: "$buildDir/intermediates/res/merged/release",
- *
- * // by default the gradle tasks are skipped if none of the JS files or assets change; this means
- * // that we don't look at files in android/ or ios/ to determine whether the tasks are up to
- * // date; if you have any other folders that you want to ignore for performance reasons (gradle
- * // indexes the entire tree), add them here. Alternatively, if you have JS files in android/
- * // for example, you might want to remove it from here.
- * inputExcludes: ["android/**", "ios/**"],
- *
- * // override which node gets called and with what additional arguments
- * nodeExecutableAndArgs: ["node"],
- *
- * // supply additional arguments to the packager
- * extraPackagerArgs: []
- * ]
- */
-
-project.ext.react = [
- enableHermes: true, // clean and rebuild if changing
-]
-
-apply from: "../../node_modules/react-native/react.gradle"
-
/**
- * Set this to true to create two separate APKs instead of one:
- * - An APK that only works on ARM devices
- * - An APK that only works on x86 devices
- * The advantage is the size of the APK is reduced by about 4MB.
- * Upload all the APKs to the Play Store and people will download
- * the correct one based on the CPU architecture of their device.
+ * This is the configuration block to customize your React Native Android app.
+ * By default you don't need to apply any configuration, just uncomment the lines you need.
*/
-def enableSeparateBuildPerCPUArchitecture = false
+react {
+ /* Folders */
+ // The root of your project, i.e. where "package.json" lives. Default is '../..'
+ // root = file("../../")
+ // The folder where the react-native NPM package is. Default is ../../node_modules/react-native
+ // reactNativeDir = file("../../node_modules/react-native")
+ // The folder where the react-native Codegen package is. Default is ../../node_modules/@react-native/codegen
+ // codegenDir = file("../../node_modules/@react-native/codegen")
+ // The cli.js file which is the React Native CLI entrypoint. Default is ../../node_modules/react-native/cli.js
+ // cliFile = file("../../node_modules/react-native/cli.js")
+
+ /* Variants */
+ // The list of variants to that are debuggable. For those we're going to
+ // skip the bundling of the JS bundle and the assets. By default is just 'debug'.
+ // If you add flavors like lite, prod, etc. you'll have to list your debuggableVariants.
+ // debuggableVariants = ["liteDebug", "prodDebug"]
+
+ /* Bundling */
+ // A list containing the node command and its flags. Default is just 'node'.
+ // nodeExecutableAndArgs = ["node"]
+ //
+ // The command to run when bundling. By default is 'bundle'
+ // bundleCommand = "ram-bundle"
+ //
+ // The path to the CLI configuration file. Default is empty.
+ // bundleConfig = file(../rn-cli.config.js)
+ //
+ // The name of the generated asset file containing your JS bundle
+ // bundleAssetName = "MyApplication.android.bundle"
+ //
+ // The entry file for bundle generation. Default is 'index.android.js' or 'index.js'
+ // entryFile = file("../js/MyApplication.android.js")
+ //
+ // A list of extra flags to pass to the 'bundle' commands.
+ // See https://github.com/react-native-community/cli/blob/main/docs/commands.md#bundle
+ // extraPackagerArgs = []
+
+ /* Hermes Commands */
+ // The hermes compiler command to run. By default it is 'hermesc'
+ // hermesCommand = "$rootDir/my-custom-hermesc/bin/hermesc"
+ //
+ // The list of flags to pass to the Hermes compiler. By default is "-O", "-output-source-map"
+ // hermesFlags = ["-O", "-output-source-map"]
+
+ /* Autolinking */
+ autolinkLibrariesWithApp()
+}
/**
- * Run Proguard to shrink the Java bytecode in release builds.
+ * Set this to true to Run Proguard on Release builds to minify the Java bytecode.
*/
def enableProguardInReleaseBuilds = false
/**
- * The preferred build flavor of JavaScriptCore.
+ * The preferred build flavor of JavaScriptCore (JSC)
*
* For example, to use the international variant, you can use:
- * `def jscFlavor = 'org.webkit:android-jsc-intl:+'`
+ * `def jscFlavor = io.github.react-native-community:jsc-android-intl:2026004.+`
*
* The international variant includes ICU i18n library and necessary data
* allowing to use e.g. `Date.toLocaleString` and `String.localeCompare` that
- * give correct results when using with locales other than en-US. Note that
+ * give correct results when using with locales other than en-US. Note that
* this variant is about 6MiB larger per architecture than default.
*/
-def jscFlavor = 'org.webkit:android-jsc:+'
-
-/**
- * Whether to enable the Hermes VM.
- *
- * This should be set on project.ext.react and that value will be read here. If it is not set
- * on project.ext.react, JavaScript will not be compiled to Hermes Bytecode
- * and the benefits of using Hermes will therefore be sharply reduced.
- */
-def enableHermes = project.ext.react.get("enableHermes", false);
-
-/**
- * Architectures to build native code for.
- */
-def reactNativeArchitectures() {
- def value = project.getProperties().get("reactNativeArchitectures")
- return value ? value.split(",") : ["armeabi-v7a", "x86", "x86_64", "arm64-v8a"]
-}
+def jscFlavor = 'io.github.react-native-community:jsc-android:2026004.+'
android {
ndkVersion rootProject.ext.ndkVersion
+ buildToolsVersion rootProject.ext.buildToolsVersion
+ compileSdk rootProject.ext.compileSdkVersion
- compileSdkVersion rootProject.ext.compileSdkVersion
-
+ namespace "com.demoreactnative"
defaultConfig {
applicationId "com.demoreactnative"
minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1
versionName "1.0"
- buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
-
- if (isNewArchitectureEnabled()) {
- // We configure the CMake build only if you decide to opt-in for the New Architecture.
- externalNativeBuild {
- cmake {
- arguments "-DPROJECT_BUILD_DIR=$buildDir",
- "-DREACT_ANDROID_DIR=$rootDir/../node_modules/react-native/ReactAndroid",
- "-DREACT_ANDROID_BUILD_DIR=$rootDir/../node_modules/react-native/ReactAndroid/build",
- "-DNODE_MODULES_DIR=$rootDir/../node_modules",
- "-DANDROID_STL=c++_shared"
- }
- }
- if (!enableSeparateBuildPerCPUArchitecture) {
- ndk {
- //noinspection ChromeOsAbiSupport
- abiFilters (*reactNativeArchitectures())
- }
- }
- }
- }
-
- if (isNewArchitectureEnabled()) {
- // We configure the NDK build only if you decide to opt-in for the New Architecture.
- externalNativeBuild {
- cmake {
- path "$projectDir/src/main/jni/CMakeLists.txt"
- }
- }
- def reactAndroidProjectDir = project(':ReactAndroid').projectDir
- def packageReactNdkDebugLibs = tasks.register("packageReactNdkDebugLibs", Copy) {
- dependsOn(":ReactAndroid:packageReactNdkDebugLibsForBuck")
- from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
- into("$buildDir/react-ndk/exported")
- }
- def packageReactNdkReleaseLibs = tasks.register("packageReactNdkReleaseLibs", Copy) {
- dependsOn(":ReactAndroid:packageReactNdkReleaseLibsForBuck")
- from("$reactAndroidProjectDir/src/main/jni/prebuilt/lib")
- into("$buildDir/react-ndk/exported")
- }
- afterEvaluate {
- // If you wish to add a custom TurboModule or component locally,
- // you should uncomment this line.
- // preBuild.dependsOn("generateCodegenArtifactsFromSchema")
- preDebugBuild.dependsOn(packageReactNdkDebugLibs)
- preReleaseBuild.dependsOn(packageReactNdkReleaseLibs)
-
- // Due to a bug inside AGP, we have to explicitly set a dependency
- // between configureCMakeDebug* tasks and the preBuild tasks.
- // This can be removed once this is solved: https://issuetracker.google.com/issues/207403732
- configureCMakeRelWithDebInfo.dependsOn(preReleaseBuild)
- configureCMakeDebug.dependsOn(preDebugBuild)
- reactNativeArchitectures().each { architecture ->
- tasks.findByName("configureCMakeDebug[${architecture}]")?.configure {
- dependsOn("preDebugBuild")
- }
- tasks.findByName("configureCMakeRelWithDebInfo[${architecture}]")?.configure {
- dependsOn("preReleaseBuild")
- }
- }
- }
- }
-
- splits {
- abi {
- reset()
- enable enableSeparateBuildPerCPUArchitecture
- universalApk false // If true, also generate a universal APK
- //noinspection ChromeOsAbiSupport
- include (*reactNativeArchitectures())
- }
}
signingConfigs {
debug {
@@ -232,87 +105,31 @@ android {
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"
}
}
-
- // applicationVariants are e.g. debug, release
- applicationVariants.all { variant ->
- variant.outputs.each { output ->
- // For each separate APK per architecture, set a unique version code as described here:
- // https://developer.android.com/studio/build/configure-apk-splits.html
- // Example: versionCode 1 will generate 1001 for armeabi-v7a, 1002 for x86, etc.
- def versionCodes = ["armeabi-v7a": 1, "x86": 2, "arm64-v8a": 3, "x86_64": 4]
- def abi = output.getFilter(OutputFile.ABI)
- if (abi != null) { // null for the universal-debug, universal-release variants
- output.versionCodeOverride =
- defaultConfig.versionCode * 1000 + versionCodes.get(abi)
- }
-
- }
- }
-
sourceSets {
main {
- assets.srcDirs = ["../../web/Web.bundle"]
+ assets.srcDirs += ["../../web/Web.bundle"]
}
}
}
-dependencies {
- implementation fileTree(dir: "libs", include: ["*.jar"])
+configurations.all {
+ resolutionStrategy {
+ force 'androidx.core:core:1.13.1'
+ force 'androidx.core:core-ktx:1.13.1'
+ }
+}
+dependencies {
// The version of react-native is set by the React Native Gradle Plugin
implementation("com.facebook.react:react-android")
- implementation "androidx.swiperefreshlayout:swiperefreshlayout:1.1.0"
-
- debugImplementation("com.facebook.flipper:flipper:${FLIPPER_VERSION}") {
- exclude group:'com.facebook.fbjni'
- }
-
- debugImplementation("com.facebook.flipper:flipper-network-plugin:${FLIPPER_VERSION}") {
- exclude group:'com.facebook.flipper'
- exclude group:'com.squareup.okhttp3', module:'okhttp'
- }
-
- debugImplementation("com.facebook.flipper:flipper-fresco-plugin:${FLIPPER_VERSION}") {
- exclude group:'com.facebook.flipper'
- }
+ // Force androidx.core to version 1.13.1 to avoid AGP 8.9.1 requirement
+ implementation("androidx.core:core:1.13.1")
+ implementation("androidx.core:core-ktx:1.13.1")
- if (enableHermes) {
+ if (hermesEnabled.toBoolean()) {
implementation("com.facebook.react:hermes-android")
} else {
implementation jscFlavor
}
}
-
-if (isNewArchitectureEnabled()) {
- // If new architecture is enabled, we let you build RN from source
- // Otherwise we fallback to a prebuilt .aar bundled in the NPM package.
- // This will be applied to all the imported transtitive dependency.
- configurations.configureEach {
- resolutionStrategy.dependencySubstitution {
- substitute(module("com.facebook.react:react-native"))
- .using(project(":ReactAndroid"))
- .because("On New Architecture we're building React Native from source")
- substitute(module("com.facebook.react:hermes-engine"))
- .using(project(":ReactAndroid:hermes-engine"))
- .because("On New Architecture we're building Hermes from source")
- }
- }
-}
-
-// Run this once to be able to run the application with BUCK
-// puts all compile dependencies into folder libs for BUCK to use
-tasks.register('copyDownloadableDepsToLibs', Copy) {
- from configurations.implementation
- into 'libs'
-}
-
-apply from: file("../../node_modules/@react-native-community/cli-platform-android/native_modules.gradle"); applyNativeModulesAppBuildGradle(project)
-
-def isNewArchitectureEnabled() {
- // To opt-in for the New Architecture, you can either:
- // - Set `newArchEnabled` to true inside the `gradle.properties` file
- // - Invoke gradle with `-newArchEnabled=true`
- // - Set an environment variable `ORG_GRADLE_PROJECT_newArchEnabled=true`
- return project.hasProperty("newArchEnabled") && project.newArchEnabled == "true"
-}
diff --git a/demos/demo-react-native/android/app/build_defs.bzl b/demos/demo-react-native/android/app/build_defs.bzl
deleted file mode 100644
index fff270f8d1d..00000000000
--- a/demos/demo-react-native/android/app/build_defs.bzl
+++ /dev/null
@@ -1,19 +0,0 @@
-"""Helper definitions to glob .aar and .jar targets"""
-
-def create_aar_targets(aarfiles):
- for aarfile in aarfiles:
- name = "aars__" + aarfile[aarfile.rindex("/") + 1:aarfile.rindex(".aar")]
- lib_deps.append(":" + name)
- android_prebuilt_aar(
- name = name,
- aar = aarfile,
- )
-
-def create_jar_targets(jarfiles):
- for jarfile in jarfiles:
- name = "jars__" + jarfile[jarfile.rindex("/") + 1:jarfile.rindex(".jar")]
- lib_deps.append(":" + name)
- prebuilt_jar(
- name = name,
- binary_jar = jarfile,
- )
diff --git a/demos/demo-react-native/android/app/src/debug/AndroidManifest.xml b/demos/demo-react-native/android/app/src/debug/AndroidManifest.xml
index 4b185bc1597..eb98c01afd7 100644
--- a/demos/demo-react-native/android/app/src/debug/AndroidManifest.xml
+++ b/demos/demo-react-native/android/app/src/debug/AndroidManifest.xml
@@ -2,12 +2,8 @@
-
-
-
-
+ tools:ignore="GoogleAppIndexingWarning"/>
diff --git a/demos/demo-react-native/android/app/src/debug/java/com/demoreactnative/ReactNativeFlipper.java b/demos/demo-react-native/android/app/src/debug/java/com/demoreactnative/ReactNativeFlipper.java
deleted file mode 100644
index 08897824e5e..00000000000
--- a/demos/demo-react-native/android/app/src/debug/java/com/demoreactnative/ReactNativeFlipper.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/**
- * Copyright (c) Meta Platforms, Inc. and affiliates.
- *
- *
This source code is licensed under the MIT license found in the LICENSE file in the root
- * directory of this source tree.
- */
-package com.demoreactnative;
-
-import android.content.Context;
-import com.facebook.flipper.android.AndroidFlipperClient;
-import com.facebook.flipper.android.utils.FlipperUtils;
-import com.facebook.flipper.core.FlipperClient;
-import com.facebook.flipper.plugins.crashreporter.CrashReporterPlugin;
-import com.facebook.flipper.plugins.databases.DatabasesFlipperPlugin;
-import com.facebook.flipper.plugins.fresco.FrescoFlipperPlugin;
-import com.facebook.flipper.plugins.inspector.DescriptorMapping;
-import com.facebook.flipper.plugins.inspector.InspectorFlipperPlugin;
-import com.facebook.flipper.plugins.network.FlipperOkhttpInterceptor;
-import com.facebook.flipper.plugins.network.NetworkFlipperPlugin;
-import com.facebook.flipper.plugins.react.ReactFlipperPlugin;
-import com.facebook.flipper.plugins.sharedpreferences.SharedPreferencesFlipperPlugin;
-import com.facebook.react.ReactInstanceEventListener;
-import com.facebook.react.ReactInstanceManager;
-import com.facebook.react.bridge.ReactContext;
-import com.facebook.react.modules.network.NetworkingModule;
-import okhttp3.OkHttpClient;
-
-public class ReactNativeFlipper {
- public static void initializeFlipper(Context context, ReactInstanceManager reactInstanceManager) {
- if (FlipperUtils.shouldEnableFlipper(context)) {
- final FlipperClient client = AndroidFlipperClient.getInstance(context);
-
- client.addPlugin(new InspectorFlipperPlugin(context, DescriptorMapping.withDefaults()));
- client.addPlugin(new ReactFlipperPlugin());
- client.addPlugin(new DatabasesFlipperPlugin(context));
- client.addPlugin(new SharedPreferencesFlipperPlugin(context));
- client.addPlugin(CrashReporterPlugin.getInstance());
-
- NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
- NetworkingModule.setCustomClientBuilder(
- new NetworkingModule.CustomClientBuilder() {
- @Override
- public void apply(OkHttpClient.Builder builder) {
- builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin));
- }
- });
- client.addPlugin(networkFlipperPlugin);
- client.start();
-
- // Fresco Plugin needs to ensure that ImagePipelineFactory is initialized
- // Hence we run if after all native modules have been initialized
- ReactContext reactContext = reactInstanceManager.getCurrentReactContext();
- if (reactContext == null) {
- reactInstanceManager.addReactInstanceEventListener(
- new ReactInstanceEventListener() {
- @Override
- public void onReactContextInitialized(ReactContext reactContext) {
- reactInstanceManager.removeReactInstanceEventListener(this);
- reactContext.runOnNativeModulesQueueThread(
- new Runnable() {
- @Override
- public void run() {
- client.addPlugin(new FrescoFlipperPlugin());
- }
- });
- }
- });
- } else {
- client.addPlugin(new FrescoFlipperPlugin());
- }
- }
- }
-}
diff --git a/demos/demo-react-native/android/app/src/main/AndroidManifest.xml b/demos/demo-react-native/android/app/src/main/AndroidManifest.xml
index 2b045f08616..e1892528b8d 100644
--- a/demos/demo-react-native/android/app/src/main/AndroidManifest.xml
+++ b/demos/demo-react-native/android/app/src/main/AndroidManifest.xml
@@ -1,5 +1,4 @@
-
+
@@ -9,7 +8,8 @@
android:icon="@mipmap/ic_launcher"
android:roundIcon="@mipmap/ic_launcher_round"
android:allowBackup="false"
- android:theme="@style/AppTheme">
+ android:theme="@style/AppTheme"
+ android:supportsRtl="true">
getPackages() {
- @SuppressWarnings("UnnecessaryLocalVariable")
- List packages = new PackageList(this).getPackages();
- // Packages that cannot be autolinked yet can be added manually here, for example:
- // packages.add(new MyReactNativePackage());
- return packages;
- }
-
- @Override
- protected String getJSMainModuleName() {
- return "index";
- }
- };
-
- private final ReactNativeHost mNewArchitectureNativeHost =
- new MainApplicationReactNativeHost(this);
-
- @Override
- public ReactNativeHost getReactNativeHost() {
- if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
- return mNewArchitectureNativeHost;
- } else {
- return mReactNativeHost;
- }
- }
-
- @Override
- public void onCreate() {
- super.onCreate();
- // If you opted-in for the New Architecture, we enable the TurboModule system
- ReactFeatureFlags.useTurboModules = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED;
- SoLoader.init(this, /* native exopackage */ false);
- initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- }
-
- /**
- * Loads Flipper in React Native templates. Call this in the onCreate method with something like
- * initializeFlipper(this, getReactNativeHost().getReactInstanceManager());
- *
- * @param context
- * @param reactInstanceManager
- */
- private static void initializeFlipper(
- Context context, ReactInstanceManager reactInstanceManager) {
- if (BuildConfig.DEBUG) {
- try {
- /*
- We use reflection here to pick up the class that initializes Flipper,
- since Flipper library is not available in release mode
- */
- Class> aClass = Class.forName("com.demoreactnative.ReactNativeFlipper");
- aClass
- .getMethod("initializeFlipper", Context.class, ReactInstanceManager.class)
- .invoke(null, context, reactInstanceManager);
- } catch (ClassNotFoundException e) {
- e.printStackTrace();
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- }
- }
- }
-}
diff --git a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/MainApplication.kt b/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/MainApplication.kt
new file mode 100644
index 00000000000..911ce45af4b
--- /dev/null
+++ b/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/MainApplication.kt
@@ -0,0 +1,44 @@
+package com.demoreactnative
+
+import android.app.Application
+import com.facebook.react.PackageList
+import com.facebook.react.ReactApplication
+import com.facebook.react.ReactHost
+import com.facebook.react.ReactNativeHost
+import com.facebook.react.ReactPackage
+import com.facebook.react.defaults.DefaultNewArchitectureEntryPoint.load
+import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
+import com.facebook.react.defaults.DefaultReactNativeHost
+import com.facebook.react.soloader.OpenSourceMergedSoMapping
+import com.facebook.soloader.SoLoader
+
+class MainApplication : Application(), ReactApplication {
+
+ override val reactNativeHost: ReactNativeHost =
+ object : DefaultReactNativeHost(this) {
+ override fun getPackages(): List =
+ PackageList(this).packages.apply {
+ // Packages that cannot be autolinked yet can be added manually here, for example:
+ // add(MyReactNativePackage())
+ }
+
+ override fun getJSMainModuleName(): String = "index"
+
+ override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG
+
+ override val isNewArchEnabled: Boolean = BuildConfig.IS_NEW_ARCHITECTURE_ENABLED
+ override val isHermesEnabled: Boolean = BuildConfig.IS_HERMES_ENABLED
+ }
+
+ override val reactHost: ReactHost
+ get() = getDefaultReactHost(applicationContext, reactNativeHost)
+
+ override fun onCreate() {
+ super.onCreate()
+ SoLoader.init(this, OpenSourceMergedSoMapping)
+ if (BuildConfig.IS_NEW_ARCHITECTURE_ENABLED) {
+ // If you opted-in for the New Architecture, we load the native entry point for this app.
+ load()
+ }
+ }
+}
diff --git a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/MainApplicationReactNativeHost.java b/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/MainApplicationReactNativeHost.java
deleted file mode 100644
index 0d6a82b0e09..00000000000
--- a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/MainApplicationReactNativeHost.java
+++ /dev/null
@@ -1,116 +0,0 @@
-package com.demoreactnative.newarchitecture;
-
-import android.app.Application;
-import androidx.annotation.NonNull;
-import com.facebook.react.PackageList;
-import com.facebook.react.ReactInstanceManager;
-import com.facebook.react.ReactNativeHost;
-import com.facebook.react.ReactPackage;
-import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
-import com.facebook.react.bridge.JSIModulePackage;
-import com.facebook.react.bridge.JSIModuleProvider;
-import com.facebook.react.bridge.JSIModuleSpec;
-import com.facebook.react.bridge.JSIModuleType;
-import com.facebook.react.bridge.JavaScriptContextHolder;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.facebook.react.bridge.UIManager;
-import com.facebook.react.fabric.ComponentFactory;
-import com.facebook.react.fabric.CoreComponentsRegistry;
-import com.facebook.react.fabric.FabricJSIModuleProvider;
-import com.facebook.react.fabric.ReactNativeConfig;
-import com.facebook.react.uimanager.ViewManagerRegistry;
-import com.demoreactnative.BuildConfig;
-import com.demoreactnative.newarchitecture.components.MainComponentsRegistry;
-import com.demoreactnative.newarchitecture.modules.MainApplicationTurboModuleManagerDelegate;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * A {@link ReactNativeHost} that helps you load everything needed for the New Architecture, both
- * TurboModule delegates and the Fabric Renderer.
- *
- * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
- * `newArchEnabled` property). Is ignored otherwise.
- */
-public class MainApplicationReactNativeHost extends ReactNativeHost {
- public MainApplicationReactNativeHost(Application application) {
- super(application);
- }
-
- @Override
- public boolean getUseDeveloperSupport() {
- return BuildConfig.DEBUG;
- }
-
- @Override
- protected List getPackages() {
- List packages = new PackageList(this).getPackages();
- // Packages that cannot be autolinked yet can be added manually here, for example:
- // packages.add(new MyReactNativePackage());
- // TurboModules must also be loaded here providing a valid TurboReactPackage implementation:
- // packages.add(new TurboReactPackage() { ... });
- // If you have custom Fabric Components, their ViewManagers should also be loaded here
- // inside a ReactPackage.
- return packages;
- }
-
- @Override
- protected String getJSMainModuleName() {
- return "index";
- }
-
- @NonNull
- @Override
- protected ReactPackageTurboModuleManagerDelegate.Builder
- getReactPackageTurboModuleManagerDelegateBuilder() {
- // Here we provide the ReactPackageTurboModuleManagerDelegate Builder. This is necessary
- // for the new architecture and to use TurboModules correctly.
- return new MainApplicationTurboModuleManagerDelegate.Builder();
- }
-
- @Override
- protected JSIModulePackage getJSIModulePackage() {
- return new JSIModulePackage() {
- @Override
- public List getJSIModules(
- final ReactApplicationContext reactApplicationContext,
- final JavaScriptContextHolder jsContext) {
- final List specs = new ArrayList<>();
-
- // Here we provide a new JSIModuleSpec that will be responsible of providing the
- // custom Fabric Components.
- specs.add(
- new JSIModuleSpec() {
- @Override
- public JSIModuleType getJSIModuleType() {
- return JSIModuleType.UIManager;
- }
-
- @Override
- public JSIModuleProvider getJSIModuleProvider() {
- final ComponentFactory componentFactory = new ComponentFactory();
- CoreComponentsRegistry.register(componentFactory);
-
- // Here we register a Components Registry.
- // The one that is generated with the template contains no components
- // and just provides you the one from React Native core.
- MainComponentsRegistry.register(componentFactory);
-
- final ReactInstanceManager reactInstanceManager = getReactInstanceManager();
-
- ViewManagerRegistry viewManagerRegistry =
- new ViewManagerRegistry(
- reactInstanceManager.getOrCreateViewManagers(reactApplicationContext));
-
- return new FabricJSIModuleProvider(
- reactApplicationContext,
- componentFactory,
- ReactNativeConfig.DEFAULT_CONFIG,
- viewManagerRegistry);
- }
- });
- return specs;
- }
- };
- }
-}
diff --git a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/components/MainComponentsRegistry.java b/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/components/MainComponentsRegistry.java
deleted file mode 100644
index b9fbec5af10..00000000000
--- a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/components/MainComponentsRegistry.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.demoreactnative.newarchitecture.components;
-
-import com.facebook.jni.HybridData;
-import com.facebook.proguard.annotations.DoNotStrip;
-import com.facebook.react.fabric.ComponentFactory;
-import com.facebook.soloader.SoLoader;
-
-/**
- * Class responsible to load the custom Fabric Components. This class has native methods and needs a
- * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
- * folder for you).
- *
- * Please note that this class is used ONLY if you opt-in for the New Architecture (see the
- * `newArchEnabled` property). Is ignored otherwise.
- */
-@DoNotStrip
-public class MainComponentsRegistry {
- static {
- SoLoader.loadLibrary("fabricjni");
- }
-
- @DoNotStrip private final HybridData mHybridData;
-
- @DoNotStrip
- private native HybridData initHybrid(ComponentFactory componentFactory);
-
- @DoNotStrip
- private MainComponentsRegistry(ComponentFactory componentFactory) {
- mHybridData = initHybrid(componentFactory);
- }
-
- @DoNotStrip
- public static MainComponentsRegistry register(ComponentFactory componentFactory) {
- return new MainComponentsRegistry(componentFactory);
- }
-}
diff --git a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java b/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java
deleted file mode 100644
index aee857c0671..00000000000
--- a/demos/demo-react-native/android/app/src/main/java/com/demoreactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate.java
+++ /dev/null
@@ -1,48 +0,0 @@
-package com.demoreactnative.newarchitecture.modules;
-
-import com.facebook.jni.HybridData;
-import com.facebook.react.ReactPackage;
-import com.facebook.react.ReactPackageTurboModuleManagerDelegate;
-import com.facebook.react.bridge.ReactApplicationContext;
-import com.facebook.soloader.SoLoader;
-import java.util.List;
-
-/**
- * Class responsible to load the TurboModules. This class has native methods and needs a
- * corresponding C++ implementation/header file to work correctly (already placed inside the jni/
- * folder for you).
- *
- *
Please note that this class is used ONLY if you opt-in for the New Architecture (see the
- * `newArchEnabled` property). Is ignored otherwise.
- */
-public class MainApplicationTurboModuleManagerDelegate
- extends ReactPackageTurboModuleManagerDelegate {
-
- private static volatile boolean sIsSoLibraryLoaded;
-
- protected MainApplicationTurboModuleManagerDelegate(
- ReactApplicationContext reactApplicationContext, List packages) {
- super(reactApplicationContext, packages);
- }
-
- protected native HybridData initHybrid();
-
- native boolean canCreateTurboModule(String moduleName);
-
- public static class Builder extends ReactPackageTurboModuleManagerDelegate.Builder {
- protected MainApplicationTurboModuleManagerDelegate build(
- ReactApplicationContext context, List packages) {
- return new MainApplicationTurboModuleManagerDelegate(context, packages);
- }
- }
-
- @Override
- protected synchronized void maybeLoadOtherSoLibraries() {
- if (!sIsSoLibraryLoaded) {
- // If you change the name of your application .so file in the Android.mk file,
- // make sure you update the name here as well.
- SoLoader.loadLibrary("demoreactnative_appmodules");
- sIsSoLibraryLoaded = true;
- }
- }
-}
diff --git a/demos/demo-react-native/android/app/src/main/jni/CMakeLists.txt b/demos/demo-react-native/android/app/src/main/jni/CMakeLists.txt
deleted file mode 100644
index 3e3249da2b1..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/CMakeLists.txt
+++ /dev/null
@@ -1,7 +0,0 @@
-cmake_minimum_required(VERSION 3.13)
-
-# Define the library name here.
-project(demoreactnative_appmodules)
-
-# This file includes all the necessary to let you build your application with the New Architecture.
-include(${REACT_ANDROID_DIR}/cmake-utils/ReactNative-application.cmake)
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.cpp b/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.cpp
deleted file mode 100644
index 26162dd8723..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.cpp
+++ /dev/null
@@ -1,32 +0,0 @@
-#include "MainApplicationModuleProvider.h"
-
-#include
-#include
-
-namespace facebook {
-namespace react {
-
-std::shared_ptr MainApplicationModuleProvider(
- const std::string &moduleName,
- const JavaTurboModule::InitParams ¶ms) {
- // Here you can provide your own module provider for TurboModules coming from
- // either your application or from external libraries. The approach to follow
- // is similar to the following (for a library called `samplelibrary`:
- //
- // auto module = samplelibrary_ModuleProvider(moduleName, params);
- // if (module != nullptr) {
- // return module;
- // }
- // return rncore_ModuleProvider(moduleName, params);
-
- // Module providers autolinked by RN CLI
- auto rncli_module = rncli_ModuleProvider(moduleName, params);
- if (rncli_module != nullptr) {
- return rncli_module;
- }
-
- return rncore_ModuleProvider(moduleName, params);
-}
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.h b/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.h
deleted file mode 100644
index b38ccf53fd4..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainApplicationModuleProvider.h
+++ /dev/null
@@ -1,16 +0,0 @@
-#pragma once
-
-#include
-#include
-
-#include
-
-namespace facebook {
-namespace react {
-
-std::shared_ptr MainApplicationModuleProvider(
- const std::string &moduleName,
- const JavaTurboModule::InitParams ¶ms);
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp b/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp
deleted file mode 100644
index 5fd688c509d..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.cpp
+++ /dev/null
@@ -1,45 +0,0 @@
-#include "MainApplicationTurboModuleManagerDelegate.h"
-#include "MainApplicationModuleProvider.h"
-
-namespace facebook {
-namespace react {
-
-jni::local_ref
-MainApplicationTurboModuleManagerDelegate::initHybrid(
- jni::alias_ref) {
- return makeCxxInstance();
-}
-
-void MainApplicationTurboModuleManagerDelegate::registerNatives() {
- registerHybrid({
- makeNativeMethod(
- "initHybrid", MainApplicationTurboModuleManagerDelegate::initHybrid),
- makeNativeMethod(
- "canCreateTurboModule",
- MainApplicationTurboModuleManagerDelegate::canCreateTurboModule),
- });
-}
-
-std::shared_ptr
-MainApplicationTurboModuleManagerDelegate::getTurboModule(
- const std::string &name,
- const std::shared_ptr &jsInvoker) {
- // Not implemented yet: provide pure-C++ NativeModules here.
- return nullptr;
-}
-
-std::shared_ptr
-MainApplicationTurboModuleManagerDelegate::getTurboModule(
- const std::string &name,
- const JavaTurboModule::InitParams ¶ms) {
- return MainApplicationModuleProvider(name, params);
-}
-
-bool MainApplicationTurboModuleManagerDelegate::canCreateTurboModule(
- const std::string &name) {
- return getTurboModule(name, nullptr) != nullptr ||
- getTurboModule(name, {.moduleName = name}) != nullptr;
-}
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h b/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h
deleted file mode 100644
index 75a42a6f944..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainApplicationTurboModuleManagerDelegate.h
+++ /dev/null
@@ -1,38 +0,0 @@
-#include
-#include
-
-#include
-#include
-
-namespace facebook {
-namespace react {
-
-class MainApplicationTurboModuleManagerDelegate
- : public jni::HybridClass<
- MainApplicationTurboModuleManagerDelegate,
- TurboModuleManagerDelegate> {
- public:
- // Adapt it to the package you used for your Java class.
- static constexpr auto kJavaDescriptor =
- "Lcom/demoreactnative/newarchitecture/modules/MainApplicationTurboModuleManagerDelegate;";
-
- static jni::local_ref initHybrid(jni::alias_ref);
-
- static void registerNatives();
-
- std::shared_ptr getTurboModule(
- const std::string &name,
- const std::shared_ptr &jsInvoker) override;
- std::shared_ptr getTurboModule(
- const std::string &name,
- const JavaTurboModule::InitParams ¶ms) override;
-
- /**
- * Test-only method. Allows user to verify whether a TurboModule can be
- * created by instances of this class.
- */
- bool canCreateTurboModule(const std::string &name);
-};
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.cpp b/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.cpp
deleted file mode 100644
index 54f598a486a..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.cpp
+++ /dev/null
@@ -1,65 +0,0 @@
-#include "MainComponentsRegistry.h"
-
-#include
-#include
-#include
-#include
-#include
-
-namespace facebook {
-namespace react {
-
-MainComponentsRegistry::MainComponentsRegistry(ComponentFactory *delegate) {}
-
-std::shared_ptr
-MainComponentsRegistry::sharedProviderRegistry() {
- auto providerRegistry = CoreComponentsRegistry::sharedProviderRegistry();
-
- // Autolinked providers registered by RN CLI
- rncli_registerProviders(providerRegistry);
-
- // Custom Fabric Components go here. You can register custom
- // components coming from your App or from 3rd party libraries here.
- //
- // providerRegistry->add(concreteComponentDescriptorProvider<
- // AocViewerComponentDescriptor>());
- return providerRegistry;
-}
-
-jni::local_ref
-MainComponentsRegistry::initHybrid(
- jni::alias_ref,
- ComponentFactory *delegate) {
- auto instance = makeCxxInstance(delegate);
-
- auto buildRegistryFunction =
- [](EventDispatcher::Weak const &eventDispatcher,
- ContextContainer::Shared const &contextContainer)
- -> ComponentDescriptorRegistry::Shared {
- auto registry = MainComponentsRegistry::sharedProviderRegistry()
- ->createComponentDescriptorRegistry(
- {eventDispatcher, contextContainer});
-
- auto mutableRegistry =
- std::const_pointer_cast(registry);
-
- mutableRegistry->setFallbackComponentDescriptor(
- std::make_shared(
- ComponentDescriptorParameters{
- eventDispatcher, contextContainer, nullptr}));
-
- return registry;
- };
-
- delegate->buildRegistryFunction = buildRegistryFunction;
- return instance;
-}
-
-void MainComponentsRegistry::registerNatives() {
- registerHybrid({
- makeNativeMethod("initHybrid", MainComponentsRegistry::initHybrid),
- });
-}
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.h b/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.h
deleted file mode 100644
index 8a1ac146172..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/MainComponentsRegistry.h
+++ /dev/null
@@ -1,32 +0,0 @@
-#pragma once
-
-#include
-#include
-#include
-#include
-
-namespace facebook {
-namespace react {
-
-class MainComponentsRegistry
- : public facebook::jni::HybridClass {
- public:
- // Adapt it to the package you used for your Java class.
- constexpr static auto kJavaDescriptor =
- "Lcom/demoreactnative/newarchitecture/components/MainComponentsRegistry;";
-
- static void registerNatives();
-
- MainComponentsRegistry(ComponentFactory *delegate);
-
- private:
- static std::shared_ptr
- sharedProviderRegistry();
-
- static jni::local_ref initHybrid(
- jni::alias_ref,
- ComponentFactory *delegate);
-};
-
-} // namespace react
-} // namespace facebook
diff --git a/demos/demo-react-native/android/app/src/main/jni/OnLoad.cpp b/demos/demo-react-native/android/app/src/main/jni/OnLoad.cpp
deleted file mode 100644
index c569b6e865d..00000000000
--- a/demos/demo-react-native/android/app/src/main/jni/OnLoad.cpp
+++ /dev/null
@@ -1,11 +0,0 @@
-#include
-#include "MainApplicationTurboModuleManagerDelegate.h"
-#include "MainComponentsRegistry.h"
-
-JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *) {
- return facebook::jni::initialize(vm, [] {
- facebook::react::MainApplicationTurboModuleManagerDelegate::
- registerNatives();
- facebook::react::MainComponentsRegistry::registerNatives();
- });
-}
diff --git a/demos/demo-react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml b/demos/demo-react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml
index f35d9962026..5c25e728ea2 100644
--- a/demos/demo-react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml
+++ b/demos/demo-react-native/android/app/src/main/res/drawable/rn_edit_text_material.xml
@@ -17,10 +17,11 @@
android:insetLeft="@dimen/abc_edit_text_inset_horizontal_material"
android:insetRight="@dimen/abc_edit_text_inset_horizontal_material"
android:insetTop="@dimen/abc_edit_text_inset_top_material"
- android:insetBottom="@dimen/abc_edit_text_inset_bottom_material">
+ android:insetBottom="@dimen/abc_edit_text_inset_bottom_material"
+ >
-
+ NSAllowsArbitraryLoads
+
+ NSAllowsLocalNetworking
+
NSLocationWhenInUseUsageDescription
@@ -41,7 +38,7 @@
LaunchScreen
UIRequiredDeviceCapabilities
- armv7
+ arm64
UISupportedInterfaceOrientations
diff --git a/react-native/verification-tool/ios/ThetaClientVerificationTool/PrivacyInfo.xcprivacy b/react-native/verification-tool/ios/ThetaClientVerificationTool/PrivacyInfo.xcprivacy
new file mode 100644
index 00000000000..41b8317f065
--- /dev/null
+++ b/react-native/verification-tool/ios/ThetaClientVerificationTool/PrivacyInfo.xcprivacy
@@ -0,0 +1,37 @@
+
+
+
+
+ NSPrivacyAccessedAPITypes
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryFileTimestamp
+ NSPrivacyAccessedAPITypeReasons
+
+ C617.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategoryUserDefaults
+ NSPrivacyAccessedAPITypeReasons
+
+ CA92.1
+
+
+
+ NSPrivacyAccessedAPIType
+ NSPrivacyAccessedAPICategorySystemBootTime
+ NSPrivacyAccessedAPITypeReasons
+
+ 35F9.1
+
+
+
+ NSPrivacyCollectedDataTypes
+
+ NSPrivacyTracking
+
+
+
diff --git a/react-native/verification-tool/ios/ThetaClientVerificationTool/main.m b/react-native/verification-tool/ios/ThetaClientVerificationTool/main.m
deleted file mode 100644
index d645c7246c4..00000000000
--- a/react-native/verification-tool/ios/ThetaClientVerificationTool/main.m
+++ /dev/null
@@ -1,10 +0,0 @@
-#import
-
-#import "AppDelegate.h"
-
-int main(int argc, char *argv[])
-{
- @autoreleasepool {
- return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
- }
-}
diff --git a/react-native/verification-tool/ios/ThetaClientVerificationToolTests/Info.plist b/react-native/verification-tool/ios/ThetaClientVerificationToolTests/Info.plist
deleted file mode 100644
index ba72822e872..00000000000
--- a/react-native/verification-tool/ios/ThetaClientVerificationToolTests/Info.plist
+++ /dev/null
@@ -1,24 +0,0 @@
-
-
-
-
- CFBundleDevelopmentRegion
- en
- CFBundleExecutable
- $(EXECUTABLE_NAME)
- CFBundleIdentifier
- $(PRODUCT_BUNDLE_IDENTIFIER)
- CFBundleInfoDictionaryVersion
- 6.0
- CFBundleName
- $(PRODUCT_NAME)
- CFBundlePackageType
- BNDL
- CFBundleShortVersionString
- 1.0
- CFBundleSignature
- ????
- CFBundleVersion
- 1
-
-
diff --git a/react-native/verification-tool/ios/ThetaClientVerificationToolTests/ThetaClientReactNativeExampleTests.m b/react-native/verification-tool/ios/ThetaClientVerificationToolTests/ThetaClientReactNativeExampleTests.m
deleted file mode 100644
index c1d86dc8ef9..00000000000
--- a/react-native/verification-tool/ios/ThetaClientVerificationToolTests/ThetaClientReactNativeExampleTests.m
+++ /dev/null
@@ -1,66 +0,0 @@
-#import
-#import
-
-#import
-#import
-
-#define TIMEOUT_SECONDS 600
-#define TEXT_TO_LOOK_FOR @"Welcome to React"
-
-@interface ThetaClientVerificationToolTest : XCTestCase
-
-@end
-
-@implementation ThetaClientVerificationToolTest
-
-- (BOOL)findSubviewInView:(UIView *)view matching:(BOOL (^)(UIView *view))test
-{
- if (test(view)) {
- return YES;
- }
- for (UIView *subview in [view subviews]) {
- if ([self findSubviewInView:subview matching:test]) {
- return YES;
- }
- }
- return NO;
-}
-
-- (void)testRendersWelcomeScreen
-{
- UIViewController *vc = [[[RCTSharedApplication() delegate] window] rootViewController];
- NSDate *date = [NSDate dateWithTimeIntervalSinceNow:TIMEOUT_SECONDS];
- BOOL foundElement = NO;
-
- __block NSString *redboxError = nil;
-#ifdef DEBUG
- RCTSetLogFunction(
- ^(RCTLogLevel level, RCTLogSource source, NSString *fileName, NSNumber *lineNumber, NSString *message) {
- if (level >= RCTLogLevelError) {
- redboxError = message;
- }
- });
-#endif
-
- while ([date timeIntervalSinceNow] > 0 && !foundElement && !redboxError) {
- [[NSRunLoop mainRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
- [[NSRunLoop mainRunLoop] runMode:NSRunLoopCommonModes beforeDate:[NSDate dateWithTimeIntervalSinceNow:0.1]];
-
- foundElement = [self findSubviewInView:vc.view
- matching:^BOOL(UIView *view) {
- if ([view.accessibilityLabel isEqualToString:TEXT_TO_LOOK_FOR]) {
- return YES;
- }
- return NO;
- }];
- }
-
-#ifdef DEBUG
- RCTSetLogFunction(RCTDefaultLogFunction);
-#endif
-
- XCTAssertNil(redboxError, @"RedBox error: %@", redboxError);
- XCTAssertTrue(foundElement, @"Couldn't find element with text '%@' in %d seconds", TEXT_TO_LOOK_FOR, TIMEOUT_SECONDS);
-}
-
-@end
diff --git a/react-native/verification-tool/jest.config.js b/react-native/verification-tool/jest.config.js
new file mode 100644
index 00000000000..8eb675e9bc6
--- /dev/null
+++ b/react-native/verification-tool/jest.config.js
@@ -0,0 +1,3 @@
+module.exports = {
+ preset: 'react-native',
+};
diff --git a/react-native/verification-tool/metro.config.js b/react-native/verification-tool/metro.config.js
index b5c0064bb93..bff64248649 100644
--- a/react-native/verification-tool/metro.config.js
+++ b/react-native/verification-tool/metro.config.js
@@ -2,6 +2,7 @@ const path = require('path');
const escape = require('escape-string-regexp');
const exclusionList = require('metro-config/src/defaults/exclusionList');
const pak = require('../package.json');
+const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
const root = path.resolve(__dirname, '..');
@@ -9,14 +10,14 @@ const modules = Object.keys({
...pak.peerDependencies,
});
-module.exports = {
+const config = {
projectRoot: __dirname,
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(
+ blockList: exclusionList(
modules.map(
(m) =>
new RegExp(`^${escape(path.join(root, 'node_modules', m))}\\/.*$`)
@@ -26,7 +27,9 @@ module.exports = {
extraNodeModules: modules.reduce((acc, name) => {
acc[name] = path.join(__dirname, 'node_modules', name);
return acc;
- }, {}),
+ }, {
+ 'theta-client-react-native': root,
+ }),
},
transformer: {
@@ -38,3 +41,5 @@ module.exports = {
}),
},
};
+
+module.exports = mergeConfig(getDefaultConfig(__dirname), config);
diff --git a/react-native/verification-tool/package.json b/react-native/verification-tool/package.json
index 022a79aa1f2..010483832e3 100644
--- a/react-native/verification-tool/package.json
+++ b/react-native/verification-tool/package.json
@@ -1,30 +1,48 @@
{
- "name": "verification-tool",
+ "name": "ThetaClientVerificationTool",
"version": "0.0.1",
"private": true,
"scripts": {
"android": "react-native run-android",
"ios": "react-native run-ios",
+ "lint": "eslint .",
"start": "react-native start",
- "pods": "pod-install --quiet",
+ "test": "jest",
+ "pods": "cd ios && pod install",
"postinstall": "./scripts/copy-npm-module-to-web-bundles.sh"
},
"dependencies": {
- "@react-navigation/native": "^6.1.7",
- "@react-navigation/native-stack": "^6.9.13",
+ "babel-plugin-module-resolver": "^5.0.2",
"marzipano": "0.10.2",
- "react": "18.2.0",
- "react-native": "0.71.19",
- "react-native-safe-area-context": "^4.7.1",
- "react-native-screens": "^3.24.0",
- "react-native-webview": "^13.6.0"
+ "react": "19.0.0",
+ "react-native": "0.78.2",
+ "react-native-svg": "15.11.2",
+ "react-native-webview": "^13.16.0"
},
"devDependencies": {
- "@babel/core": "^7.20.0",
- "@babel/preset-env": "^7.20.0",
- "@babel/runtime": "^7.20.0",
- "@types/lodash": "^4.14.200",
- "babel-plugin-module-resolver": "^4.1.0",
- "metro-react-native-babel-preset": "0.73.9"
+ "@babel/core": "^7.25.2",
+ "@babel/preset-env": "^7.25.3",
+ "@babel/runtime": "^7.25.0",
+ "@react-native-community/cli": "15.0.1",
+ "@react-native-community/cli-platform-android": "15.0.1",
+ "@react-native-community/cli-platform-ios": "15.0.1",
+ "@react-native/babel-preset": "0.78.2",
+ "@react-native/eslint-config": "0.78.2",
+ "@react-native/metro-config": "0.78.2",
+ "@react-native/typescript-config": "0.78.2",
+ "@types/jest": "^29.5.13",
+ "@types/react": "^19.0.0",
+ "@types/react-test-renderer": "^19.0.0",
+ "@typescript-eslint/eslint-plugin": "^7.0.0",
+ "@typescript-eslint/parser": "^7.0.0",
+ "eslint": "^8.19.0",
+ "jest": "^29.6.3",
+ "prettier": "2.8.8",
+ "react-native-svg-transformer": "^1.5.3",
+ "react-test-renderer": "19.0.0",
+ "typescript": "^5.7.2"
+ },
+ "engines": {
+ "node": ">=22"
}
}
diff --git a/react-native/verification-tool/react-native.config.js b/react-native/verification-tool/react-native.config.js
index a5166956f49..d870039571b 100644
--- a/react-native/verification-tool/react-native.config.js
+++ b/react-native/verification-tool/react-native.config.js
@@ -1,9 +1,12 @@
const path = require('path');
-const pak = require('../package.json');
+/**
+ * theta-client-react-native is referenced via file:..,
+ * so we explicitly set the root to ensure autolinking detects it correctly.
+ */
module.exports = {
dependencies: {
- [pak.name]: {
+ 'theta-client-react-native': {
root: path.join(__dirname, '..'),
},
},
diff --git a/react-native/verification-tool/src/App.tsx b/react-native/verification-tool/src/App.tsx
index ee4f57a9722..73559a0e448 100644
--- a/react-native/verification-tool/src/App.tsx
+++ b/react-native/verification-tool/src/App.tsx
@@ -1,85 +1,106 @@
-import React from 'react';
-import { NavigationContainer } from '@react-navigation/native';
-import {
- NativeStackNavigationOptions,
- createNativeStackNavigator,
-} from '@react-navigation/native-stack';
+import React, { useState, useEffect } from 'react';
+import { View, Text, TouchableOpacity, StyleSheet, StatusBar, Platform, SafeAreaView, Button } from 'react-native';
+import Svg, { Path } from 'react-native-svg';
import MenuScreen from './screen/menu-screen';
-import VideoConvertScreen from './screen/video-convert-screen';
+import GetInfoScreen from './screen/get-info-screen';
+import PhotoCaptureScreen from './screen/photo-capture-screen';
+import OptionsScreen from './screen/options-screen';
+import ListFilesScreen from './screen/list-files-screen';
+import GetMetadataScreen from './screen/get-metadata-screen';
+import DeleteFilesScreen from './screen/delete-files-screen';
+import VideoCaptureScreen from './screen/video-capture-screen';
+import TimeShiftCaptureScreen from './screen/time-shift-capture-screen';
+import TimeShiftManualCaptureScreen from './screen/time-shift-manual-capture-screen';
+import LimitlessIntervalCaptureScreen from './screen/limitless-interval-capture-screen';
+import CompositeIntervalCaptureScreen from './screen/composite-interval-capture-screen';
+import ShotCountSpecifiedIntervalCaptureScreen from './screen/shot-count-specified-interval-capture-screen';
+import BurstCaptureScreen from './screen/burst-capture-screen';
+import MultiBracketCaptureScreen from './screen/multi-bracket-capture-screen';
+import ContinuousCaptureScreen from './screen/continuous-capture-screen';
import LivePreviewScreen from './screen/live-preview-screen';
-import OptionsScreen from './screen/options-screen/options-screen';
+import VideoConvertScreen from './screen/video-convert-screen';
import CommandsScreen from './screen/commands-screen';
-import PhotoCaptureScreen from './screen/photo-capture-screen';
import FilePreviewScreen from './screen/file-preview-screen';
-import ListFilesScreen from './screen/list-files-screen';
-import VideoCaptureScreen from './screen/video-capture-screen/video-capture-screen';
-import DeleteFilesScreen from './screen/delete-files-screen/delete-files-screen';
-import GetMetadataScreen from './screen/get-metadata-screen/get-metadata-screen';
-import GetInfoScreen from './screen/get-info-screen/get-info-screen';
-import TimeShiftCaptureScreen from './screen/time-shift-capture-screen/time-shift-capture-screen';
-import TimeShiftManualCaptureScreen from './screen/time-shift-manual-capture-screen/time-shift-manual-capture-screen';
-import LimitlessIntervalCaptureScreen from './screen/limitless-interval-capture-screen/limitless-interval-capture-screen';
-import ShotCountSpecifiedIntervalCaptureScreen from './screen/shot-count-specified-interval-capture-screen/shot-count-specified-interval-capture-screen';
-import CompositeIntervalCaptureScreen from './screen/composite-interval-capture-screen/composite-interval-capture-screen';
-import BurstCaptureScreen from './screen/burst-capture-screen/burst-capture-screen';
-import ContinuousCaptureScreen from './screen/continuous-capture-screen/continuous-capture-screen';
-import MultiBracketCaptureScreen from './screen/multi-bracket-capture-screen/multi-bracket-capture-screen';
-import { setApiLogListener, type FileInfo } from './modules/theta-client';
-import { Button } from 'react-native';
import LogPopupView from './components/log-popup-view/log-popup-view';
+import { FileTypeEnum, setApiLogListener } from './modules/theta-client';
-export type RootStackParamList = {
- menu: undefined;
- getInfo: undefined;
- listFiles: undefined;
- deleteFiles: undefined;
- getMetadata: undefined;
- livePreview: undefined;
- videoConvert: undefined;
- options: undefined;
- commands: undefined;
- photoCapture: undefined;
- videoCapture: undefined;
- limitlessIntervalCapture: undefined;
- timeShiftCapture: undefined;
- timeShiftManualCapture: undefined;
- shotCountSpecifiedIntervalCapture: undefined;
- compositeIntervalCapture: undefined;
- burstCapture: undefined;
- continuousCapture: undefined;
- multiBracketCapture: undefined;
- filePreview: {
- item: FileInfo;
- };
-};
+const BackIcon = () => (
+
+
+
+);
-const Stack = createNativeStackNavigator();
+type ScreenName =
+ | 'menu'
+ | 'getInfo'
+ | 'listFiles'
+ | 'deleteFiles'
+ | 'getMetadata'
+ | 'livePreview'
+ | 'videoConvert'
+ | 'options'
+ | 'commands'
+ | 'photoCapture'
+ | 'videoCapture'
+ | 'limitlessIntervalCapture'
+ | 'timeShiftCapture'
+ | 'timeShiftManualCapture'
+ | 'shotCountSpecifiedIntervalCapture'
+ | 'compositeIntervalCapture'
+ | 'burstCapture'
+ | 'continuousCapture'
+ | 'multiBracketCapture'
+ | 'filePreview';
-const screenOptions = {
- headerStyle: {
- backgroundColor: '#6200ee',
- },
- headerTintColor: '#fff',
- headerTitleStyle: {
- fontWeight: 'bold',
- },
- headerBackTitle: '',
-} as NativeStackNavigationOptions;
+const screenTitles: Record = {
+ menu: 'Menu',
+ getInfo: 'Get Info',
+ listFiles: 'List Files',
+ deleteFiles: 'Delete Files',
+ getMetadata: 'Get Metadata',
+ livePreview: 'Live Preview',
+ videoConvert: 'Video Convert',
+ options: 'Options',
+ commands: 'Commands',
+ photoCapture: 'Photo Capture',
+ videoCapture: 'Video Capture',
+ limitlessIntervalCapture: 'Limitless Interval Capture',
+ timeShiftCapture: 'Time Shift Capture',
+ timeShiftManualCapture: 'Time Shift Manual Capture',
+ shotCountSpecifiedIntervalCapture: 'Shot Count Specified Interval Capture',
+ compositeIntervalCapture: 'Composite Interval Capture',
+ burstCapture: 'Burst Capture',
+ continuousCapture: 'Continuous Capture',
+ multiBracketCapture: 'Multi Bracket Capture',
+ filePreview: 'Preview',
+};
const App = () => {
- const [log, setLog] = React.useState('');
- const [isShowLog, setShowLog] = React.useState(false);
- const headerRight = () => (
- <>
- setShowLog(true)} title="Api log" />
- setShowLog(false)}
- onClear={() => setLog('')}
- />
- >
- );
+ const [currentScreen, setCurrentScreen] = useState('menu');
+ const [screenHistory, setScreenHistory] = useState([]);
+ const [menuMessage, setMenuMessage] = useState('');
+ const [screenParams, setScreenParams] = useState(null);
+ const [screenTitle, setScreenTitle] = useState('');
+ const [log, setLog] = useState('');
+ const [isShowLog, setShowLog] = useState(false);
+
+ // list-files screen state
+ const [listFilesState, setListFilesState] = useState({
+ fileType: FileTypeEnum.ALL,
+ startPosition: 0,
+ entryCount: 100,
+ storage: undefined as any,
+ message: '',
+ selectedFileInfo: null as any,
+ listFilesProps: undefined as any,
+ refreshCounter: 0,
+ });
const getDateTime = () => {
const dt = new Date();
@@ -103,7 +124,7 @@ const App = () => {
});
};
- React.useEffect(() => {
+ useEffect(() => {
setApiLogListener((message) => {
addLog(message);
});
@@ -113,115 +134,193 @@ const App = () => {
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
+ const navigate = (screen: string, params?: any) => {
+ setScreenHistory([...screenHistory, currentScreen]);
+ setCurrentScreen(screen as ScreenName);
+ setScreenParams(params || null);
+ if (params?.fileInfo) {
+ setScreenTitle(params.fileInfo.name);
+ } else {
+ setScreenTitle('');
+ }
+
+ if (screen === 'listFiles' && params?.reset) {
+ setListFilesState({
+ fileType: FileTypeEnum.ALL,
+ startPosition: 0,
+ entryCount: 100,
+ storage: undefined,
+ message: '',
+ selectedFileInfo: null,
+ listFilesProps: undefined,
+ refreshCounter: 0,
+ });
+ }
+ };
+
+ const goBack = () => {
+ if (screenHistory.length > 0) {
+ const previousScreen = screenHistory[screenHistory.length - 1];
+ setScreenHistory(screenHistory.slice(0, -1));
+ setCurrentScreen(previousScreen);
+ setScreenParams(null);
+ setScreenTitle('');
+ }
+ };
+
+ const setOptions = (_options: { title: string }) => {
+ };
+
+ const navigation = {
+ navigate,
+ goBack,
+ setOptions,
+ };
+
+ const renderScreen = () => {
+ switch (currentScreen) {
+ case 'menu':
+ return (
+
+ );
+ case 'getInfo':
+ return ;
+ case 'photoCapture':
+ return ;
+ case 'options':
+ return ;
+ case 'listFiles':
+ return (
+
+ );
+ case 'getMetadata':
+ return ;
+ case 'deleteFiles':
+ return ;
+ case 'videoCapture':
+ return ;
+ case 'timeShiftCapture':
+ return ;
+ case 'timeShiftManualCapture':
+ return ;
+ case 'limitlessIntervalCapture':
+ return ;
+ case 'compositeIntervalCapture':
+ return ;
+ case 'shotCountSpecifiedIntervalCapture':
+ return ;
+ case 'burstCapture':
+ return ;
+ case 'multiBracketCapture':
+ return ;
+ case 'continuousCapture':
+ return ;
+ case 'livePreview':
+ return ;
+ case 'videoConvert':
+ return ;
+ case 'commands':
+ return ;
+ case 'filePreview':
+ return screenParams?.fileInfo ? (
+
+ ) : null;
+ default:
+ return (
+
+
+ {screenTitles[currentScreen]} Screen
+
+ Not implemented yet
+
+ );
+ }
+ };
+
return (
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
+
+
+
+ {screenHistory.length > 0 && (
+
+
+
+ )}
+
+ {screenTitle || screenTitles[currentScreen]}
+
+
+ setShowLog(true)} title="Api log" />
+
+
+ {renderScreen()}
+ setShowLog(false)}
+ onClear={() => setLog('')}
+ />
+
);
};
+const styles = StyleSheet.create({
+ container: {
+ flex: 1,
+ backgroundColor: '#6200ee',
+ marginTop: Platform.select({
+ ios: 0,
+ android: (typeof Platform.Version === 'number' && Platform.Version >= 35) ? (StatusBar.currentHeight || 0) : 0,
+ }),
+ },
+ header: {
+ backgroundColor: '#6200ee',
+ paddingVertical: 15,
+ paddingHorizontal: 16,
+ flexDirection: 'row',
+ alignItems: 'center',
+ justifyContent: 'space-between',
+ },
+ headerRight: {
+ marginLeft: 'auto',
+ },
+ backButton: {
+ marginRight: 16,
+ padding: 4,
+ },
+ headerTitle: {
+ color: '#fff',
+ fontSize: 18,
+ fontWeight: 'bold',
+ },
+ content: {
+ flex: 1,
+ backgroundColor: '#fff',
+ },
+ placeholderContainer: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ padding: 20,
+ },
+ placeholderText: {
+ fontSize: 20,
+ fontWeight: 'bold',
+ marginBottom: 8,
+ },
+ placeholderSubtext: {
+ fontSize: 16,
+ color: '#666',
+ },
+});
+
export default App;
+
diff --git a/react-native/verification-tool/src/components/capture/capture-common-options/capture-common-options.tsx b/react-native/verification-tool/src/components/capture/capture-common-options/capture-common-options.tsx
index 65551ec1946..da1c0a48596 100644
--- a/react-native/verification-tool/src/components/capture/capture-common-options/capture-common-options.tsx
+++ b/react-native/verification-tool/src/components/capture/capture-common-options/capture-common-options.tsx
@@ -1,112 +1,112 @@
import * as React from 'react';
import type { OptionEditProps } from '../../options';
import { View } from 'react-native';
-import { GpsInfoEdit } from '../../../components/options';
-import { NumberEdit } from '../../../components/options/number-edit';
+import { GpsInfoEdit } from '../../options';
+import { NumberEdit } from '../../options/number-edit';
import { EnumEdit } from '../../options/enum-edit';
import {
- ApertureEnum,
- ExposureCompensationEnum,
- ExposureDelayEnum,
- ExposureProgramEnum,
- GpsTagRecordingEnum,
- IsoAutoHighLimitEnum,
- IsoEnum,
- WhiteBalanceEnum,
+ ApertureEnum,
+ ExposureCompensationEnum,
+ ExposureDelayEnum,
+ ExposureProgramEnum,
+ GpsTagRecordingEnum,
+ IsoAutoHighLimitEnum,
+ IsoEnum,
+ WhiteBalanceEnum,
} from '../../../modules/theta-client';
export const CaptureCommonOptionsEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- return (
-
- {
- onChange({ ...options, aperture });
- }}
- optionEnum={ApertureEnum}
- />
- {
- onChange({
- ...options,
- colorTemperature: option.colorTemperature,
- });
- }}
- options={options}
- placeHolder="Input value"
- />
- {
- onChange({ ...options, exposureCompensation });
- }}
- optionEnum={ExposureCompensationEnum}
- />
- {
- onChange({ ...options, exposureDelay });
- }}
- optionEnum={ExposureDelayEnum}
- />
- {
- onChange({ ...options, exposureProgram });
- }}
- optionEnum={ExposureProgramEnum}
- />
- {
- onChange({
- ...options,
- gpsInfo: option.gpsInfo,
- });
- }}
- options={options}
- />
- {
- onChange({ ...options, _gpsTagRecording });
- }}
- optionEnum={GpsTagRecordingEnum}
- />
- {
- onChange({ ...options, iso });
- }}
- optionEnum={IsoEnum}
- />
- {
- onChange({ ...options, isoAutoHighLimit });
- }}
- optionEnum={IsoAutoHighLimitEnum}
- />
- {
- onChange({ ...options, whiteBalance });
- }}
- optionEnum={WhiteBalanceEnum}
- />
-
- );
+ return (
+
+ {
+ onChange({ ...options, aperture });
+ }}
+ optionEnum={ApertureEnum}
+ />
+ {
+ onChange({
+ ...options,
+ colorTemperature: option.colorTemperature,
+ });
+ }}
+ options={options}
+ placeHolder="Input value"
+ />
+ {
+ onChange({ ...options, exposureCompensation });
+ }}
+ optionEnum={ExposureCompensationEnum}
+ />
+ {
+ onChange({ ...options, exposureDelay });
+ }}
+ optionEnum={ExposureDelayEnum}
+ />
+ {
+ onChange({ ...options, exposureProgram });
+ }}
+ optionEnum={ExposureProgramEnum}
+ />
+ {
+ onChange({
+ ...options,
+ gpsInfo: option.gpsInfo,
+ });
+ }}
+ options={options}
+ />
+ {
+ onChange({ ...options, _gpsTagRecording });
+ }}
+ optionEnum={GpsTagRecordingEnum}
+ />
+ {
+ onChange({ ...options, iso });
+ }}
+ optionEnum={IsoEnum}
+ />
+ {
+ onChange({ ...options, isoAutoHighLimit });
+ }}
+ optionEnum={IsoAutoHighLimitEnum}
+ />
+ {
+ onChange({ ...options, whiteBalance });
+ }}
+ optionEnum={WhiteBalanceEnum}
+ />
+
+ );
};
CaptureCommonOptionsEdit.displayName = 'CaptureCommonOptionsEdit';
diff --git a/react-native/verification-tool/src/components/list-files-view/list-files-view.tsx b/react-native/verification-tool/src/components/list-files-view/list-files-view.tsx
index 147bb62c409..ae871ebc476 100644
--- a/react-native/verification-tool/src/components/list-files-view/list-files-view.tsx
+++ b/react-native/verification-tool/src/components/list-files-view/list-files-view.tsx
@@ -1,152 +1,156 @@
import React from 'react';
import {
- type ViewProps,
- type ViewStyle,
- StyleProp,
- TouchableOpacity,
- Text,
- View,
- ScrollView,
- RefreshControl,
+ type ViewProps,
+ type ViewStyle,
+ StyleProp,
+ TouchableOpacity,
+ Text,
+ View,
+ ScrollView,
+ RefreshControl,
} from 'react-native';
-import styles from './styles';
+import styles from './styles.tsx';
import {
- FileInfo,
- FileTypeEnum,
- StorageEnum,
- ThetaFiles,
- listFiles,
+ FileInfo,
+ FileTypeEnum,
+ StorageEnum,
+ ThetaFiles,
+ listFiles,
} from '../../modules/theta-client';
interface Props extends Pick {
- style?: StyleProp;
- selectedFiles?: FileInfo[];
- onSelected?: (files: FileInfo[]) => void;
- fileType?: FileTypeEnum;
- startPosition?: number;
- entryCount?: number;
- storage?: StorageEnum;
- multiselect?: boolean;
- onError?: (error: any) => void;
- refreshCounter?: number;
- onRefreshed?: (thetaFiles?: ThetaFiles) => void;
+ style?: StyleProp;
+ selectedFiles?: FileInfo[];
+ onSelected?: (files: FileInfo[]) => void;
+ fileType?: FileTypeEnum;
+ startPosition?: number;
+ entryCount?: number;
+ storage?: StorageEnum;
+ multiselect?: boolean;
+ onError?: (error: any) => void;
+ refreshCounter?: number;
+ onRefreshed?: (thetaFiles?: ThetaFiles) => void;
}
export const ListFilesView: React.FC = ({
- onSelected,
- selectedFiles,
- fileType,
- startPosition,
- entryCount,
- storage,
- multiselect,
- onError,
- refreshCounter,
- onRefreshed,
+ onSelected,
+ selectedFiles,
+ fileType,
+ startPosition,
+ entryCount,
+ storage,
+ multiselect,
+ onError,
+ refreshCounter,
+ onRefreshed,
}) => {
- const [refreshing, setRefreshing] = React.useState(false);
- const [thetaFiles, setThetaFiles] = React.useState();
- const [selected, setSelected] = React.useState(
- selectedFiles ?? []
- );
+ const [refreshing, setRefreshing] = React.useState(false);
+ const [thetaFiles, setThetaFiles] = React.useState();
+ const [selected, setSelected] = React.useState(
+ selectedFiles ?? []
+ );
- React.useEffect(() => {
- setSelected(selectedFiles ?? []);
- }, [selectedFiles]);
+ React.useEffect(() => {
+ setSelected(selectedFiles ?? []);
+ }, [selectedFiles]);
- const getFileList = React.useCallback(async () => {
- try {
- if (entryCount != null && entryCount < 0) {
- return undefined;
- }
- const result = await listFiles(
- fileType ?? FileTypeEnum.ALL,
- startPosition,
- entryCount ?? 100,
- storage
- );
- return result;
- } catch (error) {
- console.log('listFiles error: ' + JSON.stringify(error));
- onError?.(error);
- return undefined;
- }
- }, [entryCount, fileType, onError, startPosition, storage]);
+ const getFileList = React.useCallback(async () => {
+ try {
+ if (entryCount != null && entryCount < 0) {
+ return undefined;
+ }
+ const result = await listFiles(
+ fileType ?? FileTypeEnum.ALL,
+ startPosition,
+ entryCount ?? 100,
+ storage
+ );
+ return result;
+ } catch (error) {
+ console.log('listFiles error: ' + JSON.stringify(error));
+ onError?.(error);
+ return undefined;
+ }
+ }, [entryCount, fileType, onError, startPosition, storage]);
+
+ const onPressItem = (item: FileInfo) => {
+ let items: FileInfo[] = [];
+ if (multiselect) {
+ const findFile = selected.find((element) => {
+ return element.fileUrl === item.fileUrl;
+ });
+ if (findFile == null) {
+ items = [...selected, item];
+ } else {
+ items = selected.filter((element) => {
+ return element.fileUrl !== item.fileUrl;
+ });
+ }
+ } else {
+ items = [item];
+ }
+ setSelected(items);
+ onSelected?.(items);
+ };
- const onPressItem = (item: FileInfo) => {
- let items: FileInfo[] = [];
- if (multiselect) {
- const findFile = selected.find((element) => {
- return element.fileUrl === item.fileUrl;
- });
- if (findFile == null) {
- items = [...selected, item];
- } else {
- items = selected.filter((element) => {
- return element.fileUrl !== item.fileUrl;
+ const isSelectedFile = (fileInfo: FileInfo) => {
+ const foundItem = selected.find((item) => {
+ return item.fileUrl === fileInfo.fileUrl;
});
- }
- } else {
- items = [item];
- }
- setSelected(items);
- onSelected?.(items);
- };
+ if (foundItem == null) {
+ return false;
+ }
+ return true;
+ };
- const isSelectedFile = (fileInfo: FileInfo) => {
- const foundItem = selected.find((item) => {
- return item.fileUrl === fileInfo.fileUrl;
- });
- if (foundItem == null) {
- return false;
- }
- return true;
- };
+ const onRefresh = React.useCallback(async () => {
+ console.log('ListFilesView onRefresh');
+ if (!selectedFiles || selectedFiles.length === 0) {
+ setSelected([]);
+ }
+ setRefreshing(true);
+ const resultListFiles = await getFileList();
+ setThetaFiles(resultListFiles);
+ setRefreshing(false);
+ onRefreshed?.(resultListFiles);
+ }, [getFileList, onRefreshed, selectedFiles]);
- const onRefresh = React.useCallback(async () => {
- console.log('ListFilesView onRefresh');
- setSelected([]);
- setRefreshing(true);
- const resultListFiles = await getFileList();
- setThetaFiles(resultListFiles);
- setRefreshing(false);
- onRefreshed?.(resultListFiles);
- }, [getFileList, onRefreshed]);
+ React.useEffect(() => {
+ onRefresh();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [startPosition, entryCount, fileType, storage, refreshCounter]);
- React.useEffect(() => {
- onRefresh();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [startPosition, entryCount, fileType, storage, refreshCounter]);
+ const items =
+ thetaFiles?.fileList.map((item) => (
+ onPressItem(item)}
+ >
+
+ {item.name}
+
+
+ )) ?? [];
- const items =
- thetaFiles?.fileList.map((item) => (
- onPressItem(item)}
- >
-
- {item.name}
+ return (
+
+
+ }
+ >
+ {items}
+
-
- )) ?? [];
-
- return (
-
-
- }
- >
- {items}
-
-
- );
+ );
};
export default ListFilesView;
diff --git a/react-native/verification-tool/src/components/list-files-view/styles.tsx b/react-native/verification-tool/src/components/list-files-view/styles.tsx
index f0e1113b169..aaeed4f3a4e 100644
--- a/react-native/verification-tool/src/components/list-files-view/styles.tsx
+++ b/react-native/verification-tool/src/components/list-files-view/styles.tsx
@@ -1,25 +1,25 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
- container: {
- flex: 1,
- },
- listContentContainer: {
- flex: 1,
- },
- listItemBase: {
- width: '100%',
- },
- listItemBaseSelected: {
- width: '100%',
- backgroundColor: 'yellow',
- },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
+ container: {
+ flex: 1,
+ },
+ listContentContainer: {
+ flex: 1,
+ },
+ listItemBase: {
+ width: '100%',
+ },
+ listItemBaseSelected: {
+ width: '100%',
+ backgroundColor: 'yellow',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/log-popup-view/index.ts b/react-native/verification-tool/src/components/log-popup-view/index.ts
deleted file mode 100644
index 1e3577c4a54..00000000000
--- a/react-native/verification-tool/src/components/log-popup-view/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './log-popup-view';
diff --git a/react-native/verification-tool/src/components/log-popup-view/log-popup-view.tsx b/react-native/verification-tool/src/components/log-popup-view/log-popup-view.tsx
index 57cc9365e0e..76677792172 100644
--- a/react-native/verification-tool/src/components/log-popup-view/log-popup-view.tsx
+++ b/react-native/verification-tool/src/components/log-popup-view/log-popup-view.tsx
@@ -1,55 +1,55 @@
import * as React from 'react';
import {
- View,
- Text,
- Modal,
- SafeAreaView,
- ModalProps,
- ScrollView,
+ View,
+ Text,
+ Modal,
+ SafeAreaView,
+ ModalProps,
+ ScrollView,
} from 'react-native';
import styles from './styles';
import Button from '../ui/button';
interface Props extends Pick {
- log: string;
- onClose?: () => void;
- onClear?: () => void;
+ log: string;
+ onClose?: () => void;
+ onClear?: () => void;
}
export const LogPopupView: React.FC = ({
- visible,
- log,
- onClose,
- onClear,
+ visible,
+ log,
+ onClose,
+ onClear,
}) => {
- return (
-
-
-
-
- log
-
-
-
- {log}
-
-
-
-
-
-
-
-
-
- );
+ return (
+
+
+
+
+ log
+
+
+
+ {log}
+
+
+
+
+
+
+
+
+
+ );
};
LogPopupView.displayName = 'LogPopupView';
diff --git a/react-native/verification-tool/src/components/log-popup-view/styles.tsx b/react-native/verification-tool/src/components/log-popup-view/styles.tsx
index 60f115e4e0c..8a982aa6d35 100644
--- a/react-native/verification-tool/src/components/log-popup-view/styles.tsx
+++ b/react-native/verification-tool/src/components/log-popup-view/styles.tsx
@@ -1,51 +1,51 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: '#000000A0',
- alignItems: 'center',
- justifyContent: 'center',
- },
- modalContainerLayout: {
- backgroundColor: 'white',
- width: '90%',
- height: '90%',
- alignItems: 'center',
- },
- listTitle: {
- color: 'black',
- fontSize: 18,
- textAlign: 'center',
- },
- listTitleBack: {
- alignItems: 'center',
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageLayout: {
- width: '100%',
- flex: 1,
- alignItems: 'center',
- },
- messageArea: {
- width: '90%',
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
- bottomViewContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- marginVertical: 10,
- },
- CloseButton: {
- width: 150,
- marginHorizontal: 10,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: '#000000A0',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ modalContainerLayout: {
+ backgroundColor: 'white',
+ width: '90%',
+ height: '90%',
+ alignItems: 'center',
+ },
+ listTitle: {
+ color: 'black',
+ fontSize: 18,
+ textAlign: 'center',
+ },
+ listTitleBack: {
+ alignItems: 'center',
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageLayout: {
+ width: '100%',
+ flex: 1,
+ alignItems: 'center',
+ },
+ messageArea: {
+ width: '90%',
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
+ bottomViewContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ marginVertical: 10,
+ },
+ CloseButton: {
+ width: 150,
+ marginHorizontal: 10,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/options/auto-bracket/auto-bracket-edit.tsx b/react-native/verification-tool/src/components/options/auto-bracket/auto-bracket-edit.tsx
index 32e5fbe543c..eb1cbf65333 100644
--- a/react-native/verification-tool/src/components/options/auto-bracket/auto-bracket-edit.tsx
+++ b/react-native/verification-tool/src/components/options/auto-bracket/auto-bracket-edit.tsx
@@ -2,163 +2,163 @@ import * as React from 'react';
import type { OptionEditProps } from '..';
import { View, Text } from 'react-native';
import { InputNumber } from '../../ui/input-number';
-import styles from './styles';
+import styles from './styles.tsx';
import Button from '../../ui/button';
import {
- ApertureEnum,
- BracketSetting,
- ExposureCompensationEnum,
- ExposureProgramEnum,
- IsoEnum,
- ShutterSpeedEnum,
- WhiteBalanceEnum,
+ ApertureEnum,
+ BracketSetting,
+ ExposureCompensationEnum,
+ ExposureProgramEnum,
+ IsoEnum,
+ ShutterSpeedEnum,
+ WhiteBalanceEnum,
} from '../../../modules/theta-client';
import { EnumEdit } from '../enum-edit';
const EditItem = ({
- item,
- onChange,
+ item,
+ onChange,
}: {
- item: BracketSetting;
- onChange: (newItem: BracketSetting) => void;
+ item: BracketSetting;
+ onChange: (newItem: BracketSetting) => void;
}) => {
- return (
-
- {
- onChange({ ...item, aperture });
- }}
- optionEnum={ApertureEnum}
- />
- {
- onChange({ ...item, colorTemperature: value });
- }}
- value={item.colorTemperature}
- />
- {
- onChange({ ...item, exposureCompensation });
- }}
- optionEnum={ExposureCompensationEnum}
- />
- {
- onChange({ ...item, exposureProgram });
- }}
- optionEnum={ExposureProgramEnum}
- />
- {
- onChange({ ...item, iso });
- }}
- optionEnum={IsoEnum}
- />
- {
- onChange({ ...item, shutterSpeed });
- }}
- optionEnum={ShutterSpeedEnum}
- />
- {
- onChange({ ...item, whiteBalance });
- }}
- optionEnum={WhiteBalanceEnum}
- />
-
- );
+ return (
+
+ {
+ onChange({ ...item, aperture });
+ }}
+ optionEnum={ApertureEnum}
+ />
+ {
+ onChange({ ...item, colorTemperature: value });
+ }}
+ value={item.colorTemperature}
+ />
+ {
+ onChange({ ...item, exposureCompensation });
+ }}
+ optionEnum={ExposureCompensationEnum}
+ />
+ {
+ onChange({ ...item, exposureProgram });
+ }}
+ optionEnum={ExposureProgramEnum}
+ />
+ {
+ onChange({ ...item, iso });
+ }}
+ optionEnum={IsoEnum}
+ />
+ {
+ onChange({ ...item, shutterSpeed });
+ }}
+ optionEnum={ShutterSpeedEnum}
+ />
+ {
+ onChange({ ...item, whiteBalance });
+ }}
+ optionEnum={WhiteBalanceEnum}
+ />
+
+ );
};
interface BracketSettingMenuProps {
- item: BracketSetting;
- index: number;
- onChange: (index: number, setting: BracketSetting) => void;
- onRemove: (index: number) => void;
+ item: BracketSetting;
+ index: number;
+ onChange: (index: number, setting: BracketSetting) => void;
+ onRemove: (index: number) => void;
}
const BracketSettingMenu: React.FC = ({
- item,
- index,
- onChange,
- onRemove,
+ item,
+ index,
+ onChange,
+ onRemove,
}) => {
- return (
-
-
- {'Bracket parameters: ' + (index + 1)}
-
-
- onRemove(index)}
- />
-
- onChange(index, setting)} />
-
- );
+ return (
+
+
+ {'Bracket parameters: ' + (index + 1)}
+
+
+ onRemove(index)}
+ />
+
+ onChange(index, setting)} />
+
+ );
};
export const AutoBracketEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- const onChangeSetting = (index: number, autoBracket: BracketSetting) => {
- const autoBracketList = (options?.autoBracket ?? []).map((item, idx) =>
- idx === index ? autoBracket : item
- );
- onChange({ ...options, autoBracket: autoBracketList });
- };
- const onRemoveSetting = (index: number) => {
- const autoBracketList = [...(options?.autoBracket ?? [])].filter(
- (_, idx) => idx !== index
- );
- const autoBracket =
- autoBracketList.length > 0 ? autoBracketList : undefined;
- onChange({
- ...options,
- autoBracket,
- });
- };
- const onAddSetting = () => {
- const newList = [...(options?.autoBracket ?? []), {}];
- onChange({ ...options, autoBracket: newList });
- };
+ const onChangeSetting = (index: number, autoBracket: BracketSetting) => {
+ const autoBracketList = (options?.autoBracket ?? []).map((item, idx) =>
+ idx === index ? autoBracket : item
+ );
+ onChange({ ...options, autoBracket: autoBracketList });
+ };
+ const onRemoveSetting = (index: number) => {
+ const autoBracketList = [...(options?.autoBracket ?? [])].filter(
+ (_, idx) => idx !== index
+ );
+ const autoBracket =
+ autoBracketList.length > 0 ? autoBracketList : undefined;
+ onChange({
+ ...options,
+ autoBracket,
+ });
+ };
+ const onAddSetting = () => {
+ const newList = [...(options?.autoBracket ?? []), {}];
+ onChange({ ...options, autoBracket: newList });
+ };
- return (
-
- {options?.autoBracket?.map((item, index) => (
-
- )) ?? null}
-
-
-
-
- );
+ return (
+
+ {options?.autoBracket?.map((item, index) => (
+
+ )) ?? null}
+
+
+
+
+ );
};
AutoBracketEdit.displayName = 'AutoBracketEdit';
diff --git a/react-native/verification-tool/src/components/options/auto-bracket/styles.tsx b/react-native/verification-tool/src/components/options/auto-bracket/styles.tsx
index 9dfab540100..a8df3dbaa1f 100644
--- a/react-native/verification-tool/src/components/options/auto-bracket/styles.tsx
+++ b/react-native/verification-tool/src/components/options/auto-bracket/styles.tsx
@@ -1,31 +1,31 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- scrollViewLayout: {
- height: 300,
- },
- editorContainerLayout: {
- flexDirection: 'column',
- justifyContent: 'center',
- },
- addButtonContainerLayout: {
- flexDirection: 'column',
- alignItems: 'center',
- },
- removeButtonContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- button: {
- margin: 5,
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- fontWeight: 'bold',
- },
+ scrollViewLayout: {
+ height: 300,
+ },
+ editorContainerLayout: {
+ flexDirection: 'column',
+ justifyContent: 'center',
+ },
+ addButtonContainerLayout: {
+ flexDirection: 'column',
+ alignItems: 'center',
+ },
+ removeButtonContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ button: {
+ margin: 5,
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ fontWeight: 'bold',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/options/burst-option/burst-option-edit.tsx b/react-native/verification-tool/src/components/options/burst-option/burst-option-edit.tsx
index 098a285795d..a08e3cbe817 100644
--- a/react-native/verification-tool/src/components/options/burst-option/burst-option-edit.tsx
+++ b/react-native/verification-tool/src/components/options/burst-option/burst-option-edit.tsx
@@ -3,112 +3,112 @@ import type { OptionEditProps } from '../../options';
import { View } from 'react-native';
import { EnumEdit } from '../../options/enum-edit';
import {
- BurstBracketStepEnum,
- BurstCaptureNumEnum,
- BurstCompensationEnum,
- BurstEnableIsoControlEnum,
- BurstMaxExposureTimeEnum,
- BurstOrderEnum,
+ BurstBracketStepEnum,
+ BurstCaptureNumEnum,
+ BurstCompensationEnum,
+ BurstEnableIsoControlEnum,
+ BurstMaxExposureTimeEnum,
+ BurstOrderEnum,
} from '../../../modules/theta-client';
export const BurstOptionsEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- return (
-
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstCaptureNum,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstCaptureNumEnum}
- />
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstBracketStep,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstBracketStepEnum}
- />
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstCompensation,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstCompensationEnum}
- />
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstMaxExposureTime,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstMaxExposureTimeEnum}
- />
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstEnableIsoControl,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstEnableIsoControlEnum}
- />
- {
- const newOptions = {
- ...options,
- burstOption: {
- ...options?.burstOption,
- burstOrder,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={BurstOrderEnum}
- />
-
- );
+ return (
+
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstCaptureNum,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstCaptureNumEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstBracketStep,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstBracketStepEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstCompensation,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstCompensationEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstMaxExposureTime,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstMaxExposureTimeEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstEnableIsoControl,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstEnableIsoControlEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ burstOption: {
+ ...options?.burstOption,
+ burstOrder,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={BurstOrderEnum}
+ />
+
+ );
};
BurstOptionsEdit.displayName = 'BurstOptionsEdit';
diff --git a/react-native/verification-tool/src/components/options/camera-lock-config/camera-lock-config-edit.tsx b/react-native/verification-tool/src/components/options/camera-lock-config/camera-lock-config-edit.tsx
index 8e8c1ebf40e..c1762598233 100644
--- a/react-native/verification-tool/src/components/options/camera-lock-config/camera-lock-config-edit.tsx
+++ b/react-native/verification-tool/src/components/options/camera-lock-config/camera-lock-config-edit.tsx
@@ -4,98 +4,98 @@ import { View } from 'react-native';
import { TitledSwitch } from '../../ui/titled-switch';
export const CameraLockConfigEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- const cameraLockConfig = options?.cameraLockConfig;
- return (
-
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isPowerKeyLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isShutterKeyLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isModeKeyLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isWlanKeyLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isFnKeyLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- cameraLockConfig: {
- ...cameraLockConfig,
- isPanelLocked: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
-
- );
+ const cameraLockConfig = options?.cameraLockConfig;
+ return (
+
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isPowerKeyLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isShutterKeyLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isModeKeyLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isWlanKeyLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isFnKeyLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ cameraLockConfig: {
+ ...cameraLockConfig,
+ isPanelLocked: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+
+ );
};
CameraLockConfigEdit.displayName = 'CameraLockConfigEdit';
diff --git a/react-native/verification-tool/src/components/options/enum-edit/enum-edit.tsx b/react-native/verification-tool/src/components/options/enum-edit/enum-edit.tsx
index d686ad18e07..db28f1530b7 100644
--- a/react-native/verification-tool/src/components/options/enum-edit/enum-edit.tsx
+++ b/react-native/verification-tool/src/components/options/enum-edit/enum-edit.tsx
@@ -1,40 +1,100 @@
import * as React from 'react';
-import { ItemSelectorView } from '../../ui/item-list';
+import {
+ StyleProp,
+ TouchableOpacity,
+ View,
+ ViewStyle,
+ type ButtonProps,
+ Text,
+ StyleSheet,
+} from 'react-native';
+import { type Item, ItemListPopupView } from '../../ui/item-list';
-interface Props {
- title: string;
- option: T;
- onChange: (option: T) => void;
- optionEnum: Record;
+interface Props extends Pick {
+ style?: StyleProp;
+ option: T;
+ onChange: (option: T) => void;
+ optionEnum: Record;
}
export const EnumEdit = ({
- title,
- option,
- onChange,
- optionEnum,
+ title,
+ option,
+ onChange,
+ optionEnum,
+ disabled = false,
+ style,
}: Props) => {
- const enumList = [
- { name: '[undefined]', value: undefined },
- ...Object.entries(optionEnum).map((item) => {
- return { name: item[0], value: item[1] };
- }),
- ];
-
- return (
- {
- onChange(item.value);
- }}
- selectedItem={enumList.find((item) => {
- return item.value === option;
- })}
- />
- );
+ const [isShowList, setShowList] = React.useState(false);
+
+ const enumList: Item[] = [
+ { name: '[undefined]', value: undefined },
+ ...Object.entries(optionEnum).map((item) => {
+ return { name: item[0], value: item[1] } as Item;
+ }),
+ ];
+
+ const selectedItem = enumList.find((item) => item.value === option);
+
+ return (
+
+ {
+ setShowList(false);
+ onChange(item.value as T);
+ }}
+ />
+
+
+ {title}
+
+ setShowList(true)}
+ disabled={disabled}
+ >
+
+ {selectedItem?.name || 'select value'}
+
+
+
+
+ );
};
+const styles = StyleSheet.create({
+ titleText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ },
+ containerLayout: {
+ flexDirection: 'row',
+ padding: 5,
+ alignItems: 'center',
+ justifyContent: 'flex-start',
+ },
+ titleBack: {
+ alignItems: 'center',
+ alignSelf: 'center',
+ },
+ itemBack: {
+ alignItems: 'center',
+ padding: 5,
+ alignSelf: 'center',
+ borderColor: 'gray',
+ borderWidth: 1,
+ },
+});
+
EnumEdit.displayName = 'EnumEdit';
export default EnumEdit;
diff --git a/react-native/verification-tool/src/components/options/ethernet-config/ethernet-config-edit.tsx b/react-native/verification-tool/src/components/options/ethernet-config/ethernet-config-edit.tsx
index b9e322f591e..0921b8fe58f 100644
--- a/react-native/verification-tool/src/components/options/ethernet-config/ethernet-config-edit.tsx
+++ b/react-native/verification-tool/src/components/options/ethernet-config/ethernet-config-edit.tsx
@@ -4,225 +4,227 @@ import { View, Text } from 'react-native';
import { InputString } from '../../ui/input-string';
import { InputNumber } from '../../ui/input-number';
import { TitledSwitch } from '../../ui/titled-switch';
-import styles from './styles';
+import styles from './styles.tsx';
export const EthernetConfigEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- const ethernetConfig = options?.ethernetConfig ?? { usingDhcp: true };
+ const ethernetConfig = options?.ethernetConfig ?? { usingDhcp: true };
- return (
-
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- usingDhcp: newValue,
- ...(newValue
- ? {
- ipAddress: undefined,
- subnetMask: undefined,
- defaultGateway: undefined,
- dns1: undefined,
- dns2: undefined,
- }
- : {}),
- },
- };
- onChange(newOptions);
- }}
- />
- {!ethernetConfig.usingDhcp && (
+ return (
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- ipAddress: newValue,
- },
- };
- onChange(newOptions);
- }}
- value={ethernetConfig.ipAddress}
- />
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- subnetMask: newValue,
- },
- };
- onChange(newOptions);
- }}
- value={ethernetConfig.subnetMask}
- />
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- defaultGateway: newValue,
- },
- };
- onChange(newOptions);
- }}
- value={ethernetConfig.defaultGateway}
- />
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- dns1: newValue,
- },
- };
- onChange(newOptions);
- }}
- value={ethernetConfig.dns1}
- />
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- dns2: newValue,
- },
- };
- onChange(newOptions);
- }}
- value={ethernetConfig.dns2}
- />
-
- )}
-
- proxy
-
- {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- proxy: {
- ...(newValue ? ethernetConfig.proxy ?? { use: true } : {}),
- use: newValue,
- },
- },
- };
- onChange(newOptions);
- }}
- />
- {ethernetConfig.proxy?.use && (
-
- {
- const use = ethernetConfig.proxy?.use;
- if (use !== undefined) {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- proxy: {
- ...ethernetConfig.proxy,
- use: use,
- url: newValue,
- },
- },
- };
- onChange(newOptions);
- }
- }}
- value={ethernetConfig.proxy?.url}
- />
- {
- const use = ethernetConfig.proxy?.use;
- if (use !== undefined) {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- proxy: {
- ...ethernetConfig.proxy,
- use: use,
- port: newValue,
- },
- },
- };
- onChange(newOptions);
- }
- }}
- value={ethernetConfig.proxy?.port}
- />
- {
- const use = ethernetConfig.proxy?.use;
- if (use !== undefined) {
- const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- proxy: {
- ...ethernetConfig.proxy,
- use: use,
- userid: newValue,
- },
- },
- };
- onChange(newOptions);
- }
- }}
- value={ethernetConfig.proxy?.userid}
- />
- {
- const use = ethernetConfig.proxy?.use;
- if (use !== undefined) {
const newOptions = {
- ...options,
- ethernetConfig: {
- ...ethernetConfig,
- proxy: {
- ...ethernetConfig.proxy,
- use: use,
- password: newValue,
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ usingDhcp: newValue,
+ ...(newValue
+ ? {
+ ipAddress: undefined,
+ subnetMask: undefined,
+ defaultGateway: undefined,
+ dns1: undefined,
+ dns2: undefined,
+ }
+ : {}),
},
- },
};
onChange(newOptions);
- }
}}
- value={ethernetConfig.proxy?.password}
- />
+ />
+ {!ethernetConfig.usingDhcp && (
+
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ ipAddress: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ value={ethernetConfig.ipAddress}
+ />
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ subnetMask: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ value={ethernetConfig.subnetMask}
+ />
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ defaultGateway: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ value={ethernetConfig.defaultGateway}
+ />
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ dns1: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ value={ethernetConfig.dns1}
+ />
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ dns2: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ value={ethernetConfig.dns2}
+ />
+
+ )}
+
+ proxy
+
+ {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ proxy: {
+ ...(newValue
+ ? (ethernetConfig.proxy ?? { use: true })
+ : {}),
+ use: newValue,
+ },
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {ethernetConfig.proxy?.use && (
+
+ {
+ const use = ethernetConfig.proxy?.use;
+ if (use !== undefined) {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ proxy: {
+ ...ethernetConfig.proxy,
+ use: use,
+ url: newValue,
+ },
+ },
+ };
+ onChange(newOptions);
+ }
+ }}
+ value={ethernetConfig.proxy?.url}
+ />
+ {
+ const use = ethernetConfig.proxy?.use;
+ if (use !== undefined) {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ proxy: {
+ ...ethernetConfig.proxy,
+ use: use,
+ port: newValue,
+ },
+ },
+ };
+ onChange(newOptions);
+ }
+ }}
+ value={ethernetConfig.proxy?.port}
+ />
+ {
+ const use = ethernetConfig.proxy?.use;
+ if (use !== undefined) {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ proxy: {
+ ...ethernetConfig.proxy,
+ use: use,
+ userid: newValue,
+ },
+ },
+ };
+ onChange(newOptions);
+ }
+ }}
+ value={ethernetConfig.proxy?.userid}
+ />
+ {
+ const use = ethernetConfig.proxy?.use;
+ if (use !== undefined) {
+ const newOptions = {
+ ...options,
+ ethernetConfig: {
+ ...ethernetConfig,
+ proxy: {
+ ...ethernetConfig.proxy,
+ use: use,
+ password: newValue,
+ },
+ },
+ };
+ onChange(newOptions);
+ }
+ }}
+ value={ethernetConfig.proxy?.password}
+ />
+
+ )}
+
- )}
-
-
- );
+ );
};
EthernetConfigEdit.displayName = 'EthernetConfigEdit';
diff --git a/react-native/verification-tool/src/components/options/ethernet-config/styles.tsx b/react-native/verification-tool/src/components/options/ethernet-config/styles.tsx
index 874447f5c55..986d409eb5d 100644
--- a/react-native/verification-tool/src/components/options/ethernet-config/styles.tsx
+++ b/react-native/verification-tool/src/components/options/ethernet-config/styles.tsx
@@ -1,20 +1,20 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- colContainerLayout: {
- justifyContent: 'center',
- flexDirection: 'column',
- },
- rowContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- labelText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- marginLeft: 5,
- },
+ colContainerLayout: {
+ justifyContent: 'center',
+ flexDirection: 'column',
+ },
+ rowContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ labelText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ marginLeft: 5,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/options/gps-info/gps-info-edit.tsx b/react-native/verification-tool/src/components/options/gps-info/gps-info-edit.tsx
index 1a23407a581..15c61869bbc 100644
--- a/react-native/verification-tool/src/components/options/gps-info/gps-info-edit.tsx
+++ b/react-native/verification-tool/src/components/options/gps-info/gps-info-edit.tsx
@@ -8,200 +8,199 @@ import styles from './styles';
import Button from '../../ui/button';
interface Props extends OptionEditProps {
- hideLabel?: boolean;
+ hideLabel?: boolean;
}
export const GpsInfoEdit: React.FC = ({
- onChange,
- options,
- hideLabel = false,
+ onChange,
+ options,
+ hideLabel = false,
}) => {
- const [editGpsInfo, setEditGpsInfo] = React.useState();
- const [useGpsInfo, setUseGpsInfo] = React.useState(false);
+ const [editGpsInfo, setEditGpsInfo] = React.useState();
+ const [useGpsInfo, setUseGpsInfo] = React.useState(false);
- const getDateTimeZone = () => {
- const dt = new Date();
- const y = dt.getFullYear();
- const mm = ('00' + (dt.getMonth() + 1)).slice(-2);
- const dd = ('00' + dt.getDate()).slice(-2);
+ const getDateTimeZone = () => {
+ const dt = new Date();
+ const y = dt.getFullYear();
+ const mm = ('00' + (dt.getMonth() + 1)).slice(-2);
+ const dd = ('00' + dt.getDate()).slice(-2);
- const HH = ('00' + dt.getHours()).slice(-2);
- const MM = ('00' + dt.getMinutes()).slice(-2);
- const SS = ('00' + dt.getSeconds()).slice(-2);
+ const HH = ('00' + dt.getHours()).slice(-2);
+ const MM = ('00' + dt.getMinutes()).slice(-2);
+ const SS = ('00' + dt.getSeconds()).slice(-2);
- const offset = dt.getTimezoneOffset();
- const offsetHH = ('00' + Math.floor(Math.abs(offset) / 60)).slice(-2);
- const offsetMM = ('00' + (Math.abs(offset) % 60)).slice(-2);
- const offsetSign = offset < 0 ? '+' : '-';
+ const offset = dt.getTimezoneOffset();
+ const offsetHH = ('00' + Math.floor(Math.abs(offset) / 60)).slice(-2);
+ const offsetMM = ('00' + (Math.abs(offset) % 60)).slice(-2);
+ const offsetSign = offset < 0 ? '+' : '-';
- const result = `${y}:${mm}:${dd} ${HH}:${MM}:${SS}${offsetSign}${offsetHH}:${offsetMM}`;
- return result;
- };
-
- const defaultInfo = React.useMemo(() => {
- return {
- latitude: 35.485577,
- longitude: 134.24005,
- altitude: 47.1,
- dateTimeZone: getDateTimeZone(),
+ const result = `${y}:${mm}:${dd} ${HH}:${MM}:${SS}${offsetSign}${offsetHH}:${offsetMM}`;
+ return result;
};
- }, []);
- const infoDisable: GpsInfo = {
- latitude: 65535,
- longitude: 65535,
- altitude: 0,
- dateTimeZone: '',
- };
+ const defaultInfo = React.useMemo(() => {
+ return {
+ latitude: 35.485577,
+ longitude: 134.24005,
+ altitude: 47.1,
+ dateTimeZone: getDateTimeZone(),
+ };
+ }, []);
- const isUseGpsInfo = () => {
- return hideLabel || useGpsInfo;
- };
+ const infoDisable: GpsInfo = {
+ latitude: 65535,
+ longitude: 65535,
+ altitude: 0,
+ dateTimeZone: '',
+ };
- React.useEffect(() => {
- const gpsInfo = options?.gpsInfo || { ...defaultInfo };
- setEditGpsInfo(gpsInfo);
- }, [options, defaultInfo]);
+ const isUseGpsInfo = () => {
+ return hideLabel || useGpsInfo;
+ };
- const onChangeUseGpsInfo = (newValue: boolean) => {
- setUseGpsInfo(newValue);
- if (!newValue) {
- // keep values of editGpsInfo
- const newOptions = options && {
- ...options,
- gpsInfo: undefined,
- };
- onChange(newOptions ?? {});
- } else {
- const newGpsInfo =
- editGpsInfo == null
- ? {
- ...defaultInfo,
- }
- : { ...editGpsInfo };
+ React.useEffect(() => {
+ const gpsInfo = options?.gpsInfo || { ...defaultInfo };
+ setEditGpsInfo(gpsInfo);
+ }, [options, defaultInfo]);
- setEditGpsInfo(newGpsInfo);
- const newOptions = {
- ...options,
- gpsInfo: newGpsInfo,
- };
- onChange(newOptions);
- }
- };
+ const onChangeUseGpsInfo = (newValue: boolean) => {
+ setUseGpsInfo(newValue);
+ if (!newValue) {
+ const newOptions = options && {
+ ...options,
+ gpsInfo: undefined,
+ };
+ onChange(newOptions ?? {});
+ } else {
+ const newGpsInfo =
+ editGpsInfo == null
+ ? {
+ ...defaultInfo,
+ }
+ : { ...editGpsInfo };
+
+ setEditGpsInfo(newGpsInfo);
+ const newOptions = {
+ ...options,
+ gpsInfo: newGpsInfo,
+ };
+ onChange(newOptions);
+ }
+ };
- return (
-
-
- {!hideLabel && (
-
- gpsInfo
-
-
- )}
- {isUseGpsInfo() && (
-
+ return (
+
- {
- const newGpsInfo = {
- ...infoDisable,
- };
- setEditGpsInfo(newGpsInfo);
- const newOptions = {
- ...options,
- gpsInfo: newGpsInfo,
- };
- onChange(newOptions);
- }}
- />
- {
- const newGpsInfo = {
- ...defaultInfo,
- };
- setEditGpsInfo(newGpsInfo);
- const newOptions = {
- ...options,
- gpsInfo: newGpsInfo,
- };
- onChange(newOptions);
- }}
- />
+ {!hideLabel && (
+
+ gpsInfo
+
+
+ )}
+ {isUseGpsInfo() && (
+
+
+ {
+ const newGpsInfo = {
+ ...infoDisable,
+ };
+ setEditGpsInfo(newGpsInfo);
+ const newOptions = {
+ ...options,
+ gpsInfo: newGpsInfo,
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newGpsInfo = {
+ ...defaultInfo,
+ };
+ setEditGpsInfo(newGpsInfo);
+ const newOptions = {
+ ...options,
+ gpsInfo: newGpsInfo,
+ };
+ onChange(newOptions);
+ }}
+ />
+
+ {
+ if (editGpsInfo != null) {
+ const targetValue = newValue ?? 0;
+ const newInfo: GpsInfo = {
+ ...editGpsInfo,
+ latitude: targetValue,
+ };
+ setEditGpsInfo(newInfo);
+ onChange({ ...options, gpsInfo: newInfo });
+ }
+ }}
+ value={options?.gpsInfo?.latitude}
+ />
+ {
+ if (editGpsInfo != null) {
+ const targetValue = newValue ?? 0;
+ const newInfo: GpsInfo = {
+ ...editGpsInfo,
+ longitude: targetValue,
+ };
+ setEditGpsInfo(newInfo);
+ onChange({ ...options, gpsInfo: newInfo });
+ }
+ }}
+ value={options?.gpsInfo?.longitude}
+ />
+ {
+ if (editGpsInfo != null) {
+ const targetValue = newValue ?? 0;
+ const newInfo: GpsInfo = {
+ ...editGpsInfo,
+ altitude: targetValue,
+ };
+ setEditGpsInfo(newInfo);
+ onChange({ ...options, gpsInfo: newInfo });
+ }
+ }}
+ value={options?.gpsInfo?.altitude}
+ />
+ {
+ if (editGpsInfo != null) {
+ const newInfo: GpsInfo = {
+ ...editGpsInfo,
+ dateTimeZone: newValue,
+ };
+ setEditGpsInfo(newInfo);
+ onChange({ ...options, gpsInfo: newInfo });
+ }
+ }}
+ value={options?.gpsInfo?.dateTimeZone}
+ />
+
+ )}
- {
- if (editGpsInfo != null) {
- const targetValue = newValue ?? 0;
- const newInfo: GpsInfo = {
- ...editGpsInfo,
- latitude: targetValue,
- };
- setEditGpsInfo(newInfo);
- onChange({ ...options, gpsInfo: newInfo });
- }
- }}
- value={options?.gpsInfo?.latitude}
- />
- {
- if (editGpsInfo != null) {
- const targetValue = newValue ?? 0;
- const newInfo: GpsInfo = {
- ...editGpsInfo,
- longitude: targetValue,
- };
- setEditGpsInfo(newInfo);
- onChange({ ...options, gpsInfo: newInfo });
- }
- }}
- value={options?.gpsInfo?.longitude}
- />
- {
- if (editGpsInfo != null) {
- const targetValue = newValue ?? 0;
- const newInfo: GpsInfo = {
- ...editGpsInfo,
- altitude: targetValue,
- };
- setEditGpsInfo(newInfo);
- onChange({ ...options, gpsInfo: newInfo });
- }
- }}
- value={options?.gpsInfo?.altitude}
- />
- {
- if (editGpsInfo != null) {
- const newInfo: GpsInfo = {
- ...editGpsInfo,
- dateTimeZone: newValue,
- };
- setEditGpsInfo(newInfo);
- onChange({ ...options, gpsInfo: newInfo });
- }
- }}
- value={options?.gpsInfo?.dateTimeZone}
- />
-
- )}
-
-
- );
+
+ );
};
GpsInfoEdit.displayName = 'GpsInfoEdit';
diff --git a/react-native/verification-tool/src/components/options/gps-info/styles.tsx b/react-native/verification-tool/src/components/options/gps-info/styles.tsx
index ca6fe8e0247..d36d5a12205 100644
--- a/react-native/verification-tool/src/components/options/gps-info/styles.tsx
+++ b/react-native/verification-tool/src/components/options/gps-info/styles.tsx
@@ -1,23 +1,23 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- colContainerLayout: {
- justifyContent: 'center',
- flexDirection: 'column',
- },
- rowContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- labelText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- marginLeft: 5,
- },
- button: {
- marginHorizontal: 5,
- },
+ colContainerLayout: {
+ justifyContent: 'center',
+ flexDirection: 'column',
+ },
+ rowContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ labelText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ marginLeft: 5,
+ },
+ button: {
+ marginHorizontal: 5,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/options/index.ts b/react-native/verification-tool/src/components/options/index.ts
index 5d92efcaba8..88247b4438c 100644
--- a/react-native/verification-tool/src/components/options/index.ts
+++ b/react-native/verification-tool/src/components/options/index.ts
@@ -1,15 +1,17 @@
import type { Options } from '../../modules/theta-client';
export interface OptionEditProps {
- onChange: (options: Options) => void;
- options?: Options;
+ onChange: (options: Options) => void;
+ options?: Options;
}
+
export * from './auto-bracket';
-export * from './enum-edit';
export * from './camera-lock-config';
+export * from './enum-edit';
export * from './ethernet-config';
export * from './gps-info';
export * from './mobile-network-setting';
+export * from './number-edit';
export * from './time-shift';
export * from './top-bottom-correction-rotation';
export * from './wlan-frequency-cl-mode';
diff --git a/react-native/verification-tool/src/components/options/mobile-network-setting/mobile-network-setting-edit.tsx b/react-native/verification-tool/src/components/options/mobile-network-setting/mobile-network-setting-edit.tsx
index 9ee7dbff8df..e0c7e4c094a 100644
--- a/react-native/verification-tool/src/components/options/mobile-network-setting/mobile-network-setting-edit.tsx
+++ b/react-native/verification-tool/src/components/options/mobile-network-setting/mobile-network-setting-edit.tsx
@@ -5,43 +5,43 @@ import { EnumEdit } from '../enum-edit';
import { PlanEnum, RoamingEnum } from '../../../modules/theta-client';
export const MobileNetworkSettingEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- return (
-
- {
- const newOptions = {
- ...options,
- mobileNetworkSetting: {
- ...options?.mobileNetworkSetting,
- roaming,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={RoamingEnum}
- />
- {
- const newOptions = {
- ...options,
- mobileNetworkSetting: {
- ...options?.mobileNetworkSetting,
- plan,
- },
- };
- onChange(newOptions);
- }}
- optionEnum={PlanEnum}
- />
-
- );
+ return (
+
+ {
+ const newOptions = {
+ ...options,
+ mobileNetworkSetting: {
+ ...options?.mobileNetworkSetting,
+ roaming,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={RoamingEnum}
+ />
+ {
+ const newOptions = {
+ ...options,
+ mobileNetworkSetting: {
+ ...options?.mobileNetworkSetting,
+ plan,
+ },
+ };
+ onChange(newOptions);
+ }}
+ optionEnum={PlanEnum}
+ />
+
+ );
};
MobileNetworkSettingEdit.displayName = 'MobileNetworkSettingEdit';
diff --git a/react-native/verification-tool/src/components/options/number-edit/number-edit.tsx b/react-native/verification-tool/src/components/options/number-edit/number-edit.tsx
index 61f7354a44e..9bea4af0a92 100644
--- a/react-native/verification-tool/src/components/options/number-edit/number-edit.tsx
+++ b/react-native/verification-tool/src/components/options/number-edit/number-edit.tsx
@@ -4,40 +4,38 @@ import { InputNumber } from '../../ui/input-number';
import type { Options } from '../../../modules/theta-client';
interface Props extends OptionEditProps {
- propName: string;
- placeHolder?: string;
+ propName: string;
+ placeHolder?: string;
}
export const NumberEdit: React.FC = ({
- propName,
- onChange,
- options,
- placeHolder,
+ propName,
+ onChange,
+ options,
+ placeHolder,
}) => {
- const getOptionPropNumber = (_options: Options, _propName: string) => {
- if (_options != null) {
- const option = Object.entries(_options).find(
- (element) => element[0] === _propName
- );
- if (option != null) {
- return option[1] as number;
- }
- }
- return undefined;
- };
- return (
- {
- let option = { ...options, [propName]: value };
- onChange(option);
- }}
- />
- );
+ const getOptionPropNumber = (_options: Options, _propName: string) => {
+ if (_options != null) {
+ const option = Object.entries(_options).find(
+ (element) => element[0] === _propName
+ );
+ if (option != null) {
+ return option[1] as number;
+ }
+ }
+ return undefined;
+ };
+ return (
+ {
+ const option = { ...options, [propName]: value } as Options;
+ onChange(option);
+ }}
+ />
+ );
};
NumberEdit.displayName = 'NumberEdit';
diff --git a/react-native/verification-tool/src/components/options/string-edit/index.ts b/react-native/verification-tool/src/components/options/string-edit/index.ts
deleted file mode 100644
index ee7a75d21c7..00000000000
--- a/react-native/verification-tool/src/components/options/string-edit/index.ts
+++ /dev/null
@@ -1 +0,0 @@
-export * from './string-edit';
diff --git a/react-native/verification-tool/src/components/options/string-edit/string-edit.tsx b/react-native/verification-tool/src/components/options/string-edit/string-edit.tsx
deleted file mode 100644
index 684d12d17e9..00000000000
--- a/react-native/verification-tool/src/components/options/string-edit/string-edit.tsx
+++ /dev/null
@@ -1,46 +0,0 @@
-import * as React from 'react';
-import type { OptionEditProps } from '..';
-import { InputString } from '../../ui/input-string';
-import type { Options } from '../../../modules/theta-client';
-
-interface Props extends OptionEditProps {
- propName: string;
- placeHolder?: string;
-}
-
-export const StringEdit: React.FC = ({
- propName,
- onChange,
- options,
- placeHolder,
-}) => {
- const getOptionPropString = (_options: Options, _propName: string) => {
- if (_options != null) {
- const option = Object.entries(_options).find(
- (element) => element[0] === _propName
- );
- if (option != null) {
- return option[1] as string;
- }
- }
- return undefined;
- };
- return (
- {
- let newValue = value.length === 0 ? undefined : value;
- let option = { ...options, [propName]: newValue };
- onChange(option);
- }}
- />
- );
-};
-
-StringEdit.displayName = 'StringEdit';
-
-export default StringEdit;
diff --git a/react-native/verification-tool/src/components/options/time-shift/styles.tsx b/react-native/verification-tool/src/components/options/time-shift/styles.tsx
deleted file mode 100644
index ebd6b017e66..00000000000
--- a/react-native/verification-tool/src/components/options/time-shift/styles.tsx
+++ /dev/null
@@ -1,63 +0,0 @@
-import { StyleSheet } from 'react-native';
-
-const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: 'white',
- },
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 70,
- },
- contentContainer: {
- width: '100%',
- },
- bottomViewContainer: {
- flex: 1,
- alignItems: 'center',
- },
- rowContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- },
- colContainerLayout: {
- flex: 1,
- flexDirection: 'column',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- thumbnail: {
- width: 100,
- height: 50,
- },
- fileItemBase: {
- flexDirection: 'row',
- width: '100%',
- marginTop: 4,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- largeSpacer: {
- flex: 99,
- },
- messageArea: {
- flex: 1,
- width: '90%',
- height: '100%',
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
-});
-
-export default styles;
diff --git a/react-native/verification-tool/src/components/options/time-shift/time-shift-edit.tsx b/react-native/verification-tool/src/components/options/time-shift/time-shift-edit.tsx
index d5fb401af4b..eba4d6d818f 100644
--- a/react-native/verification-tool/src/components/options/time-shift/time-shift-edit.tsx
+++ b/react-native/verification-tool/src/components/options/time-shift/time-shift-edit.tsx
@@ -1,65 +1,65 @@
import * as React from 'react';
import {
- TimeShift,
- TimeShiftIntervalEnum,
+ TimeShift,
+ TimeShiftIntervalEnum,
} from '../../../modules/theta-client';
import { EnumEdit, type OptionEditProps } from '..';
import { View } from 'react-native';
import { TitledSwitch } from '../../ui/titled-switch';
export const TimeShiftEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- const [editTimeShift, setEditTimeSHift] = React.useState({});
+ const [editTimeShift, setEditTimeSHift] = React.useState({});
- React.useEffect(() => {
- const timeShift = options?.timeShift || {};
- if (timeShift.isFrontFirst == null) {
- timeShift.isFrontFirst = true;
- }
- setEditTimeSHift(timeShift);
- }, [options]);
+ React.useEffect(() => {
+ const timeShift = options?.timeShift || {};
+ if (timeShift.isFrontFirst == null) {
+ timeShift.isFrontFirst = true;
+ }
+ setEditTimeSHift(timeShift);
+ }, [options]);
- return (
-
- {
- const timeShift = { ...editTimeShift, isFrontFirst };
- setEditTimeSHift(timeShift);
- onChange({
- timeShift,
- });
- }}
- />
- {
- const timeShift = { ...editTimeShift, firstInterval };
- setEditTimeSHift(timeShift);
- onChange({
- timeShift,
- });
- }}
- optionEnum={TimeShiftIntervalEnum}
- />
- {
- const timeShift = { ...editTimeShift, secondInterval };
- setEditTimeSHift(timeShift);
- onChange({
- timeShift,
- });
- }}
- optionEnum={TimeShiftIntervalEnum}
- />
-
- );
+ return (
+
+ {
+ const timeShift = { ...editTimeShift, isFrontFirst };
+ setEditTimeSHift(timeShift);
+ onChange({
+ timeShift,
+ });
+ }}
+ />
+ {
+ const timeShift = { ...editTimeShift, firstInterval };
+ setEditTimeSHift(timeShift);
+ onChange({
+ timeShift,
+ });
+ }}
+ optionEnum={TimeShiftIntervalEnum}
+ />
+ {
+ const timeShift = { ...editTimeShift, secondInterval };
+ setEditTimeSHift(timeShift);
+ onChange({
+ timeShift,
+ });
+ }}
+ optionEnum={TimeShiftIntervalEnum}
+ />
+
+ );
};
TimeShiftEdit.displayName = 'TimeShiftEdit';
diff --git a/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/styles.tsx b/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/styles.tsx
deleted file mode 100644
index b84e4a468f9..00000000000
--- a/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/styles.tsx
+++ /dev/null
@@ -1,14 +0,0 @@
-import { StyleSheet } from 'react-native';
-
-const styles = StyleSheet.create({
- colContainerLayout: {
- justifyContent: 'center',
- flexDirection: 'column',
- },
- rowContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- },
-});
-
-export default styles;
diff --git a/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/top-bottom-correction-rotation-edit.tsx b/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/top-bottom-correction-rotation-edit.tsx
index d91e9c2f70b..c81891e616b 100644
--- a/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/top-bottom-correction-rotation-edit.tsx
+++ b/react-native/verification-tool/src/components/options/top-bottom-correction-rotation/top-bottom-correction-rotation-edit.tsx
@@ -5,76 +5,76 @@ import type { TopBottomCorrectionRotation } from '../../../modules/theta-client'
import { InputNumber } from '../../ui/input-number';
export const TopBottomCorrectionRotationEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- const [editRotation, setEditRotation] =
- React.useState();
+ const [editRotation, setEditRotation] =
+ React.useState();
- const defaultRotation = React.useMemo(() => {
- return {
- pitch: 0.0,
- roll: 0.0,
- yaw: 0.0,
- };
- }, []);
+ const defaultRotation = React.useMemo(() => {
+ return {
+ pitch: 0.0,
+ roll: 0.0,
+ yaw: 0.0,
+ };
+ }, []);
- React.useEffect(() => {
- const rotation = options?.topBottomCorrectionRotation || {
- ...defaultRotation,
- };
- setEditRotation(rotation);
- }, [options, defaultRotation]);
+ React.useEffect(() => {
+ const rotation = options?.topBottomCorrectionRotation || {
+ ...defaultRotation,
+ };
+ setEditRotation(rotation);
+ }, [options, defaultRotation]);
- return (
-
- {
- if (editRotation != null) {
- const targetValue = newValue ?? 0;
- const newVal: TopBottomCorrectionRotation = {
- ...editRotation,
- pitch: targetValue,
- };
- setEditRotation(newVal);
- onChange({ ...options, topBottomCorrectionRotation: newVal });
- }
- }}
- value={options?.topBottomCorrectionRotation?.pitch}
- />
- {
- if (editRotation != null) {
- const targetValue = newValue ?? 0;
- const newVal: TopBottomCorrectionRotation = {
- ...editRotation,
- roll: targetValue,
- };
- setEditRotation(newVal);
- onChange({ ...options, topBottomCorrectionRotation: newVal });
- }
- }}
- value={options?.topBottomCorrectionRotation?.roll}
- />
- {
- if (editRotation != null) {
- const targetValue = newValue ?? 0;
- const newVal: TopBottomCorrectionRotation = {
- ...editRotation,
- yaw: targetValue,
- };
- setEditRotation(newVal);
- onChange({ ...options, topBottomCorrectionRotation: newVal });
- }
- }}
- value={options?.topBottomCorrectionRotation?.yaw}
- />
-
- );
+ return (
+
+ {
+ if (editRotation != null) {
+ const targetValue = newValue ?? 0;
+ const newVal: TopBottomCorrectionRotation = {
+ ...editRotation,
+ pitch: targetValue,
+ };
+ setEditRotation(newVal);
+ onChange({ ...options, topBottomCorrectionRotation: newVal });
+ }
+ }}
+ value={options?.topBottomCorrectionRotation?.pitch}
+ />
+ {
+ if (editRotation != null) {
+ const targetValue = newValue ?? 0;
+ const newVal: TopBottomCorrectionRotation = {
+ ...editRotation,
+ roll: targetValue,
+ };
+ setEditRotation(newVal);
+ onChange({ ...options, topBottomCorrectionRotation: newVal });
+ }
+ }}
+ value={options?.topBottomCorrectionRotation?.roll}
+ />
+ {
+ if (editRotation != null) {
+ const targetValue = newValue ?? 0;
+ const newVal: TopBottomCorrectionRotation = {
+ ...editRotation,
+ yaw: targetValue,
+ };
+ setEditRotation(newVal);
+ onChange({ ...options, topBottomCorrectionRotation: newVal });
+ }
+ }}
+ value={options?.topBottomCorrectionRotation?.yaw}
+ />
+
+ );
};
TopBottomCorrectionRotationEdit.displayName = 'TopBottomCorrectionRotationEdit';
diff --git a/react-native/verification-tool/src/components/options/wlan-frequency-cl-mode/wlan-frequency-cl-mode-edit.tsx b/react-native/verification-tool/src/components/options/wlan-frequency-cl-mode/wlan-frequency-cl-mode-edit.tsx
index 7a84dc8e26f..1f0522d90bc 100644
--- a/react-native/verification-tool/src/components/options/wlan-frequency-cl-mode/wlan-frequency-cl-mode-edit.tsx
+++ b/react-native/verification-tool/src/components/options/wlan-frequency-cl-mode/wlan-frequency-cl-mode-edit.tsx
@@ -4,58 +4,58 @@ import { View } from 'react-native';
import { TitledSwitch } from '../../ui/titled-switch';
export const WlanFrequencyClModeEdit: React.FC = ({
- onChange,
- options,
+ onChange,
+ options,
}) => {
- return (
-
- {
- const newOptions = {
- ...options,
- wlanFrequencyClMode: {
- enable2_4: newValue,
- enable5_2: options?.wlanFrequencyClMode?.enable5_2 ?? false,
- enable5_8: options?.wlanFrequencyClMode?.enable5_8 ?? false,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- wlanFrequencyClMode: {
- enable2_4: options?.wlanFrequencyClMode?.enable2_4 ?? false,
- enable5_2: newValue,
- enable5_8: options?.wlanFrequencyClMode?.enable5_8 ?? false,
- },
- };
- onChange(newOptions);
- }}
- />
- {
- const newOptions = {
- ...options,
- wlanFrequencyClMode: {
- enable2_4: options?.wlanFrequencyClMode?.enable2_4 ?? false,
- enable5_2: options?.wlanFrequencyClMode?.enable5_2 ?? false,
- enable5_8: newValue,
- },
- };
- onChange(newOptions);
- }}
- />
-
- );
+ return (
+
+ {
+ const newOptions = {
+ ...options,
+ wlanFrequencyClMode: {
+ enable2_4: newValue,
+ enable5_2: options?.wlanFrequencyClMode?.enable5_2 ?? false,
+ enable5_8: options?.wlanFrequencyClMode?.enable5_8 ?? false,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ wlanFrequencyClMode: {
+ enable2_4: options?.wlanFrequencyClMode?.enable2_4 ?? false,
+ enable5_2: newValue,
+ enable5_8: options?.wlanFrequencyClMode?.enable5_8 ?? false,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+ {
+ const newOptions = {
+ ...options,
+ wlanFrequencyClMode: {
+ enable2_4: options?.wlanFrequencyClMode?.enable2_4 ?? false,
+ enable5_2: options?.wlanFrequencyClMode?.enable5_2 ?? false,
+ enable5_8: newValue,
+ },
+ };
+ onChange(newOptions);
+ }}
+ />
+
+ );
};
WlanFrequencyClModeEdit.displayName = 'WlanFrequencyClModeEdit';
diff --git a/react-native/verification-tool/src/components/ui/button/button.tsx b/react-native/verification-tool/src/components/ui/button/button.tsx
index 0f17b4f222a..0f1f67d131f 100644
--- a/react-native/verification-tool/src/components/ui/button/button.tsx
+++ b/react-native/verification-tool/src/components/ui/button/button.tsx
@@ -1,38 +1,38 @@
import * as React from 'react';
import {
- StyleProp,
- TouchableOpacity,
- View,
- ViewStyle,
- type ButtonProps,
- Text,
+ StyleProp,
+ TouchableOpacity,
+ View,
+ ViewStyle,
+ type ButtonProps,
+ Text,
} from 'react-native';
import styles from './styles';
interface Props
- extends Pick {
- style?: StyleProp;
+ extends Pick {
+ style?: StyleProp;
}
export const Button: React.FC = ({
- disabled = false,
- onPress,
- style,
- title,
+ disabled = false,
+ onPress,
+ style,
+ title,
}) => {
- return (
-
-
-
- {title}
-
-
-
- );
+ return (
+
+
+
+ {title}
+
+
+
+ );
};
Button.displayName = 'Button';
diff --git a/react-native/verification-tool/src/components/ui/button/index.ts b/react-native/verification-tool/src/components/ui/button/index.ts
index 0245aa0a1fb..9e24aed7a59 100644
--- a/react-native/verification-tool/src/components/ui/button/index.ts
+++ b/react-native/verification-tool/src/components/ui/button/index.ts
@@ -1 +1,2 @@
export { default } from './button';
+export * from './button';
diff --git a/react-native/verification-tool/src/components/ui/button/styles.tsx b/react-native/verification-tool/src/components/ui/button/styles.tsx
index 17d5296a383..accbb29b518 100644
--- a/react-native/verification-tool/src/components/ui/button/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/button/styles.tsx
@@ -1,24 +1,24 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- button: {
- color: 'white',
- fontSize: 16,
- },
- buttonBack: {
- backgroundColor: '#6200ee',
- borderRadius: 10,
- padding: 10,
- alignItems: 'center',
- justifyContent: 'center',
- },
- buttonBackDisabled: {
- backgroundColor: 'gray',
- borderRadius: 10,
- padding: 10,
- alignItems: 'center',
- justifyContent: 'center',
- },
+ button: {
+ color: 'white',
+ fontSize: 16,
+ },
+ buttonBack: {
+ backgroundColor: '#6200ee',
+ borderRadius: 10,
+ padding: 10,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ buttonBackDisabled: {
+ backgroundColor: 'gray',
+ borderRadius: 10,
+ padding: 10,
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/input-number/input-number.tsx b/react-native/verification-tool/src/components/ui/input-number/input-number.tsx
index 65089ac6776..4e6139c4b40 100644
--- a/react-native/verification-tool/src/components/ui/input-number/input-number.tsx
+++ b/react-native/verification-tool/src/components/ui/input-number/input-number.tsx
@@ -1,71 +1,74 @@
import * as React from 'react';
import {
- StyleProp,
- View,
- ViewStyle,
- Text,
- TextInput,
- ViewProps,
+ StyleProp,
+ View,
+ ViewStyle,
+ Text,
+ TextInput,
+ ViewProps,
} from 'react-native';
import styles from './styles';
interface Props extends Pick {
- title?: string;
- style?: StyleProp;
- value?: number;
- editable?: boolean;
- onChange?: (value?: number) => void;
- placeHolder?: string;
+ title?: string;
+ style?: StyleProp;
+ value?: number;
+ editable?: boolean;
+ onChange?: (value?: number) => void;
+ placeHolder?: string;
}
export const InputNumber: React.FC = ({
- style,
- title,
- value,
- editable,
- placeHolder,
- onChange,
+ style,
+ title,
+ value,
+ editable,
+ placeHolder = 'Input value',
+ onChange,
}) => {
- const [editText, setEditText] = React.useState(value?.toString() ?? '');
+ const [editText, setEditText] = React.useState(value?.toString() ?? '');
- React.useEffect(() => {
- if (value != null) {
- setEditText(String(value));
- }
- }, [value]);
+ React.useEffect(() => {
+ if (value != null) {
+ setEditText(String(value));
+ } else {
+ setEditText('');
+ }
+ }, [value]);
- const onChangeText = (text: string) => {
- setEditText(text);
- if (text.length === 0) {
- onChange?.(undefined);
- return;
- }
- const numValue = Number(text);
- if (isNaN(numValue)) {
- return;
- }
- onChange?.(numValue);
- };
+ const onChangeText = (text: string) => {
+ setEditText(text);
+ if (text.length === 0) {
+ onChange?.(undefined);
+ return;
+ }
+ const numValue = Number(text);
+ if (isNaN(numValue)) {
+ return;
+ }
+ onChange?.(numValue);
+ };
- return (
-
-
-
- {title}
+ return (
+
+
+
+ {title}
+
+
+
+
+
-
-
-
-
-
- );
+ );
};
InputNumber.displayName = 'InputNumber';
diff --git a/react-native/verification-tool/src/components/ui/input-number/styles.tsx b/react-native/verification-tool/src/components/ui/input-number/styles.tsx
index 50250cd30f9..a2272df5a01 100644
--- a/react-native/verification-tool/src/components/ui/input-number/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/input-number/styles.tsx
@@ -1,32 +1,35 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- titleText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- },
- containerLayout: {
- flexDirection: 'row',
- padding: 5,
- alignItems: 'center',
- },
- titleBack: {
- alignItems: 'center',
- alignSelf: 'center',
- },
- itemBack: {
- alignItems: 'center',
- padding: 5,
- alignSelf: 'center',
- borderColor: 'gray',
- borderWidth: 1,
- },
- inputText: {
- minWidth: 70,
- textAlign: 'right',
- color: 'black',
- },
+ titleText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ },
+ containerLayout: {
+ flexDirection: 'row',
+ padding: 5,
+ alignItems: 'center',
+ },
+ titleBack: {
+ alignItems: 'center',
+ alignSelf: 'center',
+ },
+ itemBack: {
+ alignItems: 'center',
+ padding: 5,
+ alignSelf: 'center',
+ borderColor: 'gray',
+ borderWidth: 1,
+ },
+ inputText: {
+ minWidth: 70,
+ textAlign: 'right',
+ color: 'black',
+ fontSize: 16,
+ paddingVertical: 0,
+ paddingHorizontal: 0,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/input-string/input-string.tsx b/react-native/verification-tool/src/components/ui/input-string/input-string.tsx
index 47fe3ff4e46..f4d690c7616 100644
--- a/react-native/verification-tool/src/components/ui/input-string/input-string.tsx
+++ b/react-native/verification-tool/src/components/ui/input-string/input-string.tsx
@@ -1,62 +1,62 @@
import * as React from 'react';
import {
- StyleProp,
- View,
- ViewStyle,
- Text,
- TextInput,
- ViewProps,
+ StyleProp,
+ View,
+ ViewStyle,
+ Text,
+ TextInput,
+ ViewProps,
} from 'react-native';
import styles from './styles';
interface Props extends Pick {
- title?: string;
- style?: StyleProp;
- value?: string;
- editable?: boolean;
- onChange?: (value: string) => void;
- placeHolder?: string;
+ title?: string;
+ style?: StyleProp;
+ value?: string;
+ editable?: boolean;
+ onChange?: (value: string) => void;
+ placeHolder?: string;
}
export const InputString: React.FC = ({
- style,
- title,
- value,
- editable,
- placeHolder,
- onChange,
+ style,
+ title,
+ value,
+ editable,
+ placeHolder,
+ onChange,
}) => {
- const [editText, setEditText] = React.useState(value ?? '');
+ const [editText, setEditText] = React.useState(value ?? '');
- React.useEffect(() => {
- if (value != null) {
- setEditText(value);
- }
- }, [value]);
+ React.useEffect(() => {
+ if (value != null) {
+ setEditText(value);
+ }
+ }, [value]);
- const onChangeText = (text: string) => {
- setEditText(text);
- onChange?.(text);
- };
+ const onChangeText = (text: string) => {
+ setEditText(text);
+ onChange?.(text);
+ };
- return (
-
-
-
- {title}
+ return (
+
+
+
+ {title}
+
+
+
+
+
-
-
-
-
-
- );
+ );
};
InputString.displayName = 'InputString';
diff --git a/react-native/verification-tool/src/components/ui/input-string/styles.tsx b/react-native/verification-tool/src/components/ui/input-string/styles.tsx
index e912e14fff2..86fe6ce95b2 100644
--- a/react-native/verification-tool/src/components/ui/input-string/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/input-string/styles.tsx
@@ -1,31 +1,31 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- titleText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- },
- containerLayout: {
- flexDirection: 'row',
- padding: 5,
- alignItems: 'center',
- },
- titleBack: {
- alignItems: 'center',
- alignSelf: 'center',
- },
- itemBack: {
- alignItems: 'center',
- padding: 5,
- alignSelf: 'center',
- borderColor: 'gray',
- borderWidth: 1,
- },
- inputText: {
- minWidth: 100,
- color: 'black',
- },
+ titleText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ },
+ containerLayout: {
+ flexDirection: 'row',
+ padding: 5,
+ alignItems: 'center',
+ },
+ titleBack: {
+ alignItems: 'center',
+ alignSelf: 'center',
+ },
+ itemBack: {
+ alignItems: 'center',
+ padding: 5,
+ alignSelf: 'center',
+ borderColor: 'gray',
+ borderWidth: 1,
+ },
+ inputText: {
+ minWidth: 100,
+ color: 'black',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/item-list/index.ts b/react-native/verification-tool/src/components/ui/item-list/index.ts
index e20a33fae2c..a8c28259977 100644
--- a/react-native/verification-tool/src/components/ui/item-list/index.ts
+++ b/react-native/verification-tool/src/components/ui/item-list/index.ts
@@ -1,6 +1,7 @@
export interface Item {
- name: string;
- value: any;
+ name: string;
+ value: any;
}
-export * from './item-selector-view';
export * from './item-list-view';
+export * from './item-list-popup-view';
+export * from './item-selector-view';
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/index.ts b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/index.ts
index a15ae6cb64f..47fe04ba04b 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/index.ts
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/index.ts
@@ -1 +1,2 @@
+export { default } from './item-list-popup-view';
export * from './item-list-popup-view';
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/item-list-popup-view.tsx b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/item-list-popup-view.tsx
index 168ecf26260..57f4824276e 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/item-list-popup-view.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/item-list-popup-view.tsx
@@ -1,43 +1,49 @@
import * as React from 'react';
-import { View, Text, Modal, SafeAreaView, ModalProps } from 'react-native';
+import {
+ View,
+ Text,
+ Modal,
+ SafeAreaView,
+ ModalProps,
+} from 'react-native';
import styles from './styles';
-import ItemListView from '../item-list-view/item-list-view';
+import ItemListView from '../item-list-view';
import type { Item } from '..';
interface Props extends Pick {
- title: string;
- itemList: Item[];
- selectedItem?: Item;
- onSelected?: (item: Item) => void;
+ title: string;
+ itemList: Item[];
+ selectedItem?: Item;
+ onSelected?: (item: Item) => void;
}
export const ItemListPopupView: React.FC = ({
- visible,
- title,
- itemList,
- selectedItem,
- onSelected,
+ visible,
+ title,
+ itemList,
+ selectedItem,
+ onSelected,
}) => {
- return (
-
-
-
-
- {title}
-
- {
- onSelected?.(item);
- }}
- />
-
-
-
- );
+ return (
+
+
+
+
+ {title}
+
+ {
+ onSelected?.(item);
+ }}
+ />
+
+
+
+ );
};
-ItemListPopupView.displayName = 'ItemSelectorView';
+ItemListPopupView.displayName = 'ItemListPopupView';
export default ItemListPopupView;
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/styles.tsx b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/styles.tsx
index edbf8a96a31..7e0721e7c0f 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-popup-view/styles.tsx
@@ -1,34 +1,25 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: '#000000A0',
- alignItems: 'center',
- justifyContent: 'center',
- },
- modalContainerLayout: {
- backgroundColor: 'white',
- width: '80%',
- height: '80%',
- },
- // titleText: {
- // color: 'black',
- // fontSize: 16,
- // paddingRight: 10,
- // },
- // itemText: {
- // color: 'black',
- // fontSize: 16,
- // },
- listTitle: {
- color: 'black',
- fontSize: 18,
- textAlign: 'center',
- },
- listTitleBack: {
- alignItems: 'center',
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: '#000000A0',
+ alignItems: 'center',
+ justifyContent: 'center',
+ },
+ modalContainerLayout: {
+ backgroundColor: 'white',
+ width: '80%',
+ height: '80%',
+ },
+ listTitle: {
+ color: 'black',
+ fontSize: 18,
+ textAlign: 'center',
+ },
+ listTitleBack: {
+ alignItems: 'center',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-view/index.ts b/react-native/verification-tool/src/components/ui/item-list/item-list-view/index.ts
index 3c36735b173..4cdcd317d07 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-view/index.ts
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-view/index.ts
@@ -1 +1,2 @@
+export { default } from './item-list-view';
export * from './item-list-view';
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-view/item-list-view.tsx b/react-native/verification-tool/src/components/ui/item-list/item-list-view/item-list-view.tsx
index c4e8ccabd92..e620fdf8ac2 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-view/item-list-view.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-view/item-list-view.tsx
@@ -1,53 +1,53 @@
import React from 'react';
import {
- type ViewProps,
- type ViewStyle,
- StyleProp,
- TouchableOpacity,
- Text,
- View,
- ScrollView,
+ type ViewProps,
+ type ViewStyle,
+ StyleProp,
+ TouchableOpacity,
+ Text,
+ View,
+ ScrollView,
} from 'react-native';
import styles from './styles';
import type { Item } from '..';
interface Props extends Pick {
- style?: StyleProp;
- itemList: Item[];
- selectedItem?: Item;
- onSelected?: (item: Item) => void;
+ style?: StyleProp;
+ itemList: Item[];
+ selectedItem?: Item;
+ onSelected?: (item: Item) => void;
}
export const ItemListView: React.FC = ({
- itemList,
- onSelected,
- selectedItem,
+ itemList,
+ onSelected,
+ selectedItem,
}) => {
- const onPressItem = (item: Item) => {
- onSelected?.(item);
- };
+ const onPressItem = (item: Item) => {
+ onSelected?.(item);
+ };
- const items = itemList.map((item) => (
- onPressItem(item)}
- >
-
- {item.name}
-
-
- ));
+ const items = itemList.map((item) => (
+ onPressItem(item)}
+ >
+
+ {item.name}
+
+
+ ));
- return (
-
- {items}
-
- );
+ return (
+
+ {items}
+
+ );
};
export default ItemListView;
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-list-view/styles.tsx b/react-native/verification-tool/src/components/ui/item-list/item-list-view/styles.tsx
index e947b9261bd..91e98c353f2 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-list-view/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-list-view/styles.tsx
@@ -1,25 +1,25 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- itemText: {
- color: 'black',
- fontSize: 18,
- paddingHorizontal: 10,
- paddingVertical: 1,
- },
- container: {
- flex: 1,
- },
- listContentContainer: {
- flex: 1,
- },
- listItemBase: {
- width: '100%',
- },
- selectedListItemBase: {
- width: '100%',
- backgroundColor: 'lightgray',
- },
+ itemText: {
+ color: 'black',
+ fontSize: 18,
+ paddingHorizontal: 10,
+ paddingVertical: 1,
+ },
+ container: {
+ flex: 1,
+ },
+ listContentContainer: {
+ flex: 1,
+ },
+ listItemBase: {
+ width: '100%',
+ },
+ selectedListItemBase: {
+ width: '100%',
+ backgroundColor: 'lightgray',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/index.ts b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/index.ts
index be6f78b3253..a4597c38ac9 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/index.ts
+++ b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/index.ts
@@ -1 +1,2 @@
+export { default } from './item-selector-view';
export * from './item-selector-view';
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/item-selector-view.tsx b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/item-selector-view.tsx
index 33c50f28b01..5907f7ca0ce 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/item-selector-view.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/item-selector-view.tsx
@@ -1,66 +1,66 @@
import * as React from 'react';
import {
- StyleProp,
- TouchableOpacity,
- View,
- ViewStyle,
- type ButtonProps,
- Text,
+ StyleProp,
+ TouchableOpacity,
+ View,
+ ViewStyle,
+ type ButtonProps,
+ Text,
} from 'react-native';
import styles from './styles';
import type { Item } from '..';
import { ItemListPopupView } from '../item-list-popup-view';
interface Props extends Pick {
- style?: StyleProp;
- itemList: Item[];
- selectedItem?: Item;
- onSelected?: (item: Item) => void;
- placeHolder?: string;
+ style?: StyleProp;
+ itemList: Item[];
+ selectedItem?: Item;
+ onSelected?: (item: Item) => void;
+ placeHolder?: string;
}
export const ItemSelectorView: React.FC = ({
- disabled = false,
- style,
- title,
- itemList,
- selectedItem,
- placeHolder,
- onSelected,
+ disabled = false,
+ style,
+ title,
+ itemList,
+ selectedItem,
+ placeHolder,
+ onSelected,
}) => {
- const [isShowList, setShowList] = React.useState(false);
+ const [isShowList, setShowList] = React.useState(false);
- const onPress = () => {
- setShowList(true);
- };
- return (
-
- {
- setShowList(false);
- onSelected?.(item);
- }}
- />
-
-
- {title}
+ const onPress = () => {
+ setShowList(true);
+ };
+ return (
+
+ {
+ setShowList(false);
+ onSelected?.(item);
+ }}
+ />
+
+
+ {title}
+
+
+
+ {selectedItem?.name || placeHolder || 'select value'}
+
+
+
-
-
- {selectedItem?.name || placeHolder || 'select value'}
-
-
-
-
- );
+ );
};
ItemSelectorView.displayName = 'ItemSelectorView';
diff --git a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/styles.tsx b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/styles.tsx
index 0aaf2bf1bae..17c56d84f7d 100644
--- a/react-native/verification-tool/src/components/ui/item-list/item-selector-view/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/item-list/item-selector-view/styles.tsx
@@ -1,31 +1,31 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- titleText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- },
- containerLayout: {
- flexDirection: 'row',
- padding: 5,
- alignItems: 'center',
- },
- titleBack: {
- alignItems: 'center',
- alignSelf: 'center',
- },
- itemBack: {
- alignItems: 'center',
- padding: 5,
- alignSelf: 'center',
- borderColor: 'gray',
- borderWidth: 1,
- },
+ titleText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ },
+ containerLayout: {
+ flexDirection: 'row',
+ padding: 5,
+ alignItems: 'center',
+ },
+ titleBack: {
+ alignItems: 'center',
+ alignSelf: 'center',
+ },
+ itemBack: {
+ alignItems: 'center',
+ padding: 5,
+ alignSelf: 'center',
+ borderColor: 'gray',
+ borderWidth: 1,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/item-selector/item-selector-view.tsx b/react-native/verification-tool/src/components/ui/item-selector/item-selector-view.tsx
new file mode 100644
index 00000000000..5272a6d6308
--- /dev/null
+++ b/react-native/verification-tool/src/components/ui/item-selector/item-selector-view.tsx
@@ -0,0 +1,68 @@
+import * as React from 'react';
+import {
+ StyleProp,
+ TouchableOpacity,
+ View,
+ ViewStyle,
+ type ButtonProps,
+ Text,
+} from 'react-native';
+import styles from './styles.tsx';
+import { Item } from '../item-list';
+import { ItemListPopupView } from '../../item-list-popup-view';
+
+interface Props extends Pick {
+ style?: StyleProp;
+ itemList: Item[];
+ selectedItem?: Item;
+ onSelected?: (item: Item) => void;
+ placeHolder?: string;
+}
+
+export const ItemSelectorView: React.FC = ({
+ disabled = false,
+ style,
+ title,
+ itemList,
+ selectedItem,
+ placeHolder,
+ onSelected,
+}) => {
+ const [isShowList, setShowList] = React.useState(false);
+
+ const onPress = () => {
+ setShowList(true);
+ };
+ return (
+
+ {
+ setShowList(false);
+ onSelected?.(item);
+ }}
+ />
+
+
+ {title}
+
+
+
+ {selectedItem?.name || placeHolder || 'select value'}
+
+
+
+
+ );
+};
+
+ItemSelectorView.displayName = 'ItemSelectorView';
+
+export default ItemSelectorView;
diff --git a/react-native/verification-tool/src/components/ui/titled-switch/styles.tsx b/react-native/verification-tool/src/components/ui/titled-switch/styles.tsx
index 33bf56d5e97..854d3a9b7b6 100644
--- a/react-native/verification-tool/src/components/ui/titled-switch/styles.tsx
+++ b/react-native/verification-tool/src/components/ui/titled-switch/styles.tsx
@@ -1,25 +1,25 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- titleText: {
- color: 'black',
- fontSize: 16,
- paddingRight: 10,
- },
- containerLayout: {
- flexDirection: 'row',
- padding: 5,
- alignItems: 'center',
- },
- titleBack: {
- alignItems: 'center',
- alignSelf: 'center',
- },
- itemBack: {
- alignItems: 'center',
- padding: 5,
- alignSelf: 'center',
- },
+ titleText: {
+ color: 'black',
+ fontSize: 16,
+ paddingRight: 10,
+ },
+ containerLayout: {
+ flexDirection: 'row',
+ padding: 5,
+ alignItems: 'center',
+ },
+ titleBack: {
+ alignItems: 'center',
+ alignSelf: 'center',
+ },
+ itemBack: {
+ alignItems: 'center',
+ padding: 5,
+ alignSelf: 'center',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/components/ui/titled-switch/titled-switch.tsx b/react-native/verification-tool/src/components/ui/titled-switch/titled-switch.tsx
index 123e9c4e1cd..3eca99dc9e9 100644
--- a/react-native/verification-tool/src/components/ui/titled-switch/titled-switch.tsx
+++ b/react-native/verification-tool/src/components/ui/titled-switch/titled-switch.tsx
@@ -1,52 +1,52 @@
import * as React from 'react';
import {
- StyleProp,
- View,
- ViewStyle,
- Text,
- ViewProps,
- Switch,
+ StyleProp,
+ View,
+ ViewStyle,
+ Text,
+ ViewProps,
+ Switch,
} from 'react-native';
-import styles from './styles';
+import styles from './styles.tsx';
interface Props extends Pick {
- title?: string;
- style?: StyleProp;
- value?: boolean;
- onChange?: (value: boolean) => void;
+ title?: string;
+ style?: StyleProp;
+ value?: boolean;
+ onChange?: (value: boolean) => void;
}
export const TitledSwitch: React.FC = ({
- style,
- title,
- value,
- onChange,
+ style,
+ title,
+ value,
+ onChange,
}) => {
- const [editValue, setEditValue] = React.useState(value ?? false);
+ const [editValue, setEditValue] = React.useState(value ?? false);
- React.useEffect(() => {
- if (value != null) {
- setEditValue(value);
- }
- }, [value]);
+ React.useEffect(() => {
+ if (value != null) {
+ setEditValue(value);
+ }
+ }, [value]);
- const onChangeValue = (newValue: boolean) => {
- setEditValue(newValue);
- onChange?.(newValue);
- };
+ const onChangeValue = (newValue: boolean) => {
+ setEditValue(newValue);
+ onChange?.(newValue);
+ };
- return (
-
-
-
- {title}
+ return (
+
+
+
+ {title}
+
+
+
+
+
-
-
-
-
-
- );
+ );
};
TitledSwitch.displayName = 'TitledSwitch';
diff --git a/react-native/verification-tool/src/screen/burst-capture-screen/burst-capture-screen.tsx b/react-native/verification-tool/src/screen/burst-capture-screen/burst-capture-screen.tsx
index 823f7f20bd6..46693685f31 100644
--- a/react-native/verification-tool/src/screen/burst-capture-screen/burst-capture-screen.tsx
+++ b/react-native/verification-tool/src/screen/burst-capture-screen/burst-capture-screen.tsx
@@ -1,272 +1,270 @@
import React from 'react';
-import { View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { View, Alert, ScrollView, Text, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- BurstBracketStepEnum,
- BurstCapture,
- BurstCaptureNumEnum,
- BurstCompensationEnum,
- BurstEnableIsoControlEnum,
- BurstMaxExposureTimeEnum,
- BurstModeEnum,
- BurstOrderEnum,
- CapturingStatusEnum,
- Options,
- getBurstCaptureBuilder,
- stopSelfTimer,
+ BurstBracketStepEnum,
+ BurstCapture,
+ BurstCaptureNumEnum,
+ BurstCompensationEnum,
+ BurstEnableIsoControlEnum,
+ BurstMaxExposureTimeEnum,
+ BurstModeEnum,
+ BurstOrderEnum,
+ CapturingStatusEnum,
+ Options,
+ getBurstCaptureBuilder,
+ stopSelfTimer,
} from '../../modules/theta-client';
import { CaptureCommonOptionsEdit } from '../../components/capture/capture-common-options';
import { InputNumber } from '../../components/ui/input-number';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
import { BurstOptionsEdit } from '../../components/options/burst-option';
import { EnumEdit } from '../../components/options';
-const BurstCaptureScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [interval, setInterval] = React.useState();
- const [message, setMessage] = React.useState('');
- const [capturingStatus, setCapturingStatus] =
- React.useState();
- const [progress, setProgress] = React.useState();
- const [captureOptions, setCaptureOptions] = React.useState();
- const [isTaking, setIsTaking] = React.useState(false);
- const [capture, setCapture] = React.useState();
+interface BurstCaptureScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
- const onTake = async () => {
- if (
- isTaking ||
- captureOptions?.burstOption?.burstCaptureNum == null ||
- captureOptions?.burstOption?.burstBracketStep == null ||
- captureOptions?.burstOption?.burstCompensation == null ||
- captureOptions?.burstOption?.burstMaxExposureTime == null ||
- captureOptions?.burstOption?.burstEnableIsoControl == null ||
- captureOptions?.burstOption?.burstOrder == null
- ) {
- return;
- }
+const BurstCaptureScreen: React.FC = ({ navigation }) => {
+ const [interval, setInterval] = React.useState();
+ const [message, setMessage] = React.useState('');
+ const [capturingStatus, setCapturingStatus] =
+ React.useState();
+ const [progress, setProgress] = React.useState();
+ const [captureOptions, setCaptureOptions] = React.useState();
+ const [isTaking, setIsTaking] = React.useState(false);
+ const [capture, setCapture] = React.useState();
- const builder = getBurstCaptureBuilder(
- captureOptions.burstOption.burstCaptureNum,
- captureOptions.burstOption.burstBracketStep,
- captureOptions.burstOption.burstCompensation,
- captureOptions.burstOption.burstMaxExposureTime,
- captureOptions.burstOption.burstEnableIsoControl,
- captureOptions.burstOption.burstOrder
- );
+ const onTake = async () => {
+ if (
+ isTaking ||
+ captureOptions?.burstOption?.burstCaptureNum == null ||
+ captureOptions?.burstOption?.burstBracketStep == null ||
+ captureOptions?.burstOption?.burstCompensation == null ||
+ captureOptions?.burstOption?.burstMaxExposureTime == null ||
+ captureOptions?.burstOption?.burstEnableIsoControl == null ||
+ captureOptions?.burstOption?.burstOrder == null
+ ) {
+ return;
+ }
- if (interval != null) {
- builder.setCheckStatusCommandInterval(interval);
- }
- captureOptions?.burstMode && builder.setBurstMode(captureOptions.burstMode);
+ const builder = getBurstCaptureBuilder(
+ captureOptions.burstOption.burstCaptureNum,
+ captureOptions.burstOption.burstBracketStep,
+ captureOptions.burstOption.burstCompensation,
+ captureOptions.burstOption.burstMaxExposureTime,
+ captureOptions.burstOption.burstEnableIsoControl,
+ captureOptions.burstOption.burstOrder
+ );
- captureOptions?.aperture && builder.setAperture(captureOptions.aperture);
- if (captureOptions?.colorTemperature != null) {
- builder.setColorTemperature(captureOptions.colorTemperature);
- }
- captureOptions?.exposureCompensation &&
- builder.setExposureCompensation(captureOptions.exposureCompensation);
- captureOptions?.exposureDelay &&
- builder.setExposureDelay(captureOptions.exposureDelay);
- captureOptions?.exposureProgram &&
- builder.setExposureProgram(captureOptions.exposureProgram);
- captureOptions?.gpsInfo && builder.setGpsInfo(captureOptions.gpsInfo);
- captureOptions?._gpsTagRecording &&
- builder.setGpsTagRecording(captureOptions._gpsTagRecording);
- captureOptions?.iso && builder.setIso(captureOptions.iso);
- captureOptions?.isoAutoHighLimit &&
- builder.setIsoAutoHighLimit(captureOptions.isoAutoHighLimit);
- captureOptions?.whiteBalance &&
- builder.setWhiteBalance(captureOptions.whiteBalance);
+ if (interval != null) {
+ builder.setCheckStatusCommandInterval(interval);
+ }
+ captureOptions?.burstMode && builder.setBurstMode(captureOptions.burstMode);
- console.log('BurstCapture interval: ' + interval);
- console.log('BurstCapture options: ' + JSON.stringify(captureOptions));
- console.log('BurstCapture builder: ' + JSON.stringify(builder));
+ captureOptions?.aperture && builder.setAperture(captureOptions.aperture);
+ if (captureOptions?.colorTemperature != null) {
+ builder.setColorTemperature(captureOptions.colorTemperature);
+ }
+ captureOptions?.exposureCompensation &&
+ builder.setExposureCompensation(captureOptions.exposureCompensation);
+ captureOptions?.exposureDelay &&
+ builder.setExposureDelay(captureOptions.exposureDelay);
+ captureOptions?.exposureProgram &&
+ builder.setExposureProgram(captureOptions.exposureProgram);
+ captureOptions?.gpsInfo && builder.setGpsInfo(captureOptions.gpsInfo);
+ captureOptions?._gpsTagRecording &&
+ builder.setGpsTagRecording(captureOptions._gpsTagRecording);
+ captureOptions?.iso && builder.setIso(captureOptions.iso);
+ captureOptions?.isoAutoHighLimit &&
+ builder.setIsoAutoHighLimit(captureOptions.isoAutoHighLimit);
+ captureOptions?.whiteBalance &&
+ builder.setWhiteBalance(captureOptions.whiteBalance);
- try {
- setCapture(await builder.build());
- setIsTaking(false);
- } catch (error) {
- setIsTaking(false);
- if (error instanceof Error) {
- Alert.alert(
- 'BurstCaptureBuilder build error',
- error.name + ': ' + error.message,
- [{ text: 'OK' }]
- );
- }
- }
- };
+ console.log('BurstCapture interval: ' + interval);
+ console.log('BurstCapture options: ' + JSON.stringify(captureOptions));
+ console.log('BurstCapture builder: ' + JSON.stringify(builder));
+
+ try {
+ setCapture(await builder.build());
+ setIsTaking(false);
+ } catch (error) {
+ setIsTaking(false);
+ if (error instanceof Error) {
+ Alert.alert(
+ 'BurstCaptureBuilder build error',
+ error.name + ': ' + error.message,
+ [{ text: 'OK' }]
+ );
+ }
+ }
+ };
- const initCapture = () => {
- setCapture(undefined);
- setIsTaking(false);
- };
+ const initCapture = () => {
+ setCapture(undefined);
+ setIsTaking(false);
+ };
- const startCapture = async () => {
- if (capture == null) {
- initCapture();
- return;
- }
- setProgress(undefined);
- setCapturingStatus(undefined);
- try {
- console.log('BurstCapture startCapture');
- const urls = await capture.startCapture(
- (completion) => {
- if (isTaking) return;
- setProgress(completion);
- },
- (error) => {
- if (error instanceof Error) {
- Alert.alert('Cancel error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- },
- (status) => {
- setCapturingStatus(status);
+ const startCapture = async () => {
+ if (capture == null) {
+ initCapture();
+ return;
+ }
+ setProgress(undefined);
+ setCapturingStatus(undefined);
+ try {
+ console.log('BurstCapture startCapture');
+ const urls = await capture.startCapture(
+ (completion) => {
+ if (isTaking) { return; }
+ setProgress(completion);
+ },
+ (error) => {
+ if (error instanceof Error) {
+ Alert.alert('Cancel error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ },
+ (status) => {
+ setCapturingStatus(status);
+ }
+ );
+ initCapture();
+ if (urls) {
+ Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
+ { text: 'OK' },
+ ]);
+ } else {
+ Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
+ }
+ } catch (error) {
+ initCapture();
+ if (error instanceof Error) {
+ Alert.alert('startCapture error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
}
- );
- initCapture();
- if (urls) {
- Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
- { text: 'OK' },
- ]);
- } else {
- Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
- }
- } catch (error) {
- initCapture();
- if (error instanceof Error) {
- Alert.alert('startCapture error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
+ };
- const onCancel = async () => {
- if (capture == null) {
- return;
- }
- console.log('ready to cancel...');
- try {
- capture.cancelCapture();
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('stopCapture error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
+ const onCancel = async () => {
+ if (capture == null) {
+ return;
+ }
+ console.log('ready to cancel...');
+ try {
+ capture.cancelCapture();
+ } catch (error) {
+ if (error instanceof Error) {
+ Alert.alert('stopCapture error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
- const onStopSelfTimer = async () => {
- try {
- await stopSelfTimer();
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('stopSelfTimer error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
+ const onStopSelfTimer = async () => {
+ try {
+ await stopSelfTimer();
+ } catch (error) {
+ if (error instanceof Error) {
+ Alert.alert('stopSelfTimer error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
- React.useEffect(() => {
- navigation.setOptions({
- title: 'burst shooting',
- });
- setCaptureOptions({
- burstOption: {
- burstCaptureNum: BurstCaptureNumEnum.BURST_CAPTURE_NUM_9,
- burstBracketStep: BurstBracketStepEnum.BRACKET_STEP_0_0,
- burstCompensation: BurstCompensationEnum.BURST_COMPENSATION_0_0,
- burstMaxExposureTime: BurstMaxExposureTimeEnum.MAX_EXPOSURE_TIME_15,
- burstEnableIsoControl: BurstEnableIsoControlEnum.OFF,
- burstOrder: BurstOrderEnum.BURST_BRACKET_ORDER_0,
- },
- });
- }, [navigation]);
+ React.useEffect(() => {
+ navigation.setOptions({
+ title: 'burst shooting',
+ });
+ setCaptureOptions({
+ burstOption: {
+ burstCaptureNum: BurstCaptureNumEnum.BURST_CAPTURE_NUM_9,
+ burstBracketStep: BurstBracketStepEnum.BRACKET_STEP_0_0,
+ burstCompensation: BurstCompensationEnum.BURST_COMPENSATION_0_0,
+ burstMaxExposureTime: BurstMaxExposureTimeEnum.MAX_EXPOSURE_TIME_15,
+ burstEnableIsoControl: BurstEnableIsoControlEnum.OFF,
+ burstOrder: BurstOrderEnum.BURST_BRACKET_ORDER_0,
+ },
+ });
+ }, [navigation]);
- React.useEffect(() => {
- if (capture != null && !isTaking) {
- setIsTaking(true);
- startCapture();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [capture]);
+ React.useEffect(() => {
+ if (capture != null && !isTaking) {
+ setIsTaking(true);
+ startCapture();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [capture]);
- React.useEffect(() => {
- setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
- }, [capturingStatus, progress]);
+ React.useEffect(() => {
+ setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
+ }, [capturingStatus, progress]);
- return (
-
-
- {message}
-
-
-
-
-
-
-
-
- {
- setInterval(value);
- }}
- />
- {
- setCaptureOptions(option);
- }}
- options={captureOptions}
- />
- {
- setCaptureOptions({ ...captureOptions, burstMode });
- }}
- optionEnum={BurstModeEnum}
- />
- {
- setCaptureOptions(option);
- }}
- options={captureOptions}
- />
-
-
-
- );
+ return (
+
+
+ {message}
+
+
+
+
+
+
+
+
+ {
+ setInterval(value);
+ }}
+ />
+ {
+ setCaptureOptions(option);
+ }}
+ options={captureOptions}
+ />
+ {
+ setCaptureOptions({ ...captureOptions, burstMode });
+ }}
+ optionEnum={BurstModeEnum}
+ />
+ {
+ setCaptureOptions(option);
+ }}
+ options={captureOptions}
+ />
+
+
+
+ );
};
export default BurstCaptureScreen;
diff --git a/react-native/verification-tool/src/screen/burst-capture-screen/index.ts b/react-native/verification-tool/src/screen/burst-capture-screen/index.ts
index b61a46d55a4..23d32397010 100644
--- a/react-native/verification-tool/src/screen/burst-capture-screen/index.ts
+++ b/react-native/verification-tool/src/screen/burst-capture-screen/index.ts
@@ -1 +1 @@
-export { default } from './burst-capture-screen';
+export { default } from './burst-capture-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/burst-capture-screen/styles.tsx b/react-native/verification-tool/src/screen/burst-capture-screen/styles.tsx
index 58f6eadca72..3235adee4c5 100644
--- a/react-native/verification-tool/src/screen/burst-capture-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/burst-capture-screen/styles.tsx
@@ -1,34 +1,34 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 140,
- alignItems: 'center',
- },
- contentContainer: {
- width: '100%',
- height: '85%',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- itemText: {
- height: 50,
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ topViewContainer: {
+ height: 140,
+ alignItems: 'center',
+ },
+ contentContainer: {
+ width: '100%',
+ height: '85%',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ itemText: {
+ height: 50,
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/commands-screen/commands-screen.tsx b/react-native/verification-tool/src/screen/commands-screen/commands-screen.tsx
index 97285d3d311..1db5e5d150b 100644
--- a/react-native/verification-tool/src/screen/commands-screen/commands-screen.tsx
+++ b/react-native/verification-tool/src/screen/commands-screen/commands-screen.tsx
@@ -1,129 +1,131 @@
import React, { useState } from 'react';
-import { ScrollView, Text, View } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { ScrollView, Text, View, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import {
- reset,
- restoreSettings,
- finishWlan,
- reboot,
+ reset,
+ restoreSettings,
+ finishWlan,
+ reboot,
} from '../../modules/theta-client';
import Button from '../../components/ui/button';
import { ItemListView, type Item } from '../../components/ui/item-list';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
+
+interface CommandsScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
interface CommandItem extends Item {
- value: {
- commandFunction: () => Promise;
- };
+ value: {
+ commandFunction: () => Promise;
+ };
}
const commandList: CommandItem[] = [
- {
- name: 'reboot',
- value: {
- commandFunction: async () => {
- try {
- await reboot();
- } catch (error) {
- return JSON.stringify(error, null, 2);
- }
- return 'OK';
- },
+ {
+ name: 'reboot',
+ value: {
+ commandFunction: async () => {
+ try {
+ await reboot();
+ } catch (error) {
+ console.log('reboot error', error);
+ return JSON.stringify(error, null, 2);
+ }
+ return 'OK';
+ },
+ },
},
- },
- {
- name: 'reset',
- value: {
- commandFunction: async () => {
- try {
- await reset();
- } catch (error) {
- return JSON.stringify(error, null, 2);
- }
- return 'OK';
- },
+ {
+ name: 'reset',
+ value: {
+ commandFunction: async () => {
+ try {
+ await reset();
+ } catch (error) {
+ console.log('reset error', error);
+ return JSON.stringify(error, null, 2);
+ }
+ return 'OK';
+ },
+ },
},
- },
- {
- name: 'restoreSettings',
- value: {
- commandFunction: async () => {
- try {
- await restoreSettings();
- } catch (error) {
- return JSON.stringify(error, null, 2);
- }
- return 'OK';
- },
+ {
+ name: 'restoreSettings',
+ value: {
+ commandFunction: async () => {
+ try {
+ await restoreSettings();
+ } catch (error) {
+ console.log('restoreSettings error', error);
+ return JSON.stringify(error, null, 2);
+ }
+ return 'OK';
+ },
+ },
},
- },
- {
- name: 'finishWlan',
- value: {
- commandFunction: async () => {
- try {
- await finishWlan();
- } catch (error) {
- return JSON.stringify(error, null, 2);
- }
- return 'OK';
- },
+ {
+ name: 'finishWlan',
+ value: {
+ commandFunction: async () => {
+ try {
+ await finishWlan();
+ } catch (error) {
+ console.log('finishWlan error', error);
+ return JSON.stringify(error, null, 2);
+ }
+ return 'OK';
+ },
+ },
},
- },
];
-const CommandsScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [selectedCommand, setSelectedCommand] = useState();
- const [message, setMessage] = React.useState('');
+const CommandsScreen: React.FC = ({ navigation }) => {
+ const [selectedCommand, setSelectedCommand] = useState();
+ const [message, setMessage] = React.useState('');
- React.useEffect(() => {
- navigation.setOptions({ title: 'Commands' });
- }, [navigation]);
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'Commands' });
+ }, [navigation]);
- const onSelected = (item: Item) => {
- console.log('selected: ' + item.name);
- setSelectedCommand(item);
- setMessage('');
- };
+ const onSelected = (item: Item) => {
+ console.log('selected: ' + item.name);
+ setSelectedCommand(item as CommandItem);
+ setMessage('');
+ };
- const onExecute = () => {
- if (selectedCommand == null) {
- return;
- }
- selectedCommand.value.commandFunction().then((result) => {
- setMessage(result);
- });
- };
+ const onExecute = () => {
+ if (selectedCommand == null) {
+ return;
+ }
+ selectedCommand.value.commandFunction().then((result) => {
+ setMessage(result);
+ });
+ };
- return (
-
-
-
-
-
-
-
-
- {message}
-
-
- );
+ return (
+
+
+
+
+
+
+
+
+ {message}
+
+
+ );
};
export default CommandsScreen;
diff --git a/react-native/verification-tool/src/screen/commands-screen/index.ts b/react-native/verification-tool/src/screen/commands-screen/index.ts
index 3bee97970d2..7688cdd7131 100644
--- a/react-native/verification-tool/src/screen/commands-screen/index.ts
+++ b/react-native/verification-tool/src/screen/commands-screen/index.ts
@@ -1 +1 @@
-export { default } from './commands-screen';
+export { default } from './commands-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/commands-screen/styles.tsx b/react-native/verification-tool/src/screen/commands-screen/styles.tsx
index 7dc353222fe..54e0980224a 100644
--- a/react-native/verification-tool/src/screen/commands-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/commands-screen/styles.tsx
@@ -1,36 +1,36 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- bottomViewContainer: {
- height: 110,
- alignItems: 'center',
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageArea: {
- flex: 1,
- width: '90%',
- height: '100%',
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ bottomViewContainer: {
+ height: 110,
+ alignItems: 'center',
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageArea: {
+ flex: 1,
+ width: '90%',
+ height: '100%',
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/composite-interval-capture-screen/composite-interval-capture-screen.tsx b/react-native/verification-tool/src/screen/composite-interval-capture-screen/composite-interval-capture-screen.tsx
index 22d490fa003..1aaf58ac580 100644
--- a/react-native/verification-tool/src/screen/composite-interval-capture-screen/composite-interval-capture-screen.tsx
+++ b/react-native/verification-tool/src/screen/composite-interval-capture-screen/composite-interval-capture-screen.tsx
@@ -1,233 +1,231 @@
import React from 'react';
-import { View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { View, Alert, ScrollView, Text, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- CapturingStatusEnum,
- CompositeIntervalCapture,
- Options,
- getCompositeIntervalCaptureBuilder,
- stopSelfTimer,
+ CapturingStatusEnum,
+ CompositeIntervalCapture,
+ Options,
+ getCompositeIntervalCaptureBuilder,
+ stopSelfTimer,
} from '../../modules/theta-client';
import { CaptureCommonOptionsEdit } from '../../components/capture/capture-common-options';
import { InputNumber } from '../../components/ui/input-number';
import { NumberEdit } from '../../components/options/number-edit';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
-
-const CompositeIntervalCaptureScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [interval, setInterval] = React.useState();
- const [shootingTimeSec, setShootingTimeSec] = React.useState(600);
- const [message, setMessage] = React.useState('');
- const [capturingStatus, setCapturingStatus] =
- React.useState();
- const [progress, setProgress] = React.useState();
- const [captureOptions, setCaptureOptions] = React.useState();
- const [isTaking, setIsTaking] = React.useState(false);
- const [capture, setCapture] = React.useState();
-
- const onTake = async () => {
- if (isTaking) {
- return;
- }
-
- const builder = getCompositeIntervalCaptureBuilder(shootingTimeSec);
- if (interval != null) {
- builder.setCheckStatusCommandInterval(interval);
- }
-
- if (captureOptions?.compositeShootingOutputInterval != null) {
- builder.setCompositeShootingOutputInterval(
- captureOptions.compositeShootingOutputInterval
- );
- }
- captureOptions?.aperture && builder.setAperture(captureOptions.aperture);
- if (captureOptions?.colorTemperature != null) {
- builder.setColorTemperature(captureOptions.colorTemperature);
- }
- captureOptions?.exposureCompensation &&
- builder.setExposureCompensation(captureOptions.exposureCompensation);
- captureOptions?.exposureDelay &&
- builder.setExposureDelay(captureOptions.exposureDelay);
- captureOptions?.exposureProgram &&
- builder.setExposureProgram(captureOptions.exposureProgram);
- captureOptions?.gpsInfo && builder.setGpsInfo(captureOptions.gpsInfo);
- captureOptions?._gpsTagRecording &&
- builder.setGpsTagRecording(captureOptions._gpsTagRecording);
- captureOptions?.iso && builder.setIso(captureOptions.iso);
- captureOptions?.isoAutoHighLimit &&
- builder.setIsoAutoHighLimit(captureOptions.isoAutoHighLimit);
- captureOptions?.whiteBalance &&
- builder.setWhiteBalance(captureOptions.whiteBalance);
-
- console.log('CompositeIntervalCapture interval: ' + interval);
- console.log(
- 'CompositeIntervalCapture options: ' + JSON.stringify(captureOptions)
- );
- console.log('CompositeIntervalCapture builder: ' + JSON.stringify(builder));
-
- try {
- setCapture(await builder.build());
- setIsTaking(false);
- } catch (error) {
- setIsTaking(false);
- Alert.alert(
- 'CompositeIntervalCapture build error',
- JSON.stringify(error),
- [{ text: 'OK' }]
- );
- }
- };
-
- const initCapture = () => {
- setCapture(undefined);
- setIsTaking(false);
- };
-
- const startCapture = async () => {
- if (capture == null) {
- initCapture();
- return;
- }
- setProgress(undefined);
- setCapturingStatus(undefined);
- try {
- console.log('CompositeIntervalCapture startCapture');
- const urls = await capture.startCapture(
- (completion) => {
- if (isTaking) return;
- setProgress(completion);
- },
- (error) => {
- Alert.alert('Cancel error', JSON.stringify(error), [{ text: 'OK' }]);
- },
- (status) => {
- setCapturingStatus(status);
+
+interface CompositeIntervalCaptureScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
+
+const CompositeIntervalCaptureScreen: React.FC = ({ navigation }) => {
+ const [interval, setInterval] = React.useState();
+ const [shootingTimeSec, setShootingTimeSec] = React.useState(600);
+ const [message, setMessage] = React.useState('');
+ const [capturingStatus, setCapturingStatus] =
+ React.useState();
+ const [progress, setProgress] = React.useState();
+ const [captureOptions, setCaptureOptions] = React.useState();
+ const [isTaking, setIsTaking] = React.useState(false);
+ const [capture, setCapture] = React.useState();
+
+ const onTake = async () => {
+ if (isTaking) {
+ return;
+ }
+
+ const builder = getCompositeIntervalCaptureBuilder(shootingTimeSec);
+ if (interval != null) {
+ builder.setCheckStatusCommandInterval(interval);
+ }
+
+ if (captureOptions?.compositeShootingOutputInterval != null) {
+ builder.setCompositeShootingOutputInterval(
+ captureOptions.compositeShootingOutputInterval
+ );
+ }
+ captureOptions?.aperture && builder.setAperture(captureOptions.aperture);
+ if (captureOptions?.colorTemperature != null) {
+ builder.setColorTemperature(captureOptions.colorTemperature);
}
- );
- initCapture();
- if (urls) {
- Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
- { text: 'OK' },
- ]);
- } else {
- Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
- }
- } catch (error) {
- initCapture();
- Alert.alert('startCapture error', JSON.stringify(error), [
- { text: 'OK' },
- ]);
- }
- };
-
- const onCancel = async () => {
- if (capture == null) {
- return;
- }
- console.log('ready to cancel...');
- try {
- capture.cancelCapture();
- } catch (error) {
- Alert.alert('stopCapture error', JSON.stringify(error), [{ text: 'OK' }]);
- }
- };
-
- const onStopSelfTimer = async () => {
- try {
- await stopSelfTimer();
- } catch (error) {
- Alert.alert('stopSelfTimer error', JSON.stringify(error), [
- { text: 'OK' },
- ]);
- }
- };
-
- React.useEffect(() => {
- navigation.setOptions({
- title: 'interval composite shooting',
- });
- }, [navigation]);
-
- React.useEffect(() => {
- if (capture != null && !isTaking) {
- setIsTaking(true);
- startCapture();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [capture]);
-
- React.useEffect(() => {
- setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
- }, [capturingStatus, progress]);
-
- return (
-
-
- {message}
-
-
-
-
-
-
-
-
- {
- setInterval(value);
- }}
- />
- {
- setShootingTimeSec(value ?? 600);
- }}
- />
- {
- setCaptureOptions(option);
- }}
- options={captureOptions}
- placeHolder="Input value"
- />
- {
- setCaptureOptions(option);
- }}
- options={captureOptions}
- />
-
-
-
- );
+ captureOptions?.exposureCompensation &&
+ builder.setExposureCompensation(captureOptions.exposureCompensation);
+ captureOptions?.exposureDelay &&
+ builder.setExposureDelay(captureOptions.exposureDelay);
+ captureOptions?.exposureProgram &&
+ builder.setExposureProgram(captureOptions.exposureProgram);
+ captureOptions?.gpsInfo && builder.setGpsInfo(captureOptions.gpsInfo);
+ captureOptions?._gpsTagRecording &&
+ builder.setGpsTagRecording(captureOptions._gpsTagRecording);
+ captureOptions?.iso && builder.setIso(captureOptions.iso);
+ captureOptions?.isoAutoHighLimit &&
+ builder.setIsoAutoHighLimit(captureOptions.isoAutoHighLimit);
+ captureOptions?.whiteBalance &&
+ builder.setWhiteBalance(captureOptions.whiteBalance);
+
+ console.log('CompositeIntervalCapture interval: ' + interval);
+ console.log(
+ 'CompositeIntervalCapture options: ' + JSON.stringify(captureOptions)
+ );
+ console.log('CompositeIntervalCapture builder: ' + JSON.stringify(builder));
+
+ try {
+ setCapture(await builder.build());
+ setIsTaking(false);
+ } catch (error) {
+ setIsTaking(false);
+ Alert.alert(
+ 'CompositeIntervalCapture build error',
+ JSON.stringify(error),
+ [{ text: 'OK' }]
+ );
+ }
+ };
+
+ const initCapture = () => {
+ setCapture(undefined);
+ setIsTaking(false);
+ };
+
+ const startCapture = async () => {
+ if (capture == null) {
+ initCapture();
+ return;
+ }
+ setProgress(undefined);
+ setCapturingStatus(undefined);
+ try {
+ console.log('CompositeIntervalCapture startCapture');
+ const urls = await capture.startCapture(
+ (completion) => {
+ if (isTaking) { return; }
+ setProgress(completion);
+ },
+ (error) => {
+ Alert.alert('Cancel error', JSON.stringify(error), [{ text: 'OK' }]);
+ },
+ (status) => {
+ setCapturingStatus(status);
+ }
+ );
+ initCapture();
+ if (urls) {
+ Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
+ { text: 'OK' },
+ ]);
+ } else {
+ Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
+ }
+ } catch (error) {
+ initCapture();
+ Alert.alert('startCapture error', JSON.stringify(error), [
+ { text: 'OK' },
+ ]);
+ }
+ };
+
+ const onCancel = async () => {
+ if (capture == null) {
+ return;
+ }
+ console.log('ready to cancel...');
+ try {
+ capture.cancelCapture();
+ } catch (error) {
+ Alert.alert('stopCapture error', JSON.stringify(error), [{ text: 'OK' }]);
+ }
+ };
+
+ const onStopSelfTimer = async () => {
+ try {
+ await stopSelfTimer();
+ } catch (error) {
+ Alert.alert('stopSelfTimer error', JSON.stringify(error), [
+ { text: 'OK' },
+ ]);
+ }
+ };
+
+ React.useEffect(() => {
+ navigation.setOptions({
+ title: 'interval composite shooting',
+ });
+ }, [navigation]);
+
+ React.useEffect(() => {
+ if (capture != null && !isTaking) {
+ setIsTaking(true);
+ startCapture();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [capture]);
+
+ React.useEffect(() => {
+ setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
+ }, [capturingStatus, progress]);
+
+ return (
+
+
+ {message}
+
+
+
+
+
+
+
+
+ {
+ setInterval(value);
+ }}
+ />
+ {
+ setShootingTimeSec(value ?? 600);
+ }}
+ />
+ {
+ setCaptureOptions(option);
+ }}
+ options={captureOptions}
+ placeHolder="Input value"
+ />
+ {
+ setCaptureOptions(option);
+ }}
+ options={captureOptions}
+ />
+
+
+
+ );
};
export default CompositeIntervalCaptureScreen;
diff --git a/react-native/verification-tool/src/screen/composite-interval-capture-screen/index.ts b/react-native/verification-tool/src/screen/composite-interval-capture-screen/index.ts
index 527e28abe68..fc854155e70 100644
--- a/react-native/verification-tool/src/screen/composite-interval-capture-screen/index.ts
+++ b/react-native/verification-tool/src/screen/composite-interval-capture-screen/index.ts
@@ -1 +1 @@
-export { default } from './composite-interval-capture-screen';
+export { default } from './composite-interval-capture-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/composite-interval-capture-screen/styles.tsx b/react-native/verification-tool/src/screen/composite-interval-capture-screen/styles.tsx
index 17423ff6337..27550e13c01 100644
--- a/react-native/verification-tool/src/screen/composite-interval-capture-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/composite-interval-capture-screen/styles.tsx
@@ -1,33 +1,33 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 140,
- alignItems: 'center',
- },
- contentContainer: {
- width: '100%',
- height: '85%',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ topViewContainer: {
+ height: 140,
+ alignItems: 'center',
+ },
+ contentContainer: {
+ width: '100%',
+ height: '85%',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/continuous-capture-screen/continuous-capture-screen.tsx b/react-native/verification-tool/src/screen/continuous-capture-screen/continuous-capture-screen.tsx
index 85a90dd39b3..57bcb2fbec5 100644
--- a/react-native/verification-tool/src/screen/continuous-capture-screen/continuous-capture-screen.tsx
+++ b/react-native/verification-tool/src/screen/continuous-capture-screen/continuous-capture-screen.tsx
@@ -1,219 +1,164 @@
import React from 'react';
-import { View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { View, Alert, ScrollView, Text, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- CapturingStatusEnum,
- ContinuousCapture,
- ContinuousNumberEnum,
- Options,
- PhotoFileFormatEnum,
- getContinuousCaptureBuilder,
- stopSelfTimer,
+ CaptureModeEnum,
+ ContinuousCapture,
+ ContinuousNumberEnum,
+ PhotoFileFormatEnum,
+ getContinuousCaptureBuilder,
+ setOptions,
} from '../../modules/theta-client';
import { CaptureCommonOptionsEdit } from '../../components/capture/capture-common-options';
-import { InputNumber } from '../../components/ui/input-number';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
import { EnumEdit } from '../../components/options';
+import { InputNumber } from '../../components/ui/input-number';
+
+interface ContinuousCaptureScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
+
+const ContinuousCaptureScreen: React.FC = ({ navigation }) => {
+ const [interval, setInterval] = React.useState();
+ const [captureOptions, setCaptureOptions] = React.useState({});
+ const [isTaking, setIsTaking] = React.useState(false);
+ const [capture, setCapture] = React.useState();
+ const [continuousNumber, setContinuousNumber] =
+ React.useState();
+
+ const onTake = async () => {
+ if (isTaking) {
+ return;
+ }
+
+ const builder = getContinuousCaptureBuilder();
+ if (interval != null) {
+ builder.setCheckStatusCommandInterval(interval);
+ }
+ captureOptions?.fileFormat &&
+ builder.setFileFormat(captureOptions.fileFormat);
+
+ console.log('ContinuousCapture interval: ' + interval);
+ console.log('ContinuousCapture options: ' + JSON.stringify(captureOptions));
+ console.log('ContinuousCapture builder: ' + JSON.stringify(builder));
+
+ try {
+ setCapture(await builder.build());
+ setIsTaking(false);
+ } catch (error) {
+ setIsTaking(false);
+ if (error instanceof Error) {
+ Alert.alert(
+ 'ContinuousCaptureBuilder build error',
+ error.name + ': ' + error.message,
+ [{ text: 'OK' }]
+ );
+ }
+ }
+ };
-const ContinuousCaptureScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [interval, setInterval] = React.useState();
- const [message, setMessage] = React.useState('');
- const [capturingStatus, setCapturingStatus] =
- React.useState();
- const [progress, setProgress] = React.useState();
- const [captureOptions, setCaptureOptions] = React.useState();
- const [isTaking, setIsTaking] = React.useState(false);
- const [capture, setCapture] = React.useState();
- const [continuousNumber, setContinuousNumber] =
- React.useState(ContinuousNumberEnum.OFF);
-
- const onTake = async () => {
- if (isTaking) {
- return;
- }
-
- const builder = getContinuousCaptureBuilder();
-
- if (interval != null) {
- builder.setCheckStatusCommandInterval(interval);
- }
- captureOptions?.fileFormat &&
- builder.setFileFormat(captureOptions.fileFormat as PhotoFileFormatEnum);
-
- captureOptions?.aperture && builder.setAperture(captureOptions.aperture);
- if (captureOptions?.colorTemperature != null) {
- builder.setColorTemperature(captureOptions.colorTemperature);
- }
- captureOptions?.exposureCompensation &&
- builder.setExposureCompensation(captureOptions.exposureCompensation);
- captureOptions?.exposureDelay &&
- builder.setExposureDelay(captureOptions.exposureDelay);
- captureOptions?.exposureProgram &&
- builder.setExposureProgram(captureOptions.exposureProgram);
- captureOptions?.gpsInfo && builder.setGpsInfo(captureOptions.gpsInfo);
- captureOptions?._gpsTagRecording &&
- builder.setGpsTagRecording(captureOptions._gpsTagRecording);
- captureOptions?.iso && builder.setIso(captureOptions.iso);
- captureOptions?.isoAutoHighLimit &&
- builder.setIsoAutoHighLimit(captureOptions.isoAutoHighLimit);
- captureOptions?.whiteBalance &&
- builder.setWhiteBalance(captureOptions.whiteBalance);
-
- console.log('ContinuousCapture interval: ' + interval);
- console.log('ContinuousCapture options: ' + JSON.stringify(captureOptions));
- console.log('ContinuousCapture builder: ' + JSON.stringify(builder));
-
- try {
- setCapture(await builder.build());
- setIsTaking(false);
- } catch (error) {
- setIsTaking(false);
- if (error instanceof Error) {
- Alert.alert(
- 'ContinuousCaptureBuilder build error',
- error.name + ': ' + error.message,
- [{ text: 'OK' }]
- );
- }
- }
- };
-
- const initCapture = () => {
- setCapture(undefined);
- setIsTaking(false);
- };
-
- const startCapture = async () => {
- if (capture == null) {
- initCapture();
- return;
- }
- setProgress(undefined);
- setCapturingStatus(undefined);
- try {
- console.log('ContinuousCapture startCapture');
-
- const number = await capture.getContinuousNumber();
- setContinuousNumber(number);
-
- const urls = await capture.startCapture(
- (completion) => {
- if (isTaking) return;
- setProgress(completion);
- },
- (status) => {
- setCapturingStatus(status);
+ const initCapture = () => {
+ setCapture(undefined);
+ setIsTaking(false);
+ };
+
+ const startCapture = async () => {
+ if (capture == null) {
+ initCapture();
+ return;
+ }
+ try {
+ console.log('ContinuousCapture startCapture');
+
+ const number = await capture.getContinuousNumber();
+ setContinuousNumber(number);
+
+ const urls = await capture.startCapture();
+ initCapture();
+ if (urls) {
+ Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
+ { text: 'OK' },
+ ]);
+ } else {
+ Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
+ }
+ } catch (error) {
+ initCapture();
+ if (error instanceof Error) {
+ Alert.alert('startCapture error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
}
- );
- initCapture();
- if (urls) {
- Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
- { text: 'OK' },
- ]);
- } else {
- Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
- }
- } catch (error) {
- initCapture();
- if (error instanceof Error) {
- Alert.alert('startCapture error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
-
- const onStopSelfTimer = async () => {
- try {
- await stopSelfTimer();
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('stopSelfTimer error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
-
- React.useEffect(() => {
- navigation.setOptions({
- title: 'continuous shooting',
- });
- }, [navigation]);
-
- React.useEffect(() => {
- if (capture != null && !isTaking) {
- setIsTaking(true);
- startCapture();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [capture]);
-
- React.useEffect(() => {
- setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
- }, [capturingStatus, progress]);
-
- return (
-
-
- {message}
-
- ContinuousNumber = {continuousNumber}
-
-
-
-
-
-
-
-
- {
- setInterval(value);
- }}
- />
- {
- setCaptureOptions((prevState) => ({
- ...prevState,
- fileFormat,
- }));
- }}
- optionEnum={PhotoFileFormatEnum}
- />
- {
- setCaptureOptions(option);
- }}
- options={captureOptions}
- />
-
-
-
- );
+ };
+
+ React.useEffect(() => {
+ setOptions({ captureMode: CaptureModeEnum.IMAGE }).catch();
+ }, []);
+
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'Continuous Capture' });
+ }, [navigation]);
+
+ React.useEffect(() => {
+ if (capture != null && !isTaking) {
+ setIsTaking(true);
+ startCapture();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [capture]);
+
+ return (
+
+
+
+ ContinuousNumber: {continuousNumber ?? 'unknown'}
+
+
+
+
+
+
+
+ {
+ setInterval(value);
+ }}
+ />
+ {
+ setCaptureOptions((prevState: any) => ({
+ ...prevState,
+ fileFormat,
+ }));
+ }}
+ optionEnum={PhotoFileFormatEnum}
+ />
+ {
+ setCaptureOptions((prevState: any) => ({
+ ...prevState,
+ ...options,
+ }));
+ }}
+ />
+
+
+
+ );
};
export default ContinuousCaptureScreen;
+
diff --git a/react-native/verification-tool/src/screen/continuous-capture-screen/index.ts b/react-native/verification-tool/src/screen/continuous-capture-screen/index.ts
index f11b7b29094..57551f9eea2 100644
--- a/react-native/verification-tool/src/screen/continuous-capture-screen/index.ts
+++ b/react-native/verification-tool/src/screen/continuous-capture-screen/index.ts
@@ -1 +1 @@
-export { default } from './continuous-capture-screen';
+export { default } from './continuous-capture-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/continuous-capture-screen/styles.tsx b/react-native/verification-tool/src/screen/continuous-capture-screen/styles.tsx
index 90de8fd362d..53453ee257d 100644
--- a/react-native/verification-tool/src/screen/continuous-capture-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/continuous-capture-screen/styles.tsx
@@ -1,33 +1,33 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 110,
- alignItems: 'center',
- },
- contentContainer: {
- width: '100%',
- height: '85%',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ topViewContainer: {
+ height: 110,
+ alignItems: 'center',
+ },
+ contentContainer: {
+ width: '100%',
+ height: '85%',
+ },
+ button: {
+ width: 170,
+ paddingHorizontal: 10,
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/delete-files-screen/delete-files-screen.tsx b/react-native/verification-tool/src/screen/delete-files-screen/delete-files-screen.tsx
index aec8bd35e6b..68954f92ed5 100644
--- a/react-native/verification-tool/src/screen/delete-files-screen/delete-files-screen.tsx
+++ b/react-native/verification-tool/src/screen/delete-files-screen/delete-files-screen.tsx
@@ -1,202 +1,199 @@
import React, { useEffect, useState } from 'react';
-import { StatusBar, Text, View, ScrollView, Alert } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { StatusBar, Text, View, ScrollView, Alert, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import {
- FileInfo,
- FileTypeEnum,
- ThetaFiles,
- deleteAllFiles,
- deleteAllImageFiles,
- deleteAllVideoFiles,
- deleteFiles,
+ FileInfo,
+ FileTypeEnum,
+ ThetaFiles,
+ deleteAllFiles,
+ deleteAllImageFiles,
+ deleteAllVideoFiles,
+ deleteFiles,
} from '../../modules/theta-client';
import Button from '../../components/ui/button';
import { ListFilesView } from '../../components/list-files-view';
-import { Item, ItemSelectorView } from '../../components/ui/item-list';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
+import { ItemSelectorView, Item } from '../../components/ui/item-list';
interface ListFilesProps {
- fileType: FileTypeEnum;
- isMultiselect: boolean;
+ fileType: FileTypeEnum;
+ isMultiselect: boolean;
}
-const DeleteFilesScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [deleteType, setDeleteType] = useState- ();
- const [selectedFiles, setSelectedFiles] = React.useState
([]);
- const [message, setMessage] = React.useState('');
- const [listFilesProps, setListFilesProps] = React.useState();
- const [refreshCounter, setRefreshCounter] = React.useState(0);
- const [thetaFiles, setThetaFiles] = React.useState();
+interface DeleteFilesScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
- const DeleteTypeEnum = {
- All: {
- name: 'deleteAllFiles',
- fileType: FileTypeEnum.ALL,
- isMultiselect: false,
- executeDelete: async (_selected?: FileInfo[]) => {
- await deleteAllFiles();
- },
- },
- Files: {
- name: 'deleteFiles',
- fileType: FileTypeEnum.ALL,
- isMultiselect: true,
- executeDelete: async (_selected?: FileInfo[]) => {
- if ((_selected?.length ?? 0) <= 0) {
- throw 'Not file select.';
- }
- const fileUrls = _selected?.map((element) => element.fileUrl) ?? [];
- await deleteFiles(fileUrls);
- },
- },
- AllImageFile: {
- name: 'deleteAllFiles',
- fileType: FileTypeEnum.IMAGE,
- isMultiselect: false,
- executeDelete: async (_selected?: FileInfo[]) => {
- await deleteAllImageFiles();
- },
- },
- AllVideoFiles: {
- name: 'deleteAllFiles',
- fileType: FileTypeEnum.VIDEO,
- isMultiselect: false,
- executeDelete: async (_selected?: FileInfo[]) => {
- await deleteAllVideoFiles();
- },
- },
- };
- type DeleteTypeEnum = (typeof DeleteTypeEnum)[keyof typeof DeleteTypeEnum];
+const DeleteFilesScreen: React.FC = ({ navigation }) => {
+ const [deleteType, setDeleteType] = useState- ();
+ const [selectedFiles, setSelectedFiles] = React.useState
([]);
+ const [message, setMessage] = React.useState('');
+ const [listFilesProps, setListFilesProps] = React.useState();
+ const [refreshCounter, setRefreshCounter] = React.useState(0);
+ const [thetaFiles, setThetaFiles] = React.useState();
- const deleteTypeList = [
- { name: 'deleteAll', value: DeleteTypeEnum.All },
- { name: 'deleteFiles', value: DeleteTypeEnum.Files },
- { name: 'deleteAllImageFile', value: DeleteTypeEnum.AllImageFile },
- { name: 'deleteAllVideoFiles', value: DeleteTypeEnum.AllVideoFiles },
- ];
+ const DeleteTypeEnum = {
+ All: {
+ name: 'deleteAllFiles',
+ fileType: FileTypeEnum.ALL,
+ isMultiselect: false,
+ executeDelete: async (_selected?: FileInfo[]) => {
+ await deleteAllFiles();
+ },
+ },
+ Files: {
+ name: 'deleteFiles',
+ fileType: FileTypeEnum.ALL,
+ isMultiselect: true,
+ executeDelete: async (_selected?: FileInfo[]) => {
+ if ((_selected?.length ?? 0) <= 0) {
+ throw 'Not file select.';
+ }
+ const fileUrls = _selected?.map((element) => element.fileUrl) ?? [];
+ await deleteFiles(fileUrls);
+ },
+ },
+ AllImageFiles: {
+ name: 'deleteAllFiles',
+ fileType: FileTypeEnum.IMAGE,
+ isMultiselect: false,
+ executeDelete: async (_selected?: FileInfo[]) => {
+ await deleteAllImageFiles();
+ },
+ },
+ AllVideoFiles: {
+ name: 'deleteAllFiles',
+ fileType: FileTypeEnum.VIDEO,
+ isMultiselect: false,
+ executeDelete: async (_selected?: FileInfo[]) => {
+ await deleteAllVideoFiles();
+ },
+ },
+ };
+ type DeleteTypeEnum = (typeof DeleteTypeEnum)[keyof typeof DeleteTypeEnum];
- const execDelete = async (deleteItem: Item) => {
- try {
- deleteItem.value.executeDelete(selectedFiles);
- setMessage('OK.\n' + deleteItem.name);
- } catch (error) {
- setMessage('Error.\n' + JSON.stringify(error));
- } finally {
- showList();
- }
- };
+ const deleteTypeList = [
+ { name: 'deleteAll', value: DeleteTypeEnum.All },
+ { name: 'deleteFiles', value: DeleteTypeEnum.Files },
+ { name: 'deleteAllImageFiles', value: DeleteTypeEnum.AllImageFiles },
+ { name: 'deleteAllVideoFiles', value: DeleteTypeEnum.AllVideoFiles },
+ ];
- const onDeletePress = () => {
- if (deleteType == null) {
- return;
- }
+ const execDelete = async (deleteItem: Item) => {
+ try {
+ deleteItem.value.executeDelete(selectedFiles);
+ setMessage('OK.\n' + deleteItem.name);
+ } catch (error) {
+ setMessage('Error.\n' + JSON.stringify(error));
+ } finally {
+ showList();
+ }
+ };
- Alert.alert(deleteType.name, `Execute ${deleteType.name} ?`, [
- {
- text: 'No',
- },
- {
- text: 'Yes',
- onPress: () => {
- execDelete(deleteType);
- },
- },
- ]);
- };
+ const onDeletePress = () => {
+ if (deleteType == null) {
+ return;
+ }
+
+ Alert.alert(deleteType.name, `Execute ${deleteType.name} ?`, [
+ {
+ text: 'No',
+ },
+ {
+ text: 'Yes',
+ onPress: () => {
+ execDelete(deleteType);
+ },
+ },
+ ]);
+ };
- const showList = () => {
- if (deleteType == null) {
- return;
- }
- setListFilesProps({
- fileType: deleteType.value.fileType,
- isMultiselect: deleteType.value.isMultiselect,
- });
- setRefreshCounter(refreshCounter + 1);
- };
+ const showList = () => {
+ if (deleteType == null) {
+ return;
+ }
+ setListFilesProps({
+ fileType: deleteType.value.fileType,
+ isMultiselect: deleteType.value.isMultiselect,
+ });
+ setRefreshCounter(refreshCounter + 1);
+ };
- useEffect(() => {
- showList();
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [deleteType]);
+ useEffect(() => {
+ showList();
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [deleteType]);
- useEffect(() => {
- navigation.setOptions({ title: 'DeleteFiles' });
- }, [navigation]);
+ useEffect(() => {
+ navigation.setOptions({ title: 'DeleteFiles' });
+ }, [navigation]);
- return (
-
-
-
-
- {message}
-
-
- {
- setDeleteType(item);
- }}
- selectedItem={deleteTypeList.find(
- (item) => item.name === deleteType?.name
- )}
- />
-
-
-
+ return (
+
+
+
+
+ {message}
+
+
+ {
+ setDeleteType(item);
+ }}
+ selectedItem={deleteTypeList.find(
+ (item) => item.name === deleteType?.name
+ )}
+ />
+
+
+
- {listFilesProps && (
-
- {`total: ${
- thetaFiles?.totalEntries
- } entryCount: ${thetaFiles?.fileList.length ?? 0}`}
- {
- setSelectedFiles(files);
- const fileNames = files.map((element) => element.name);
- setMessage('select:\n' + JSON.stringify(fileNames));
- }}
- onRefreshed={(filesInfo) => {
- setSelectedFiles([]);
- setThetaFiles(filesInfo);
- }}
- onError={(error) => {
- Alert.alert('listFiles', 'get error\n' + JSON.stringify(error), [
- {
- text: 'OK',
- onPress: () => {
- setListFilesProps(undefined);
- },
- },
- ]);
- }}
- refreshCounter={refreshCounter}
- multiselect={listFilesProps.isMultiselect}
- />
-
- )}
-
- );
+ {listFilesProps && (
+
+ {`total: ${thetaFiles?.totalEntries
+ } entryCount: ${thetaFiles?.fileList.length ?? 0}`}
+ {
+ setSelectedFiles(files);
+ const fileNames = files.map((element) => element.name);
+ setMessage('select:\n' + JSON.stringify(fileNames));
+ }}
+ onRefreshed={(filesInfo) => {
+ setSelectedFiles([]);
+ setThetaFiles(filesInfo);
+ }}
+ onError={(error) => {
+ Alert.alert('listFiles', 'get error\n' + JSON.stringify(error), [
+ {
+ text: 'OK',
+ onPress: () => {
+ setListFilesProps(undefined);
+ },
+ },
+ ]);
+ }}
+ refreshCounter={refreshCounter}
+ multiselect={listFilesProps.isMultiselect}
+ />
+
+ )}
+
+ );
};
export default DeleteFilesScreen;
diff --git a/react-native/verification-tool/src/screen/delete-files-screen/index.ts b/react-native/verification-tool/src/screen/delete-files-screen/index.ts
index 41807de4b22..6fc1e88f0f4 100644
--- a/react-native/verification-tool/src/screen/delete-files-screen/index.ts
+++ b/react-native/verification-tool/src/screen/delete-files-screen/index.ts
@@ -1 +1 @@
-export { default } from './delete-files-screen';
+export { default } from './delete-files-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/delete-files-screen/styles.tsx b/react-native/verification-tool/src/screen/delete-files-screen/styles.tsx
index 36b849efa18..8fb7d94da3b 100644
--- a/react-native/verification-tool/src/screen/delete-files-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/delete-files-screen/styles.tsx
@@ -1,39 +1,39 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- buttonViewContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- height: 70,
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageArea: {
- width: '90%',
- height: 200,
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
- listFilesContainerLayout: {
- flex: 1,
- },
- entryText: {
- marginLeft: 4,
- marginBottom: 5,
- color: 'black',
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ buttonViewContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ height: 70,
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageArea: {
+ width: '90%',
+ height: 200,
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
+ listFilesContainerLayout: {
+ flex: 1,
+ },
+ entryText: {
+ marginLeft: 4,
+ marginBottom: 5,
+ color: 'black',
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/file-preview-screen/file-preview-screen.tsx b/react-native/verification-tool/src/screen/file-preview-screen/file-preview-screen.tsx
index 998c6fb3f89..0e692fb043d 100644
--- a/react-native/verification-tool/src/screen/file-preview-screen/file-preview-screen.tsx
+++ b/react-native/verification-tool/src/screen/file-preview-screen/file-preview-screen.tsx
@@ -1,24 +1,21 @@
import React from 'react';
import { View, Image } from 'react-native';
import styles from './styles';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
+import type { FileInfo } from '../../modules/theta-client';
-const FilePreviewScreen: React.FC<
- NativeStackScreenProps
-> = ({ route, navigation }) => {
- React.useEffect(() => {
- navigation.setOptions({ title: route.params.item.name });
- }, [navigation, route.params.item.name]);
+interface FilePreviewScreenProps {
+ fileInfo: FileInfo;
+}
- return (
-
-
-
- );
+const FilePreviewScreen: React.FC = ({ fileInfo }) => {
+ return (
+
+
+
+ );
};
export default FilePreviewScreen;
diff --git a/react-native/verification-tool/src/screen/file-preview-screen/styles.tsx b/react-native/verification-tool/src/screen/file-preview-screen/styles.tsx
index d69cc44cd50..c4a694124fb 100644
--- a/react-native/verification-tool/src/screen/file-preview-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/file-preview-screen/styles.tsx
@@ -1,19 +1,19 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- takePhotoBack: {
- flex: 1,
- alignItems: 'center',
- backgroundColor: 'white',
- },
- takePhoto: {
- width: '100%',
- height: '100%',
- backgroundColor: 'white',
- resizeMode: 'contain',
- zIndex: 0,
- elevation: 0,
- },
+ takePhotoBack: {
+ flex: 1,
+ alignItems: 'center',
+ backgroundColor: 'white',
+ },
+ takePhoto: {
+ width: '100%',
+ height: '100%',
+ backgroundColor: 'white',
+ resizeMode: 'contain',
+ zIndex: 0,
+ elevation: 0,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx b/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx
index 0958d1c22d1..6efa7d7d820 100644
--- a/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx
+++ b/react-native/verification-tool/src/screen/get-info-screen/get-info-screen.tsx
@@ -1,185 +1,170 @@
+
import React, { useState } from 'react';
import { ScrollView, Text, View } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
import {
- getPluginOrders,
- getThetaInfo,
- getThetaLicense,
- getThetaState,
- listAccessPoints,
- listPlugins,
+ getPluginOrders,
+ getThetaInfo,
+ getThetaLicense,
+ getThetaState,
+ listAccessPoints,
+ listPlugins,
} from '../../modules/theta-client';
import Button from '../../components/ui/button';
import { ItemListView, type Item } from '../../components/ui/item-list';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
+import styles from './styles';
interface CommandItem extends Item {
- value: {
- commandFunction: () => Promise;
- };
+ value: {
+ commandFunction: () => Promise;
+ };
}
function getJsonString(object: Object) {
- return JSON.stringify(JSON.parse(JSON.stringify(object)), null, 2);
+ return JSON.stringify(JSON.parse(JSON.stringify(object)), null, 2);
}
+
const commandList: CommandItem[] = [
- {
- name: 'getThetaInfo',
- value: {
- commandFunction: async () => {
- try {
- const result = await getThetaInfo();
- return `OK getThetaInfo()\n${getJsonString(result)}`;
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'getThetaInfo',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await getThetaInfo();
+ return `OK getThetaInfo()\n${getJsonString(result)}`;
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
- {
- name: 'getThetaLicense',
- value: {
- commandFunction: async () => {
- try {
- const result = await getThetaLicense();
- const maxChars = 200;
- return (
- `OK getThetaLicense()\nlength:${result.length}\n\n${result.slice(
- 0,
- maxChars
- )}\n\n` +
- (result.length > maxChars
- ? `(The remaining ${
- result.length - maxChars
- } characters were omitted.)`
- : '')
- );
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'getThetaLicense',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await getThetaLicense();
+ const maxChars = 200;
+ return (
+ `OK getThetaLicense()\nlength:${result.length}\n\n${result.slice(
+ 0,
+ maxChars
+ )}\n\n` +
+ (result.length > maxChars
+ ? `(The remaining ${result.length - maxChars} characters were omitted.)`
+ : '')
+ );
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
- {
- name: 'getThetaState',
- value: {
- commandFunction: async () => {
- try {
- const result = await getThetaState();
- return `OK getThetaState()\n${getJsonString(result)}`;
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'getThetaState',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await getThetaState();
+ return `OK getThetaState()\n${getJsonString(result)}`;
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
- {
- name: 'listAccessPoints',
- value: {
- commandFunction: async () => {
- try {
- const result = await listAccessPoints();
- return `OK listAccessPoints()\n${getJsonString(result)}`;
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'listAccessPoints',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await listAccessPoints();
+ return `OK listAccessPoints()\n${getJsonString(result)}`;
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
- {
- name: 'listPlugins',
- value: {
- commandFunction: async () => {
- try {
- const result = await listPlugins();
- return `OK listPlugins()\n${getJsonString(result)}`;
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'listPlugins',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await listPlugins();
+ return `OK listPlugins()\n${getJsonString(result)}`;
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
- {
- name: 'getPluginOrders',
- value: {
- commandFunction: async () => {
- try {
- const result = await getPluginOrders();
- return `OK getPluginOrders()\n${getJsonString(result)}`;
- } catch (error) {
- return error instanceof Error
- ? error.toString()
- : 'An error occurred.';
- }
- },
+ {
+ name: 'getPluginOrders',
+ value: {
+ commandFunction: async () => {
+ try {
+ const result = await getPluginOrders();
+ return `OK getPluginOrders()\n${getJsonString(result)}`;
+ } catch (error) {
+ return error instanceof Error
+ ? error.toString()
+ : 'An error occurred.';
+ }
+ },
+ },
},
- },
];
-const GetInfoScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [selectedCommand, setSelectedCommand] = useState();
- const [message, setMessage] = React.useState('');
-
- React.useEffect(() => {
- navigation.setOptions({ title: 'Get Info' });
- }, [navigation]);
+const GetInfoScreen: React.FC = () => {
+ const [selectedCommand, setSelectedCommand] = useState();
+ const [message, setMessage] = useState('');
- const onSelected = (item: Item) => {
- console.log('selected: ' + item.name);
- setSelectedCommand(item);
- setMessage('');
- };
+ const onSelected = (item: Item) => {
+ setSelectedCommand(item as CommandItem);
+ setMessage('');
+ };
- const onExecute = () => {
- if (selectedCommand == null) {
- return;
- }
- selectedCommand.value.commandFunction().then((result) => {
- setMessage(result);
- });
- };
+ const onExecute = () => {
+ if (!selectedCommand) { return; }
+ selectedCommand.value.commandFunction().then((result) => {
+ setMessage(result);
+ });
+ };
- return (
-
-
-
-
-
-
-
+ return (
+
+
+
+
+
+
+
+
+
+
+ {message}
+
-
-
- {message}
-
-
- );
+ );
};
export default GetInfoScreen;
diff --git a/react-native/verification-tool/src/screen/get-info-screen/index.ts b/react-native/verification-tool/src/screen/get-info-screen/index.ts
index c8a83fea831..2da886b32ff 100644
--- a/react-native/verification-tool/src/screen/get-info-screen/index.ts
+++ b/react-native/verification-tool/src/screen/get-info-screen/index.ts
@@ -1 +1 @@
-export { default } from './get-info-screen';
+export { default } from './get-info-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/get-info-screen/styles.tsx b/react-native/verification-tool/src/screen/get-info-screen/styles.tsx
index 3134c12b9b1..64f6ed91159 100644
--- a/react-native/verification-tool/src/screen/get-info-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/get-info-screen/styles.tsx
@@ -1,42 +1,42 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- commandListContainer: {
- width: '100%',
- height: 130,
- borderColor: 'gray',
- borderWidth: 1,
- },
- buttonViewContainer: {
- height: 90,
- alignItems: 'center',
- },
- buttonViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageArea: {
- flex: 1,
- width: '90%',
- height: '100%',
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ commandListContainer: {
+ width: '100%',
+ height: 130,
+ borderColor: 'gray',
+ borderWidth: 1,
+ },
+ buttonViewContainer: {
+ height: 90,
+ alignItems: 'center',
+ },
+ buttonViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageArea: {
+ flex: 1,
+ width: '90%',
+ height: '100%',
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/get-metadata-screen/get-metadata-screen.tsx b/react-native/verification-tool/src/screen/get-metadata-screen/get-metadata-screen.tsx
index d17406a156f..06aac1d962d 100644
--- a/react-native/verification-tool/src/screen/get-metadata-screen/get-metadata-screen.tsx
+++ b/react-native/verification-tool/src/screen/get-metadata-screen/get-metadata-screen.tsx
@@ -1,85 +1,84 @@
import React, { useState } from 'react';
-import { StatusBar, Text, View, ScrollView, Alert } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { StatusBar, Text, View, ScrollView, Alert, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import {
- FileTypeEnum,
- FileInfo,
- getMetadata,
+ FileTypeEnum,
+ FileInfo,
+ getMetadata,
} from '../../modules/theta-client';
import Button from '../../components/ui/button';
import { ListFilesView } from '../../components/list-files-view';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
-const GetMetadataScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [selectedFile, setSelectedFile] = useState();
- const [message, setMessage] = React.useState('');
+interface GetMetadataScreenProps {
+ navigation: {
+ goBack: () => void;
+ setOptions: (options: { title: string }) => void;
+ };
+}
- React.useEffect(() => {
- navigation.setOptions({ title: 'getMetadata' });
- }, [navigation]);
+const GetMetadataScreen: React.FC = ({ navigation }) => {
+ const [selectedFile, setSelectedFile] = useState();
+ const [message, setMessage] = React.useState('');
- const onPress = () => {
- if (selectedFile == null) {
- return;
- }
- execGetMetadata(selectedFile.fileUrl, selectedFile.name);
- };
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'getMetadata' });
+ }, [navigation]);
- const execGetMetadata = async (fileUrl: string, name: string) => {
- try {
- const result = await getMetadata(fileUrl);
- const jsonString = JSON.stringify(
- JSON.parse(JSON.stringify(result)),
- null,
- 2
- );
- setMessage(`getMetadata\nname: ${name}\nmetadata:\n${jsonString}`);
- } catch (error) {
- console.log('getMetadata error: ' + JSON.stringify(error));
- setMessage('getMetadata error\n' + JSON.stringify(error));
- }
- };
+ const onPress = () => {
+ if (selectedFile == null) {
+ return;
+ }
+ execGetMetadata(selectedFile.fileUrl, selectedFile.name);
+ };
- return (
-
-
-
-
- {message}
-
-
+ const execGetMetadata = async (fileUrl: string, name: string) => {
+ try {
+ const result = await getMetadata(fileUrl);
+ const jsonString = JSON.stringify(
+ JSON.parse(JSON.stringify(result)),
+ null,
+ 2
+ );
+ setMessage(`getMetadata\nname: ${name}\nmetadata:\n${jsonString}`);
+ } catch (error) {
+ console.log('getMetadata error: ' + JSON.stringify(error));
+ setMessage('getMetadata error\n' + JSON.stringify(error));
+ }
+ };
-
-
-
+ return (
+
+
+
+
+ {message}
+
+
- {
- const fileInfo = files.length > 0 ? files[0] : undefined;
- setSelectedFile(fileInfo);
- fileInfo && setMessage('select: ' + fileInfo?.fileUrl);
- }}
- fileType={FileTypeEnum.ALL}
- onError={() => {
- Alert.alert('listFiles', 'get error', [
- { text: 'OK', onPress: () => navigation.goBack() },
- ]);
- }}
- />
-
- );
+
+
+
+
+ {
+ const fileInfo = files.length > 0 ? files[0] : undefined;
+ setSelectedFile(fileInfo);
+ fileInfo && setMessage('select: ' + fileInfo?.fileUrl);
+ }}
+ fileType={FileTypeEnum.ALL}
+ onError={() => {
+ Alert.alert('listFiles', 'get error', [
+ { text: 'OK', onPress: () => navigation.goBack() },
+ ]);
+ }}
+ />
+
+ );
};
export default GetMetadataScreen;
diff --git a/react-native/verification-tool/src/screen/get-metadata-screen/index.ts b/react-native/verification-tool/src/screen/get-metadata-screen/index.ts
index effafda905b..88b6ebf2d58 100644
--- a/react-native/verification-tool/src/screen/get-metadata-screen/index.ts
+++ b/react-native/verification-tool/src/screen/get-metadata-screen/index.ts
@@ -1 +1 @@
-export { default } from './get-metadata-screen';
+export { default } from './get-metadata-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/get-metadata-screen/styles.tsx b/react-native/verification-tool/src/screen/get-metadata-screen/styles.tsx
index 5cf339d9dc6..0418785ae38 100644
--- a/react-native/verification-tool/src/screen/get-metadata-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/get-metadata-screen/styles.tsx
@@ -1,31 +1,31 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- buttonViewContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- height: 70,
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageArea: {
- width: '90%',
- height: 250,
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ buttonViewContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ height: 70,
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageArea: {
+ width: '90%',
+ height: 250,
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/index.ts b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/index.ts
index f568f0755bf..e2bcd7d106e 100644
--- a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/index.ts
+++ b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/index.ts
@@ -1 +1 @@
-export { default } from './limitless-interval-capture-screen';
+export { default } from './limitless-interval-capture-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/limitless-interval-capture-screen.tsx b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/limitless-interval-capture-screen.tsx
index 0eed3a79c8c..23f3316e3a7 100644
--- a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/limitless-interval-capture-screen.tsx
+++ b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/limitless-interval-capture-screen.tsx
@@ -1,214 +1,212 @@
import React from 'react';
-import { View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { View, Alert, ScrollView, Text, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- CapturingStatusEnum,
- LimitlessIntervalCapture,
- Options,
- getLimitlessIntervalCaptureBuilder,
- stopSelfTimer,
+ CapturingStatusEnum,
+ LimitlessIntervalCapture,
+ Options,
+ getLimitlessIntervalCaptureBuilder,
+ stopSelfTimer,
} from '../../modules/theta-client';
import { CaptureCommonOptionsEdit } from '../../components/capture/capture-common-options';
import { NumberEdit } from '../../components/options/number-edit';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
import { InputNumber } from '../../components/ui/input-number';
-const LimitlessIntervalCaptureScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [interval, setInterval] = React.useState();
- const [message, setMessage] = React.useState('');
- const [capturingStatus, setCapturingStatus] =
- React.useState();
- const [options, setOptions] = React.useState();
- const [isTaking, setIsTaking] = React.useState(false);
- const [capture, setCapture] = React.useState();
-
- React.useEffect(() => {
- navigation.setOptions({ title: 'Limitless Interval Capture' });
- }, [navigation]);
-
- const onTake = async () => {
- if (isTaking) {
- return;
- }
-
- const builder = getLimitlessIntervalCaptureBuilder();
- if (interval != null) {
- builder.setCheckStatusCommandInterval(interval);
- }
- if (options?.captureInterval != null) {
- builder.setCaptureInterval(options.captureInterval);
- }
-
- options?.aperture && builder.setAperture(options.aperture);
- if (options?.colorTemperature != null) {
- builder.setColorTemperature(options.colorTemperature);
- }
- options?.exposureCompensation &&
- builder.setExposureCompensation(options.exposureCompensation);
- options?.exposureDelay && builder.setExposureDelay(options.exposureDelay);
- options?.exposureProgram &&
- builder.setExposureProgram(options.exposureProgram);
- options?.gpsInfo && builder.setGpsInfo(options.gpsInfo);
- options?._gpsTagRecording &&
- builder.setGpsTagRecording(options._gpsTagRecording);
- options?.iso && builder.setIso(options.iso);
- options?.isoAutoHighLimit &&
- builder.setIsoAutoHighLimit(options.isoAutoHighLimit);
- options?.whiteBalance && builder.setWhiteBalance(options.whiteBalance);
-
- console.log(
- 'LimitlessIntervalCapture options: :' + JSON.stringify(options)
- );
- console.log(
- 'LimitlessIntervalCapture builder: :' + JSON.stringify(builder)
- );
+interface LimitlessIntervalCaptureScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
+
+const LimitlessIntervalCaptureScreen: React.FC = ({ navigation }) => {
+ const [interval, setInterval] = React.useState();
+ const [message, setMessage] = React.useState('');
+ const [capturingStatus, setCapturingStatus] =
+ React.useState();
+ const [options, setOptions] = React.useState();
+ const [isTaking, setIsTaking] = React.useState(false);
+ const [capture, setCapture] = React.useState();
+
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'Limitless Interval Capture' });
+ }, [navigation]);
+
+ const onTake = async () => {
+ if (isTaking) {
+ return;
+ }
+
+ const builder = getLimitlessIntervalCaptureBuilder();
+ if (interval != null) {
+ builder.setCheckStatusCommandInterval(interval);
+ }
+ if (options?.captureInterval != null) {
+ builder.setCaptureInterval(options.captureInterval);
+ }
+
+ options?.aperture && builder.setAperture(options.aperture);
+ if (options?.colorTemperature != null) {
+ builder.setColorTemperature(options.colorTemperature);
+ }
+ options?.exposureCompensation &&
+ builder.setExposureCompensation(options.exposureCompensation);
+ options?.exposureDelay && builder.setExposureDelay(options.exposureDelay);
+ options?.exposureProgram &&
+ builder.setExposureProgram(options.exposureProgram);
+ options?.gpsInfo && builder.setGpsInfo(options.gpsInfo);
+ options?._gpsTagRecording &&
+ builder.setGpsTagRecording(options._gpsTagRecording);
+ options?.iso && builder.setIso(options.iso);
+ options?.isoAutoHighLimit &&
+ builder.setIsoAutoHighLimit(options.isoAutoHighLimit);
+ options?.whiteBalance && builder.setWhiteBalance(options.whiteBalance);
+
+ console.log(
+ 'LimitlessIntervalCapture options: :' + JSON.stringify(options)
+ );
+ console.log(
+ 'LimitlessIntervalCapture builder: :' + JSON.stringify(builder)
+ );
+
+ try {
+ setCapture(await builder.build());
+ setIsTaking(false);
+ } catch (error) {
+ setIsTaking(false);
+ Alert.alert(
+ 'LimitlessIntervalCaptureBuilder build error',
+ JSON.stringify(error),
+ [{ text: 'OK' }]
+ );
+ }
+ };
+
+ const initCapture = () => {
+ setCapture(undefined);
+ setIsTaking(false);
+ };
- try {
- setCapture(await builder.build());
- setIsTaking(false);
- } catch (error) {
- setIsTaking(false);
- Alert.alert(
- 'LimitlessIntervalCaptureBuilder build error',
- JSON.stringify(error),
- [{ text: 'OK' }]
- );
- }
- };
-
- const initCapture = () => {
- setCapture(undefined);
- setIsTaking(false);
- };
-
- const startCapture = async () => {
- if (capture == null) {
- initCapture();
- return;
- }
- setCapturingStatus(undefined);
- try {
- const urls = await capture.startCapture(
- (error) => {
- Alert.alert('stopCapture error', JSON.stringify(error), [
- { text: 'OK' },
- ]);
- },
- (status) => {
- setCapturingStatus(status);
+ const startCapture = async () => {
+ if (capture == null) {
+ initCapture();
+ return;
}
- );
- initCapture();
- if (urls) {
- Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
- { text: 'OK' },
- ]);
- } else {
- Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
- }
- } catch (error) {
- initCapture();
- Alert.alert('startCapture error', JSON.stringify(error), [
- { text: 'OK' },
- ]);
- }
- };
-
- const onStop = async () => {
- if (capture == null) {
- return;
- }
- console.log('ready to stop...');
- try {
- capture.stopCapture();
- } catch (error) {
- Alert.alert('stopCapture error', JSON.stringify(error), [{ text: 'OK' }]);
- }
- };
-
- const onStopSelfTimer = async () => {
- try {
- await stopSelfTimer();
- } catch (error) {
- Alert.alert('stopSelfTimer error', JSON.stringify(error), [
- { text: 'OK' },
- ]);
- }
- };
-
- React.useEffect(() => {
- if (capture != null && !isTaking) {
- setIsTaking(true);
- startCapture();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [capture]);
-
- React.useEffect(() => {
- setMessage(`capturing = ${capturingStatus}`);
- }, [capturingStatus]);
-
- return (
-
-
- {message}
-
-
-
-
-
-
-
-
- {
- setInterval(value);
- }}
- />
- {
- setOptions(option);
- }}
- options={options}
- placeHolder="Input value"
- />
- {
- setOptions(option);
- }}
- options={options}
- />
-
-
-
- );
+ setCapturingStatus(undefined);
+ try {
+ const urls = await capture.startCapture(
+ (error) => {
+ Alert.alert('stopCapture error', JSON.stringify(error), [
+ { text: 'OK' },
+ ]);
+ },
+ (status) => {
+ setCapturingStatus(status);
+ }
+ );
+ initCapture();
+ if (urls) {
+ Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
+ { text: 'OK' },
+ ]);
+ } else {
+ Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
+ }
+ } catch (error) {
+ initCapture();
+ Alert.alert('startCapture error', JSON.stringify(error), [
+ { text: 'OK' },
+ ]);
+ }
+ };
+
+ const onStop = async () => {
+ if (capture == null) {
+ return;
+ }
+ console.log('ready to stop...');
+ try {
+ capture.stopCapture();
+ } catch (error) {
+ Alert.alert('stopCapture error', JSON.stringify(error), [{ text: 'OK' }]);
+ }
+ };
+
+ const onStopSelfTimer = async () => {
+ try {
+ await stopSelfTimer();
+ } catch (error) {
+ Alert.alert('stopSelfTimer error', JSON.stringify(error), [
+ { text: 'OK' },
+ ]);
+ }
+ };
+
+ React.useEffect(() => {
+ if (capture != null && !isTaking) {
+ setIsTaking(true);
+ startCapture();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [capture]);
+
+ React.useEffect(() => {
+ setMessage(`capturing = ${capturingStatus}`);
+ }, [capturingStatus]);
+
+ return (
+
+
+ {message}
+
+
+
+
+
+
+
+
+ {
+ setInterval(value);
+ }}
+ />
+ {
+ setOptions(option);
+ }}
+ options={options}
+ placeHolder="Input value"
+ />
+ {
+ setOptions(option);
+ }}
+ options={options}
+ />
+
+
+
+ );
};
export default LimitlessIntervalCaptureScreen;
diff --git a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/styles.tsx b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/styles.tsx
index 90de8fd362d..62afd9e041d 100644
--- a/react-native/verification-tool/src/screen/limitless-interval-capture-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/limitless-interval-capture-screen/styles.tsx
@@ -1,33 +1,33 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 110,
- alignItems: 'center',
- },
- contentContainer: {
- width: '100%',
- height: '85%',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ topViewContainer: {
+ height: 110,
+ alignItems: 'center',
+ },
+ contentContainer: {
+ width: '100%',
+ height: '85%',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/list-files-screen/index.ts b/react-native/verification-tool/src/screen/list-files-screen/index.ts
index 5f4ee254f35..c628cd7f503 100644
--- a/react-native/verification-tool/src/screen/list-files-screen/index.ts
+++ b/react-native/verification-tool/src/screen/list-files-screen/index.ts
@@ -1 +1 @@
-export { default } from './list-files-screen';
+export { default } from './list-files-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/list-files-screen/list-files-screen.tsx b/react-native/verification-tool/src/screen/list-files-screen/list-files-screen.tsx
index c771b4a5c96..5e2f0e6178e 100644
--- a/react-native/verification-tool/src/screen/list-files-screen/list-files-screen.tsx
+++ b/react-native/verification-tool/src/screen/list-files-screen/list-files-screen.tsx
@@ -1,155 +1,170 @@
-import React, { useEffect, useState } from 'react';
-import { StatusBar, Text, View, ScrollView, Alert } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import React, { useEffect } from 'react';
+import { Text, View, ScrollView, Alert, SafeAreaView, TouchableWithoutFeedback, Keyboard } from 'react-native';
+import styles from './styles.tsx';
import { FileTypeEnum, StorageEnum } from '../../modules/theta-client';
import Button from '../../components/ui/button';
import { ListFilesView } from '../../components/list-files-view';
import { ItemSelectorView } from '../../components/ui/item-list';
import { InputNumber } from '../../components/ui/input-number';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
-interface ListFilesProps {
- fileType: FileTypeEnum;
- startPosition: number;
- entryCount: number;
- storage?: StorageEnum;
+interface ListFilesScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ navigate: (screen: string, params?: any) => void;
+ };
+ state: {
+ fileType: any;
+ startPosition: number;
+ entryCount: number;
+ storage: any;
+ message: string;
+ selectedFileInfo: any;
+ listFilesProps: any;
+ refreshCounter: number;
+ };
+ setState: (state: any) => void;
}
-export const CommandEnum = {
- /** still image files. */
- IMAGE: 'IMAGE',
- /** video files. */
- VIDEO: 'VIDEO',
- /** all files. */
- ALL: 'ALL',
-} as const;
+const ListFilesScreen: React.FC = ({ navigation, state, setState }) => {
-const ListFilesScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [fileType, setFileType] = useState(FileTypeEnum.ALL);
- const [startPosition, setStartPosition] = useState(0);
- const [entryCount, setEntryCount] = useState(100);
- const [storage, setStorage] = useState();
- const [message, setMessage] = React.useState('');
- const [listFilesProps, setListFilesProps] = React.useState();
- const [refreshCounter, setRefreshCounter] = React.useState(0);
+ const fileTypeList = [
+ { name: 'ALL', value: FileTypeEnum.ALL },
+ { name: 'IMAGE', value: FileTypeEnum.IMAGE },
+ { name: 'VIDEO', value: FileTypeEnum.VIDEO },
+ ];
- const fileTypeList = [
- { name: 'ALL', value: FileTypeEnum.ALL },
- { name: 'IMAGE', value: FileTypeEnum.IMAGE },
- { name: 'VIDEO', value: FileTypeEnum.VIDEO },
- ];
- const storageList = [
- { name: '[undefined]', value: undefined },
- { name: 'INTERNAL', value: StorageEnum.INTERNAL },
- { name: 'SD', value: StorageEnum.SD },
- { name: 'CURRENT', value: StorageEnum.CURRENT },
- ];
+ const storageList = [
+ { name: '[undefined]', value: undefined },
+ { name: 'INTERNAL', value: StorageEnum.INTERNAL },
+ { name: 'SD', value: StorageEnum.SD },
+ { name: 'CURRENT', value: StorageEnum.CURRENT },
+ ];
- useEffect(() => {
- navigation.setOptions({ title: 'listFiles' });
- }, [navigation]);
+ useEffect(() => {
+ navigation.setOptions({ title: 'listFiles' });
+ }, [navigation]);
- const showList = () => {
- setListFilesProps({
- fileType,
- startPosition,
- entryCount,
- storage,
- });
- setRefreshCounter(refreshCounter + 1);
- };
+ const showList = () => {
+ const newListFilesProps = {
+ fileType: state.fileType || FileTypeEnum.ALL,
+ startPosition: state.startPosition,
+ entryCount: state.entryCount,
+ storage: state.storage,
+ };
+ setState({
+ ...state,
+ listFilesProps: newListFilesProps,
+ refreshCounter: state.refreshCounter + 1,
+ selectedFileInfo: null,
+ message: '',
+ });
+ };
- return (
-
-
-
-
- {message}
-
-
- {
- setFileType(item.value);
- }}
- selectedItem={fileTypeList.find((item) => item.value === fileType)}
- />
- setStartPosition(newValue ?? 0)}
- value={startPosition}
- />
- {
- if (newValue != null) {
- setEntryCount(newValue);
- }
- }}
- value={entryCount}
- />
- {
- setStorage(item.value);
- }}
- selectedItem={storageList.find((item) => item.value === storage)}
- />
+ const showPhoto = () => {
+ if (state.selectedFileInfo) {
+ navigation.navigate('filePreview', { fileInfo: state.selectedFileInfo });
+ } else {
+ Alert.alert('No file selected', 'Please select a file first', [{ text: 'OK' }]);
+ }
+ };
-
-
-
+ return (
+
+
+
+
+
+ {state.message}
+
+
- {listFilesProps && (
- {
- const fileInfo = files.length > 0 ? files[0] : undefined;
- console.log('onSelected:' + fileInfo?.fileUrl);
- if (fileInfo != null) {
- const jsonString = JSON.stringify(
- JSON.parse(JSON.stringify(fileInfo)),
- null,
- 2
- );
- setMessage('select:\n' + jsonString);
- }
- }}
- onError={(error) => {
- Alert.alert('listFiles', 'get error\n' + JSON.stringify(error), [
- {
- text: 'OK',
- onPress: () => {
- setListFilesProps(undefined);
- },
- },
- ]);
- }}
- refreshCounter={refreshCounter}
- onRefreshed={(thetaFiles) => {
- if (thetaFiles != null) {
- const strInfo = `listFiles\n totalEntries: ${thetaFiles.totalEntries} entryCount: ${thetaFiles.fileList.length}`;
- setMessage(strInfo);
- } else {
- setMessage('');
- }
- }}
- />
- )}
-
- );
+ {
+ setState({ ...state, fileType: item.value });
+ }}
+ selectedItem={fileTypeList.find((item) => item.value === (state.fileType || FileTypeEnum.ALL))}
+ />
+
+ setState({ ...state, startPosition: newValue ?? 0 })}
+ value={state.startPosition}
+ />
+
+ {
+ if (newValue != null) {
+ setState({ ...state, entryCount: newValue });
+ }
+ }}
+ value={state.entryCount}
+ />
+
+ {
+ setState({ ...state, storage: item.value });
+ }}
+ selectedItem={storageList.find((item) => item.value === state.storage)}
+ />
+
+
+
+
+
+
+ {state.listFilesProps && (
+ {
+ const fileInfo = files.length > 0 ? files[0] : undefined;
+ console.log('onSelected:' + fileInfo?.fileUrl);
+ if (fileInfo != null) {
+ const jsonString = JSON.stringify(
+ JSON.parse(JSON.stringify(fileInfo)),
+ null,
+ 2
+ );
+ setState({ ...state, selectedFileInfo: fileInfo, message: 'select:\n' + jsonString });
+ }
+ }}
+ onError={(error) => {
+ Alert.alert('listFiles', 'get error\n' + JSON.stringify(error), [
+ {
+ text: 'OK',
+ onPress: () => {
+ setState({ ...state, listFilesProps: undefined });
+ },
+ },
+ ]);
+ }}
+ refreshCounter={state.refreshCounter}
+ onRefreshed={(thetaFiles) => {
+ if (thetaFiles != null) {
+ const strInfo = `listFiles\ntotalEntries: ${thetaFiles.totalEntries} entryCount: ${thetaFiles.fileList.length}`;
+ if (!state.selectedFileInfo) {
+ setState({ ...state, message: strInfo });
+ }
+ } else {
+ if (!state.selectedFileInfo) {
+ setState({ ...state, message: '' });
+ }
+ }
+ }}
+ />
+ )}
+
+
+
+ );
};
export default ListFilesScreen;
diff --git a/react-native/verification-tool/src/screen/list-files-screen/styles.tsx b/react-native/verification-tool/src/screen/list-files-screen/styles.tsx
index 00884c29b62..97a0b1e5f7f 100644
--- a/react-native/verification-tool/src/screen/list-files-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/list-files-screen/styles.tsx
@@ -1,31 +1,34 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- buttonViewContainerLayout: {
- flexDirection: 'row',
- alignItems: 'center',
- height: 70,
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageArea: {
- width: '90%',
- height: 200,
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ buttonViewContainerLayout: {
+ flexDirection: 'row',
+ alignItems: 'center',
+ height: 70,
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageArea: {
+ width: '90%',
+ height: 200,
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
+ contentContainer: {
+ flex: 1,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/live-preview-screen/index.ts b/react-native/verification-tool/src/screen/live-preview-screen/index.ts
index 2c343f6d902..e605ef4fa88 100644
--- a/react-native/verification-tool/src/screen/live-preview-screen/index.ts
+++ b/react-native/verification-tool/src/screen/live-preview-screen/index.ts
@@ -1 +1 @@
-export { default } from './live-preview-screen';
+export { default } from './live-preview-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/live-preview-screen/live-preview-screen.tsx b/react-native/verification-tool/src/screen/live-preview-screen/live-preview-screen.tsx
index 346aa59c756..3f7afdec674 100644
--- a/react-native/verification-tool/src/screen/live-preview-screen/live-preview-screen.tsx
+++ b/react-native/verification-tool/src/screen/live-preview-screen/live-preview-screen.tsx
@@ -1,135 +1,139 @@
import React from 'react';
+import { View, Alert, Text, Platform, NativeModules, NativeEventEmitter } from 'react-native';
+import styles from './styles.tsx';
import {
- View,
- NativeModules,
- NativeEventEmitter,
- Alert,
- Text,
- Platform,
-} from 'react-native';
-import styles from './styles';
-import {
- getLivePreview,
- isInitialized,
- stopLivePreview,
- THETA_EVENT_NAME,
+ getLivePreview,
+ isInitialized,
+ stopLivePreview,
+ THETA_EVENT_NAME,
} from '../../modules/theta-client';
-import { useIsFocused } from '@react-navigation/native';
import Button from '../../components/ui/button';
import WebView from 'react-native-webview';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
-const LivePreviewScreen: React.FC<
- NativeStackScreenProps
-> = () => {
- const isFocused = useIsFocused();
- const [dataUrl, setDataUrl] = React.useState();
- const [previewing, setPreviewing] = React.useState(false);
- const [isLoaded, setLoaded] = React.useState(false);
- const [frameSize, setFrameSize] = React.useState(0);
- const webViewRef = React.useRef(null);
- const source =
- Platform.OS === 'android'
- ? 'file:///android_asset/live-preview/index.html'
- : './Web.bundle/live-preview/index.html';
+interface LivePreviewScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
+
+const LivePreviewScreen: React.FC = ({ navigation }) => {
+ const [dataUrl, setDataUrl] = React.useState();
+ const [previewing, setPreviewing] = React.useState(false);
+ const [isLoaded, setLoaded] = React.useState(false);
+ const [frameSize, setFrameSize] = React.useState(0);
+ const webViewRef = React.useRef(null);
+ const source =
+ Platform.OS === 'android'
+ ? 'file:///android_asset/live-preview/index.html'
+ : './Web.bundle/live-preview/index.html';
- const startLivePreview = async () => {
- setPreviewing(true);
- try {
- const ret = await getLivePreview();
- setPreviewing(false);
- console.log(`live preview done with ${ret}`);
- } catch (error) {
- Alert.alert('getLivePreview', 'error: \n' + JSON.stringify(error), [
- { text: 'OK' },
- ]);
- } finally {
- setPreviewing(false);
- }
- };
+ const startLivePreview = async () => {
+ setPreviewing(true);
+ console.log('Starting live preview...');
+ try {
+ const ret = await getLivePreview();
+ setPreviewing(false);
+ console.log(`live preview done with ${ret}`);
+ } catch (error: unknown) {
+ setPreviewing(false);
+ console.log('getLivePreview error: ' + JSON.stringify(error));
+ const errStr = error instanceof Error ? error.message : String(error);
+ const message =
+ errStr.includes('serviceUnavailable') || errStr.includes('503')
+ ? 'Please check if the THETA is in sleep mode.'
+ : 'Failed to start live preview.';
+ Alert.alert('getLivePreview', message, [{ text: 'OK' }]);
+ }
+ };
- const setFrameData = (data: string) => {
- if (isLoaded && webViewRef.current) {
- webViewRef.current.injectJavaScript(`
- setFrame('${data}');true
- `);
- }
- };
+ const setFrameData = (data: string) => {
+ console.log('setFrameData called, data length:', data?.length || 0);
+ if (!data || typeof data !== 'string' || !data.startsWith('data:')) {
+ return;
+ }
+ if (isLoaded && webViewRef.current) {
+ // JSON.stringify to avoid breaking the injected script (quotes, backslashes, length)
+ const escaped = JSON.stringify(data);
+ webViewRef.current.injectJavaScript(`setFrame(${escaped});true`);
+ } else {
+ console.log('Cannot set frame data:', { isLoaded, hasWebView: !!webViewRef.current });
+ }
+ };
- const onStart = () => {
- startLivePreview();
- };
+ const onStart = () => {
+ startLivePreview();
+ };
- const onStop = () => {
- isInitialized().then((isInit) => {
- if (isInit) {
- stopLivePreview().then((isStopped) => {
- console.log(`isStop = ${isStopped}`);
+ const onStop = () => {
+ isInitialized().then((isInit) => {
+ if (isInit) {
+ stopLivePreview().then((isStopped) => {
+ console.log(`isStop = ${isStopped}`);
+ });
+ } else {
+ Alert.alert('stopLivePreview', 'error: Not initialized.', [
+ { text: 'OK' },
+ ]);
+ }
});
- } else {
- Alert.alert('stopLivePreview', 'error: Not initialized.', [
- { text: 'OK' },
- ]);
- }
- });
- };
+ };
- const onLoad = () => {
- console.log('onLoad');
- setLoaded(true);
- };
+ const onLoad = () => {
+ console.log('onLoad');
+ setLoaded(true);
+ };
- React.useEffect(() => {
- if (isFocused) {
- const emitter = new NativeEventEmitter(
- NativeModules.ThetaClientReactNative
- );
- const eventListener = emitter.addListener(THETA_EVENT_NAME, (event) => {
- setDataUrl(event.data);
- setFrameSize(event.dataSize);
- });
- return () => {
- isInitialized().then((isInit) => {
- if (isInit) {
- stopLivePreview();
- }
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'Live Preview' });
+ }, [navigation]);
+
+ React.useEffect(() => {
+ const emitter = new NativeEventEmitter(
+ NativeModules.ThetaClientReactNative
+ );
+ const eventListener = emitter.addListener(THETA_EVENT_NAME, (event) => {
+ setDataUrl(event.data);
+ setFrameSize(event.dataSize);
});
- eventListener.remove();
- };
- }
- return;
- }, [isFocused]);
+ return () => {
+ isInitialized().then((isInit) => {
+ if (isInit) {
+ stopLivePreview();
+ }
+ });
+ eventListener.remove();
+ };
+ }, []);
- React.useEffect(() => {
- if (isLoaded && dataUrl) {
- setFrameData(dataUrl);
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [dataUrl, isLoaded]);
+ React.useEffect(() => {
+ if (isLoaded && dataUrl) {
+ setFrameData(dataUrl);
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [dataUrl, isLoaded]);
- return (
-
-
-
-
-
-
- {previewing ? 'Previewing...' : 'Stopped'} ({frameSize} byte)
-
-
-
-
+ return (
+
+
+
+
+
+
+ {previewing ? 'Previewing...' : 'Stopped'} ({frameSize} byte)
+
+
+
+
+
+
-
-
- );
+ );
};
export default LivePreviewScreen;
diff --git a/react-native/verification-tool/src/screen/live-preview-screen/styles.tsx b/react-native/verification-tool/src/screen/live-preview-screen/styles.tsx
index 2a8ba80c93b..29ed96cb422 100644
--- a/react-native/verification-tool/src/screen/live-preview-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/live-preview-screen/styles.tsx
@@ -1,49 +1,49 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- container: {
- flex: 1,
- justifyContent: 'center',
- alignItems: 'center',
- backgroundColor: 'white',
- },
- takePhotoBack: {
- flex: 1,
- backgroundColor: 'white',
- },
- takePhoto: {
- width: '100%',
- height: '100%',
- backgroundColor: 'white',
- resizeMode: 'contain',
- zIndex: 0,
- },
- contentContainer: {
- flex: 1,
- },
- bottomViewContainer: {
- height: 100,
- alignItems: 'center',
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- button: {
- width: 150,
- paddingHorizontal: 10,
- },
- webview: {
- width: '100%',
- height: '100%',
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ container: {
+ flex: 1,
+ justifyContent: 'center',
+ alignItems: 'center',
+ backgroundColor: 'white',
+ },
+ takePhotoBack: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ takePhoto: {
+ width: '100%',
+ height: '100%',
+ backgroundColor: 'white',
+ resizeMode: 'contain',
+ zIndex: 0,
+ },
+ contentContainer: {
+ flex: 1,
+ },
+ bottomViewContainer: {
+ height: 100,
+ alignItems: 'center',
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ button: {
+ width: 150,
+ paddingHorizontal: 10,
+ },
+ webview: {
+ width: '100%',
+ height: '100%',
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/menu-screen/index.ts b/react-native/verification-tool/src/screen/menu-screen/index.ts
index dd3fd067dd3..2581e55f8b1 100644
--- a/react-native/verification-tool/src/screen/menu-screen/index.ts
+++ b/react-native/verification-tool/src/screen/menu-screen/index.ts
@@ -1 +1,2 @@
-export { default } from './menu-screen';
+import MenuScreen from './menu-screen';
+export default MenuScreen;
diff --git a/react-native/verification-tool/src/screen/menu-screen/menu-screen.tsx b/react-native/verification-tool/src/screen/menu-screen/menu-screen.tsx
index 8600698c859..6472e373003 100644
--- a/react-native/verification-tool/src/screen/menu-screen/menu-screen.tsx
+++ b/react-native/verification-tool/src/screen/menu-screen/menu-screen.tsx
@@ -1,224 +1,226 @@
import React from 'react';
import { StatusBar, View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
import { getThetaModel, initialize } from '../../modules/theta-client';
-import styles from './styles';
import Button from '../../components/ui/button';
-import { ItemListPopupView } from '../../components/ui/item-list/item-list-popup-view';
-import type { Item } from '../../components/ui/item-list';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
+import { ItemListPopupView, type Item } from '../../components/ui/item-list';
+import styles from './styles.tsx';
interface CaptureItem extends Item {
- value: {
- selectedFunction: () => void;
- };
+ value: {
+ selectedFunction: () => void;
+ };
}
interface FunctionItem extends Item {
- value: {
- selectedFunction: () => void;
- };
+ value: {
+ selectedFunction: () => void;
+ };
}
-const MenuScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [message, setMessage] = React.useState('');
- const [isShowCaptureList, setShowCaptureList] =
- React.useState(false);
+interface MenuScreenProps {
+ navigation: {
+ navigate: (screen: string, params?: any) => void;
+ };
+ message: string;
+ onChangeMessage: (message: string) => void;
+}
- const captureList: CaptureItem[] = [
- {
- name: '・photo capture',
- value: {
- selectedFunction: async () => {
- navigation.navigate('photoCapture');
- },
- },
- },
- {
- name: '・video capture',
- value: {
- selectedFunction: async () => {
- navigation.navigate('videoCapture');
- },
- },
- },
- {
- name: '・time-shift capture',
- value: {
- selectedFunction: async () => {
- navigation.navigate('timeShiftCapture');
- },
- },
- },
- {
- name: '・time-shift manual capture',
- value: {
- selectedFunction: async () => {
- navigation.navigate('timeShiftManualCapture');
- },
- },
- },
- {
- name: '・limitless interval capture',
- value: {
- selectedFunction: async () => {
- navigation.navigate('limitlessIntervalCapture');
- },
- },
- },
- {
- name: '・interval shooting with the shot count specified',
- value: {
- selectedFunction: async () => {
- navigation.navigate('shotCountSpecifiedIntervalCapture');
- },
- },
- },
- {
- name: '・interval composite shooting',
- value: {
- selectedFunction: async () => {
- navigation.navigate('compositeIntervalCapture');
- },
- },
- },
- {
- name: '・burst shooting',
- value: {
- selectedFunction: async () => {
- navigation.navigate('burstCapture');
- },
- },
- },
- {
- name: '・multi bracket shooting',
- value: {
- selectedFunction: async () => {
- navigation.navigate('multiBracketCapture');
- },
- },
- },
- {
- name: '・continuous shooting',
- value: {
- selectedFunction: async () => {
- navigation.navigate('continuousCapture');
- },
- },
- },
- ];
+const MenuScreen: React.FC = ({
+ navigation,
+ message,
+ onChangeMessage,
+}) => {
+ const [isShowCaptureList, setShowCaptureList] =
+ React.useState(false);
- const functionList: FunctionItem[] = [
- {
- name: 'Get Info',
- value: {
- selectedFunction: () => navigation.navigate('getInfo'),
- },
- },
- {
- name: 'listFiles',
- value: {
- selectedFunction: () => navigation.navigate('listFiles'),
- },
- },
- {
- name: 'DeleteFiles',
- value: {
- selectedFunction: () => navigation.navigate('deleteFiles'),
- },
- },
- {
- name: 'getMetadata',
- value: {
- selectedFunction: () => navigation.navigate('getMetadata'),
- },
- },
- {
- name: 'Options',
- value: {
- selectedFunction: () => navigation.navigate('options'),
- },
- },
- {
- name: 'Live preview',
- value: {
- selectedFunction: () => navigation.navigate('livePreview'),
- },
- },
- {
- name: 'Video Convert',
- value: {
- selectedFunction: () => navigation.navigate('videoConvert'),
- },
- },
- {
- name: 'Commands',
- value: {
- selectedFunction: () => navigation.navigate('commands'),
- },
- },
- {
- name: 'Capture',
- value: {
- selectedFunction: () => setShowCaptureList(true),
- },
- },
- ];
+ const captureList: CaptureItem[] = [
+ {
+ name: '・photo capture',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('photoCapture');
+ },
+ },
+ },
+ {
+ name: '・video capture',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('videoCapture');
+ },
+ },
+ },
+ {
+ name: '・time-shift capture',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('timeShiftCapture');
+ },
+ },
+ },
+ {
+ name: '・time-shift manual capture',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('timeShiftManualCapture');
+ },
+ },
+ },
+ {
+ name: '・limitless interval capture',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('limitlessIntervalCapture');
+ },
+ },
+ },
+ {
+ name: '・interval shooting with the shot count specified',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('shotCountSpecifiedIntervalCapture');
+ },
+ },
+ },
+ {
+ name: '・interval composite shooting',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('compositeIntervalCapture');
+ },
+ },
+ },
+ {
+ name: '・burst shooting',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('burstCapture');
+ },
+ },
+ },
+ {
+ name: '・multi bracket shooting',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('multiBracketCapture');
+ },
+ },
+ },
+ {
+ name: '・continuous shooting',
+ value: {
+ selectedFunction: async () => {
+ navigation.navigate('continuousCapture');
+ },
+ },
+ },
+ ];
+
+ const functionList: FunctionItem[] = [
+ {
+ name: 'Get Info',
+ value: {
+ selectedFunction: () => navigation.navigate('getInfo'),
+ },
+ },
+ {
+ name: 'listFiles',
+ value: {
+ selectedFunction: () => navigation.navigate('listFiles', { reset: true }),
+ },
+ },
+ {
+ name: 'DeleteFiles',
+ value: {
+ selectedFunction: () => navigation.navigate('deleteFiles'),
+ },
+ },
+ {
+ name: 'getMetadata',
+ value: {
+ selectedFunction: () => navigation.navigate('getMetadata'),
+ },
+ },
+ {
+ name: 'Options',
+ value: {
+ selectedFunction: () => navigation.navigate('options'),
+ },
+ },
+ {
+ name: 'Live preview',
+ value: {
+ selectedFunction: () => navigation.navigate('livePreview'),
+ },
+ },
+ {
+ name: 'Video Convert',
+ value: {
+ selectedFunction: () => navigation.navigate('videoConvert'),
+ },
+ },
+ {
+ name: 'Commands',
+ value: {
+ selectedFunction: () => navigation.navigate('commands'),
+ },
+ },
+ {
+ name: 'Capture',
+ value: {
+ selectedFunction: () => setShowCaptureList(true),
+ },
+ },
+ ];
- const functionItems = functionList.map((item) => (
-
-
- item.value.selectedFunction()} />
-
- ));
+ const functionItems = functionList.map((item) => (
+
+
+ item.value.selectedFunction()} />
+
+ ));
- const initTheta = async () => {
- try {
- const endpoint = 'http://192.168.1.1';
- await initialize(endpoint);
- const model = await getThetaModel();
- console.log('Connected.');
- setMessage(`Connected.\nModel: ${model}`);
- } catch (error) {
- console.log('init error: ' + JSON.stringify(error));
- setMessage('Connect error.');
- Alert.alert('initialize', 'error');
- }
- };
+ const initTheta = async () => {
+ try {
+ const endpoint = 'http://192.168.1.1';
+ await initialize(endpoint);
+ const model = await getThetaModel();
+ console.log('Connected.');
+ onChangeMessage(`Connected.\nModel: ${model}`);
+ } catch (error) {
+ console.log('Connect error: ' + error);
+ onChangeMessage('Connect error: ' + error);
+ Alert.alert('initialize', 'error');
+ }
+ };
- const onPressConnect = () => {
- initTheta();
- };
+ const onPressConnect = () => {
+ initTheta();
+ };
- const onSelectedCapture = (captureItem: CaptureItem) => {
- setShowCaptureList(false);
- captureItem.value.selectedFunction();
- };
+ const onSelectedCapture = (captureItem: CaptureItem) => {
+ setShowCaptureList(false);
+ captureItem.value.selectedFunction();
+ };
- return (
-
-
-
-
-
- {message}
-
-
-
- {functionItems}
-
- );
+ return (
+
+
+
+
+
+ {message}
+
+
+
+ {functionItems}
+
+ );
};
export default MenuScreen;
diff --git a/react-native/verification-tool/src/screen/menu-screen/styles.tsx b/react-native/verification-tool/src/screen/menu-screen/styles.tsx
index 001628458d7..d7be642a6da 100644
--- a/react-native/verification-tool/src/screen/menu-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/menu-screen/styles.tsx
@@ -1,39 +1,39 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- alignItems: 'center',
- },
- messageText: {
- flex: 1,
- marginLeft: 4,
- color: 'black',
- },
- messageLayout: {
- width: '100%',
- height: 100,
- alignItems: 'center',
- },
- messageArea: {
- width: '90%',
- height: 100,
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- },
- container: {
- width: '80%',
- height: 100,
- borderColor: 'gray',
- borderWidth: 1,
- margin: 10,
- padding: 5,
- },
- spacer: {
- height: 8,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ alignItems: 'center',
+ },
+ messageText: {
+ flex: 1,
+ marginLeft: 4,
+ color: 'black',
+ },
+ messageLayout: {
+ width: '100%',
+ height: 100,
+ alignItems: 'center',
+ },
+ messageArea: {
+ width: '90%',
+ height: 100,
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ },
+ container: {
+ width: '80%',
+ height: 100,
+ borderColor: 'gray',
+ borderWidth: 1,
+ margin: 10,
+ padding: 5,
+ },
+ spacer: {
+ height: 8,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/index.ts b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/index.ts
index 7dd4d48d416..7004bb41c5c 100644
--- a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/index.ts
+++ b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/index.ts
@@ -1 +1 @@
-export { default } from './multi-bracket-capture-screen';
+export { default } from './multi-bracket-capture-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/multi-bracket-capture-screen.tsx b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/multi-bracket-capture-screen.tsx
index 071e11b46e6..df995a08c44 100644
--- a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/multi-bracket-capture-screen.tsx
+++ b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/multi-bracket-capture-screen.tsx
@@ -1,257 +1,255 @@
import React from 'react';
-import { View, Alert, ScrollView, Text } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { View, Alert, ScrollView, Text, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- CaptureModeEnum,
- CapturingStatusEnum,
- ExposureDelayEnum,
- MultiBracketCapture,
- OptionNameEnum,
- Options,
- getMultiBracketCaptureBuilder,
- getOptions,
- setOptions,
- stopSelfTimer,
+ CaptureModeEnum,
+ CapturingStatusEnum,
+ ExposureDelayEnum,
+ MultiBracketCapture,
+ OptionNameEnum,
+ Options,
+ getMultiBracketCaptureBuilder,
+ getOptions,
+ setOptions,
+ stopSelfTimer,
} from '../../modules/theta-client';
import { AutoBracketEdit } from '../../components/options/auto-bracket';
import { InputNumber } from '../../components/ui/input-number';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
import { EnumEdit } from '../../components/options';
-const MultiBracketCaptureScreen: React.FC<
- NativeStackScreenProps
-> = ({ navigation }) => {
- const [interval, setInterval] = React.useState();
- const [message, setMessage] = React.useState('');
- const [capturingStatus, setCapturingStatus] =
- React.useState();
- const [progress, setProgress] = React.useState();
- const [captureOptions, setCaptureOptions] = React.useState();
- const [isTaking, setIsTaking] = React.useState(false);
- const [capture, setCapture] = React.useState();
-
- const onTake = async () => {
- if (isTaking) {
- return;
- }
-
- const builder = getMultiBracketCaptureBuilder();
- if (interval != null) {
- builder.setCheckStatusCommandInterval(interval);
- }
- captureOptions?.exposureDelay &&
- builder.setExposureDelay(captureOptions.exposureDelay);
- captureOptions?.autoBracket &&
- builder.setBracketSettings(captureOptions.autoBracket);
-
- console.log('MultiBracketCapture interval: ' + interval);
- console.log(
- 'MultiBracketCapture options: ' + JSON.stringify(captureOptions)
- );
- console.log('MultiBracketCapture builder: ' + JSON.stringify(builder));
+interface MultiBracketCaptureScreenProps {
+ navigation: {
+ setOptions: (options: { title: string }) => void;
+ };
+}
+
+const MultiBracketCaptureScreen: React.FC = ({ navigation }) => {
+ const [interval, setInterval] = React.useState();
+ const [message, setMessage] = React.useState('');
+ const [capturingStatus, setCapturingStatus] =
+ React.useState();
+ const [progress, setProgress] = React.useState();
+ const [captureOptions, setCaptureOptions] = React.useState();
+ const [isTaking, setIsTaking] = React.useState(false);
+ const [capture, setCapture] = React.useState();
+
+ const onTake = async () => {
+ if (isTaking) {
+ return;
+ }
- try {
- setCapture(await builder.build());
- setIsTaking(false);
- } catch (error) {
- setIsTaking(false);
- if (error instanceof Error) {
- Alert.alert(
- 'MultiBracketCaptureBuilder build error',
- error.name + ': ' + error.message,
- [{ text: 'OK' }]
+ const builder = getMultiBracketCaptureBuilder();
+ if (interval != null) {
+ builder.setCheckStatusCommandInterval(interval);
+ }
+ captureOptions?.exposureDelay &&
+ builder.setExposureDelay(captureOptions.exposureDelay);
+ captureOptions?.autoBracket &&
+ builder.setBracketSettings(captureOptions.autoBracket);
+
+ console.log('MultiBracketCapture interval: ' + interval);
+ console.log(
+ 'MultiBracketCapture options: ' + JSON.stringify(captureOptions)
);
- }
- }
- };
-
- const initCapture = () => {
- setCapture(undefined);
- setIsTaking(false);
- };
-
- const startCapture = async () => {
- if (capture == null) {
- initCapture();
- return;
- }
- setProgress(undefined);
- setCapturingStatus(undefined);
- try {
- console.log('MultiBracketCapture startCapture');
- const urls = await capture.startCapture(
- (completion) => {
- if (isTaking) return;
- setProgress(completion);
- },
- (error) => {
- if (error instanceof Error) {
- Alert.alert('Cancel error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- },
- (status) => {
- setCapturingStatus(status);
+ console.log('MultiBracketCapture builder: ' + JSON.stringify(builder));
+
+ try {
+ setCapture(await builder.build());
+ setIsTaking(false);
+ } catch (error) {
+ setIsTaking(false);
+ if (error instanceof Error) {
+ Alert.alert(
+ 'MultiBracketCaptureBuilder build error',
+ error.name + ': ' + error.message,
+ [{ text: 'OK' }]
+ );
+ }
}
- );
- initCapture();
- if (urls) {
- Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
- { text: 'OK' },
- ]);
- } else {
- Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
- }
- } catch (error) {
- initCapture();
- if (error instanceof Error) {
- Alert.alert('startCapture error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
-
- const onCancel = async () => {
- if (capture == null) {
- return;
- }
- console.log('ready to cancel...');
- try {
- capture.cancelCapture();
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('stopCapture error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
+ };
- const onStopSelfTimer = async () => {
- try {
- await stopSelfTimer();
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('stopSelfTimer error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
+ const initCapture = () => {
+ setCapture(undefined);
+ setIsTaking(false);
+ };
- const onGetAutoBracket = async () => {
- try {
- const res = await getOptions([OptionNameEnum.AutoBracket]);
- if (res?.autoBracket) {
- setCaptureOptions((prevState) => ({
- ...prevState,
- autoBracket: res.autoBracket,
- }));
- }
- } catch (error) {
- if (error instanceof Error) {
- Alert.alert('getOptions error', error.name + ': ' + error.message, [
- { text: 'OK' },
- ]);
- }
- }
- };
-
- React.useEffect(() => {
- setOptions({ captureMode: CaptureModeEnum.IMAGE }).catch();
- }, []);
+ const startCapture = async () => {
+ if (capture == null) {
+ initCapture();
+ return;
+ }
+ setProgress(undefined);
+ setCapturingStatus(undefined);
+ try {
+ console.log('MultiBracketCapture startCapture');
+ const urls = await capture.startCapture(
+ (completion) => {
+ if (isTaking) { return; }
+ setProgress(completion);
+ },
+ (error) => {
+ if (error instanceof Error) {
+ Alert.alert('Cancel error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ },
+ (status) => {
+ setCapturingStatus(status);
+ }
+ );
+ initCapture();
+ if (urls) {
+ Alert.alert(`file ${urls.length} urls : `, urls.join('\n'), [
+ { text: 'OK' },
+ ]);
+ } else {
+ Alert.alert('Capture', 'Capture cancel', [{ text: 'OK' }]);
+ }
+ } catch (error) {
+ initCapture();
+ if (error instanceof Error) {
+ Alert.alert('startCapture error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
- React.useEffect(() => {
- navigation.setOptions({ title: 'MultiBracket Capture' });
- }, [navigation]);
+ const onCancel = async () => {
+ if (capture == null) {
+ return;
+ }
+ console.log('ready to cancel...');
+ try {
+ capture.cancelCapture();
+ } catch (error) {
+ if (error instanceof Error) {
+ Alert.alert('stopCapture error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
+
+ const onStopSelfTimer = async () => {
+ try {
+ await stopSelfTimer();
+ } catch (error) {
+ if (error instanceof Error) {
+ Alert.alert('stopSelfTimer error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
+
+ const onGetAutoBracket = async () => {
+ try {
+ const res = await getOptions([OptionNameEnum.AutoBracket]);
+ if (res?.autoBracket) {
+ setCaptureOptions((prevState) => ({
+ ...prevState,
+ autoBracket: res.autoBracket,
+ }));
+ }
+ } catch (error) {
+ if (error instanceof Error) {
+ Alert.alert('getOptions error', error.name + ': ' + error.message, [
+ { text: 'OK' },
+ ]);
+ }
+ }
+ };
- React.useEffect(() => {
- if (capture != null && !isTaking) {
- setIsTaking(true);
- startCapture();
- }
- // eslint-disable-next-line react-hooks/exhaustive-deps
- }, [capture]);
+ React.useEffect(() => {
+ setOptions({ captureMode: CaptureModeEnum.IMAGE }).catch();
+ }, []);
- React.useEffect(() => {
- setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
- }, [capturingStatus, progress]);
+ React.useEffect(() => {
+ navigation.setOptions({ title: 'MultiBracket Capture' });
+ }, [navigation]);
- return (
-
-
- {message}
-
-
-
-
-
-
-
-
-
-
-
- {
- setInterval(value);
- }}
- />
- {
- setCaptureOptions((prevState) => ({
- ...prevState,
- exposureDelay,
- }));
- }}
- optionEnum={ExposureDelayEnum}
- />
- {
- setCaptureOptions((prevState) => ({
- ...prevState,
- autoBracket: option.autoBracket,
- }));
- }}
- options={captureOptions}
- />
-
-
-
- );
+ React.useEffect(() => {
+ if (capture != null && !isTaking) {
+ setIsTaking(true);
+ startCapture();
+ }
+ // eslint-disable-next-line react-hooks/exhaustive-deps
+ }, [capture]);
+
+ React.useEffect(() => {
+ setMessage(`progress = ${progress}\ncapturing = ${capturingStatus}`);
+ }, [capturingStatus, progress]);
+
+ return (
+
+
+ {message}
+
+
+
+
+
+
+
+
+
+
+
+ {
+ setInterval(value);
+ }}
+ />
+ {
+ setCaptureOptions((prevState) => ({
+ ...prevState,
+ exposureDelay,
+ }));
+ }}
+ optionEnum={ExposureDelayEnum}
+ />
+ {
+ setCaptureOptions((prevState) => ({
+ ...prevState,
+ autoBracket: option.autoBracket,
+ }));
+ }}
+ options={captureOptions}
+ />
+
+
+
+ );
};
export default MultiBracketCaptureScreen;
diff --git a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/styles.tsx b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/styles.tsx
index a28be803cda..ea42f453f63 100644
--- a/react-native/verification-tool/src/screen/multi-bracket-capture-screen/styles.tsx
+++ b/react-native/verification-tool/src/screen/multi-bracket-capture-screen/styles.tsx
@@ -1,33 +1,33 @@
import { StyleSheet } from 'react-native';
const styles = StyleSheet.create({
- safeAreaContainer: {
- flex: 1,
- backgroundColor: 'white',
- },
- topViewContainer: {
- height: 140,
- alignItems: 'center',
- },
- contentContainer: {
- width: '100%',
- height: '85%',
- },
- button: {
- width: 170,
- paddingHorizontal: 10,
- },
- bottomViewContainerLayout: {
- flex: 1,
- flexDirection: 'row',
- alignItems: 'center',
- },
- itemText: {
- color: 'black',
- fontSize: 16,
- paddingHorizontal: 10,
- paddingVertical: 2,
- },
+ safeAreaContainer: {
+ flex: 1,
+ backgroundColor: 'white',
+ },
+ topViewContainer: {
+ height: 140,
+ alignItems: 'center',
+ },
+ contentContainer: {
+ width: '100%',
+ height: '85%',
+ },
+ button: {
+ width: 170,
+ paddingHorizontal: 10,
+ },
+ bottomViewContainerLayout: {
+ flex: 1,
+ flexDirection: 'row',
+ alignItems: 'center',
+ },
+ itemText: {
+ color: 'black',
+ fontSize: 16,
+ paddingHorizontal: 10,
+ paddingVertical: 2,
+ },
});
export default styles;
diff --git a/react-native/verification-tool/src/screen/options-screen/index.ts b/react-native/verification-tool/src/screen/options-screen/index.ts
index 06637891306..04b98696e8a 100644
--- a/react-native/verification-tool/src/screen/options-screen/index.ts
+++ b/react-native/verification-tool/src/screen/options-screen/index.ts
@@ -1 +1 @@
-export { default } from './options-screen';
+export { default } from './options-screen.tsx';
diff --git a/react-native/verification-tool/src/screen/options-screen/options-screen.tsx b/react-native/verification-tool/src/screen/options-screen/options-screen.tsx
index b6371256a26..94b483f631d 100644
--- a/react-native/verification-tool/src/screen/options-screen/options-screen.tsx
+++ b/react-native/verification-tool/src/screen/options-screen/options-screen.tsx
@@ -1,972 +1,973 @@
import React from 'react';
-import { ScrollView, Text, View } from 'react-native';
-import { SafeAreaView } from 'react-native-safe-area-context';
-import styles from './styles';
+import { ScrollView, Text, View, SafeAreaView } from 'react-native';
+import styles from './styles.tsx';
import Button from '../../components/ui/button';
import {
- ApertureEnum,
- BluetoothRoleEnum,
- CameraControlSourceEnum,
- CameraLockEnum,
- CameraPowerEnum,
- CaptureModeEnum,
- ContinuousNumberEnum,
- ExposureCompensationEnum,
- ExposureDelayEnum,
- ExposureProgramEnum,
- FileFormatEnum,
- FilterEnum,
- IsoAutoHighLimitEnum,
- IsoEnum,
- MaxRecordableTimeEnum,
- MicrophoneNoiseReductionEnum,
- ModeMemoryEnum,
- OffDelayEnum,
- OffDelayUsbEnum,
- OptionNameEnum,
- Options,
- PresetEnum,
- PreviewFormatEnum,
- SleepDelayEnum,
- TopBottomCorrectionOptionEnum,
- UsbConnectionEnum,
- VideoStitchingEnum,
- VisibilityReductionEnum,
- WhiteBalanceEnum,
- WlanAntennaConfigEnum,
- getOptions,
- offDelayToSeconds,
- offDelayUsbToSeconds,
- setOptions,
- sleepDelayToSeconds,
- CompassDirectionRefEnum,
- WlanFrequencyEnum,
- NetworkTypeEnum,
+ ApertureEnum,
+ BluetoothRoleEnum,
+ CameraControlSourceEnum,
+ CameraLockEnum,
+ CameraPowerEnum,
+ CaptureModeEnum,
+ ContinuousNumberEnum,
+ ExposureCompensationEnum,
+ ExposureDelayEnum,
+ ExposureProgramEnum,
+ FileFormatEnum,
+ FilterEnum,
+ IsoAutoHighLimitEnum,
+ IsoEnum,
+ MaxRecordableTimeEnum,
+ MicrophoneNoiseReductionEnum,
+ OffDelayEnum,
+ OffDelayUsbEnum,
+ OptionNameEnum,
+ Options,
+ PresetEnum,
+ PreviewFormatEnum,
+ SleepDelayEnum,
+ TopBottomCorrectionOptionEnum,
+ UsbConnectionEnum,
+ VideoStitchingEnum,
+ VisibilityReductionEnum,
+ WhiteBalanceEnum,
+ WlanAntennaConfigEnum,
+ getOptions,
+ offDelayToSeconds,
+ offDelayUsbToSeconds,
+ setOptions,
+ sleepDelayToSeconds,
+ CompassDirectionRefEnum,
+ WlanFrequencyEnum,
+ NetworkTypeEnum,
+ ModeMemoryEnum,
} from '../../modules/theta-client';
import {
- AutoBracketEdit,
- GpsInfoEdit,
- TimeShiftEdit,
- TopBottomCorrectionRotationEdit,
- EnumEdit,
- EthernetConfigEdit,
- WlanFrequencyClModeEdit,
- MobileNetworkSettingEdit,
- CameraLockConfigEdit,
+ AutoBracketEdit,
+ GpsInfoEdit,
+ TimeShiftEdit,
+ TopBottomCorrectionRotationEdit,
+ EnumEdit,
+ EthernetConfigEdit,
+ WlanFrequencyClModeEdit,
+ MobileNetworkSettingEdit,
+ CameraLockConfigEdit,
} from '../../components/options';
import { ItemSelectorView, type Item } from '../../components/ui/item-list';
import { NumberEdit } from '../../components/options/number-edit';
-import type { NativeStackScreenProps } from '@react-navigation/native-stack';
-import type { RootStackParamList } from '../../App';
import { InputNumber } from '../../components/ui/input-number';
interface OptionItem extends Item {
- value: {
- optionName: OptionNameEnum;
- editor?: (
- options: Options,
- onChange: (options: Options) => void
- ) => React.ReactElement;
- defaultValue?: Options;
- onWillSet?: (options: Options) => void;
- };
+ value: {
+ optionName: OptionNameEnum;
+ editor?: (
+ options: Options,
+ onChange: (options: Options) => void
+ ) => React.ReactElement;
+ defaultValue?: Options;
+ onWillSet?: (options: Options) => void;
+ };
}
const optionList: OptionItem[] = [
- {
- name: 'aiAutoThumbnailSupport',
- value: {
- optionName: OptionNameEnum.AiAutoThumbnailSupport,
- },
- },
- {
- name: 'accessInfo',
- value: {
- optionName: OptionNameEnum.AccessInfo,
- },
- },
- {
- name: 'aperture',
- value: {
- optionName: OptionNameEnum.Aperture,
- editor: (options, onChange) => (
- {
- onChange({ aperture });
- }}
- optionEnum={ApertureEnum}
- />
- ),
- defaultValue: { aperture: ApertureEnum.APERTURE_AUTO },
- },
- },
- {
- name: 'apertureSupport',
- value: {
- optionName: OptionNameEnum.ApertureSupport,
- },
- },
- {
- name: 'autoBracket',
- value: {
- optionName: OptionNameEnum.AutoBracket,
- editor: (options, onChange) => (
-
-
-
- ),
- },
- },
- {
- name: 'bluetoothRole',
- value: {
- optionName: OptionNameEnum.BluetoothRole,
- editor: (options, onChange) => (
- {
- onChange({ bluetoothRole });
- }}
- optionEnum={BluetoothRoleEnum}
- />
- ),
- },
- },
- {
- name: 'cameraControlSource',
- value: {
- optionName: OptionNameEnum.CameraControlSource,
- editor: (options, onChange) => (
- {
- onChange({ cameraControlSource });
- }}
- optionEnum={CameraControlSourceEnum}
- />
- ),
- defaultValue: { cameraControlSource: CameraControlSourceEnum.CAMERA },
- },
- },
- {
- name: 'cameraControlSourceSupport',
- value: {
- optionName: OptionNameEnum.CameraControlSourceSupport,
- },
- },
- {
- name: 'cameraLock',
- value: {
- optionName: OptionNameEnum.CameraLock,
- editor: (options, onChange) => (
- {
- onChange({ cameraLock });
- }}
- optionEnum={CameraLockEnum}
- />
- ),
- },
- },
- {
- name: 'cameraLockConfig',
- value: {
- optionName: OptionNameEnum.CameraLockConfig,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'cameraPower',
- value: {
- optionName: OptionNameEnum.CameraPower,
- editor: (options, onChange) => (
- {
- onChange({ cameraPower });
- }}
- optionEnum={CameraPowerEnum}
- />
- ),
- defaultValue: { cameraPower: CameraPowerEnum.ON },
- },
- },
- {
- name: 'cameraPowerSupport',
- value: {
- optionName: OptionNameEnum.CameraPowerSupport,
- },
- },
- {
- name: 'captureMode',
- value: {
- optionName: OptionNameEnum.CaptureMode,
- editor: (options, onChange) => (
- {
- onChange({ captureMode });
- }}
- optionEnum={CaptureModeEnum}
- />
- ),
- defaultValue: { captureMode: CaptureModeEnum.IMAGE },
- },
- },
- {
- name: 'colorTemperature',
- value: {
- optionName: OptionNameEnum.ColorTemperature,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'colorTemperatureSupport',
- value: {
- optionName: OptionNameEnum.ColorTemperatureSupport,
+ {
+ name: 'aiAutoThumbnailSupport',
+ value: {
+ optionName: OptionNameEnum.AiAutoThumbnailSupport,
+ },
+ },
+ {
+ name: 'accessInfo',
+ value: {
+ optionName: OptionNameEnum.AccessInfo,
+ },
+ },
+ {
+ name: 'aperture',
+ value: {
+ optionName: OptionNameEnum.Aperture,
+ editor: (options, onChange) => (
+ {
+ onChange({ aperture });
+ }}
+ optionEnum={ApertureEnum}
+ />
+ ),
+ defaultValue: { aperture: ApertureEnum.APERTURE_AUTO },
+ },
+ },
+ {
+ name: 'apertureSupport',
+ value: {
+ optionName: OptionNameEnum.ApertureSupport,
+ },
+ },
+ {
+ name: 'autoBracket',
+ value: {
+ optionName: OptionNameEnum.AutoBracket,
+ editor: (options, onChange) => (
+
+
+
+ ),
+ },
+ },
+ {
+ name: 'bluetoothRole',
+ value: {
+ optionName: OptionNameEnum.BluetoothRole,
+ editor: (options, onChange) => (
+ {
+ onChange({ bluetoothRole });
+ }}
+ optionEnum={BluetoothRoleEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'cameraControlSource',
+ value: {
+ optionName: OptionNameEnum.CameraControlSource,
+ editor: (options, onChange) => (
+ {
+ onChange({ cameraControlSource });
+ }}
+ optionEnum={CameraControlSourceEnum}
+ />
+ ),
+ defaultValue: { cameraControlSource: CameraControlSourceEnum.CAMERA },
+ },
+ },
+ {
+ name: 'cameraControlSourceSupport',
+ value: {
+ optionName: OptionNameEnum.CameraControlSourceSupport,
+ },
+ },
+ {
+ name: 'cameraLock',
+ value: {
+ optionName: OptionNameEnum.CameraLock,
+ editor: (options, onChange) => (
+ {
+ onChange({ cameraLock });
+ }}
+ optionEnum={CameraLockEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'cameraLockConfig',
+ value: {
+ optionName: OptionNameEnum.CameraLockConfig,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'cameraPower',
+ value: {
+ optionName: OptionNameEnum.CameraPower,
+ editor: (options, onChange) => (
+ {
+ onChange({ cameraPower });
+ }}
+ optionEnum={CameraPowerEnum}
+ />
+ ),
+ defaultValue: { cameraPower: CameraPowerEnum.ON },
+ },
+ },
+ {
+ name: 'cameraPowerSupport',
+ value: {
+ optionName: OptionNameEnum.CameraPowerSupport,
+ },
+ },
+ {
+ name: 'captureMode',
+ value: {
+ optionName: OptionNameEnum.CaptureMode,
+ editor: (options, onChange) => (
+ {
+ onChange({ captureMode });
+ }}
+ optionEnum={CaptureModeEnum}
+ />
+ ),
+ defaultValue: { captureMode: CaptureModeEnum.IMAGE },
+ },
+ },
+ {
+ name: 'colorTemperature',
+ value: {
+ optionName: OptionNameEnum.ColorTemperature,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'colorTemperatureSupport',
+ value: {
+ optionName: OptionNameEnum.ColorTemperatureSupport,
+ },
+ },
+ {
+ name: 'compositeShootingOutputIntervalSupport',
+ value: {
+ optionName: OptionNameEnum.CompositeShootingOutputIntervalSupport,
+ },
+ },
+ {
+ name: 'compositeShootingTime',
+ value: {
+ optionName: OptionNameEnum.CompositeShootingTime,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'compassDirectionRef',
+ value: {
+ optionName: OptionNameEnum.CompassDirectionRef,
+ editor: (options, onChange) => (
+ {
+ onChange({ compassDirectionRef });
+ }}
+ optionEnum={CompassDirectionRefEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'compositeShootingTimeSupport',
+ value: {
+ optionName: OptionNameEnum.CompositeShootingTimeSupport,
+ },
+ },
+ {
+ name: 'continuousNumber',
+ value: {
+ optionName: OptionNameEnum.ContinuousNumber,
+ editor: (options, onChange) => (
+ {
+ onChange({ continuousNumber });
+ }}
+ optionEnum={ContinuousNumberEnum}
+ />
+ ),
+ defaultValue: { continuousNumber: ContinuousNumberEnum.OFF },
+ },
+ },
+ {
+ name: 'ethernetConfig',
+ value: {
+ optionName: OptionNameEnum.EthernetConfig,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'exposureCompensation',
+ value: {
+ optionName: OptionNameEnum.ExposureCompensation,
+ editor: (options, onChange) => (
+ {
+ onChange({ exposureCompensation });
+ }}
+ optionEnum={ExposureCompensationEnum}
+ />
+ ),
+ defaultValue: { exposureCompensation: ExposureCompensationEnum.ZERO },
+ },
+ },
+ {
+ name: 'exposureDelay',
+ value: {
+ optionName: OptionNameEnum.ExposureDelay,
+ editor: (options, onChange) => (
+ {
+ onChange({ exposureDelay });
+ }}
+ optionEnum={ExposureDelayEnum}
+ />
+ ),
+ defaultValue: { exposureDelay: ExposureDelayEnum.DELAY_OFF },
+ },
+ },
+ {
+ name: 'exposureDelaySupport',
+ value: {
+ optionName: OptionNameEnum.ExposureDelaySupport,
+ },
+ },
+ {
+ name: 'exposureProgram',
+ value: {
+ optionName: OptionNameEnum.ExposureProgram,
+ editor: (options, onChange) => (
+ {
+ onChange({ exposureProgram });
+ }}
+ optionEnum={ExposureProgramEnum}
+ />
+ ),
+ defaultValue: { exposureProgram: ExposureProgramEnum.NORMAL_PROGRAM },
+ },
+ },
+ {
+ name: 'filter',
+ value: {
+ optionName: OptionNameEnum.Filter,
+ editor: (options, onChange) => (
+ {
+ onChange({ filter });
+ }}
+ optionEnum={FilterEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'fileFormat',
+ value: {
+ optionName: OptionNameEnum.FileFormat,
+ editor: (options, onChange) => (
+ {
+ onChange({ fileFormat });
+ }}
+ optionEnum={FileFormatEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'gpsInfo',
+ value: {
+ optionName: OptionNameEnum.GpsInfo,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'gpsTagRecordingSupport',
+ value: {
+ optionName: OptionNameEnum.GpsTagRecordingSupport,
+ },
+ },
+ {
+ name: 'iso',
+ value: {
+ optionName: OptionNameEnum.Iso,
+ editor: (options, onChange) => (
+ {
+ onChange({ iso });
+ }}
+ optionEnum={IsoEnum}
+ />
+ ),
+ defaultValue: { iso: IsoEnum.ISO_AUTO },
+ },
+ },
+ {
+ name: 'isoAutoHighLimit',
+ value: {
+ optionName: OptionNameEnum.IsoAutoHighLimit,
+ editor: (options, onChange) => (
+ {
+ onChange({ isoAutoHighLimit });
+ }}
+ optionEnum={IsoAutoHighLimitEnum}
+ />
+ ),
+ defaultValue: { isoAutoHighLimit: IsoAutoHighLimitEnum.ISO_100 },
+ },
+ },
+ {
+ name: 'latestEnabledExposureDelayTime',
+ value: {
+ optionName: OptionNameEnum.LatestEnabledExposureDelayTime,
+ },
+ },
+ {
+ name: 'maxRecordableTime',
+ value: {
+ optionName: OptionNameEnum.MaxRecordableTime,
+ editor: (options, onChange) => (
+ {
+ onChange({ maxRecordableTime });
+ }}
+ optionEnum={MaxRecordableTimeEnum}
+ />
+ ),
+ defaultValue: {
+ maxRecordableTime: MaxRecordableTimeEnum.RECORDABLE_TIME_1500,
+ },
+ },
+ },
+ {
+ name: 'microphoneNoiseReduction',
+ value: {
+ optionName: OptionNameEnum.MicrophoneNoiseReduction,
+ editor: (options, onChange) => (
+ {
+ onChange({ microphoneNoiseReduction });
+ }}
+ optionEnum={MicrophoneNoiseReductionEnum}
+ />
+ ),
+ defaultValue: {
+ microphoneNoiseReduction: MicrophoneNoiseReductionEnum.ON,
+ },
+ },
+ },
+ {
+ name: 'mobileNetworkSetting',
+ value: {
+ optionName: OptionNameEnum.MobileNetworkSetting,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'modeMemory',
+ value: {
+ optionName: OptionNameEnum.ModeMemory,
+ editor: (options, onChange) => (
+ {
+ onChange({ modeMemory });
+ }}
+ optionEnum={ModeMemoryEnum}
+ />
+ ),
+ defaultValue: {
+ modeMemory: ModeMemoryEnum.ON,
+ },
+ },
+ },
+ {
+ name: 'networkType',
+ value: {
+ optionName: OptionNameEnum.NetworkType,
+ editor: (options, onChange) => (
+ {
+ onChange({ networkType });
+ }}
+ optionEnum={NetworkTypeEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'offDelay enum',
+ value: {
+ optionName: OptionNameEnum.OffDelay,
+ editor: (options, onChange) => (
+ {
+ onChange({ offDelay });
+ }}
+ optionEnum={OffDelayEnum}
+ />
+ ),
+ defaultValue: { offDelay: OffDelayEnum.DISABLE },
+ },
+ },
+ {
+ name: 'offDelay number',
+ value: {
+ optionName: OptionNameEnum.OffDelay,
+ editor: (options, onChange) => (
+ {
+ onChange({ offDelay: newValue });
+ }}
+ value={
+ typeof options.offDelay === 'string'
+ ? offDelayToSeconds(options.offDelay as OffDelayEnum)
+ : typeof options.offDelay === 'number'
+ ? options.offDelay
+ : 0
+ }
+ />
+ ),
+ onWillSet: (options: Options) => {
+ if (typeof options.offDelay === 'string') {
+ options.offDelay = offDelayToSeconds(
+ options.offDelay as OffDelayEnum
+ );
+ }
+ },
+ },
+ },
+ {
+ name: 'offDelayUsb enum',
+ value: {
+ optionName: OptionNameEnum.OffDelayUsb,
+ editor: (options, onChange) => (
+ {
+ onChange({ offDelayUsb });
+ }}
+ optionEnum={OffDelayUsbEnum}
+ />
+ ),
+ defaultValue: { offDelayUsb: OffDelayUsbEnum.DISABLE },
+ },
+ },
+ {
+ name: 'offDelayUsb number',
+ value: {
+ optionName: OptionNameEnum.OffDelayUsb,
+ editor: (options, onChange) => (
+ {
+ onChange({ offDelayUsb: newValue });
+ }}
+ value={
+ typeof options.offDelayUsb === 'string'
+ ? offDelayUsbToSeconds(options.offDelayUsb as OffDelayUsbEnum)
+ : typeof options.offDelayUsb === 'number'
+ ? options.offDelayUsb
+ : 0
+ }
+ />
+ ),
+ onWillSet: (options: Options) => {
+ if (typeof options.offDelayUsb === 'string') {
+ options.offDelay = offDelayUsbToSeconds(
+ options.offDelayUsb as OffDelayUsbEnum
+ );
+ }
+ },
+ },
+ },
+ {
+ name: 'preset',
+ value: {
+ optionName: OptionNameEnum.Preset,
+ editor: (options, onChange) => (
+ {
+ onChange({ preset });
+ }}
+ optionEnum={PresetEnum}
+ />
+ ),
+ defaultValue: { preset: PresetEnum.FACE },
+ },
+ },
+ {
+ name: 'previewFormat',
+ value: {
+ optionName: OptionNameEnum.PreviewFormat,
+ editor: (options, onChange) => (
+ {
+ onChange({ previewFormat });
+ }}
+ optionEnum={PreviewFormatEnum}
+ />
+ ),
+ defaultValue: { previewFormat: PreviewFormatEnum.W1024_H512_F30 },
+ },
+ },
+ {
+ name: 'sleepDelay enum',
+ value: {
+ optionName: OptionNameEnum.SleepDelay,
+ editor: (options, onChange) => (
+ {
+ onChange({ sleepDelay });
+ }}
+ optionEnum={SleepDelayEnum}
+ />
+ ),
+ defaultValue: { sleepDelay: SleepDelayEnum.DISABLE },
+ },
+ },
+ {
+ name: 'sleepDelay number',
+ value: {
+ optionName: OptionNameEnum.SleepDelay,
+ editor: (options, onChange) => (
+ {
+ onChange({ sleepDelay: newValue });
+ }}
+ value={
+ typeof options.sleepDelay === 'string'
+ ? sleepDelayToSeconds(options.sleepDelay as SleepDelayEnum)
+ : typeof options.sleepDelay === 'number'
+ ? options.sleepDelay
+ : 0
+ }
+ />
+ ),
+ onWillSet: (options: Options) => {
+ if (typeof options.sleepDelay === 'string') {
+ options.sleepDelay = sleepDelayToSeconds(
+ options.sleepDelay as SleepDelayEnum
+ );
+ }
+ },
+ },
+ },
+ {
+ name: 'timeShift',
+ value: {
+ optionName: OptionNameEnum.TimeShift,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'topBottomCorrection',
+ value: {
+ optionName: OptionNameEnum.TopBottomCorrection,
+ editor: (options, onChange) => (
+ {
+ onChange({ topBottomCorrection });
+ }}
+ optionEnum={TopBottomCorrectionOptionEnum}
+ />
+ ),
+ defaultValue: {
+ topBottomCorrection: TopBottomCorrectionOptionEnum.APPLY_AUTO,
+ },
+ },
+ },
+ {
+ name: 'topBottomCorrectionRotation',
+ value: {
+ optionName: OptionNameEnum.TopBottomCorrectionRotation,
+ editor: (options, onChange) => (
+
+ ),
+ },
+ },
+ {
+ name: 'usbConnection',
+ value: {
+ optionName: OptionNameEnum.UsbConnection,
+ editor: (options, onChange) => (
+ {
+ onChange({ usbConnection });
+ }}
+ optionEnum={UsbConnectionEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'topBottomCorrectionRotationSupport',
+ value: {
+ optionName: OptionNameEnum.TopBottomCorrectionRotationSupport,
+ },
+ },
+ {
+ name: 'videoStitching',
+ value: {
+ optionName: OptionNameEnum.VideoStitching,
+ editor: (options, onChange) => (
+ {
+ onChange({ videoStitching });
+ }}
+ optionEnum={VideoStitchingEnum}
+ />
+ ),
+ defaultValue: {
+ videoStitching: VideoStitchingEnum.NONE,
+ },
+ },
+ },
+ {
+ name: 'visibilityReduction',
+ value: {
+ optionName: OptionNameEnum.VisibilityReduction,
+ editor: (options, onChange) => (
+ {
+ onChange({ visibilityReduction });
+ }}
+ optionEnum={VisibilityReductionEnum}
+ />
+ ),
+ defaultValue: {
+ visibilityReduction: VisibilityReductionEnum.OFF,
+ },
+ },
+ },
+ {
+ name: 'whiteBalance',
+ value: {
+ optionName: OptionNameEnum.WhiteBalance,
+ editor: (options, onChange) => (
+ {
+ onChange({ whiteBalance });
+ }}
+ optionEnum={WhiteBalanceEnum}
+ />
+ ),
+ defaultValue: { whiteBalance: WhiteBalanceEnum.AUTO },
+ },
+ },
+ {
+ name: 'wlanAntennaConfig',
+ value: {
+ optionName: OptionNameEnum.WlanAntennaConfig,
+ editor: (options, onChange) => (
+ {
+ onChange({ wlanAntennaConfig });
+ }}
+ optionEnum={WlanAntennaConfigEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'wlanFrequency',
+ value: {
+ optionName: OptionNameEnum.WlanFrequency,
+ editor: (options, onChange) => (
+ {
+ onChange({ wlanFrequency });
+ }}
+ optionEnum={WlanFrequencyEnum}
+ />
+ ),
+ },
+ },
+ {
+ name: 'wlanFrequencySupport',
+ value: {
+ optionName: OptionNameEnum.WlanFrequencySupport,
+ },
+ },
+ {
+ name: 'wlanFrequencyClMode',
+ value: {
+ optionName: OptionNameEnum.WlanFrequencyClMode,
+ editor: (options, onChange) => (
+
+ ),
+ defaultValue: { whiteBalance: WhiteBalanceEnum.AUTO },
+ },
},
- },
- {
- name: 'compositeShootingOutputIntervalSupport',
- value: {
- optionName: OptionNameEnum.CompositeShootingOutputIntervalSupport,
- },
- },
- {
- name: 'compositeShootingTime',
- value: {
- optionName: OptionNameEnum.CompositeShootingTime,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'compassDirectionRef',
- value: {
- optionName: OptionNameEnum.CompassDirectionRef,
- editor: (options, onChange) => (
- {
- onChange({ compassDirectionRef });
- }}
- optionEnum={CompassDirectionRefEnum}
- />
- ),
- },
- },
- {
- name: 'compositeShootingTimeSupport',
- value: {
- optionName: OptionNameEnum.CompositeShootingTimeSupport,
- },
- },
- {
- name: 'continuousNumber',
- value: {
- optionName: OptionNameEnum.ContinuousNumber,
- editor: (options, onChange) => (
- {
- onChange({ continuousNumber });
- }}
- optionEnum={ContinuousNumberEnum}
- />
- ),
- defaultValue: { continuousNumber: ContinuousNumberEnum.OFF },
- },
- },
- {
- name: 'ethernetConfig',
- value: {
- optionName: OptionNameEnum.EthernetConfig,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'exposureCompensation',
- value: {
- optionName: OptionNameEnum.ExposureCompensation,
- editor: (options, onChange) => (
- {
- onChange({ exposureCompensation });
- }}
- optionEnum={ExposureCompensationEnum}
- />
- ),
- defaultValue: { exposureCompensation: ExposureCompensationEnum.ZERO },
- },
- },
- {
- name: 'exposureDelay',
- value: {
- optionName: OptionNameEnum.ExposureDelay,
- editor: (options, onChange) => (
- {
- onChange({ exposureDelay });
- }}
- optionEnum={ExposureDelayEnum}
- />
- ),
- defaultValue: { exposureDelay: ExposureDelayEnum.DELAY_OFF },
- },
- },
- {
- name: 'exposureDelaySupport',
- value: {
- optionName: OptionNameEnum.ExposureDelaySupport,
- },
- },
- {
- name: 'exposureProgram',
- value: {
- optionName: OptionNameEnum.ExposureProgram,
- editor: (options, onChange) => (
- {
- onChange({ exposureProgram });
- }}
- optionEnum={ExposureProgramEnum}
- />
- ),
- defaultValue: { exposureProgram: ExposureProgramEnum.NORMAL_PROGRAM },
- },
- },
- {
- name: 'filter',
- value: {
- optionName: OptionNameEnum.Filter,
- editor: (options, onChange) => (
- {
- onChange({ filter });
- }}
- optionEnum={FilterEnum}
- />
- ),
- },
- },
- {
- name: 'fileFormat',
- value: {
- optionName: OptionNameEnum.FileFormat,
- editor: (options, onChange) => (
- {
- onChange({ fileFormat });
- }}
- optionEnum={FileFormatEnum}
- />
- ),
- },
- },
- {
- name: 'gpsInfo',
- value: {
- optionName: OptionNameEnum.GpsInfo,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'gpsTagRecordingSupport',
- value: {
- optionName: OptionNameEnum.GpsTagRecordingSupport,
- },
- },
- {
- name: 'iso',
- value: {
- optionName: OptionNameEnum.Iso,
- editor: (options, onChange) => (
- {
- onChange({ iso });
- }}
- optionEnum={IsoEnum}
- />
- ),
- defaultValue: { iso: IsoEnum.ISO_AUTO },
- },
- },
- {
- name: 'isoAutoHighLimit',
- value: {
- optionName: OptionNameEnum.IsoAutoHighLimit,
- editor: (options, onChange) => (
- {
- onChange({ isoAutoHighLimit });
- }}
- optionEnum={IsoAutoHighLimitEnum}
- />
- ),
- defaultValue: { isoAutoHighLimit: IsoAutoHighLimitEnum.ISO_100 },
- },
- },
- {
- name: 'latestEnabledExposureDelayTime',
- value: {
- optionName: OptionNameEnum.LatestEnabledExposureDelayTime,
- },
- },
- {
- name: 'maxRecordableTime',
- value: {
- optionName: OptionNameEnum.MaxRecordableTime,
- editor: (options, onChange) => (
- {
- onChange({ maxRecordableTime });
- }}
- optionEnum={MaxRecordableTimeEnum}
- />
- ),
- defaultValue: {
- maxRecordableTime: MaxRecordableTimeEnum.RECORDABLE_TIME_1500,
- },
- },
- },
- {
- name: 'microphoneNoiseReduction',
- value: {
- optionName: OptionNameEnum.MicrophoneNoiseReduction,
- editor: (options, onChange) => (
- {
- onChange({ microphoneNoiseReduction });
- }}
- optionEnum={MicrophoneNoiseReductionEnum}
- />
- ),
- defaultValue: {
- microphoneNoiseReduction: MicrophoneNoiseReductionEnum.ON,
- },
- },
- },
- {
- name: 'mobileNetworkSetting',
- value: {
- optionName: OptionNameEnum.MobileNetworkSetting,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'modeMemory',
- value: {
- optionName: OptionNameEnum.ModeMemory,
- editor: (options, onChange) => (
- {
- onChange({ modeMemory });
- }}
- optionEnum={ModeMemoryEnum}
- />
- ),
- defaultValue: {
- modeMemory: ModeMemoryEnum.ON,
- },
- },
- },
- {
- name: 'networkType',
- value: {
- optionName: OptionNameEnum.NetworkType,
- editor: (options, onChange) => (
- {
- onChange({ networkType });
- }}
- optionEnum={NetworkTypeEnum}
- />
- ),
- },
- },
- {
- name: 'offDelay enum',
- value: {
- optionName: OptionNameEnum.OffDelay,
- editor: (options, onChange) => (
- {
- onChange({ offDelay });
- }}
- optionEnum={OffDelayEnum}
- />
- ),
- defaultValue: { offDelay: OffDelayEnum.DISABLE },
- },
- },
- {
- name: 'offDelay number',
- value: {
- optionName: OptionNameEnum.OffDelay,
- editor: (options, onChange) => (
- {
- onChange({ offDelay: newValue });
- }}
- value={
- typeof options.offDelay === 'string'
- ? offDelayToSeconds(options.offDelay as OffDelayEnum)
- : typeof options.offDelay === 'number'
- ? options.offDelay
- : 0
- }
- />
- ),
- onWillSet: (options: Options) => {
- if (typeof options.offDelay === 'string') {
- options.offDelay = offDelayToSeconds(
- options.offDelay as OffDelayEnum
- );
- }
- },
- },
- },
- {
- name: 'offDelayUsb enum',
- value: {
- optionName: OptionNameEnum.OffDelayUsb,
- editor: (options, onChange) => (
- {
- onChange({ offDelayUsb });
- }}
- optionEnum={OffDelayUsbEnum}
- />
- ),
- defaultValue: { offDelayUsb: OffDelayUsbEnum.DISABLE },
- },
- },
- {
- name: 'offDelayUsb number',
- value: {
- optionName: OptionNameEnum.OffDelayUsb,
- editor: (options, onChange) => (
- {
- onChange({ offDelayUsb: newValue });
- }}
- value={
- typeof options.offDelayUsb === 'string'
- ? offDelayUsbToSeconds(options.offDelayUsb as OffDelayUsbEnum)
- : typeof options.offDelayUsb === 'number'
- ? options.offDelayUsb
- : 0
- }
- />
- ),
- onWillSet: (options: Options) => {
- if (typeof options.offDelayUsb === 'string') {
- options.offDelay = offDelayUsbToSeconds(
- options.offDelayUsb as OffDelayUsbEnum
- );
- }
- },
- },
- },
- {
- name: 'preset',
- value: {
- optionName: OptionNameEnum.Preset,
- editor: (options, onChange) => (
- {
- onChange({ preset });
- }}
- optionEnum={PresetEnum}
- />
- ),
- defaultValue: { preset: PresetEnum.FACE },
- },
- },
- {
- name: 'previewFormat',
- value: {
- optionName: OptionNameEnum.PreviewFormat,
- editor: (options, onChange) => (
- {
- onChange({ previewFormat });
- }}
- optionEnum={PreviewFormatEnum}
- />
- ),
- defaultValue: { previewFormat: PreviewFormatEnum.W1024_H512_F30 },
- },
- },
- {
- name: 'sleepDelay enum',
- value: {
- optionName: OptionNameEnum.SleepDelay,
- editor: (options, onChange) => (
- {
- onChange({ sleepDelay });
- }}
- optionEnum={SleepDelayEnum}
- />
- ),
- defaultValue: { sleepDelay: SleepDelayEnum.DISABLE },
- },
- },
- {
- name: 'sleepDelay number',
- value: {
- optionName: OptionNameEnum.SleepDelay,
- editor: (options, onChange) => (
- {
- onChange({ sleepDelay: newValue });
- }}
- value={
- typeof options.sleepDelay === 'string'
- ? sleepDelayToSeconds(options.sleepDelay as SleepDelayEnum)
- : typeof options.sleepDelay === 'number'
- ? options.sleepDelay
- : 0
- }
- />
- ),
- onWillSet: (options: Options) => {
- if (typeof options.sleepDelay === 'string') {
- options.sleepDelay = sleepDelayToSeconds(
- options.sleepDelay as SleepDelayEnum
- );
- }
- },
- },
- },
- {
- name: 'timeShift',
- value: {
- optionName: OptionNameEnum.TimeShift,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'topBottomCorrection',
- value: {
- optionName: OptionNameEnum.TopBottomCorrection,
- editor: (options, onChange) => (
- {
- onChange({ topBottomCorrection });
- }}
- optionEnum={TopBottomCorrectionOptionEnum}
- />
- ),
- defaultValue: {
- topBottomCorrection: TopBottomCorrectionOptionEnum.APPLY_AUTO,
- },
- },
- },
- {
- name: 'topBottomCorrectionRotation',
- value: {
- optionName: OptionNameEnum.TopBottomCorrectionRotation,
- editor: (options, onChange) => (
-
- ),
- },
- },
- {
- name: 'usbConnection',
- value: {
- optionName: OptionNameEnum.UsbConnection,
- editor: (options, onChange) => (
- {
- onChange({ usbConnection });
- }}
- optionEnum={UsbConnectionEnum}
- />
- ),
- },
- },
- {
- name: 'topBottomCorrectionRotationSupport',
- value: {
- optionName: OptionNameEnum.TopBottomCorrectionRotationSupport,
- },
- },
- {
- name: 'videoStitching',
- value: {
- optionName: OptionNameEnum.VideoStitching,
- editor: (options, onChange) => (
- {
- onChange({ videoStitching });
- }}
- optionEnum={VideoStitchingEnum}
- />
- ),
- defaultValue: {
- videoStitching: VideoStitchingEnum.NONE,
- },
- },
- },
- {
- name: 'visibilityReduction',
- value: {
- optionName: OptionNameEnum.VisibilityReduction,
- editor: (options, onChange) => (
- {
- onChange({ visibilityReduction });
- }}
- optionEnum={VisibilityReductionEnum}
- />
- ),
- defaultValue: {
- visibilityReduction: VisibilityReductionEnum.OFF,
- },
- },
- },
- {
- name: 'whiteBalance',
- value: {
- optionName: OptionNameEnum.WhiteBalance,
- editor: (options, onChange) => (
-