diff --git a/.gitignore b/.gitignore
index 1465524..b960f34 100644
--- a/.gitignore
+++ b/.gitignore
@@ -61,6 +61,7 @@ local.properties
build/
*.tgz
yarn.lock
+.env
# Fastlane
ios/fastlane/report.xml
diff --git a/README.md b/README.md
index c1ef031..5b6a294 100644
--- a/README.md
+++ b/README.md
@@ -10,7 +10,7 @@
# ViroReact
-ViroReact is a library for developers to rapidly build augmented reality (AR) and virtual reality (VR) experiences. Developers write in React Native, and Viro runs their code natively across all mobile VR (including Google Daydream, Samsung Gear VR, and Google Cardboard for iOS and Android) and AR (iOS ARKit and Android ARCore) platforms.
+ViroReact is a library for developers to rapidly build augmented reality (AR) and virtual reality (VR) experiences. Developers write in React Native and Viro runs their code natively across all mobile VR (including Google Daydream, Samsung Gear VR, and Google Cardboard for iOS and Android) and AR (iOS ARKit and Android ARCore) platforms.
@@ -23,21 +23,17 @@ ViroReact is a library for developers to rapidly build augmented reality (AR) an
-# [Installing](readmes/INSTALL.md)
-
-If you are integrating ViroReact into an existing project, have a look at our [Installation instructions](readmes/INSTALL.md).
-
-If you are starting a fresh project with ViroReact, consider cloning our [starter kit](https://github.com/ViroCommunity/starter-kit) repo instead.
-
# Documentation
-The documentation is found [here](https://viro-community.readme.io/docs/overview). Currently, the documentation is migrated with issues to code samples and broken links. If you would like to help fix these issues, either submit an edit or [get in touch](https://discord.gg/H3ksm5NhzT)!
+[Documentation can be found here!](https://viro-community.readme.io/docs/overview). Currently, the documentation has some issues with code samples and broken links. If you would like to help fix these issues, either submit an edit or [get in touch](https://discord.gg/H3ksm5NhzT)!
-# FAQ
+## Getting Started
-- _Older versions couldn't be submitted to Apple's app store due to use of `UIWebView`. Is this still a problem?_
+If you are starting a fresh project with ViroReact, consider cloning one of our starter kits:
- Reliance on `UIWebView` has been removed from the project, so you should not have this problem if using the `@viro-community/react-viro` package.
+- [Expo + TypeScript](https://github.com/NativeVision/expo-starter-kit-typescript)
+- [React Native](https://github.com/NativeVision/starter-kit)
+- [Expo + JavaScript](https://github.com/NativeVision/expo-starter-kit)
# Examples
diff --git a/components/AR/ViroARScene.tsx b/components/AR/ViroARScene.tsx
index 5e53fe8..8a6d44e 100644
--- a/components/AR/ViroARScene.tsx
+++ b/components/AR/ViroARScene.tsx
@@ -47,6 +47,7 @@ import { ViroBase } from "../ViroBase";
import { ViroCamera } from "../ViroCamera";
import { ViroTrackingStateConstants } from "../ViroConstants";
import { ViroCommonProps } from "./ViroCommonProps";
+import { ViroTelemetry } from "../Telemetry";
const ViroCameraModule = NativeModules.ViroCameraModule;
diff --git a/components/AR/ViroARSceneNavigator.tsx b/components/AR/ViroARSceneNavigator.tsx
index 7c7e7a8..43b3ac9 100644
--- a/components/AR/ViroARSceneNavigator.tsx
+++ b/components/AR/ViroARSceneNavigator.tsx
@@ -27,6 +27,7 @@ import {
ViroScene,
ViroSceneDictionary,
} from "../Types/ViroUtils";
+import { ViroTelemetry } from "../Telemetry";
const ViroARSceneNavigatorModule = NativeModules.VRTARSceneNavigatorModule;
@@ -79,6 +80,7 @@ export class ViroARSceneNavigator extends React.Component {
constructor(props: Props) {
super(props);
+ ViroTelemetry.recordTelemetry("INIT", { ar: true });
let initialSceneTag = this.props.initialSceneKey;
if (initialSceneTag == null) {
initialSceneTag = this.getRandomTag();
diff --git a/components/Telemetry/index.ts b/components/Telemetry/index.ts
new file mode 100644
index 0000000..47f4eef
--- /dev/null
+++ b/components/Telemetry/index.ts
@@ -0,0 +1,103 @@
+import { VIRO_VERSION } from "../Utilities/ViroVersion";
+import { Platform } from "react-native";
+
+export class ViroTelemetry {
+ private static _isDisabled = false;
+ private static _isDebugging = false;
+ // TODO: use custom domain
+ // private static _telemetryUrl = "https://telemetry.nativevision.xyz";
+ private static _telemetryUrl = "https://native-vision-telemetry.onrender.com";
+ private static _timeout = 8000;
+
+ /**
+ * Allow a user to start debugging the telemetry to see what is sent.
+ */
+ public static setDebugging() {
+ this._isDebugging = true;
+ }
+
+ /**
+ * Allow a user to opt out of telemetry.
+ */
+ public static optOutTelemetry() {
+ this._isDisabled = true;
+ }
+
+ public static recordTelemetry(eventName: string, payload: any = {}) {
+ // Skip recording telemetry if the feature is disabled
+ if (this._isDisabled) return;
+ // Do not send the telemetry data if debugging. Users may use this feature
+ // to preview what data would be sent.
+ if (this._isDebugging) {
+ console.log(
+ `[telemetry] ` + JSON.stringify({ eventName, payload }, null, 2)
+ );
+ return;
+ }
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), this._timeout);
+
+ payload = { ...payload, ...this.getAnonymousMeta() };
+
+ fetch(`${this._telemetryUrl}/api/v1/record`, {
+ method: "PUT",
+ body: JSON.stringify({ eventName, payload }),
+ headers: { "content-type": "application/json" },
+ signal: controller.signal,
+ })
+ .catch((e) => console.error(e))
+ .finally(() => clearTimeout(timeoutId));
+ }
+
+ private static getAnonymousMeta() {
+ let isExpo = false;
+ try {
+ const myModule = require("expo");
+ isExpo = true;
+ } catch (err) {
+ // send error to log file
+ }
+
+ try {
+ const traits = {
+ // expo
+ isExpo:
+ // @ts-ignore
+ Boolean(window?.expo) || false,
+ sdkVersion:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.sdkVersion || undefined,
+ androidPackage:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.android?.package ||
+ undefined,
+ iosBundleIdentifier:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.ios?.bundleIdentifier ||
+ undefined,
+ expoDebugMode:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.debugMode || undefined,
+ isDevice:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.isDevice || undefined,
+ // library version
+ viroVersion: VIRO_VERSION,
+ platform: Platform.OS,
+ deviceOsVersion: Platform.Version,
+ reactNativeVersion:
+ Platform.constants.reactNativeVersion.major +
+ "." +
+ Platform.constants.reactNativeVersion.minor +
+ "." +
+ Platform.constants.reactNativeVersion.patch,
+ };
+
+ return traits;
+ } catch (e) {
+ console.error(e);
+ }
+
+ return {};
+ }
+}
diff --git a/components/Utilities/ViroVersion.ts b/components/Utilities/ViroVersion.ts
new file mode 100644
index 0000000..8094d41
--- /dev/null
+++ b/components/Utilities/ViroVersion.ts
@@ -0,0 +1 @@
+export const VIRO_VERSION = "2.40.0";
diff --git a/components/Viro3DSceneNavigator.tsx b/components/Viro3DSceneNavigator.tsx
index e0fdf00..5f48efc 100644
--- a/components/Viro3DSceneNavigator.tsx
+++ b/components/Viro3DSceneNavigator.tsx
@@ -25,6 +25,7 @@ import {
ViroSceneDictionary,
} from "./Types/ViroUtils";
import { ViroScene } from "./ViroScene";
+import { ViroTelemetry } from "./Telemetry";
const Viro3DSceneNavigatorModule = NativeModules.VRT3DSceneNavigatorModule;
var mathRandomOffset = 0;
@@ -93,6 +94,7 @@ export class Viro3DSceneNavigator extends React.Component {
constructor(props: Props) {
super(props);
+ ViroTelemetry.recordTelemetry("INIT", { vr: true });
var initialSceneTag = this.props.initialSceneKey;
if (initialSceneTag == null) {
initialSceneTag = this.getRandomTag();
diff --git a/components/ViroSceneNavigator.tsx b/components/ViroSceneNavigator.tsx
index 7eeac51..756ea6d 100644
--- a/components/ViroSceneNavigator.tsx
+++ b/components/ViroSceneNavigator.tsx
@@ -25,6 +25,7 @@ import { ViroExitViroEvent } from "./Types/ViroEvents";
import { Viro3DPoint } from "./Types/ViroUtils";
import { ViroSceneDictionary } from "./Types/ViroUtils";
import { ViroScene } from "./ViroScene";
+import { ViroTelemetry } from "./Telemetry";
var ViroSceneNavigatorModule = NativeModules.VRTSceneNavigatorModule;
var mathRandomOffset = 0;
diff --git a/dist/components/AR/ViroARSceneNavigator.js b/dist/components/AR/ViroARSceneNavigator.js
index 9cacfe5..8d92d7d 100644
--- a/dist/components/AR/ViroARSceneNavigator.js
+++ b/dist/components/AR/ViroARSceneNavigator.js
@@ -37,6 +37,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.ViroARSceneNavigator = void 0;
const React = __importStar(require("react"));
const react_native_1 = require("react-native");
+const Telemetry_1 = require("../Telemetry");
const ViroARSceneNavigatorModule = react_native_1.NativeModules.VRTARSceneNavigatorModule;
let mathRandomOffset = 0;
/**
@@ -46,6 +47,7 @@ class ViroARSceneNavigator extends React.Component {
_component = null;
constructor(props) {
super(props);
+ Telemetry_1.ViroTelemetry.recordTelemetry("INIT", { ar: true });
let initialSceneTag = this.props.initialSceneKey;
if (initialSceneTag == null) {
initialSceneTag = this.getRandomTag();
diff --git a/dist/components/Telemetry/index.d.ts b/dist/components/Telemetry/index.d.ts
new file mode 100644
index 0000000..211f7f9
--- /dev/null
+++ b/dist/components/Telemetry/index.d.ts
@@ -0,0 +1,16 @@
+export declare class ViroTelemetry {
+ private static _isDisabled;
+ private static _isDebugging;
+ private static _telemetryUrl;
+ private static _timeout;
+ /**
+ * Allow a user to start debugging the telemetry to see what is sent.
+ */
+ static setDebugging(): void;
+ /**
+ * Allow a user to opt out of telemetry.
+ */
+ static optOutTelemetry(): void;
+ static recordTelemetry(eventName: string, payload?: any): void;
+ private static getAnonymousMeta;
+}
diff --git a/dist/components/Telemetry/index.js b/dist/components/Telemetry/index.js
new file mode 100644
index 0000000..0748863
--- /dev/null
+++ b/dist/components/Telemetry/index.js
@@ -0,0 +1,97 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.ViroTelemetry = void 0;
+const ViroVersion_1 = require("../Utilities/ViroVersion");
+const react_native_1 = require("react-native");
+class ViroTelemetry {
+ static _isDisabled = false;
+ static _isDebugging = false;
+ // TODO: use custom domain
+ // private static _telemetryUrl = "https://telemetry.nativevision.xyz";
+ static _telemetryUrl = "https://native-vision-telemetry.onrender.com";
+ static _timeout = 8000;
+ /**
+ * Allow a user to start debugging the telemetry to see what is sent.
+ */
+ static setDebugging() {
+ this._isDebugging = true;
+ }
+ /**
+ * Allow a user to opt out of telemetry.
+ */
+ static optOutTelemetry() {
+ this._isDisabled = true;
+ }
+ static recordTelemetry(eventName, payload = {}) {
+ // Skip recording telemetry if the feature is disabled
+ if (this._isDisabled)
+ return;
+ // Do not send the telemetry data if debugging. Users may use this feature
+ // to preview what data would be sent.
+ if (this._isDebugging) {
+ console.log(`[telemetry] ` + JSON.stringify({ eventName, payload }, null, 2));
+ return;
+ }
+ const controller = new AbortController();
+ const timeoutId = setTimeout(() => controller.abort(), this._timeout);
+ payload = { ...payload, ...this.getAnonymousMeta() };
+ fetch(`${this._telemetryUrl}/api/v1/record`, {
+ method: "PUT",
+ body: JSON.stringify({ eventName, payload }),
+ headers: { "content-type": "application/json" },
+ signal: controller.signal,
+ })
+ .catch((e) => console.error(e))
+ .finally(() => clearTimeout(timeoutId));
+ }
+ static getAnonymousMeta() {
+ let isExpo = false;
+ try {
+ const myModule = require("expo");
+ isExpo = true;
+ }
+ catch (err) {
+ // send error to log file
+ }
+ try {
+ const traits = {
+ // expo
+ isExpo:
+ // @ts-ignore
+ Boolean(window?.expo) || false,
+ sdkVersion:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.sdkVersion || undefined,
+ androidPackage:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.android?.package ||
+ undefined,
+ iosBundleIdentifier:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.ios?.bundleIdentifier ||
+ undefined,
+ expoDebugMode:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.debugMode || undefined,
+ isDevice:
+ // @ts-ignore
+ window?.expo?.modules?.ExponentConstants?.isDevice || undefined,
+ // library version
+ viroVersion: ViroVersion_1.VIRO_VERSION,
+ platform: react_native_1.Platform.OS,
+ deviceOsVersion: react_native_1.Platform.Version,
+ reactNativeVersion: react_native_1.Platform.constants.reactNativeVersion.major +
+ "." +
+ react_native_1.Platform.constants.reactNativeVersion.minor +
+ "." +
+ react_native_1.Platform.constants.reactNativeVersion.patch,
+ };
+ return traits;
+ }
+ catch (e) {
+ console.error(e);
+ }
+ return {};
+ }
+}
+exports.ViroTelemetry = ViroTelemetry;
diff --git a/dist/components/Utilities/ViroVersion.d.ts b/dist/components/Utilities/ViroVersion.d.ts
new file mode 100644
index 0000000..86a72e1
--- /dev/null
+++ b/dist/components/Utilities/ViroVersion.d.ts
@@ -0,0 +1 @@
+export declare const VIRO_VERSION = "2.40.0";
diff --git a/dist/components/Utilities/ViroVersion.js b/dist/components/Utilities/ViroVersion.js
new file mode 100644
index 0000000..07f32e9
--- /dev/null
+++ b/dist/components/Utilities/ViroVersion.js
@@ -0,0 +1,4 @@
+"use strict";
+Object.defineProperty(exports, "__esModule", { value: true });
+exports.VIRO_VERSION = void 0;
+exports.VIRO_VERSION = "2.40.0";
diff --git a/dist/components/Viro3DSceneNavigator.js b/dist/components/Viro3DSceneNavigator.js
index 5200277..6bd1121 100644
--- a/dist/components/Viro3DSceneNavigator.js
+++ b/dist/components/Viro3DSceneNavigator.js
@@ -37,6 +37,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
exports.Viro3DSceneNavigator = void 0;
const React = __importStar(require("react"));
const react_native_1 = require("react-native");
+const Telemetry_1 = require("./Telemetry");
const Viro3DSceneNavigatorModule = react_native_1.NativeModules.VRT3DSceneNavigatorModule;
var mathRandomOffset = 0;
/**
@@ -53,6 +54,7 @@ class Viro3DSceneNavigator extends React.Component {
}
constructor(props) {
super(props);
+ Telemetry_1.ViroTelemetry.recordTelemetry("INIT", { vr: true });
var initialSceneTag = this.props.initialSceneKey;
if (initialSceneTag == null) {
initialSceneTag = this.getRandomTag();
diff --git a/dist/index.d.ts b/dist/index.d.ts
index a3d5aac..b909f0a 100644
--- a/dist/index.d.ts
+++ b/dist/index.d.ts
@@ -1,8 +1,3 @@
-/**
- * Copyright (c) 2016-present, Viro Media, Inc.
- * All rights reserved.
- *
- */
import { ViroAnimations } from "./components/Animation/ViroAnimations";
import { Viro3DObject } from "./components/Viro3DObject";
import { Viro360Image } from "./components/Viro360Image";
diff --git a/dist/index.js b/dist/index.js
index 7b8e120..683788a 100644
--- a/dist/index.js
+++ b/dist/index.js
@@ -1,9 +1,4 @@
"use strict";
-/**
- * Copyright (c) 2016-present, Viro Media, Inc.
- * All rights reserved.
- *
- */
Object.defineProperty(exports, "__esModule", { value: true });
exports.ViroARTrackingReasonConstants = exports.Viro3DSceneNavigator = exports.ViroVRSceneNavigator = exports.ViroVideo = exports.ViroText = exports.ViroSpotLight = exports.ViroSpinner = exports.ViroSphere = exports.ViroSpatialSound = exports.ViroSoundField = exports.ViroSound = exports.ViroAnimatedComponent = exports.ViroAmbientLight = exports.ViroAnimatedImage = exports.Viro360Video = exports.Viro360Image = exports.Viro3DObject = exports.ViroAnimations = exports.ViroSkyBox = exports.ViroSceneNavigator = exports.ViroSurface = exports.ViroScene = exports.ViroQuad = exports.ViroPortalScene = exports.ViroPortal = exports.ViroPolyline = exports.ViroPolygon = exports.ViroParticleEmitter = exports.ViroOrbitCamera = exports.ViroOmniLight = exports.ViroNode = exports.ViroMaterialVideo = exports.ViroARCamera = exports.ViroMaterials = exports.ViroImage = exports.ViroLightingEnvironment = exports.ViroGeometry = exports.ViroFlexView = exports.ViroDirectionalLight = exports.ViroController = exports.ViroCamera = exports.ViroButton = exports.ViroBox = exports.ViroARSceneNavigator = exports.ViroARScene = exports.ViroARPlaneSelector = exports.ViroARPlane = exports.ViroARTrackingTargets = exports.ViroARObjectMarker = exports.ViroARImageMarker = void 0;
exports.ViroRotateStateTypes = exports.ViroPinchStateTypes = exports.ViroClickStateTypes = exports.isARSupportedOnDevice = exports.polarToCartesianActual = exports.polarToCartesian = exports.ViroTrackingStateConstants = exports.ViroRecordingErrorConstants = void 0;
diff --git a/index.ts b/index.ts
index fcd80f7..3157d3c 100644
--- a/index.ts
+++ b/index.ts
@@ -3,7 +3,7 @@
* All rights reserved.
*
*/
-
+import { ViroTelemetry } from "./components/Telemetry";
import { ViroAnimations } from "./components/Animation/ViroAnimations";
import { Viro3DObject } from "./components/Viro3DObject";
import { Viro360Image } from "./components/Viro360Image";
diff --git a/package-lock.json b/package-lock.json
index a00019e..39d4811 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -24,6 +24,7 @@
"expo": "^50.0.0",
"jest": "^29.7.0",
"react-native": "0.71.14",
+ "react-native-dotenv": "^3.4.9",
"ts-node": "^10.9.2",
"typescript": "^4.6.3"
},
@@ -12784,6 +12785,30 @@
"nullthrows": "^1.1.1"
}
},
+ "node_modules/react-native-dotenv": {
+ "version": "3.4.9",
+ "resolved": "https://registry.npmjs.org/react-native-dotenv/-/react-native-dotenv-3.4.9.tgz",
+ "integrity": "sha512-dbyd+mcy7SUzxEgmt33TRf1FGcNe6swJhXmB0unKkI49F7+pidog9kPtjxMLTAfmKA8gcN2XHQSKltGfGbGCLQ==",
+ "dev": true,
+ "dependencies": {
+ "dotenv": "^16.3.1"
+ },
+ "peerDependencies": {
+ "@babel/runtime": "^7.20.6"
+ }
+ },
+ "node_modules/react-native-dotenv/node_modules/dotenv": {
+ "version": "16.4.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.1.tgz",
+ "integrity": "sha512-CjA3y+Dr3FyFDOAMnxZEGtnW9KBR2M0JvvUtXNW+dYJL5ROWxP9DUHCwgFqpMk0OXCc0ljhaNTr2w/kutYIcHQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/motdotla/dotenv?sponsor=1"
+ }
+ },
"node_modules/react-native-gradle-plugin": {
"version": "0.71.19",
"resolved": "https://registry.npmjs.org/react-native-gradle-plugin/-/react-native-gradle-plugin-0.71.19.tgz",
diff --git a/package.json b/package.json
index 7491a28..41cc427 100644
--- a/package.json
+++ b/package.json
@@ -3,7 +3,7 @@
"main": "dist/index.js",
"module": "dist/index.js",
"types": "dist/index.d.ts",
- "version": "2.23.3",
+ "version": "2.40.0",
"license": "MIT",
"publishConfig": {
"registry": "https://registry.npmjs.org/"
@@ -14,6 +14,7 @@
"start": "echo 'I dont think you meant to run npm start here.'",
"test": "jest",
"tsc": "tsc",
+ "prebuild": "node -p \"'export const VIRO_VERSION = ' + JSON.stringify(require('./package.json').version) + ';'\" > components/Utilities/ViroVersion.ts",
"build": "tsc && npm run copy-files",
"bundle": "./prepare_release.sh",
"copy-files": "cp -r ./components/Resources/ ./dist/components/Resources/",
diff --git a/prepare_release.sh b/prepare_release.sh
index e5f6707..4fc5eb3 100755
--- a/prepare_release.sh
+++ b/prepare_release.sh
@@ -5,6 +5,7 @@
#
# set -x
+set -e
echo '========================================================================='
echo 'Cleaning local tarballs'
@@ -44,7 +45,7 @@ echo '========================================================================='
echo 'Copying build artifacts to the lib directory'
echo '========================================================================='
# rm android/react_viro/*.aar
-cp android/viro_bridge/build/outputs/aar/viro_bridge-release.aar android/react_viro/react_viro-release.aar
+# cp android/viro_bridge/build/outputs/aar/viro_bridge-release.aar android/react_viro/react_viro-release.aar
echo '========================================================================='
echo 'Packing Tarball for NPM'