diff --git a/Podfile b/Podfile index 5d612e89c4e0..c67d28b68b3c 100644 --- a/Podfile +++ b/Podfile @@ -179,7 +179,7 @@ abstract_target 'Apps' do ## Gutenberg (React Native) ## ===================== ## - gutenberg tag: 'v1.85.0' + gutenberg tag: 'v1.85.1' ## Third party libraries ## ===================== diff --git a/Podfile.lock b/Podfile.lock index 2bf5073dc486..9c0d8a4b89c8 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -57,7 +57,7 @@ PODS: - AppAuth/Core (~> 1.6) - GTMSessionFetcher/Core (< 3.0, >= 1.5) - GTMSessionFetcher/Core (1.7.2) - - Gutenberg (1.85.0): + - Gutenberg (1.85.1): - React (= 0.66.2) - React-CoreModules (= 0.66.2) - React-RCTImage (= 0.66.2) @@ -472,7 +472,7 @@ PODS: - React-Core - RNSVG (9.13.6): - React-Core - - RNTAztecView (1.85.0): + - RNTAztecView (1.85.1): - React-Core - WordPress-Aztec-iOS (~> 1.19.8) - SDWebImage (5.11.1): @@ -537,18 +537,18 @@ DEPENDENCIES: - AppCenter (~> 4.1) - AppCenter/Distribute (~> 4.1) - Automattic-Tracks-iOS (~> 0.13) - - boost (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/boost.podspec.json`) - - BVLinearGradient (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/BVLinearGradient.podspec.json`) + - boost (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/boost.podspec.json`) + - BVLinearGradient (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/BVLinearGradient.podspec.json`) - CocoaLumberjack (~> 3.0) - CropViewController (= 2.5.3) - Down (~> 0.6.6) - - FBLazyVector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/FBLazyVector.podspec.json`) - - FBReactNativeSpec (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/FBReactNativeSpec/FBReactNativeSpec.podspec.json`) + - FBLazyVector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/FBLazyVector.podspec.json`) + - FBReactNativeSpec (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/FBReactNativeSpec/FBReactNativeSpec.podspec.json`) - FSInteractiveMap (from `https://github.com/wordpress-mobile/FSInteractiveMap.git`, tag `0.2.0`) - Gifu (= 3.2.0) - - glog (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/glog.podspec.json`) + - glog (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/glog.podspec.json`) - Gridicons (~> 1.1.0) - - Gutenberg (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.85.0`) + - Gutenberg (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.85.1`) - JTAppleCalendar (~> 8.0.2) - Kanvas (~> 1.4.4) - MediaEditor (~> 1.2.1) @@ -557,47 +557,47 @@ DEPENDENCIES: - "NSURL+IDN (~> 0.4)" - OCMock (~> 3.4.3) - OHHTTPStubs/Swift (~> 9.1.0) - - RCT-Folly (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCT-Folly.podspec.json`) - - RCTRequired (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCTRequired.podspec.json`) - - RCTTypeSafety (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCTTypeSafety.podspec.json`) + - RCT-Folly (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCT-Folly.podspec.json`) + - RCTRequired (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCTRequired.podspec.json`) + - RCTTypeSafety (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCTTypeSafety.podspec.json`) - Reachability (= 3.2) - - React (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React.podspec.json`) - - React-callinvoker (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-callinvoker.podspec.json`) - - React-Core (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-Core.podspec.json`) - - React-CoreModules (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-CoreModules.podspec.json`) - - React-cxxreact (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-cxxreact.podspec.json`) - - React-jsi (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsi.podspec.json`) - - React-jsiexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsiexecutor.podspec.json`) - - React-jsinspector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsinspector.podspec.json`) - - React-logger (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-logger.podspec.json`) - - react-native-blur (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-blur.podspec.json`) - - react-native-get-random-values (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-get-random-values.podspec.json`) - - react-native-keyboard-aware-scroll-view (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json`) - - react-native-safe-area (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-safe-area.podspec.json`) - - react-native-safe-area-context (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-safe-area-context.podspec.json`) - - react-native-slider (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-slider.podspec.json`) - - react-native-video (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-video.podspec.json`) - - react-native-webview (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-webview.podspec.json`) - - React-perflogger (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-perflogger.podspec.json`) - - React-RCTActionSheet (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTActionSheet.podspec.json`) - - React-RCTAnimation (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTAnimation.podspec.json`) - - React-RCTBlob (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTBlob.podspec.json`) - - React-RCTImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTImage.podspec.json`) - - React-RCTLinking (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTLinking.podspec.json`) - - React-RCTNetwork (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTNetwork.podspec.json`) - - React-RCTSettings (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTSettings.podspec.json`) - - React-RCTText (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTText.podspec.json`) - - React-RCTVibration (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTVibration.podspec.json`) - - React-runtimeexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-runtimeexecutor.podspec.json`) - - ReactCommon (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/ReactCommon.podspec.json`) - - RNCClipboard (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNCClipboard.podspec.json`) - - RNCMaskedView (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNCMaskedView.podspec.json`) - - RNFastImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNFastImage.podspec.json`) - - RNGestureHandler (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNGestureHandler.podspec.json`) - - RNReanimated (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNReanimated.podspec.json`) - - RNScreens (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNScreens.podspec.json`) - - RNSVG (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNSVG.podspec.json`) - - RNTAztecView (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.85.0`) + - React (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React.podspec.json`) + - React-callinvoker (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-callinvoker.podspec.json`) + - React-Core (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-Core.podspec.json`) + - React-CoreModules (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-CoreModules.podspec.json`) + - React-cxxreact (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-cxxreact.podspec.json`) + - React-jsi (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsi.podspec.json`) + - React-jsiexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsiexecutor.podspec.json`) + - React-jsinspector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsinspector.podspec.json`) + - React-logger (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-logger.podspec.json`) + - react-native-blur (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-blur.podspec.json`) + - react-native-get-random-values (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-get-random-values.podspec.json`) + - react-native-keyboard-aware-scroll-view (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json`) + - react-native-safe-area (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-safe-area.podspec.json`) + - react-native-safe-area-context (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-safe-area-context.podspec.json`) + - react-native-slider (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-slider.podspec.json`) + - react-native-video (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-video.podspec.json`) + - react-native-webview (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-webview.podspec.json`) + - React-perflogger (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-perflogger.podspec.json`) + - React-RCTActionSheet (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTActionSheet.podspec.json`) + - React-RCTAnimation (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTAnimation.podspec.json`) + - React-RCTBlob (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTBlob.podspec.json`) + - React-RCTImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTImage.podspec.json`) + - React-RCTLinking (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTLinking.podspec.json`) + - React-RCTNetwork (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTNetwork.podspec.json`) + - React-RCTSettings (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTSettings.podspec.json`) + - React-RCTText (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTText.podspec.json`) + - React-RCTVibration (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTVibration.podspec.json`) + - React-runtimeexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-runtimeexecutor.podspec.json`) + - ReactCommon (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/ReactCommon.podspec.json`) + - RNCClipboard (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNCClipboard.podspec.json`) + - RNCMaskedView (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNCMaskedView.podspec.json`) + - RNFastImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNFastImage.podspec.json`) + - RNGestureHandler (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNGestureHandler.podspec.json`) + - RNReanimated (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNReanimated.podspec.json`) + - RNScreens (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNScreens.podspec.json`) + - RNSVG (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNSVG.podspec.json`) + - RNTAztecView (from `https://github.com/wordpress-mobile/gutenberg-mobile.git`, tag `v1.85.1`) - Starscream (= 3.0.6) - SVProgressHUD (= 2.2.5) - WordPress-Editor-iOS (~> 1.19.8) @@ -606,7 +606,7 @@ DEPENDENCIES: - WordPressShared (~> 1.18.0) - WordPressUI (~> 1.12.5) - WPMediaPicker (~> 1.8.7) - - Yoga (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/Yoga.podspec.json`) + - Yoga (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/Yoga.podspec.json`) - ZendeskSupportSDK (= 5.3.0) - ZIPFoundation (~> 0.9.8) @@ -666,106 +666,106 @@ SPEC REPOS: EXTERNAL SOURCES: boost: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/boost.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/boost.podspec.json BVLinearGradient: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/BVLinearGradient.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/BVLinearGradient.podspec.json FBLazyVector: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/FBLazyVector.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/FBLazyVector.podspec.json FBReactNativeSpec: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/FBReactNativeSpec/FBReactNativeSpec.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/FBReactNativeSpec/FBReactNativeSpec.podspec.json FSInteractiveMap: :git: https://github.com/wordpress-mobile/FSInteractiveMap.git :tag: 0.2.0 glog: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/glog.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/glog.podspec.json Gutenberg: :git: https://github.com/wordpress-mobile/gutenberg-mobile.git :submodules: true - :tag: v1.85.0 + :tag: v1.85.1 RCT-Folly: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCT-Folly.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCT-Folly.podspec.json RCTRequired: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCTRequired.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCTRequired.podspec.json RCTTypeSafety: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RCTTypeSafety.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RCTTypeSafety.podspec.json React: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React.podspec.json React-callinvoker: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-callinvoker.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-callinvoker.podspec.json React-Core: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-Core.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-Core.podspec.json React-CoreModules: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-CoreModules.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-CoreModules.podspec.json React-cxxreact: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-cxxreact.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-cxxreact.podspec.json React-jsi: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsi.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsi.podspec.json React-jsiexecutor: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsiexecutor.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsiexecutor.podspec.json React-jsinspector: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-jsinspector.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-jsinspector.podspec.json React-logger: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-logger.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-logger.podspec.json react-native-blur: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-blur.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-blur.podspec.json react-native-get-random-values: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-get-random-values.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-get-random-values.podspec.json react-native-keyboard-aware-scroll-view: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json react-native-safe-area: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-safe-area.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-safe-area.podspec.json react-native-safe-area-context: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-safe-area-context.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-safe-area-context.podspec.json react-native-slider: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-slider.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-slider.podspec.json react-native-video: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-video.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-video.podspec.json react-native-webview: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/react-native-webview.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/react-native-webview.podspec.json React-perflogger: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-perflogger.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-perflogger.podspec.json React-RCTActionSheet: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTActionSheet.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTActionSheet.podspec.json React-RCTAnimation: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTAnimation.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTAnimation.podspec.json React-RCTBlob: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTBlob.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTBlob.podspec.json React-RCTImage: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTImage.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTImage.podspec.json React-RCTLinking: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTLinking.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTLinking.podspec.json React-RCTNetwork: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTNetwork.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTNetwork.podspec.json React-RCTSettings: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTSettings.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTSettings.podspec.json React-RCTText: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTText.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTText.podspec.json React-RCTVibration: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-RCTVibration.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-RCTVibration.podspec.json React-runtimeexecutor: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/React-runtimeexecutor.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/React-runtimeexecutor.podspec.json ReactCommon: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/ReactCommon.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/ReactCommon.podspec.json RNCClipboard: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNCClipboard.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNCClipboard.podspec.json RNCMaskedView: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNCMaskedView.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNCMaskedView.podspec.json RNFastImage: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNFastImage.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNFastImage.podspec.json RNGestureHandler: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNGestureHandler.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNGestureHandler.podspec.json RNReanimated: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNReanimated.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNReanimated.podspec.json RNScreens: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNScreens.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNScreens.podspec.json RNSVG: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/RNSVG.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/RNSVG.podspec.json RNTAztecView: :git: https://github.com/wordpress-mobile/gutenberg-mobile.git :submodules: true - :tag: v1.85.0 + :tag: v1.85.1 Yoga: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.0/third-party-podspecs/Yoga.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.85.1/third-party-podspecs/Yoga.podspec.json CHECKOUT OPTIONS: FSInteractiveMap: @@ -774,11 +774,11 @@ CHECKOUT OPTIONS: Gutenberg: :git: https://github.com/wordpress-mobile/gutenberg-mobile.git :submodules: true - :tag: v1.85.0 + :tag: v1.85.1 RNTAztecView: :git: https://github.com/wordpress-mobile/gutenberg-mobile.git :submodules: true - :tag: v1.85.0 + :tag: v1.85.1 SPEC CHECKSUMS: Alamofire: 3ec537f71edc9804815215393ae2b1a8ea33a844 @@ -804,7 +804,7 @@ SPEC CHECKSUMS: Gridicons: 17d660b97ce4231d582101b02f8280628b141c9a GTMAppAuth: 0ff230db599948a9ad7470ca667337803b3fc4dd GTMSessionFetcher: 5595ec75acf5be50814f81e9189490412bad82ba - Gutenberg: 387b010e396588027538e351899bf1cc730a7009 + Gutenberg: cbeb7133c8a80d21980d92c97287d00c387c3114 JTAppleCalendar: 932cadea40b1051beab10f67843451d48ba16c99 Kanvas: f932eaed3d3f47aae8aafb6c2d27c968bdd49030 libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c @@ -854,7 +854,7 @@ SPEC CHECKSUMS: RNReanimated: e9b24be225e2d6b04bce30bc73322fd3b3b05f52 RNScreens: bd1f43d7dfcd435bc11d4ee5c60086717c45a113 RNSVG: 259ef12cbec2591a45fc7c5f09d7aa09e6692533 - RNTAztecView: f7d8790bed08a070420540cc68fd57e7433d9414 + RNTAztecView: 0c9bda60aca89b65093e3cda2c9992c50322cae2 SDWebImage: a7f831e1a65eb5e285e3fb046a23fcfbf08e696d SDWebImageWebPCoder: 908b83b6adda48effe7667cd2b7f78c897e5111d Sentry: 026b36fdc09531604db9279e55f047fe652e3f4a @@ -880,6 +880,6 @@ SPEC CHECKSUMS: ZendeskSupportSDK: 3a8e508ab1d9dd22dc038df6c694466414e037ba ZIPFoundation: ae5b4b813d216d3bf0a148773267fff14bd51d37 -PODFILE CHECKSUM: e4762593ef0d1097286d309c828f611976c1e771 +PODFILE CHECKSUM: 1244a13ad31cc499410b4901755c8810df5acb33 COCOAPODS: 1.11.2 diff --git a/WordPress/Classes/Extensions/UIApplication+AppAvailability.swift b/WordPress/Classes/Extensions/UIApplication+AppAvailability.swift new file mode 100644 index 000000000000..2890b5ffe767 --- /dev/null +++ b/WordPress/Classes/Extensions/UIApplication+AppAvailability.swift @@ -0,0 +1,15 @@ +import Foundation + +enum AppScheme: String { + case wordpress = "wordpress://" + case wordpressMigrationV1 = "wordpressmigration+v1://" +} + +extension UIApplication { + func canOpen(app: AppScheme) -> Bool { + guard let url = URL(string: app.rawValue) else { + return false + } + return canOpenURL(url) + } +} diff --git a/WordPress/Classes/Services/JetpackNotificationMigrationService.swift b/WordPress/Classes/Services/JetpackNotificationMigrationService.swift index f42bda545256..420b72525aa1 100644 --- a/WordPress/Classes/Services/JetpackNotificationMigrationService.swift +++ b/WordPress/Classes/Services/JetpackNotificationMigrationService.swift @@ -11,12 +11,14 @@ protocol JetpackNotificationMigrationServiceProtocol { final class JetpackNotificationMigrationService: JetpackNotificationMigrationServiceProtocol { private let remoteNotificationRegister: RemoteNotificationRegister private let featureFlagStore: RemoteFeatureFlagStore + private let userDefaults: UserDefaults private let isWordPress: Bool static let shared = JetpackNotificationMigrationService() static let wordPressScheme = "wordpressnotificationmigration" static let jetpackScheme = "jetpacknotificationmigration" + private let wordPressNotificationsToggledDefaultsKey = "wordPressNotificationsToggledDefaultsKey" private let jetpackNotificationMigrationDefaultsKey = "jetpackNotificationMigrationDefaultsKey" private var jetpackMigrationPreventDuplicateNotifications: Bool { @@ -38,6 +40,8 @@ final class JetpackNotificationMigrationService: JetpackNotificationMigrationSer } set { + userDefaults.set(true, forKey: wordPressNotificationsToggledDefaultsKey) + if newValue, isWordPress { remoteNotificationRegister.registerForRemoteNotifications() rescheduleLocalNotifications() @@ -63,18 +67,20 @@ final class JetpackNotificationMigrationService: JetpackNotificationMigrationSer /// disableWordPressNotificationsFromJetpack may get triggered multiple times from Jetpack app but it only needs to be executed the first time private var isMigrationDone: Bool { get { - return UserDefaults.standard.bool(forKey: jetpackNotificationMigrationDefaultsKey) + return userDefaults.bool(forKey: jetpackNotificationMigrationDefaultsKey) } set { - UserDefaults.standard.setValue(newValue, forKey: jetpackNotificationMigrationDefaultsKey) + userDefaults.setValue(newValue, forKey: jetpackNotificationMigrationDefaultsKey) } } init(remoteNotificationRegister: RemoteNotificationRegister = UIApplication.shared, featureFlagStore: RemoteFeatureFlagStore = RemoteFeatureFlagStore(), + userDefaults: UserDefaults = .standard, isWordPress: Bool = AppConfiguration.isWordPress) { self.remoteNotificationRegister = remoteNotificationRegister self.featureFlagStore = featureFlagStore + self.userDefaults = userDefaults self.isWordPress = isWordPress } @@ -85,6 +91,7 @@ final class JetpackNotificationMigrationService: JetpackNotificationMigrationSer func shouldPresentNotifications() -> Bool { let disableNotifications = jetpackMigrationPreventDuplicateNotifications && isWordPress + && userDefaults.bool(forKey: wordPressNotificationsToggledDefaultsKey) && !wordPressNotificationsEnabled if disableNotifications { diff --git a/WordPress/Classes/Stores/UserPersistentRepositoryUtility.swift b/WordPress/Classes/Stores/UserPersistentRepositoryUtility.swift index 4bc805303bc8..b456c1be73dd 100644 --- a/WordPress/Classes/Stores/UserPersistentRepositoryUtility.swift +++ b/WordPress/Classes/Stores/UserPersistentRepositoryUtility.swift @@ -15,6 +15,7 @@ private enum UPRUConstants { static let currentAnnouncementsKey = "currentAnnouncements" static let currentAnnouncementsDateKey = "currentAnnouncementsDate" static let announcementsVersionDisplayedKey = "announcementsVersionDisplayed" + static let isJPContentImportCompleteKey = "jetpackContentImportComplete" } protocol UserPersistentRepositoryUtility: AnyObject { @@ -164,4 +165,13 @@ extension UserPersistentRepositoryUtility { UserPersistentStoreFactory.instance().set(newValue, forKey: UPRUConstants.announcementsVersionDisplayedKey) } } + + var isJPContentImportComplete: Bool { + get { + return UserPersistentStoreFactory.instance().bool(forKey: UPRUConstants.isJPContentImportCompleteKey) + } + set { + UserPersistentStoreFactory.instance().set(newValue, forKey: UPRUConstants.isJPContentImportCompleteKey) + } + } } diff --git a/WordPress/Classes/System/WordPressAppDelegate.swift b/WordPress/Classes/System/WordPressAppDelegate.swift index 167d4ccfa904..9e4b60e4f559 100644 --- a/WordPress/Classes/System/WordPressAppDelegate.swift +++ b/WordPress/Classes/System/WordPressAppDelegate.swift @@ -196,6 +196,13 @@ class WordPressAppDelegate: UIResponder, UIApplicationDelegate { uploadsManager.resume() updateFeatureFlags() updateRemoteConfig() + + #if JETPACK + if let windowManager = windowManager as? JetpackWindowManager, + windowManager.shouldImportMigrationData { + windowManager.importAndShowMigrationContent(nil, failureCompletion: nil) + } + #endif } func applicationWillResignActive(_ application: UIApplication) { diff --git a/WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift b/WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift index a64f44cd16a3..a16abe35bb4f 100644 --- a/WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift +++ b/WordPress/Classes/Utility/Analytics/WPAnalyticsEvent.swift @@ -415,6 +415,11 @@ import Foundation case jetpackSiteCreationOverlayButtonTapped case jetpackSiteCreationOverlayDismissed + // WordPress to Jetpack Migration + case migrationEmailTriggered + case migrationEmailSent + case migrationEmailFailed + /// A String that represents the event var value: String { switch self { @@ -1123,6 +1128,15 @@ import Foundation return "remove_site_creation_overlay_button_tapped" case .jetpackSiteCreationOverlayDismissed: return "remove_site_creation_overlay_dismissed" + + // WordPress to Jetpack Migration + case .migrationEmailTriggered: + return "migration_email_triggered" + case .migrationEmailSent: + return "migration_email_sent" + case .migrationEmailFailed: + return "migration_email_failed" + } // END OF SWITCH } diff --git a/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift b/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift index d5d24128d4b7..7b7daa42c266 100644 --- a/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift +++ b/WordPress/Classes/Utility/Migration/ContentMigrationCoordinator.swift @@ -8,13 +8,16 @@ class ContentMigrationCoordinator { // MARK: Dependencies + private let coreDataStack: CoreDataStack private let dataMigrator: ContentDataMigrating private let userPersistentRepository: UserPersistentRepository private let eligibilityProvider: ContentMigrationEligibilityProvider - init(dataMigrator: ContentDataMigrating = DataMigrator(), + init(coreDataStack: CoreDataStack = ContextManager.shared, + dataMigrator: ContentDataMigrating = DataMigrator(), userPersistentRepository: UserPersistentRepository = UserDefaults.standard, eligibilityProvider: ContentMigrationEligibilityProvider = AppConfiguration()) { + self.coreDataStack = coreDataStack self.dataMigrator = dataMigrator self.userPersistentRepository = userPersistentRepository self.eligibilityProvider = eligibilityProvider @@ -23,6 +26,7 @@ class ContentMigrationCoordinator { enum ContentMigrationCoordinatorError: Error { case ineligible case exportFailure + case localDraftsNotSynced } // MARK: Methods @@ -41,7 +45,10 @@ class ContentMigrationCoordinator { return } - // TODO: Sync local post drafts here. + guard isLocalPostsSynced() else { + completion?(.failure(.localDraftsNotSynced)) + return + } dataMigrator.exportData { result in switch result { @@ -78,6 +85,26 @@ class ContentMigrationCoordinator { } } +// MARK: - Preflights Local Draft Check + +private extension ContentMigrationCoordinator { + + func isLocalPostsSynced() -> Bool { + let fetchRequest = NSFetchRequest(entityName: String(describing: Post.self)) + fetchRequest.predicate = NSPredicate(format: "remoteStatusNumber = %@ || remoteStatusNumber = %@ || remoteStatusNumber = %@ || remoteStatusNumber = %@", + NSNumber(value: AbstractPostRemoteStatus.pushing.rawValue), + NSNumber(value: AbstractPostRemoteStatus.failed.rawValue), + NSNumber(value: AbstractPostRemoteStatus.local.rawValue), + NSNumber(value: AbstractPostRemoteStatus.pushingMedia.rawValue)) + guard let count = try? coreDataStack.mainContext.count(for: fetchRequest) else { + return false + } + + return count == 0 + } + +} + // MARK: - Content Migration Eligibility Provider protocol ContentMigrationEligibilityProvider { diff --git a/WordPress/Classes/ViewRelated/Support/LogOutActionHandler.swift b/WordPress/Classes/ViewRelated/Support/LogOutActionHandler.swift index f9fff153f878..05682bf88f11 100644 --- a/WordPress/Classes/ViewRelated/Support/LogOutActionHandler.swift +++ b/WordPress/Classes/ViewRelated/Support/LogOutActionHandler.swift @@ -2,12 +2,19 @@ import UIKit struct LogOutActionHandler { + private weak var windowManager: WindowManager? + + init(windowManager: WindowManager? = WordPressAppDelegate.shared?.windowManager) { + self.windowManager = windowManager + } + func logOut(with viewController: UIViewController) { let alert = UIAlertController(title: logOutAlertTitle, message: nil, preferredStyle: .alert) alert.addActionWithTitle(Strings.alertCancelAction, style: .cancel) alert.addActionWithTitle(Strings.alertLogoutAction, style: .destructive) { [weak viewController] _ in viewController?.dismiss(animated: true) { AccountHelper.logOutDefaultWordPressComAccount() + windowManager?.showSignInUI() } } viewController.present(alert, animated: true) diff --git a/WordPress/Info.plist b/WordPress/Info.plist index 999326b6d2d5..26dda15bb966 100644 --- a/WordPress/Info.plist +++ b/WordPress/Info.plist @@ -477,6 +477,7 @@ wordpress-oauth-v2 ${WPCOM_SCHEME} + wordpressmigration+v1 wordpressnotificationmigration diff --git a/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift b/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift index e880ef86314a..a68104327070 100644 --- a/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift +++ b/WordPress/Jetpack/Classes/System/JetpackWindowManager.swift @@ -5,25 +5,62 @@ class JetpackWindowManager: WindowManager { /// receives migration flow updates in order to dismiss it when needed. private var cancellable: AnyCancellable? + var shouldImportMigrationData: Bool { + return !AccountHelper.isLoggedIn && !UserPersistentStoreFactory.instance().isJPContentImportComplete + } + override func showUI(for blog: Blog?) { // If the user is logged in and has blogs sync'd to their account if AccountHelper.isLoggedIn && AccountHelper.hasBlogs { - shouldShowMigrationUI ? showMigrationUI(blog) : showAppUI(for: blog) + showAppUI(for: blog) return } - // Show the sign in UI if the user isn't logged in guard AccountHelper.isLoggedIn else { - showSignInUI() + if shouldImportMigrationData { + importAndShowMigrationContent(blog) { [weak self] in + self?.showSignInUI() + } + } else { + showSignInUI() + } return } - // If the user doesn't have any blogs, but they're still logged in, log them out // the `logOutDefaultWordPressComAccount` method will trigger the `showSignInUI` automatically AccountHelper.logOutDefaultWordPressComAccount() } - private func showMigrationUI(_ blog: Blog?) { + func importAndShowMigrationContent(_ blog: Blog?, failureCompletion: (() -> ())?) { + DataMigrator().importData() { [weak self] result in + guard let self else { + return + } + + switch result { + case .success: + UserPersistentStoreFactory.instance().isJPContentImportComplete = true + NotificationCenter.default.post(name: .WPAccountDefaultWordPressComAccountChanged, object: nil) + self.showMigrationUIIfNeeded(blog) + self.sendMigrationEmail() + case .failure: + failureCompletion?() + } + } + } + + private func sendMigrationEmail() { + Task { + let service = try? MigrationEmailService() + try? await service?.sendMigrationEmail() + } + } + + private func showMigrationUIIfNeeded(_ blog: Blog?) { + guard shouldShowMigrationUI else { + return + } + let container = MigrationDependencyContainer() cancellable = container.migrationCoordinator.$currentStep .receive(on: DispatchQueue.main) @@ -41,8 +78,7 @@ class JetpackWindowManager: WindowManager { showAppUI(for: blog) } - // TODO: Add logic in here to trigger migration UI if needed private var shouldShowMigrationUI: Bool { - return FeatureFlag.contentMigration.enabled + return FeatureFlag.contentMigration.enabled && AccountHelper.isLoggedIn } } diff --git a/WordPress/Jetpack/Classes/Utility/DataMigrator.swift b/WordPress/Jetpack/Classes/Utility/DataMigrator.swift index 1d8ea5fe46bc..9904e78589d9 100644 --- a/WordPress/Jetpack/Classes/Utility/DataMigrator.swift +++ b/WordPress/Jetpack/Classes/Utility/DataMigrator.swift @@ -4,7 +4,6 @@ protocol ContentDataMigrating { } enum DataMigrationError: Error { - case localDraftsNotSynced case databaseCopyError case sharedUserDefaultsNil } @@ -81,10 +80,6 @@ final class DataMigrator { extension DataMigrator: ContentDataMigrating { func exportData(completion: ((Result) -> Void)? = nil) { - guard isLocalDraftsSynced() else { - completion?(.failure(.localDraftsNotSynced)) - return - } guard let backupLocation, copyDatabase(to: backupLocation) else { completion?(.failure(.databaseCopyError)) return @@ -119,21 +114,6 @@ extension DataMigrator: ContentDataMigrating { private extension DataMigrator { - func isLocalDraftsSynced() -> Bool { - let fetchRequest = NSFetchRequest(entityName: String(describing: Post.self)) - fetchRequest.predicate = NSPredicate(format: "status = %@ && (remoteStatusNumber = %@ || remoteStatusNumber = %@ || remoteStatusNumber = %@ || remoteStatusNumber = %@)", - BasePost.Status.draft.rawValue, - NSNumber(value: AbstractPostRemoteStatus.pushing.rawValue), - NSNumber(value: AbstractPostRemoteStatus.failed.rawValue), - NSNumber(value: AbstractPostRemoteStatus.local.rawValue), - NSNumber(value: AbstractPostRemoteStatus.pushingMedia.rawValue)) - guard let count = try? coreDataStack.mainContext.count(for: fetchRequest) else { - return false - } - - return count == 0 - } - func copyDatabase(to destination: URL) -> Bool { do { try coreDataStack.createStoreCopy(to: destination) diff --git a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationAppDetection.swift b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationAppDetection.swift new file mode 100644 index 000000000000..6802bfd1aeed --- /dev/null +++ b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationAppDetection.swift @@ -0,0 +1,47 @@ +import Foundation + +enum WordPressInstallationState { + case wordPressNotInstalled + case wordPressInstalledNotMigratable + case wordPressInstalledAndMigratable +} + +struct MigrationAppDetection { + + static func getWordPressInstallationState() -> WordPressInstallationState { + let tracker = MigratatableStateTracker() + + if UIApplication.shared.canOpen(app: .wordpressMigrationV1) { + tracker.trackMigratable() + return .wordPressInstalledAndMigratable + } + + if UIApplication.shared.canOpen(app: .wordpress) { + tracker.trackNotMigratable() + return .wordPressInstalledNotMigratable + } + + return .wordPressNotInstalled + } +} + +struct MigratatableStateTracker { + + private static let eventName = "jpmigration_wordpressapp_detected" + + private func track(_ event: AnalyticsEvent) { + WPAnalytics.track(event) + } + + private func event(_ eventName: String, properties: [String: String]) -> AnalyticsEvent { + AnalyticsEvent(name: eventName, properties: properties) + } + + func trackMigratable() { + track(event(Self.eventName, properties: ["compatible": "true"])) + } + + func trackNotMigratable() { + track(event(Self.eventName, properties: ["compatible": "false"])) + } +} diff --git a/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationEmailService.swift b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationEmailService.swift new file mode 100644 index 000000000000..2d761ae1d9c3 --- /dev/null +++ b/WordPress/Jetpack/Classes/ViewRelated/WordPress-to-Jetpack Migration/Common/MigrationEmailService.swift @@ -0,0 +1,91 @@ +import Foundation + +final class MigrationEmailService { + + // MARK: - Dependencies + + private let api: WordPressComRestApi + + // MARK: - Init + + init(api: WordPressComRestApi) { + self.api = api + } + + convenience init(account: WPAccount) { + self.init(api: account.wordPressComRestV2Api) + } + + /// Convenience initializer that tries to set the `WordPressComRestApi` property, or fails. + convenience init() throws { + do { + let context = ContextManager.shared.mainContext + guard let account = try WPAccount.lookupDefaultWordPressComAccount(in: context) else { + throw MigrationError.accountNotFound + } + self.init(api: account.wordPressComRestV2Api) + } catch let error { + DDLogError("[\(MigrationError.domain)] Object instantiation failed: \(error.localizedDescription)") + throw error + } + } + + // MARK: - Methods + + func sendMigrationEmail() async throws { + do { + WPAnalytics.track(.migrationEmailTriggered) + let response = try await sendMigrationEmail(path: Endpoint.migrationEmail) + if !response.success { + throw MigrationError.unsuccessfulResponse + } + WPAnalytics.track(.migrationEmailSent) + } catch let error { + let properties = ["error_type": error.localizedDescription] + WPAnalytics.track(.migrationEmailFailed, properties: properties) + DDLogError("[\(MigrationError.domain)] Migration email sending failed: \(error.localizedDescription)") + throw error + } + } + + private func sendMigrationEmail(path: String) async throws -> SendMigrationEmailResponse { + return try await withCheckedThrowingContinuation { continuation in + api.POST(path, parameters: nil) { responseObject, httpResponse in + do { + let decoder = JSONDecoder() + let data = try JSONSerialization.data(withJSONObject: responseObject) + let response = try decoder.decode(SendMigrationEmailResponse.self, from: data) + continuation.resume(returning: response) + } catch let error { + continuation.resume(throwing: error) + } + } failure: { error, httpResponse in + continuation.resume(throwing: error) + } + } + } + + // MARK: - Types + + enum MigrationError: LocalizedError { + case accountNotFound + case unsuccessfulResponse + + var errorDescription: String? { + switch self { + case .accountNotFound: return "Account not found." + case .unsuccessfulResponse: return "Backend returned an unsuccessful response. ( success: false )" + } + } + + static let domain = "MigrationEmailService" + } + + private enum Endpoint { + static let migrationEmail = "/wpcom/v2/mobile/migration" + } + + private struct SendMigrationEmailResponse: Decodable { + let success: Bool + } +} diff --git a/WordPress/Jetpack/Info.plist b/WordPress/Jetpack/Info.plist index a034184dd2f8..cf0c1f81f737 100644 --- a/WordPress/Jetpack/Info.plist +++ b/WordPress/Jetpack/Info.plist @@ -572,6 +572,8 @@ LSApplicationQueriesSchemes + wordpress + wordpressmigration+v1 wordpressnotificationmigration org-appextension-feature-password-management twitter diff --git a/WordPress/Jetpack/Resources/AppStoreStrings.po b/WordPress/Jetpack/Resources/AppStoreStrings.po index dde9970e1d04..abc3275a72ff 100644 --- a/WordPress/Jetpack/Resources/AppStoreStrings.po +++ b/WordPress/Jetpack/Resources/AppStoreStrings.po @@ -81,9 +81,11 @@ msgctxt "app_store_keywords" msgid "social,notes,jetpack,writing,geotagging,media,blog,website,blogging,journal" msgstr "" -msgctxt "v21.2-whats-new" +msgctxt "v21.3-whats-new" msgid "" -"We fixed the positioning of the “No media matching your search” message in the Media Library. It’s now visible when there are no search results. Keep calm and search on.\n" +"We fixed a small visual issue with the Home and Menu control in the My Site dashboard.\n" +"\n" +"We also squashed a bug in My Site. The "Disconnect from WordPress.com” button now disconnects when tapped and will refresh the app.\n" msgstr "" #. translators: This is a promo message that will be attached on top of the first screenshot in the App Store. diff --git a/WordPress/Jetpack/Resources/release_notes.txt b/WordPress/Jetpack/Resources/release_notes.txt index 57bba47c5d66..1f2d9254a2e6 100644 --- a/WordPress/Jetpack/Resources/release_notes.txt +++ b/WordPress/Jetpack/Resources/release_notes.txt @@ -1,5 +1,3 @@ -* [*] [internal] When a user migrates to the Jetpack app and allows notifications, WordPress app notifications are disabled. This is released disabled and is behind a feature flag. [#19616, #19611, #19590] -* [*] Fixed a minor UI issue where the segmented control under My SIte was being clipped when "Home" is selected. [#19595] -* [*] Fixed an issue where the site wasn't removed and the app wasn't refreshed after disconnecting the site from WordPress.com. [#19634] -* [*] [internal] Fixed an issue where Jetpack extensions were conflicting with WordPress extensions. [#19665] +We fixed a small visual issue with the Home and Menu control in the My Site dashboard. +We also squashed a bug in My Site. The "Disconnect from WordPress.com” button now disconnects when tapped and will refresh the app. diff --git a/WordPress/Resources/AppStoreStrings.po b/WordPress/Resources/AppStoreStrings.po index 9979d0a79091..e08b33218b2f 100644 --- a/WordPress/Resources/AppStoreStrings.po +++ b/WordPress/Resources/AppStoreStrings.po @@ -45,9 +45,11 @@ msgctxt "app_store_keywords" msgid "blogger,writing,blogging,web,maker,online,store,business,make,create,write,blogs" msgstr "" -msgctxt "v21.2-whats-new" +msgctxt "v21.3-whats-new" msgid "" -"We fixed the positioning of the “No media matching your search” message in the Media Library. It’s now visible when there are no search results. Keep calm and search on.\n" +"We fixed a small visual issue with the Home and Menu control in the My Site dashboard.\n" +"\n" +"We also squashed a bug in My Site. The "Disconnect from WordPress.com” button now disconnects when tapped and will refresh the app.\n" msgstr "" #. translators: This is a standard chunk of text used to tell a user what's new with a release when nothing major has changed. diff --git a/WordPress/Resources/release_notes.txt b/WordPress/Resources/release_notes.txt index 57bba47c5d66..1f2d9254a2e6 100644 --- a/WordPress/Resources/release_notes.txt +++ b/WordPress/Resources/release_notes.txt @@ -1,5 +1,3 @@ -* [*] [internal] When a user migrates to the Jetpack app and allows notifications, WordPress app notifications are disabled. This is released disabled and is behind a feature flag. [#19616, #19611, #19590] -* [*] Fixed a minor UI issue where the segmented control under My SIte was being clipped when "Home" is selected. [#19595] -* [*] Fixed an issue where the site wasn't removed and the app wasn't refreshed after disconnecting the site from WordPress.com. [#19634] -* [*] [internal] Fixed an issue where Jetpack extensions were conflicting with WordPress extensions. [#19665] +We fixed a small visual issue with the Home and Menu control in the My Site dashboard. +We also squashed a bug in My Site. The "Disconnect from WordPress.com” button now disconnects when tapped and will refresh the app. diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 9d95213df753..35785632c03e 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -1550,8 +1550,6 @@ 801D951A291AC0B00051993E /* JetpackOverlayFrequencyTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D9519291AC0B00051993E /* JetpackOverlayFrequencyTracker.swift */; }; 801D951B291AC0B00051993E /* JetpackOverlayFrequencyTracker.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D9519291AC0B00051993E /* JetpackOverlayFrequencyTracker.swift */; }; 801D951D291ADB7E0051993E /* JetpackOverlayFrequencyTrackerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 801D951C291ADB7E0051993E /* JetpackOverlayFrequencyTrackerTests.swift */; }; - 800035C1292307E8007D2D26 /* ExtensionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800035C0292307E8007D2D26 /* ExtensionConfiguration.swift */; }; - 800035C329230A0B007D2D26 /* ExtensionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800035C229230A0B007D2D26 /* ExtensionConfiguration.swift */; }; 8031F346292FF46100E8F95E /* ExtensionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800035C229230A0B007D2D26 /* ExtensionConfiguration.swift */; }; 8031F347292FF46200E8F95E /* ExtensionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800035C229230A0B007D2D26 /* ExtensionConfiguration.swift */; }; 8031F348292FF46400E8F95E /* ExtensionConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = 800035C229230A0B007D2D26 /* ExtensionConfiguration.swift */; }; @@ -2584,6 +2582,7 @@ C324D7AC28C2F73F00310DEF /* SplashPrologueViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3DD4DCD28BE5D4D0046C68E /* SplashPrologueViewController.swift */; }; C32A6A2C2832BF02002E9394 /* SiteDesignCategoryThumbnailSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C32A6A2B2832BF02002E9394 /* SiteDesignCategoryThumbnailSize.swift */; }; C32A6A2D2832BF02002E9394 /* SiteDesignCategoryThumbnailSize.swift in Sources */ = {isa = PBXBuildFile; fileRef = C32A6A2B2832BF02002E9394 /* SiteDesignCategoryThumbnailSize.swift */; }; + C33A5ADC2935848F00961E3A /* MigrationAppDetection.swift in Sources */ = {isa = PBXBuildFile; fileRef = C33A5ADB2935848F00961E3A /* MigrationAppDetection.swift */; }; C3439B5F27FE3A3C0058DA55 /* SiteCreationWizardLauncherTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3439B5E27FE3A3C0058DA55 /* SiteCreationWizardLauncherTests.swift */; }; C34E94BA28EDF7D900D27A16 /* InfiniteScrollerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34E94B928EDF7D900D27A16 /* InfiniteScrollerView.swift */; }; C34E94BC28EDF80700D27A16 /* InfiniteScrollerViewDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = C34E94BB28EDF80700D27A16 /* InfiniteScrollerViewDelegate.swift */; }; @@ -2606,6 +2605,7 @@ C395FB262821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */; }; C395FB272822148400AE7C11 /* RemoteSiteDesign+Thumbnail.swift in Sources */ = {isa = PBXBuildFile; fileRef = C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */; }; C396C80B280F2401006FE7AC /* SiteDesignTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C396C80A280F2401006FE7AC /* SiteDesignTests.swift */; }; + C3AB4879292F114A001F7AF8 /* UIApplication+AppAvailability.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3AB4878292F114A001F7AF8 /* UIApplication+AppAvailability.swift */; }; C3C21EB928385EC8002296E2 /* RemoteSiteDesigns.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C21EB828385EC8002296E2 /* RemoteSiteDesigns.swift */; }; C3C21EBA28385EC8002296E2 /* RemoteSiteDesigns.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C21EB828385EC8002296E2 /* RemoteSiteDesigns.swift */; }; C3C2F84628AC8BC700937E45 /* JetpackBannerScrollVisibilityTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C3C2F84528AC8BC700937E45 /* JetpackBannerScrollVisibilityTests.swift */; }; @@ -3407,6 +3407,7 @@ F465980B28E66A5B00D5F49A /* white-on-blue-icon-app-60@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F465980628E66A5A00D5F49A /* white-on-blue-icon-app-60@2x.png */; }; F465980C28E66A5B00D5F49A /* white-on-blue-icon-app-83.5@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = F465980728E66A5B00D5F49A /* white-on-blue-icon-app-83.5@2x.png */; }; F478B152292FC1BC00AA8645 /* MigrationAppearance.swift in Sources */ = {isa = PBXBuildFile; fileRef = F478B151292FC1BC00AA8645 /* MigrationAppearance.swift */; }; + F49B99FF2937C9B4000CEFCE /* MigrationEmailService.swift in Sources */ = {isa = PBXBuildFile; fileRef = F49B99FE2937C9B4000CEFCE /* MigrationEmailService.swift */; }; F4BECD1B288EE5220078391A /* SuggestionsViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BECD1A288EE5220078391A /* SuggestionsViewModelType.swift */; }; F4BECD1C288EE5220078391A /* SuggestionsViewModelType.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4BECD1A288EE5220078391A /* SuggestionsViewModelType.swift */; }; F4CBE3D429258AE1004FFBB6 /* MeHeaderViewConfiguration.swift in Sources */ = {isa = PBXBuildFile; fileRef = F4FB0ACC292587D500F651F9 /* MeHeaderViewConfiguration.swift */; }; @@ -6852,8 +6853,6 @@ 801D950C291AB3CF0051993E /* JetpackNotificationsLogoAnimation_ltr.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = JetpackNotificationsLogoAnimation_ltr.json; sourceTree = ""; }; 801D9519291AC0B00051993E /* JetpackOverlayFrequencyTracker.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackOverlayFrequencyTracker.swift; sourceTree = ""; }; 801D951C291ADB7E0051993E /* JetpackOverlayFrequencyTrackerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackOverlayFrequencyTrackerTests.swift; sourceTree = ""; }; - 800035C0292307E8007D2D26 /* ExtensionConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionConfiguration.swift; sourceTree = ""; }; - 800035C229230A0B007D2D26 /* ExtensionConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ExtensionConfiguration.swift; sourceTree = ""; }; 80293CF6284450AD0083F946 /* WordPress-Swift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "WordPress-Swift.h"; sourceTree = ""; }; 803C493A283A7C0C00003E9B /* QuickStartChecklistHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = QuickStartChecklistHeader.swift; sourceTree = ""; }; 803C493D283A7C2200003E9B /* QuickStartChecklistHeader.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = QuickStartChecklistHeader.xib; sourceTree = ""; }; @@ -7702,6 +7701,7 @@ C32A6A2B2832BF02002E9394 /* SiteDesignCategoryThumbnailSize.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDesignCategoryThumbnailSize.swift; sourceTree = ""; }; C3302CC427EB67D0004229D3 /* IntentCell.xib */ = {isa = PBXFileReference; lastKnownFileType = file.xib; path = IntentCell.xib; sourceTree = ""; }; C3302CC527EB67D0004229D3 /* IntentCell.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IntentCell.swift; sourceTree = ""; }; + C33A5ADB2935848F00961E3A /* MigrationAppDetection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationAppDetection.swift; sourceTree = ""; }; C3439B5E27FE3A3C0058DA55 /* SiteCreationWizardLauncherTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteCreationWizardLauncherTests.swift; sourceTree = ""; }; C34E94B928EDF7D900D27A16 /* InfiniteScrollerView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfiniteScrollerView.swift; sourceTree = ""; }; C34E94BB28EDF80700D27A16 /* InfiniteScrollerViewDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = InfiniteScrollerViewDelegate.swift; sourceTree = ""; }; @@ -7715,6 +7715,7 @@ C395FB222821FE4400AE7C11 /* SiteDesignSection.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDesignSection.swift; sourceTree = ""; }; C395FB252821FE7B00AE7C11 /* RemoteSiteDesign+Thumbnail.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "RemoteSiteDesign+Thumbnail.swift"; sourceTree = ""; }; C396C80A280F2401006FE7AC /* SiteDesignTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SiteDesignTests.swift; sourceTree = ""; }; + C3AB4878292F114A001F7AF8 /* UIApplication+AppAvailability.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UIApplication+AppAvailability.swift"; sourceTree = ""; }; C3ABE791263099F7009BD402 /* WordPress 121.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 121.xcdatamodel"; sourceTree = ""; }; C3C21EB828385EC8002296E2 /* RemoteSiteDesigns.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RemoteSiteDesigns.swift; sourceTree = ""; }; C3C2F84528AC8BC700937E45 /* JetpackBannerScrollVisibilityTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = JetpackBannerScrollVisibilityTests.swift; sourceTree = ""; }; @@ -8490,6 +8491,7 @@ F4426FDA287F066400218003 /* site-suggestions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "site-suggestions.json"; sourceTree = ""; }; F44293D128E3B18E00D340AF /* AppIconListViewModelType.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconListViewModelType.swift; sourceTree = ""; }; F44293D528E3BA1700D340AF /* AppIconListViewModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppIconListViewModel.swift; sourceTree = ""; }; + F44F6ABD2937428B00DC94A2 /* MigrationEmailService.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationEmailService.swift; sourceTree = ""; }; F44FB6CA287895AF0001E3CE /* SuggestionsListViewModelTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionsListViewModelTests.swift; sourceTree = ""; }; F44FB6CC287897F90001E3CE /* SuggestionsTableViewMockDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SuggestionsTableViewMockDelegate.swift; sourceTree = ""; }; F44FB6D02878A1020001E3CE /* user-suggestions.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = "user-suggestions.json"; sourceTree = ""; }; @@ -8564,6 +8566,7 @@ F465980628E66A5A00D5F49A /* white-on-blue-icon-app-60@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "white-on-blue-icon-app-60@2x.png"; sourceTree = ""; }; F465980728E66A5B00D5F49A /* white-on-blue-icon-app-83.5@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "white-on-blue-icon-app-83.5@2x.png"; sourceTree = ""; }; F478B151292FC1BC00AA8645 /* MigrationAppearance.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MigrationAppearance.swift; sourceTree = ""; }; + F49B99FE2937C9B4000CEFCE /* MigrationEmailService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MigrationEmailService.swift; sourceTree = ""; }; F4BECD1A288EE5220078391A /* SuggestionsViewModelType.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SuggestionsViewModelType.swift; sourceTree = ""; }; F4CBE3D329258AD6004FFBB6 /* MeHeaderView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MeHeaderView.h; sourceTree = ""; }; F4CBE3D5292597E3004FFBB6 /* SupportTableViewControllerConfiguration.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SupportTableViewControllerConfiguration.swift; sourceTree = ""; }; @@ -11017,10 +11020,12 @@ 3FFDEF7D29177F4200B625CE /* Common */ = { isa = PBXGroup; children = ( + F49B99FE2937C9B4000CEFCE /* MigrationEmailService.swift */, 3FFDEF8229179CD000B625CE /* MigrationDependencyContainer.swift */, F41BDD772910AFB900B7F2B0 /* Navigation */, F4F9D5EE29096D0400502576 /* Views */, F478B151292FC1BC00AA8645 /* MigrationAppearance.swift */, + C33A5ADB2935848F00961E3A /* MigrationAppDetection.swift */, ); path = Common; sourceTree = ""; @@ -14440,6 +14445,7 @@ 179A70EF2729834B006DAC0A /* Binding+OnChange.swift */, FA20751327A86B73001A644D /* UIScrollView+Helpers.swift */, C7AFF873283C0ADC000E01DF /* UIApplication+Helpers.swift */, + C3AB4878292F114A001F7AF8 /* UIApplication+AppAvailability.swift */, ); path = Extensions; sourceTree = ""; @@ -16772,6 +16778,7 @@ F5E156B425DDD53A00EEEDFB /* Recovered References */ = { isa = PBXGroup; children = ( + F44F6ABD2937428B00DC94A2 /* MigrationEmailService.swift */, ); name = "Recovered References"; sourceTree = ""; @@ -22553,6 +22560,7 @@ FABB21022602FC2C00C8785C /* Plugin.swift in Sources */, FABB21032602FC2C00C8785C /* JetpackActivityLogViewController.swift in Sources */, 17870A712816F2A000D1C627 /* StatsLatestPostSummaryInsightsCell.swift in Sources */, + C33A5ADC2935848F00961E3A /* MigrationAppDetection.swift in Sources */, DC772AF6282009BA00664C02 /* StatsLineChartView.swift in Sources */, FABB21042602FC2C00C8785C /* FormattableMediaContent.swift in Sources */, FABB21052602FC2C00C8785C /* CollabsableHeaderFilterCollectionViewCell.swift in Sources */, @@ -23175,6 +23183,7 @@ FABB22E62602FC2C00C8785C /* MenuItemAbstractPostsViewController.m in Sources */, FABB22E72602FC2C00C8785C /* AtomicAuthenticationService.swift in Sources */, FABB22E82602FC2C00C8785C /* WPStyleGuide+Posts.swift in Sources */, + F49B99FF2937C9B4000CEFCE /* MigrationEmailService.swift in Sources */, FABB22E92602FC2C00C8785C /* GutenbergVideoUploadProcessor.swift in Sources */, FABB22EA2602FC2C00C8785C /* PostCategory.m in Sources */, 3F685B6A26D431FA001C6808 /* DomainSuggestionViewControllerWrapper.swift in Sources */, @@ -24006,6 +24015,7 @@ FABB257C2602FC2C00C8785C /* CLPlacemark+Formatting.swift in Sources */, FABB257D2602FC2C00C8785C /* SiteStatsDetailTableViewController.swift in Sources */, FABB257E2602FC2C00C8785C /* MessageAnimator.swift in Sources */, + C3AB4879292F114A001F7AF8 /* UIApplication+AppAvailability.swift in Sources */, FABB257F2602FC2C00C8785C /* JetpackRestoreOptionsViewController.swift in Sources */, FABB25802602FC2C00C8785C /* WPStyleGuide+Loader.swift in Sources */, FABB25812602FC2C00C8785C /* MediaThumbnailService.swift in Sources */, diff --git a/WordPress/WordPressTest/ContentMigrationCoordinatorTests.swift b/WordPress/WordPressTest/ContentMigrationCoordinatorTests.swift index 663a05967ea7..2d88e0731ce3 100644 --- a/WordPress/WordPressTest/ContentMigrationCoordinatorTests.swift +++ b/WordPress/WordPressTest/ContentMigrationCoordinatorTests.swift @@ -2,7 +2,7 @@ import XCTest @testable import WordPress -final class ContentMigrationCoordinatorTests: XCTestCase { +final class ContentMigrationCoordinatorTests: CoreDataTestCase { private let timeout: TimeInterval = 1 @@ -72,6 +72,80 @@ final class ContentMigrationCoordinatorTests: XCTestCase { wait(for: [expect], timeout: timeout) } + // MARK: Local draft checking tests + + func test_startAndDo_givenPostWithLocalStatus_shouldReturnFailure() { + // Given + makePost(remoteStatus: .local) + makePost(remoteStatus: .sync) + + let expect = expectation(description: "Content migration should fail") + coordinator.startAndDo { result in + guard case .failure(let error) = result else { + XCTFail() + return + } + + XCTAssertEqual(error, .localDraftsNotSynced) + expect.fulfill() + } + wait(for: [expect], timeout: timeout) + } + + func test_startAndDo_givenPostWithPushingStatus_shouldReturnFailure() { + // Given + makePost(remoteStatus: .pushing) + makePost(remoteStatus: .sync) + + let expect = expectation(description: "Content migration should fail") + coordinator.startAndDo { result in + guard case .failure(let error) = result else { + XCTFail() + return + } + + XCTAssertEqual(error, .localDraftsNotSynced) + expect.fulfill() + } + wait(for: [expect], timeout: timeout) + } + + func test_startAndDo_givenPostWithPushingMediaStatus_shouldReturnFailure() { + // Given + makePost(remoteStatus: .pushingMedia) + makePost(remoteStatus: .sync) + + let expect = expectation(description: "Content migration should fail") + coordinator.startAndDo { result in + guard case .failure(let error) = result else { + XCTFail() + return + } + + XCTAssertEqual(error, .localDraftsNotSynced) + expect.fulfill() + } + wait(for: [expect], timeout: timeout) + } + + func test_startAndDo_givenPostWithFailedStatus_shouldReturnFailure() { + // Given + makePost(remoteStatus: .failed) + makePost(remoteStatus: .sync) + + let expect = expectation(description: "Content migration should fail") + coordinator.startAndDo { result in + guard case .failure(let error) = result else { + XCTFail() + return + } + + XCTAssertEqual(error, .localDraftsNotSynced) + expect.fulfill() + } + wait(for: [expect], timeout: timeout) + } + // MARK: `startOnce` tests func test_startOnce_whenUserDefaultsDoesNotExist_shouldMigrate() { @@ -85,7 +159,7 @@ final class ContentMigrationCoordinatorTests: XCTestCase { } func test_startOnce_givenErrorResult_shouldNotSaveUserDefaults() { - mockDataMigrator.exportErrorToReturn = .localDraftsNotSynced + mockDataMigrator.exportErrorToReturn = .databaseCopyError let expect = expectation(description: "Content migration should succeed") coordinator.startOnceIfNeeded { [unowned self] in @@ -147,9 +221,17 @@ private extension ContentMigrationCoordinatorTests { } func makeCoordinator() -> ContentMigrationCoordinator { - return .init(dataMigrator: mockDataMigrator, + return .init(coreDataStack: contextManager, + dataMigrator: mockDataMigrator, userPersistentRepository: mockPersistentRepository, eligibilityProvider: mockEligibilityProvider) } + func makePost(remoteStatus: AbstractPostRemoteStatus = .failed) { + let _ = PostBuilder(contextManager.mainContext) + .published() + .with(remoteStatus: remoteStatus) + .build() + } + } diff --git a/WordPress/WordPressTest/DataMigratorTests.swift b/WordPress/WordPressTest/DataMigratorTests.swift index efc404c7b974..6d231b884231 100644 --- a/WordPress/WordPressTest/DataMigratorTests.swift +++ b/WordPress/WordPressTest/DataMigratorTests.swift @@ -29,10 +29,6 @@ class DataMigratorTests: XCTestCase { } func testExportSucceeds() { - // Given - context.addDraftPost(remoteStatus: .sync) - context.addDraftPost(remoteStatus: .sync) - // When var successful = false migrator.exportData { result in @@ -49,54 +45,6 @@ class DataMigratorTests: XCTestCase { XCTAssertTrue(successful) } - func testExportFailsWithLocalDrafts() { - // Given - context.addDraftPost(remoteStatus: .local) - context.addDraftPost(remoteStatus: .sync) - - // When - let migratorError = getExportDataMigratorError(migrator) - - // Then - XCTAssertEqual(migratorError, .localDraftsNotSynced) - } - - func testExportFailsWithPushingDrafts() { - // Given - context.addDraftPost(remoteStatus: .pushing) - context.addDraftPost(remoteStatus: .sync) - - // When - let migratorError = getExportDataMigratorError(migrator) - - // Then - XCTAssertEqual(migratorError, .localDraftsNotSynced) - } - - func testExportFailsWithPushingMediaDrafts() { - // Given - context.addDraftPost(remoteStatus: .pushingMedia) - context.addDraftPost(remoteStatus: .sync) - - // When - let migratorError = getExportDataMigratorError(migrator) - - // Then - XCTAssertEqual(migratorError, .localDraftsNotSynced) - } - - func testExportFailsWithFailedUploadDrafts() { - // Given - context.addDraftPost(remoteStatus: .failed) - context.addDraftPost(remoteStatus: .sync) - - // When - let migratorError = getExportDataMigratorError(migrator) - - // Then - XCTAssertEqual(migratorError, .localDraftsNotSynced) - } - func testUserDefaultsCopiesToSharedOnExport() { // Given let value = "Test" @@ -386,26 +334,6 @@ private extension DataMigratorTests { } } -private extension NSManagedObjectContext { - - func createBlog() -> Blog { - let blog = NSEntityDescription.insertNewObject(forEntityName: "Blog", into: self) as! Blog - blog.url = "" - blog.xmlrpc = "" - return blog - } - - func addDraftPost(remoteStatus: AbstractPostRemoteStatus) { - let post = NSEntityDescription.insertNewObject(forEntityName: "Post", into: self) as! Post - post.blog = createBlog() - post.remoteStatus = remoteStatus - post.dateModified = Date() - post.status = .draft - try! save() - } - -} - // MARK: - Mock Local File Store private final class MockLocalFileStore: LocalFileStore { diff --git a/WordPress/WordPressTest/JetpackNotificationMigrationServiceTests.swift b/WordPress/WordPressTest/JetpackNotificationMigrationServiceTests.swift index 6739aaf62e69..b93ee0a1650c 100644 --- a/WordPress/WordPressTest/JetpackNotificationMigrationServiceTests.swift +++ b/WordPress/WordPressTest/JetpackNotificationMigrationServiceTests.swift @@ -6,16 +6,19 @@ final class JetpackNotificationMigrationServiceTests: XCTestCase { private var sut: JetpackNotificationMigrationService! private var remoteNotificationsRegister: RemoteNotificationRegisterMock! private var remoteFeatureFlagStore: RemoteFeatureFlagStoreMock! + private var userDefaults: UserDefaultsMock! override func setUpWithError() throws { remoteNotificationsRegister = RemoteNotificationRegisterMock() remoteFeatureFlagStore = RemoteFeatureFlagStoreMock() + userDefaults = UserDefaultsMock() } override func tearDownWithError() throws { sut = nil remoteNotificationsRegister = nil remoteFeatureFlagStore = nil + userDefaults = nil } // MARK: - Should show notification control @@ -69,6 +72,14 @@ final class JetpackNotificationMigrationServiceTests: XCTestCase { XCTAssertFalse(sut.shouldPresentNotifications()) } + func testShouldPresentNotificationsBeforeWordPressNotificationsToggledAndNotificationsRegistered() { + setup(preventDuplicateNotificationsFlag: true, isWordPress: true) + remoteNotificationsRegister.isRegisteredForRemoteNotifications = false + userDefaults.wordPressNotificationsToggled = false + + XCTAssertTrue(sut.shouldPresentNotifications()) + } + func testShouldPresentNotificationsInWordPressWhenFeatureFlagDisabledAndWordPressNotificationsDisabled() { setup(preventDuplicateNotificationsFlag: false, isWordPress: true) sut.wordPressNotificationsEnabled = false @@ -101,8 +112,10 @@ private extension JetpackNotificationMigrationServiceTests { sut = JetpackNotificationMigrationService( remoteNotificationRegister: remoteNotificationsRegister, featureFlagStore: remoteFeatureFlagStore, + userDefaults: userDefaults, isWordPress: isWordPress ) + userDefaults.wordPressNotificationsToggled = true sut.wordPressNotificationsEnabled = true remoteNotificationsRegister.isRegisteredForRemoteNotifications = true } @@ -131,3 +144,15 @@ private class RemoteFeatureFlagStoreMock: RemoteFeatureFlagStore { return value } } + +private class UserDefaultsMock: UserDefaults { + var wordPressNotificationsToggled = false + + override func bool(forKey defaultName: String) -> Bool { + if defaultName == "wordPressNotificationsToggledDefaultsKey" { + return wordPressNotificationsToggled + } + + return super.bool(forKey: defaultName) + } +}