From 3efdcf133608b087fd9e5f2aa9e8f065ce963631 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Fri, 28 Apr 2023 15:12:27 -0500 Subject: [PATCH 01/14] feat(core): Add autoStart feature --- package/package.json | 2 ++ package/src/lib/SpotlightTour.context.ts | 5 +++ package/src/lib/SpotlightTour.provider.tsx | 28 +++++++++++++++- yarn.lock | 38 ++++++++++++++++++++++ 4 files changed, 72 insertions(+), 1 deletion(-) diff --git a/package/package.json b/package/package.json index b2f6000..4a11053 100644 --- a/package/package.json +++ b/package/package.json @@ -35,6 +35,8 @@ "test": "jest" }, "dependencies": { + "@react-native-async-storage/async-storage": "^1.18.1", + "react-native-device-info": "^10.6.0", "react-native-responsive-dimensions": "^3.1.1", "styled-components": "^5.3.9" }, diff --git a/package/src/lib/SpotlightTour.context.ts b/package/src/lib/SpotlightTour.context.ts index 72d0739..97123d3 100644 --- a/package/src/lib/SpotlightTour.context.ts +++ b/package/src/lib/SpotlightTour.context.ts @@ -33,6 +33,11 @@ export enum Position { */ export type Motion = "bounce" | "slide" | "fade"; +/** + * Possible tour autostart options + */ +export type AutoStartOptions = "never" | "always" | "once"; + export interface RenderProps { /** * The index of the current step the tour is on. diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index 765b515..b399088 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -1,9 +1,12 @@ -import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState } from "react"; +import AsyncStorage from "@react-native-async-storage/async-storage"; +import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState, useEffect } from "react"; import { ColorValue, LayoutRectangle } from "react-native"; +import { getUniqueId } from "react-native-device-info"; import { ChildFn, isChildFunction } from "../helpers/common"; import { + AutoStartOptions, BackdropPressBehavior, Motion, OSConfig, @@ -17,6 +20,12 @@ import { import { TourOverlay, TourOverlayRef } from "./components/tour-overlay/TourOverlay.component"; export interface SpotlightTourProviderProps { + /** + * Sets the default behaviour when the tour starts. + * + * @default never + */ + autoStart?: AutoStartOptions; // never - always - once /** * The children to render in the provider. It accepts either a React * component, or a function that returns a React component. When the child is @@ -75,6 +84,7 @@ export interface SpotlightTourProviderProps { */ export const SpotlightTourProvider = forwardRef((props, ref) => { const { + autoStart = "never", children, onBackdropPress, overlayColor = "black", @@ -111,6 +121,22 @@ export const SpotlightTourProvider = forwardRef => { + const deviceUniqueId = await getUniqueId(); + const isFirstTime = !(await AsyncStorage.getItem(deviceUniqueId)); + if (isFirstTime) { + await AsyncStorage.setItem(deviceUniqueId, "true", () => start()); + } + }, [renderStep]); + + useEffect(() => { + if (autoStart === "always") { + start(); + } else if (autoStart === "once") { + startOnce(); + } + }, [renderStep, autoStart]); + const stop = useCallback((): void => { setCurrent(undefined); setSpot(ZERO_SPOT); diff --git a/yarn.lock b/yarn.lock index 42ed19f..920596b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2596,6 +2596,17 @@ __metadata: languageName: node linkType: hard +"@react-native-async-storage/async-storage@npm:^1.18.1": + version: 1.18.1 + resolution: "@react-native-async-storage/async-storage@npm:1.18.1" + dependencies: + merge-options: ^3.0.4 + peerDependencies: + react-native: ^0.0.0-0 || 0.60 - 0.72 || 1000.0.0 + checksum: 58c8497fafdd4d112c4a70b0976783abdc6fa487f0cffca196901efd146fc838dee0cf498fdc4ef67a4634ba4ca97d60fec5a24720aea1d46f1999b0ba8b249b + languageName: node + linkType: hard + "@react-native-community/cli-clean@npm:^10.1.1": version: 10.1.1 resolution: "@react-native-community/cli-clean@npm:10.1.1" @@ -3270,6 +3281,7 @@ __metadata: dependencies: "@babel/core": ^7.21.3 "@babel/preset-env": ^7.20.2 + "@react-native-async-storage/async-storage": ^1.18.1 "@stackbuilders/assertive-ts": ^1.2.0 "@testing-library/jest-native": ^5.4.2 "@testing-library/react-native": ^11.5.4 @@ -3286,6 +3298,7 @@ __metadata: react: 18.2.0 react-is: ^18.2.0 react-native: 0.71.4 + react-native-device-info: ^10.6.0 react-native-responsive-dimensions: ^3.1.1 react-native-svg: 13.8.0 react-test-renderer: 18.2.0 @@ -7986,6 +7999,13 @@ __metadata: languageName: node linkType: hard +"is-plain-obj@npm:^2.1.0": + version: 2.1.0 + resolution: "is-plain-obj@npm:2.1.0" + checksum: cec9100678b0a9fe0248a81743041ed990c2d4c99f893d935545cfbc42876cbe86d207f3b895700c690ad2fa520e568c44afc1605044b535a7820c1d40e38daa + languageName: node + linkType: hard + "is-plain-object@npm:^2.0.3, is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -9555,6 +9575,15 @@ __metadata: languageName: node linkType: hard +"merge-options@npm:^3.0.4": + version: 3.0.4 + resolution: "merge-options@npm:3.0.4" + dependencies: + is-plain-obj: ^2.1.0 + checksum: d86ddb3dd6e85d558dbf25dc944f3527b6bacb944db3fdda6e84a3f59c4e4b85231095f58b835758b9a57708342dee0f8de0dffa352974a48221487fe9f4584f + languageName: node + linkType: hard + "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -11652,6 +11681,15 @@ __metadata: languageName: node linkType: hard +"react-native-device-info@npm:^10.6.0": + version: 10.6.0 + resolution: "react-native-device-info@npm:10.6.0" + peerDependencies: + react-native: "*" + checksum: 7a7cc438844552aef687b4a5b8efd0cd0a2959e0a3b771febfbe0b6a9ca8ff05a563e2912b30b83523bd3d5143d6616ca8fac0476abf01936a726e1578211ebb + languageName: node + linkType: hard + "react-native-gradle-plugin@npm:^0.71.16": version: 0.71.16 resolution: "react-native-gradle-plugin@npm:0.71.16" From a30df69d1b97a20dd0fe56aefde261fe06fda9de Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Fri, 28 Apr 2023 15:14:44 -0500 Subject: [PATCH 02/14] feat(core): Add onStart callback to SpotlightTourProvider props --- package/src/lib/SpotlightTour.provider.tsx | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index b399088..fac3012 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -61,6 +61,12 @@ export interface SpotlightTourProviderProps { * **NOTE:** You can also override this behavior on each step configuration. */ onBackdropPress?: BackdropPressBehavior; + /** + * Handler which gets executed when {@link SpotlightTour.start|start} is + * invoked. It receives the {@link SpotlightTour.current|current} step index + * so you can access the current step where the tour starts. + */ + onStart?: ((options: SpotlightTour["current"]) => void); /** * The color of the overlay of the tour. * @@ -92,6 +98,7 @@ export const SpotlightTourProvider = forwardRef(); @@ -119,7 +126,8 @@ export const SpotlightTourProvider = forwardRef { renderStep(0); - }, [renderStep]); + onStart?.(current); + }, [renderStep, onStart, current]); const startOnce = useCallback(async (): Promise => { const deviceUniqueId = await getUniqueId(); From 187ca8480ad3925e4edbde989529dfe10c3d4f3d Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Tue, 2 May 2023 16:42:03 -0500 Subject: [PATCH 03/14] fixing tests --- package/src/lib/SpotlightTour.provider.tsx | 6 +++--- package/test/setup.ts | 19 +++++++++++++------ 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index fac3012..44087cb 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -66,7 +66,7 @@ export interface SpotlightTourProviderProps { * invoked. It receives the {@link SpotlightTour.current|current} step index * so you can access the current step where the tour starts. */ - onStart?: ((options: SpotlightTour["current"]) => void); + onStart?: () => void; /** * The color of the overlay of the tour. * @@ -116,7 +116,7 @@ export const SpotlightTourProvider = forwardRef setCurrent(index)); + .then(() => setCurrent(index)); } }, [steps]); @@ -126,7 +126,7 @@ export const SpotlightTourProvider = forwardRef { renderStep(0); - onStart?.(current); + onStart?.(); }, [renderStep, onStart, current]); const startOnce = useCallback(async (): Promise => { diff --git a/package/test/setup.ts b/package/test/setup.ts index 2625798..28ff277 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -1,5 +1,8 @@ /* eslint-disable max-classes-per-file */ +/* eslint @typescript-eslint/no-var-requires: "off" */ +import AsyncStorageMock from "@react-native-async-storage/async-storage/jest/async-storage-mock"; import { Animated } from "react-native"; +import { DeviceInfoModule } from "react-native-device-info/lib/typescript/internal/privateTypes"; import { isAnimatedTimingInterpolation, @@ -17,7 +20,6 @@ import { } from "./helpers/nativeMocks"; global.context = describe; - jest .mock("react-native/Libraries/Components/View/View", () => { return mockNativeComponent("react-native/Libraries/Components/View/View", { @@ -80,16 +82,16 @@ jest start(callback) { if ( isAnimatedValueXY(value) - && !isAnimatedTimingInterpolation(config.toValue) - && isXYValue(config.toValue) + && !isAnimatedTimingInterpolation(config.toValue) + && isXYValue(config.toValue) ) { value.setValue(config.toValue); } if ( isAnimatedValue(value) - && !isAnimatedTimingInterpolation(config.toValue) - && isNumberValue(config.toValue) + && !isAnimatedTimingInterpolation(config.toValue) + && isNumberValue(config.toValue) ) { value.setValue(config.toValue); } @@ -127,7 +129,12 @@ jest timing: timingMock, }, }; - }); + }) + .mock("@react-native-async-storage/async-storage", () => + AsyncStorageMock) + + .mock("react-native-device-info", () => + require("react-native-device-info/jest/react-native-device-info-mock") as jest.Mock); afterEach(() => { jest.resetAllMocks(); From 0498fafedc1de972cde59346211c2528afe3a0c6 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Thu, 4 May 2023 14:54:46 -0500 Subject: [PATCH 04/14] test(core): autoStart SpotlightTourProvider prop --- package/src/lib/SpotlightTour.provider.tsx | 3 +- package/test/helpers/TestTour.tsx | 17 ++++++++- package/test/integration/index.test.tsx | 43 +++++++++++++++++++++- package/test/setup.ts | 8 ++-- 4 files changed, 64 insertions(+), 7 deletions(-) diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index 44087cb..2d14eea 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -133,7 +133,8 @@ export const SpotlightTourProvider = forwardRef start()); + await AsyncStorage.setItem(deviceUniqueId, "true"); + start(); } }, [renderStep]); diff --git a/package/test/helpers/TestTour.tsx b/package/test/helpers/TestTour.tsx index 84f92d4..5828e26 100644 --- a/package/test/helpers/TestTour.tsx +++ b/package/test/helpers/TestTour.tsx @@ -2,11 +2,17 @@ import React from "react"; import { Button, Text, TouchableOpacity, View } from "react-native"; import { Align, AttachStep, Position, SpotlightTourProvider, TourStep, useSpotlightTour } from "../../src"; +import { AutoStartOptions } from "../../src/lib/SpotlightTour.context"; interface TestScreenProps { steps?: TourStep[]; } +interface TestScreenAutoStartProps { + autoStart: AutoStartOptions; + steps?: TourStep[]; +} + export const BASE_STEP: TourStep = { alignTo: Align.SCREEN, position: Position.BOTTOM, @@ -29,7 +35,8 @@ export const BASE_STEP: TourStep = { ), }; -const TestComponent: React.FC = () => { +const +TestComponent: React.FC = () => { const tourContext = useSpotlightTour(); return ( @@ -61,3 +68,11 @@ export const TestScreen: React.FC = ({ steps }) => { ); }; + +export const TestScreenAutoStart: React.FC = ({ autoStart, steps }) => { + return ( + + + + ); +}; diff --git a/package/test/integration/index.test.tsx b/package/test/integration/index.test.tsx index 7833878..34e6e06 100644 --- a/package/test/integration/index.test.tsx +++ b/package/test/integration/index.test.tsx @@ -1,4 +1,5 @@ import { expect as jestExpect } from "@jest/globals"; +import AsyncStorage from "@react-native-async-storage/async-storage"; import { expect, TypeFactories } from "@stackbuilders/assertive-ts"; import "@testing-library/jest-native/extend-expect"; import { fireEvent, render, waitFor } from "@testing-library/react-native"; @@ -7,7 +8,7 @@ import { ViewStyle } from "react-native"; import { CircleProps } from "react-native-svg"; import { TourStep } from "../../src"; -import { BASE_STEP, TestScreen } from "../helpers/TestTour"; +import { BASE_STEP, TestScreen, TestScreenAutoStart } from "../helpers/TestTour"; import { checkValidIntersection, findPropsOnTestInstance } from "../helpers/helper"; import { buttonMockMeasureData, viewMockMeasureData } from "../helpers/measures"; @@ -299,4 +300,44 @@ describe("[Integration] index.test.tsx", () => { }); }); }); + + describe("autoStart property", () => { + describe("when the autoStart property is set to never", () => { + it("the overlay is not shown", async () => { + const { getByText, queryByTestId } = render(); + await waitFor(() => getByText("Start")); + expect(queryByTestId("Overlay View")).toBeNull(); + }); + }); + + describe("when the autoStart property is set to always", () => { + it("shows the overlay view", async () => { + const { getByTestId } = render(); + await waitFor(() => getByTestId("Overlay View")); + }); + }); + + describe("when the autoStart property is set to once", () => { + describe("when the device is not registered", () => { + it("shows the overlay view", async () => { + const { getByTestId } = render(); + waitFor(() => { + jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); + jestExpect(AsyncStorage.setItem).toHaveBeenCalled(); + }); + await waitFor(() => getByTestId("Overlay View")); + }); + }); + describe("when the device is already registered", () => { + it("the overlay is not shown", async () => { + await AsyncStorage.setItem("12345", "true"); + const { queryByTestId } = render(); + waitFor(() => { + jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); + }); + expect(queryByTestId("Overlay View")).toBeNull(); + }); + }); + }); + }); }); diff --git a/package/test/setup.ts b/package/test/setup.ts index 28ff277..6579c7a 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -2,7 +2,6 @@ /* eslint @typescript-eslint/no-var-requires: "off" */ import AsyncStorageMock from "@react-native-async-storage/async-storage/jest/async-storage-mock"; import { Animated } from "react-native"; -import { DeviceInfoModule } from "react-native-device-info/lib/typescript/internal/privateTypes"; import { isAnimatedTimingInterpolation, @@ -132,9 +131,10 @@ jest }) .mock("@react-native-async-storage/async-storage", () => AsyncStorageMock) - - .mock("react-native-device-info", () => - require("react-native-device-info/jest/react-native-device-info-mock") as jest.Mock); + .mock("react-native-device-info", () => + ({ + getUniqueId: () => "12345", + })); afterEach(() => { jest.resetAllMocks(); From e78150c21b5e4284fa48b43294a3e5e6cde803af Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Thu, 4 May 2023 15:03:27 -0500 Subject: [PATCH 05/14] code format --- package/test/helpers/TestTour.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package/test/helpers/TestTour.tsx b/package/test/helpers/TestTour.tsx index 5828e26..084f6e3 100644 --- a/package/test/helpers/TestTour.tsx +++ b/package/test/helpers/TestTour.tsx @@ -35,8 +35,7 @@ export const BASE_STEP: TourStep = { ), }; -const -TestComponent: React.FC = () => { +const TestComponent: React.FC = () => { const tourContext = useSpotlightTour(); return ( From 8c09f24ba2dda3ca4f1759f2b896527f67d75b73 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Thu, 4 May 2023 15:09:31 -0500 Subject: [PATCH 06/14] fix imports --- package/src/index.ts | 1 + package/test/helpers/TestTour.tsx | 11 +++++++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/package/src/index.ts b/package/src/index.ts index 04062fc..6e9a277 100644 --- a/package/src/index.ts +++ b/package/src/index.ts @@ -21,6 +21,7 @@ export { SpotlightTour, TourStep, useSpotlightTour, + AutoStartOptions, } from "./lib/SpotlightTour.context"; export { SpotlightTourProvider, diff --git a/package/test/helpers/TestTour.tsx b/package/test/helpers/TestTour.tsx index 084f6e3..eadb6d1 100644 --- a/package/test/helpers/TestTour.tsx +++ b/package/test/helpers/TestTour.tsx @@ -1,8 +1,15 @@ import React from "react"; import { Button, Text, TouchableOpacity, View } from "react-native"; -import { Align, AttachStep, Position, SpotlightTourProvider, TourStep, useSpotlightTour } from "../../src"; -import { AutoStartOptions } from "../../src/lib/SpotlightTour.context"; +import { + Align, + AttachStep, + Position, + SpotlightTourProvider, + TourStep, + useSpotlightTour, + AutoStartOptions, +} from "../../src"; interface TestScreenProps { steps?: TourStep[]; From 44ebbada4b033058849190873d932b4302482220 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Thu, 4 May 2023 15:48:38 -0500 Subject: [PATCH 07/14] adding mocked lib --- package/test/setup.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package/test/setup.ts b/package/test/setup.ts index 6579c7a..08723f4 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -131,10 +131,10 @@ jest }) .mock("@react-native-async-storage/async-storage", () => AsyncStorageMock) + .mock("react-native-device-info", () => - ({ - getUniqueId: () => "12345", - })); + require("react-native-device-info/jest/react-native-device-info-mock")); + afterEach(() => { jest.resetAllMocks(); From a445045efff4a5f1582cd69353166feae98c9c97 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Thu, 4 May 2023 16:18:33 -0500 Subject: [PATCH 08/14] Setup mock for react-native-device-info --- package/test/setup.ts | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/package/test/setup.ts b/package/test/setup.ts index 08723f4..887965d 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -133,8 +133,7 @@ jest AsyncStorageMock) .mock("react-native-device-info", () => - require("react-native-device-info/jest/react-native-device-info-mock")); - + ({ getUniqueId: () => "12345" })); afterEach(() => { jest.resetAllMocks(); From 09ffe184164dab852c67dfe10df41256cb3a4e1f Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Mon, 8 May 2023 10:11:37 -0500 Subject: [PATCH 09/14] Reusing TestScreen --- package/test/helpers/TestTour.tsx | 18 +++--------------- package/test/integration/index.test.tsx | 10 +++++----- package/test/setup.ts | 3 +-- 3 files changed, 9 insertions(+), 22 deletions(-) diff --git a/package/test/helpers/TestTour.tsx b/package/test/helpers/TestTour.tsx index eadb6d1..19a6863 100644 --- a/package/test/helpers/TestTour.tsx +++ b/package/test/helpers/TestTour.tsx @@ -12,11 +12,7 @@ import { } from "../../src"; interface TestScreenProps { - steps?: TourStep[]; -} - -interface TestScreenAutoStartProps { - autoStart: AutoStartOptions; + autoStart?: AutoStartOptions; steps?: TourStep[]; } @@ -67,17 +63,9 @@ const defaultSteps = [ { ...BASE_STEP, position: Position.TOP }, ]; -export const TestScreen: React.FC = ({ steps }) => { - return ( - - - - ); -}; - -export const TestScreenAutoStart: React.FC = ({ autoStart, steps }) => { +export const TestScreen: React.FC = ({ steps, autoStart }) => { return ( - + ); diff --git a/package/test/integration/index.test.tsx b/package/test/integration/index.test.tsx index 34e6e06..c0dcb99 100644 --- a/package/test/integration/index.test.tsx +++ b/package/test/integration/index.test.tsx @@ -8,7 +8,7 @@ import { ViewStyle } from "react-native"; import { CircleProps } from "react-native-svg"; import { TourStep } from "../../src"; -import { BASE_STEP, TestScreen, TestScreenAutoStart } from "../helpers/TestTour"; +import { BASE_STEP, TestScreen } from "../helpers/TestTour"; import { checkValidIntersection, findPropsOnTestInstance } from "../helpers/helper"; import { buttonMockMeasureData, viewMockMeasureData } from "../helpers/measures"; @@ -304,7 +304,7 @@ describe("[Integration] index.test.tsx", () => { describe("autoStart property", () => { describe("when the autoStart property is set to never", () => { it("the overlay is not shown", async () => { - const { getByText, queryByTestId } = render(); + const { getByText, queryByTestId } = render(); await waitFor(() => getByText("Start")); expect(queryByTestId("Overlay View")).toBeNull(); }); @@ -312,7 +312,7 @@ describe("[Integration] index.test.tsx", () => { describe("when the autoStart property is set to always", () => { it("shows the overlay view", async () => { - const { getByTestId } = render(); + const { getByTestId } = render(); await waitFor(() => getByTestId("Overlay View")); }); }); @@ -320,7 +320,7 @@ describe("[Integration] index.test.tsx", () => { describe("when the autoStart property is set to once", () => { describe("when the device is not registered", () => { it("shows the overlay view", async () => { - const { getByTestId } = render(); + const { getByTestId } = render(); waitFor(() => { jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); jestExpect(AsyncStorage.setItem).toHaveBeenCalled(); @@ -331,7 +331,7 @@ describe("[Integration] index.test.tsx", () => { describe("when the device is already registered", () => { it("the overlay is not shown", async () => { await AsyncStorage.setItem("12345", "true"); - const { queryByTestId } = render(); + const { queryByTestId } = render(); waitFor(() => { jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); }); diff --git a/package/test/setup.ts b/package/test/setup.ts index 887965d..6904e9a 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -132,8 +132,7 @@ jest .mock("@react-native-async-storage/async-storage", () => AsyncStorageMock) - .mock("react-native-device-info", () => - ({ getUniqueId: () => "12345" })); + .mock("react-native-device-info", () => ({ getUniqueId: () => "12345" })); afterEach(() => { jest.resetAllMocks(); From 5d0198915323bdc7632eaf22a8f174b372f40e33 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Mon, 3 Jul 2023 16:05:52 -0500 Subject: [PATCH 10/14] refactor(autostart): using hash + mmkv libs --- example/package.json | 1 + example/src/App.tsx | 1 + package/package.json | 8 ++- package/src/helpers/storage.ts | 5 ++ package/src/lib/SpotlightTour.provider.tsx | 23 +++---- yarn.lock | 71 ++++++++++------------ 6 files changed, 55 insertions(+), 54 deletions(-) create mode 100644 package/src/helpers/storage.ts diff --git a/example/package.json b/example/package.json index 171ed5f..a76ff1f 100644 --- a/example/package.json +++ b/example/package.json @@ -20,6 +20,7 @@ "react": "18.2.0", "react-is": "^18.2.0", "react-native": "0.71.6", + "react-native-mmkv-storage": "^0.9.1", "react-native-svg": "^13.8.0", "styled-components": "^5.3.9" }, diff --git a/example/src/App.tsx b/example/src/App.tsx index 356ea21..338d0de 100644 --- a/example/src/App.tsx +++ b/example/src/App.tsx @@ -113,6 +113,7 @@ export function App(): ReactElement { onBackdropPress="continue" motion="bounce" onStop={onStopTour} + autoStart="always" > {({ start }) => ( <> diff --git a/package/package.json b/package/package.json index d5465bc..4311d72 100644 --- a/package/package.json +++ b/package/package.json @@ -35,9 +35,9 @@ "test": "jest" }, "dependencies": { - "@react-native-async-storage/async-storage": "^1.18.1", "fast-equals": "^5.0.1", - "react-native-device-info": "^10.6.0", + "object-hash": "^3.0.0", + "react-native-mmkv-storage": "^0.9.1", "react-native-responsive-dimensions": "^3.1.1", "styled-components": "^5.3.9" }, @@ -49,6 +49,7 @@ "@testing-library/react-native": "^11.5.4", "@types/jest": "^29.4.1", "@types/node": "^18.15.3", + "@types/object-hash": "^3.0.2", "@types/react-test-renderer": "^18.0.0", "@types/sinon": "^10.0.13", "@types/styled-components": "^5.1.26", @@ -75,7 +76,8 @@ "peerDependencies": { "react": ">=16.8.0", "react-native": ">=0.50.0", - "react-native-svg": ">=12.1.0" + "react-native-svg": ">=12.1.0", + "react-native-mmkv-storage": ">=0.9.1" }, "peerDependenciesMeta": { "react": { diff --git a/package/src/helpers/storage.ts b/package/src/helpers/storage.ts new file mode 100644 index 0000000..8e4452a --- /dev/null +++ b/package/src/helpers/storage.ts @@ -0,0 +1,5 @@ +import { MMKVLoader } from 'react-native-mmkv-storage'; + +const storage = new MMKVLoader().initialize(); + +export default storage; diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index 3c3154d..f0a6be9 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -1,8 +1,9 @@ -import AsyncStorage from "@react-native-async-storage/async-storage"; +import { useMMKVStorage } from 'react-native-mmkv-storage'; +import storage from '../helpers/storage'; +import hash from 'object-hash'; + import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState, useEffect } from "react"; import { ColorValue, LayoutRectangle } from "react-native"; -import { getUniqueId } from "react-native-device-info"; - import { ChildFn, isChildFunction } from "../helpers/common"; import { @@ -122,6 +123,7 @@ export const SpotlightTourProvider = forwardRef(); const [spot, setSpot] = useState(ZERO_SPOT); + const [tourId, setTourId] = useMMKVStorage('tourId', storage, ''); const overlay = useRef({ hideTooltip: () => Promise.resolve({ finished: false }), @@ -146,16 +148,15 @@ export const SpotlightTourProvider = forwardRef { renderStep(0); onStart?.(); - }, [renderStep, onStart, current]); + }, [renderStep, onStart]); - const startOnce = useCallback(async (): Promise => { - const deviceUniqueId = await getUniqueId(); - const isFirstTime = !(await AsyncStorage.getItem(deviceUniqueId)); - if (isFirstTime) { - await AsyncStorage.setItem(deviceUniqueId, "true"); - start(); + const startOnce = useCallback(() => { + if(!tourId){ + setTourId(hash(steps)); + renderStep(0); + onStart?.(); } - }, [renderStep]); + }, [renderStep, onStart, steps]); useEffect(() => { if (autoStart === "always") { diff --git a/yarn.lock b/yarn.lock index 0c9cefd..91ef7af 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2596,17 +2596,6 @@ __metadata: languageName: node linkType: hard -"@react-native-async-storage/async-storage@npm:^1.18.1": - version: 1.18.1 - resolution: "@react-native-async-storage/async-storage@npm:1.18.1" - dependencies: - merge-options: ^3.0.4 - peerDependencies: - react-native: ^0.0.0-0 || 0.60 - 0.72 || 1000.0.0 - checksum: 58c8497fafdd4d112c4a70b0976783abdc6fa487f0cffca196901efd146fc838dee0cf498fdc4ef67a4634ba4ca97d60fec5a24720aea1d46f1999b0ba8b249b - languageName: node - linkType: hard - "@react-native-community/cli-clean@npm:^10.1.1": version: 10.1.1 resolution: "@react-native-community/cli-clean@npm:10.1.1" @@ -3281,12 +3270,12 @@ __metadata: dependencies: "@babel/core": ^7.21.3 "@babel/preset-env": ^7.20.2 - "@react-native-async-storage/async-storage": ^1.18.1 "@stackbuilders/assertive-ts": ^1.2.0 "@testing-library/jest-native": ^5.4.2 "@testing-library/react-native": ^11.5.4 "@types/jest": ^29.4.1 "@types/node": ^18.15.3 + "@types/object-hash": ^3.0.2 "@types/react-test-renderer": ^18.0.0 "@types/sinon": ^10.0.13 "@types/styled-components": ^5.1.26 @@ -3296,10 +3285,11 @@ __metadata: fast-equals: ^5.0.1 jest: ^29.5.0 metro-react-native-babel-preset: ^0.76.1 + object-hash: ^3.0.0 react: ^18.2.0 react-is: ^18.2.0 react-native: 0.71.6 - react-native-device-info: ^10.6.0 + react-native-mmkv-storage: ^0.9.1 react-native-responsive-dimensions: ^3.1.1 react-native-svg: ^13.8.0 react-test-renderer: ^18.2.0 @@ -3526,6 +3516,13 @@ __metadata: languageName: node linkType: hard +"@types/object-hash@npm:^3.0.2": + version: 3.0.2 + resolution: "@types/object-hash@npm:3.0.2" + checksum: 0332e59074e7df2e74c093a7419c05c1e1c5ae1e12d3779f3240b3031835ff045b4ac591362be0b411ace24d3b5e760386b434761c33af25904f7a3645cb3785 + languageName: node + linkType: hard + "@types/parse-json@npm:^4.0.0": version: 4.0.0 resolution: "@types/parse-json@npm:4.0.0" @@ -6517,6 +6514,7 @@ __metadata: react: 18.2.0 react-is: ^18.2.0 react-native: 0.71.6 + react-native-mmkv-storage: ^0.9.1 react-native-svg: ^13.8.0 styled-components: ^5.3.9 typescript: ^4.9.5 @@ -8098,13 +8096,6 @@ __metadata: languageName: node linkType: hard -"is-plain-obj@npm:^2.1.0": - version: 2.1.0 - resolution: "is-plain-obj@npm:2.1.0" - checksum: cec9100678b0a9fe0248a81743041ed990c2d4c99f893d935545cfbc42876cbe86d207f3b895700c690ad2fa520e568c44afc1605044b535a7820c1d40e38daa - languageName: node - linkType: hard - "is-plain-object@npm:^2.0.3, is-plain-object@npm:^2.0.4": version: 2.0.4 resolution: "is-plain-object@npm:2.0.4" @@ -9685,15 +9676,6 @@ __metadata: languageName: node linkType: hard -"merge-options@npm:^3.0.4": - version: 3.0.4 - resolution: "merge-options@npm:3.0.4" - dependencies: - is-plain-obj: ^2.1.0 - checksum: d86ddb3dd6e85d558dbf25dc944f3527b6bacb944db3fdda6e84a3f59c4e4b85231095f58b835758b9a57708342dee0f8de0dffa352974a48221487fe9f4584f - languageName: node - linkType: hard - "merge-stream@npm:^2.0.0": version: 2.0.0 resolution: "merge-stream@npm:2.0.0" @@ -10886,6 +10868,13 @@ __metadata: languageName: node linkType: hard +"object-hash@npm:^3.0.0": + version: 3.0.0 + resolution: "object-hash@npm:3.0.0" + checksum: 80b4904bb3857c52cc1bfd0b52c0352532ca12ed3b8a6ff06a90cd209dfda1b95cee059a7625eb9da29537027f68ac4619363491eedb2f5d3dddbba97494fd6c + languageName: node + linkType: hard + "object-inspect@npm:^1.12.3, object-inspect@npm:^1.9.0": version: 1.12.3 resolution: "object-inspect@npm:1.12.3" @@ -11807,15 +11796,6 @@ __metadata: languageName: node linkType: hard -"react-native-device-info@npm:^10.6.0": - version: 10.6.0 - resolution: "react-native-device-info@npm:10.6.0" - peerDependencies: - react-native: "*" - checksum: 7a7cc438844552aef687b4a5b8efd0cd0a2959e0a3b771febfbe0b6a9ca8ff05a563e2912b30b83523bd3d5143d6616ca8fac0476abf01936a726e1578211ebb - languageName: node - linkType: hard - "react-native-gradle-plugin@npm:^0.71.17": version: 0.71.17 resolution: "react-native-gradle-plugin@npm:0.71.17" @@ -11823,6 +11803,17 @@ __metadata: languageName: node linkType: hard +"react-native-mmkv-storage@npm:^0.9.1": + version: 0.9.1 + resolution: "react-native-mmkv-storage@npm:0.9.1" + peerDependencies: + react-native: "*" + bin: + mmkv-link: autolink/postlink/run.js + checksum: 564f1cd971d20c9db03cff2d1cf8d55a2c69bd5a907eebbee7bcdc0592917bea5c787b424b1910931c649b3f17c9a361385565af585ec72fb7d1b63b9f2570af + languageName: node + linkType: hard + "react-native-responsive-dimensions@npm:^3.1.1": version: 3.1.1 resolution: "react-native-responsive-dimensions@npm:3.1.1" @@ -13913,11 +13904,11 @@ __metadata: "typescript@patch:typescript@^4.0.0#~builtin, typescript@patch:typescript@^4.9.5#~builtin": version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76" + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=ad5954" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: ab417a2f398380c90a6cf5a5f74badd17866adf57f1165617d6a551f059c3ba0a3e4da0d147b3ac5681db9ac76a303c5876394b13b3de75fdd5b1eaa06181c9d + checksum: 8f6260acc86b56bfdda6004bc53f32ea548f543e8baef7071c8e34d29d292f3e375c8416556c8de10b24deef6933cd1c16a8233dc84a3dd43a13a13265d0faab languageName: node linkType: hard From 6fdbc647b848dc52d44b981d5abd28d165559650 Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Wed, 5 Jul 2023 12:03:30 -0500 Subject: [PATCH 11/14] refactor(test): refactoring auto-start tests --- package/package.json | 4 ++-- package/src/helpers/storage.ts | 2 +- package/src/lib/SpotlightTour.provider.tsx | 12 ++++++------ package/test/integration/index.test.tsx | 21 +++++++-------------- package/test/setup.ts | 17 +++++++++++++---- yarn.lock | 5 +++-- 6 files changed, 32 insertions(+), 29 deletions(-) diff --git a/package/package.json b/package/package.json index 4311d72..c4d90da 100644 --- a/package/package.json +++ b/package/package.json @@ -76,8 +76,8 @@ "peerDependencies": { "react": ">=16.8.0", "react-native": ">=0.50.0", - "react-native-svg": ">=12.1.0", - "react-native-mmkv-storage": ">=0.9.1" + "react-native-mmkv-storage": ">=0.9.1", + "react-native-svg": ">=12.1.0" }, "peerDependenciesMeta": { "react": { diff --git a/package/src/helpers/storage.ts b/package/src/helpers/storage.ts index 8e4452a..0328de1 100644 --- a/package/src/helpers/storage.ts +++ b/package/src/helpers/storage.ts @@ -1,4 +1,4 @@ -import { MMKVLoader } from 'react-native-mmkv-storage'; +import { MMKVLoader } from "react-native-mmkv-storage"; const storage = new MMKVLoader().initialize(); diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index f0a6be9..db7a49b 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -1,10 +1,10 @@ -import { useMMKVStorage } from 'react-native-mmkv-storage'; -import storage from '../helpers/storage'; -import hash from 'object-hash'; - +import hash from "object-hash"; import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState, useEffect } from "react"; import { ColorValue, LayoutRectangle } from "react-native"; +import { useMMKVStorage } from "react-native-mmkv-storage"; + import { ChildFn, isChildFunction } from "../helpers/common"; +import storage from "../helpers/storage"; import { AutoStartOptions, @@ -123,7 +123,7 @@ export const SpotlightTourProvider = forwardRef(); const [spot, setSpot] = useState(ZERO_SPOT); - const [tourId, setTourId] = useMMKVStorage('tourId', storage, ''); + const [tourId, setTourId] = useMMKVStorage("tourId", storage, ""); const overlay = useRef({ hideTooltip: () => Promise.resolve({ finished: false }), @@ -151,7 +151,7 @@ export const SpotlightTourProvider = forwardRef { - if(!tourId){ + if (!tourId) { setTourId(hash(steps)); renderStep(0); onStart?.(); diff --git a/package/test/integration/index.test.tsx b/package/test/integration/index.test.tsx index 2add192..3f90f4c 100644 --- a/package/test/integration/index.test.tsx +++ b/package/test/integration/index.test.tsx @@ -1,7 +1,6 @@ import "@testing-library/jest-native/extend-expect"; import { expect as jestExpect } from "@jest/globals"; -import AsyncStorage from "@react-native-async-storage/async-storage"; import { expect, TypeFactories } from "@stackbuilders/assertive-ts"; import { fireEvent, render, waitFor } from "@testing-library/react-native"; import React from "react"; @@ -291,7 +290,7 @@ describe("[Integration] index.test.tsx", () => { describe("when the autoStart property is set to never", () => { it("the overlay is not shown", async () => { const { getByText, queryByTestId } = render(); - await waitFor(() => getByText("Start")); + await waitFor(() => expect(getByText("Start")).toBePresent()); expect(queryByTestId("Overlay View")).toBeNull(); }); }); @@ -299,29 +298,23 @@ describe("[Integration] index.test.tsx", () => { describe("when the autoStart property is set to always", () => { it("shows the overlay view", async () => { const { getByTestId } = render(); - await waitFor(() => getByTestId("Overlay View")); + await waitFor(() => expect(getByTestId("Overlay View")).toBePresent()); }); }); describe("when the autoStart property is set to once", () => { describe("when the device is not registered", () => { - it("shows the overlay view", async () => { - const { getByTestId } = render(); - waitFor(() => { - jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); - jestExpect(AsyncStorage.setItem).toHaveBeenCalled(); - }); - await waitFor(() => getByTestId("Overlay View")); + it("shows the overlay view", async() => { + const { getByTestId } = render(); + await waitFor(() => expect(getByTestId("Overlay View")).toBePresent()); }); }); describe("when the device is already registered", () => { it("the overlay is not shown", async () => { - await AsyncStorage.setItem("12345", "true"); const { queryByTestId } = render(); - waitFor(() => { - jestExpect(AsyncStorage.getItem).toHaveBeenCalled(); + await waitFor(() => { + expect(queryByTestId("Overlay View")).toBeNull(); }); - expect(queryByTestId("Overlay View")).toBeNull(); }); }); }); diff --git a/package/test/setup.ts b/package/test/setup.ts index 40b2c7c..7210c82 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -1,5 +1,7 @@ /* eslint-disable max-classes-per-file */ +import { useState } from "react"; import { Animated, LayoutRectangle } from "react-native"; +import { MMKVInstance } from "react-native-mmkv-storage"; import { isAnimatedTimingInterpolation, @@ -137,10 +139,17 @@ jest }, }; }) - .mock("@react-native-async-storage/async-storage", () => - AsyncStorageMock) - - .mock("react-native-device-info", () => ({ getUniqueId: () => "12345" })); + /* eslint-disable @typescript-eslint/no-unused-vars */ + .mock("react-native-mmkv-storage", () => ({ + MMKVLoader: jest.fn().mockImplementation(() => ({ + initialize: () => jest.fn(), + })), + useMMKVStorage: (_key: string, _storage: MMKVInstance, defaultValue: string) => { + const [value, setValue] = useState(defaultValue); + const setMockValue = (newValue: string): void => setValue(newValue); + return [value, setMockValue]; + }, + })); afterEach(() => { jest.resetAllMocks(); diff --git a/yarn.lock b/yarn.lock index 91ef7af..9ce94ef 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3306,6 +3306,7 @@ __metadata: peerDependencies: react: ">=16.8.0" react-native: ">=0.50.0" + react-native-mmkv-storage: ">=0.9.1" react-native-svg: ">=12.1.0" peerDependenciesMeta: react: @@ -13904,11 +13905,11 @@ __metadata: "typescript@patch:typescript@^4.0.0#~builtin, typescript@patch:typescript@^4.9.5#~builtin": version: 4.9.5 - resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=ad5954" + resolution: "typescript@patch:typescript@npm%3A4.9.5#~builtin::version=4.9.5&hash=23ec76" bin: tsc: bin/tsc tsserver: bin/tsserver - checksum: 8f6260acc86b56bfdda6004bc53f32ea548f543e8baef7071c8e34d29d292f3e375c8416556c8de10b24deef6933cd1c16a8233dc84a3dd43a13a13265d0faab + checksum: ab417a2f398380c90a6cf5a5f74badd17866adf57f1165617d6a551f059c3ba0a3e4da0d147b3ac5681db9ac76a303c5876394b13b3de75fdd5b1eaa06181c9d languageName: node linkType: hard From e7e11032b05c70a1687df7246b3a21a96bfc418c Mon Sep 17 00:00:00 2001 From: Ricardo Arrobo Date: Wed, 5 Jul 2023 12:15:48 -0500 Subject: [PATCH 12/14] refactor(test): reverting formatter change --- package/test/setup.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/package/test/setup.ts b/package/test/setup.ts index 7210c82..09ca5e1 100644 --- a/package/test/setup.ts +++ b/package/test/setup.ts @@ -91,16 +91,16 @@ jest start(callback) { if ( isAnimatedValueXY(value) - && !isAnimatedTimingInterpolation(config.toValue) - && isXYValue(config.toValue) + && !isAnimatedTimingInterpolation(config.toValue) + && isXYValue(config.toValue) ) { value.setValue(config.toValue); } if ( isAnimatedValue(value) - && !isAnimatedTimingInterpolation(config.toValue) - && isNumberValue(config.toValue) + && !isAnimatedTimingInterpolation(config.toValue) + && isNumberValue(config.toValue) ) { value.setValue(config.toValue); } From 7c8247e97c57bd0f638a7a069422602c1605f959 Mon Sep 17 00:00:00 2001 From: Alejandro Vivanco Date: Tue, 23 Jan 2024 13:01:44 -0500 Subject: [PATCH 13/14] feat(core): Add autoStart feature, merge changes --- package/package.json | 1 + package/src/lib/SpotlightTour.provider.tsx | 10 +--------- yarn.lock | 1 + 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/package/package.json b/package/package.json index f202ce1..ab35ed3 100644 --- a/package/package.json +++ b/package/package.json @@ -39,6 +39,7 @@ "@floating-ui/react-native": "^0.10.1", "object-hash": "^3.0.0", "react-fast-compare": "^3.2.2", + "react-native-mmkv-storage": "^0.9.1", "react-native-responsive-dimensions": "^3.1.1", "styled-components": "^6.0.8" }, diff --git a/package/src/lib/SpotlightTour.provider.tsx b/package/src/lib/SpotlightTour.provider.tsx index f978a44..3a766ae 100644 --- a/package/src/lib/SpotlightTour.provider.tsx +++ b/package/src/lib/SpotlightTour.provider.tsx @@ -1,14 +1,6 @@ +import { flip, offset, shift } from "@floating-ui/react-native"; import hash from "object-hash"; import React, { forwardRef, useCallback, useImperativeHandle, useMemo, useRef, useState, useEffect } from "react"; -import { flip, offset, shift } from "@floating-ui/react-native"; -import React, { - forwardRef, - useCallback, - useImperativeHandle, - useMemo, - useRef, - useState, -} from "react"; import { ColorValue, LayoutRectangle } from "react-native"; import { useMMKVStorage } from "react-native-mmkv-storage"; diff --git a/yarn.lock b/yarn.lock index 9140978..672bd58 100644 --- a/yarn.lock +++ b/yarn.lock @@ -12661,6 +12661,7 @@ __metadata: react-fast-compare: ^3.2.2 react-is: ^18.2.0 react-native: 0.72.4 + react-native-mmkv-storage: ^0.9.1 react-native-responsive-dimensions: ^3.1.1 react-native-svg: ^13.14.0 react-test-renderer: ^18.2.0 From 9c9f8351eaee6bd66368a461cf49e5ded117e7e6 Mon Sep 17 00:00:00 2001 From: Alejandro Vivanco Date: Fri, 26 Jan 2024 17:41:41 -0500 Subject: [PATCH 14/14] Install pods dependencies --- example/ios/Podfile.lock | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock index 9f3c52a..1a14de6 100644 --- a/example/ios/Podfile.lock +++ b/example/ios/Podfile.lock @@ -74,6 +74,9 @@ PODS: - hermes-engine/Pre-built (= 0.72.4) - hermes-engine/Pre-built (0.72.4) - libevent (2.1.12) + - MMKV (1.2.13): + - MMKVCore (~> 1.2.13) + - MMKVCore (1.2.16) - OpenSSL-Universal (1.1.1100) - RCT-Folly (2021.07.22.00): - boost @@ -375,6 +378,9 @@ PODS: - React-jsinspector (0.72.4) - React-logger (0.72.4): - glog + - react-native-mmkv-storage (0.9.1): + - MMKV (= 1.2.13) + - React-Core - React-NativeModulesApple (0.72.4): - hermes-engine - React-callinvoker @@ -538,6 +544,7 @@ DEPENDENCIES: - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector`) - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - react-native-mmkv-storage (from `../node_modules/react-native-mmkv-storage`) - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) @@ -571,6 +578,8 @@ SPEC REPOS: - FlipperKit - fmt - libevent + - MMKV + - MMKVCore - OpenSSL-Universal - SocketRocket - YogaKit @@ -619,6 +628,8 @@ EXTERNAL SOURCES: :path: "../node_modules/react-native/ReactCommon/jsinspector" React-logger: :path: "../node_modules/react-native/ReactCommon/logger" + react-native-mmkv-storage: + :path: "../node_modules/react-native-mmkv-storage" React-NativeModulesApple: :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" React-perflogger: @@ -676,6 +687,8 @@ SPEC CHECKSUMS: glog: 04b94705f318337d7ead9e6d17c019bd9b1f6b1b hermes-engine: 81191603c4eaa01f5e4ae5737a9efcf64756c7b2 libevent: 4049cae6c81cdb3654a443be001fb9bdceff7913 + MMKV: aac95d817a100479445633f2b3ed8961b4ac5043 + MMKVCore: 9cfef4c48c6c46f66226fc2e4634d78490206a48 OpenSSL-Universal: ebc357f1e6bc71fa463ccb2fe676756aff50e88c RCT-Folly: 424b8c9a7a0b9ab2886ffe9c3b041ef628fd4fb1 RCTRequired: c0569ecc035894e4a68baecb30fe6a7ea6e399f9 @@ -692,6 +705,7 @@ SPEC CHECKSUMS: React-jsiexecutor: c7f826e40fa9cab5d37cab6130b1af237332b594 React-jsinspector: aaed4cf551c4a1c98092436518c2d267b13a673f React-logger: da1ebe05ae06eb6db4b162202faeafac4b435e77 + react-native-mmkv-storage: cfb6854594cfdc5f7383a9e464bb025417d1721c React-NativeModulesApple: edb5ace14f73f4969df6e7b1f3e41bef0012740f React-perflogger: 496a1a3dc6737f964107cb3ddae7f9e265ddda58 React-RCTActionSheet: 02904b932b50e680f4e26e7a686b33ebf7ef3c00