diff --git a/MIGRATIONS.md b/MIGRATIONS.md index 5f5cc0ce6d83..127f33ec22c1 100644 --- a/MIGRATIONS.md +++ b/MIGRATIONS.md @@ -3,6 +3,13 @@ This file documents changes in the data model. Please explain any changes to the data model as well as any custom migrations. +## WordPress 103 + +@guarani 2020-10-20 + +- Add a new `SiteSuggestion` entity to support Gutenberg's xpost implementation +- Add a one-to-many relationship between `Blog` and `SiteSuggestion` + ## WordPress 101 @emilylaguna 2020-10-09 diff --git a/Podfile b/Podfile index 316160b96797..0436097edde6 100644 --- a/Podfile +++ b/Podfile @@ -152,7 +152,7 @@ target 'WordPress' do ## Gutenberg (React Native) ## ===================== ## - gutenberg :tag => 'v1.39.0' + gutenberg :commit => 'c3c47584dd18fdafc171e0fa160780ec2db41050' ## Third party libraries ## ===================== diff --git a/Podfile.lock b/Podfile.lock index 50341d0cdc2c..a7f555ddd055 100644 --- a/Podfile.lock +++ b/Podfile.lock @@ -73,7 +73,7 @@ PODS: - GTMSessionFetcher/Core (1.4.0) - GTMSessionFetcher/Full (1.4.0): - GTMSessionFetcher/Core (= 1.4.0) - - Gutenberg (1.39.0): + - Gutenberg (1.38.0): - React (= 0.61.5) - React-CoreModules (= 0.61.5) - React-RCTImage (= 0.61.5) @@ -381,7 +381,7 @@ PODS: - React - RNSVG (9.13.6-gb): - React - - RNTAztecView (1.39.0): + - RNTAztecView (1.38.0): - React-Core - WordPress-Aztec-iOS (~> 1.19.3) - Sentry (4.5.0): @@ -450,14 +450,14 @@ DEPENDENCIES: - CocoaLumberjack (~> 3.0) - CropViewController (= 2.5.3) - Down (~> 0.6.6) - - FBLazyVector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/FBLazyVector.podspec.json`) - - FBReactNativeSpec (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/FBReactNativeSpec.podspec.json`) - - Folly (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/Folly.podspec.json`) + - FBLazyVector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/FBLazyVector.podspec.json`) + - FBReactNativeSpec (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/FBReactNativeSpec.podspec.json`) + - Folly (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/Folly.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.39.0/third-party-podspecs/glog.podspec.json`) + - glog (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/glog.podspec.json`) - Gridicons (~> 1.0.1) - - Gutenberg (from `http://github.com/wordpress-mobile/gutenberg-mobile/`, tag `v1.39.0`) + - Gutenberg (from `http://github.com/wordpress-mobile/gutenberg-mobile/`, commit `c3c47584dd18fdafc171e0fa160780ec2db41050`) - JTAppleCalendar (~> 8.0.2) - MediaEditor (~> 1.2.1) - MRProgress (= 0.8.3) @@ -467,41 +467,41 @@ DEPENDENCIES: - OCMock (= 3.4.3) - OHHTTPStubs (= 6.1.0) - OHHTTPStubs/Swift (= 6.1.0) - - RCTRequired (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RCTRequired.podspec.json`) - - RCTTypeSafety (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RCTTypeSafety.podspec.json`) + - RCTRequired (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RCTRequired.podspec.json`) + - RCTTypeSafety (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RCTTypeSafety.podspec.json`) - Reachability (= 3.2) - - React (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React.podspec.json`) - - React-Core (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-Core.podspec.json`) - - React-CoreModules (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-CoreModules.podspec.json`) - - React-cxxreact (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-cxxreact.podspec.json`) - - React-jsi (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsi.podspec.json`) - - React-jsiexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsiexecutor.podspec.json`) - - React-jsinspector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsinspector.podspec.json`) - - react-native-blur (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-blur.podspec.json`) - - react-native-get-random-values (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.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.39.0/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json`) - - react-native-linear-gradient (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-linear-gradient.podspec.json`) - - react-native-safe-area (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.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.39.0/third-party-podspecs/react-native-safe-area-context.podspec.json`) - - react-native-slider (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-slider.podspec.json`) - - react-native-video (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-video.podspec.json`) - - React-RCTActionSheet (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTActionSheet.podspec.json`) - - React-RCTAnimation (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTAnimation.podspec.json`) - - React-RCTBlob (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTBlob.podspec.json`) - - React-RCTImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTImage.podspec.json`) - - React-RCTLinking (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTLinking.podspec.json`) - - React-RCTNetwork (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTNetwork.podspec.json`) - - React-RCTSettings (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTSettings.podspec.json`) - - React-RCTText (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTText.podspec.json`) - - React-RCTVibration (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTVibration.podspec.json`) - - ReactCommon (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/ReactCommon.podspec.json`) - - ReactNativeDarkMode (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/ReactNativeDarkMode.podspec.json`) - - RNCMaskedView (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNCMaskedView.podspec.json`) - - RNGestureHandler (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNGestureHandler.podspec.json`) - - RNReanimated (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNReanimated.podspec.json`) - - RNScreens (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNScreens.podspec.json`) - - RNSVG (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNSVG.podspec.json`) - - RNTAztecView (from `http://github.com/wordpress-mobile/gutenberg-mobile/`, tag `v1.39.0`) + - React (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React.podspec.json`) + - React-Core (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-Core.podspec.json`) + - React-CoreModules (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-CoreModules.podspec.json`) + - React-cxxreact (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-cxxreact.podspec.json`) + - React-jsi (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsi.podspec.json`) + - React-jsiexecutor (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsiexecutor.podspec.json`) + - React-jsinspector (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsinspector.podspec.json`) + - react-native-blur (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-blur.podspec.json`) + - react-native-get-random-values (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/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/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json`) + - react-native-linear-gradient (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-linear-gradient.podspec.json`) + - react-native-safe-area (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-safe-area.podspec.json`) + - react-native-safe-area-context (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-safe-area-context.podspec.json`) + - react-native-slider (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-slider.podspec.json`) + - react-native-video (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-video.podspec.json`) + - React-RCTActionSheet (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTActionSheet.podspec.json`) + - React-RCTAnimation (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTAnimation.podspec.json`) + - React-RCTBlob (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTBlob.podspec.json`) + - React-RCTImage (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTImage.podspec.json`) + - React-RCTLinking (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTLinking.podspec.json`) + - React-RCTNetwork (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTNetwork.podspec.json`) + - React-RCTSettings (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTSettings.podspec.json`) + - React-RCTText (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTText.podspec.json`) + - React-RCTVibration (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTVibration.podspec.json`) + - ReactCommon (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/ReactCommon.podspec.json`) + - ReactNativeDarkMode (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/ReactNativeDarkMode.podspec.json`) + - RNCMaskedView (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNCMaskedView.podspec.json`) + - RNGestureHandler (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNGestureHandler.podspec.json`) + - RNReanimated (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNReanimated.podspec.json`) + - RNScreens (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNScreens.podspec.json`) + - RNSVG (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNSVG.podspec.json`) + - RNTAztecView (from `http://github.com/wordpress-mobile/gutenberg-mobile/`, commit `c3c47584dd18fdafc171e0fa160780ec2db41050`) - SimulatorStatusMagic - Starscream (= 3.0.6) - SVProgressHUD (= 2.2.5) @@ -512,7 +512,7 @@ DEPENDENCIES: - WordPressShared (~> 1.12.0) - WordPressUI (~> 1.7.1) - WPMediaPicker (~> 1.7.2) - - Yoga (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/Yoga.podspec.json`) + - Yoga (from `https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/Yoga.podspec.json`) - ZendeskSupportSDK (= 5.0.0) - ZIPFoundation (~> 0.9.8) @@ -574,108 +574,108 @@ SPEC REPOS: EXTERNAL SOURCES: FBLazyVector: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/FBLazyVector.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/FBLazyVector.podspec.json FBReactNativeSpec: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/FBReactNativeSpec.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/FBReactNativeSpec.podspec.json Folly: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/Folly.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/Folly.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.39.0/third-party-podspecs/glog.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/glog.podspec.json Gutenberg: + :commit: c3c47584dd18fdafc171e0fa160780ec2db41050 :git: http://github.com/wordpress-mobile/gutenberg-mobile/ :submodules: true - :tag: v1.39.0 RCTRequired: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RCTRequired.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RCTRequired.podspec.json RCTTypeSafety: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RCTTypeSafety.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RCTTypeSafety.podspec.json React: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React.podspec.json React-Core: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-Core.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-Core.podspec.json React-CoreModules: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-CoreModules.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-CoreModules.podspec.json React-cxxreact: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-cxxreact.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-cxxreact.podspec.json React-jsi: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsi.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsi.podspec.json React-jsiexecutor: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsiexecutor.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsiexecutor.podspec.json React-jsinspector: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-jsinspector.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-jsinspector.podspec.json react-native-blur: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-blur.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-blur.podspec.json react-native-get-random-values: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-get-random-values.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/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.39.0/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-keyboard-aware-scroll-view.podspec.json react-native-linear-gradient: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-linear-gradient.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-linear-gradient.podspec.json react-native-safe-area: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-safe-area.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-safe-area.podspec.json react-native-safe-area-context: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-safe-area-context.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-safe-area-context.podspec.json react-native-slider: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-slider.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-slider.podspec.json react-native-video: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/react-native-video.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/react-native-video.podspec.json React-RCTActionSheet: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTActionSheet.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTActionSheet.podspec.json React-RCTAnimation: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTAnimation.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTAnimation.podspec.json React-RCTBlob: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTBlob.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTBlob.podspec.json React-RCTImage: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTImage.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTImage.podspec.json React-RCTLinking: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTLinking.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTLinking.podspec.json React-RCTNetwork: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTNetwork.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTNetwork.podspec.json React-RCTSettings: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTSettings.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTSettings.podspec.json React-RCTText: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTText.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTText.podspec.json React-RCTVibration: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/React-RCTVibration.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/React-RCTVibration.podspec.json ReactCommon: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/ReactCommon.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/ReactCommon.podspec.json ReactNativeDarkMode: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/ReactNativeDarkMode.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/ReactNativeDarkMode.podspec.json RNCMaskedView: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNCMaskedView.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNCMaskedView.podspec.json RNGestureHandler: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNGestureHandler.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNGestureHandler.podspec.json RNReanimated: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNReanimated.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNReanimated.podspec.json RNScreens: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNScreens.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNScreens.podspec.json RNSVG: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/RNSVG.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/RNSVG.podspec.json RNTAztecView: + :commit: c3c47584dd18fdafc171e0fa160780ec2db41050 :git: http://github.com/wordpress-mobile/gutenberg-mobile/ :submodules: true - :tag: v1.39.0 Yoga: - :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/v1.39.0/third-party-podspecs/Yoga.podspec.json + :podspec: https://raw.githubusercontent.com/wordpress-mobile/gutenberg-mobile/c3c47584dd18fdafc171e0fa160780ec2db41050/third-party-podspecs/Yoga.podspec.json CHECKOUT OPTIONS: FSInteractiveMap: :git: https://github.com/wordpress-mobile/FSInteractiveMap.git :tag: 0.2.0 Gutenberg: + :commit: c3c47584dd18fdafc171e0fa160780ec2db41050 :git: http://github.com/wordpress-mobile/gutenberg-mobile/ :submodules: true - :tag: v1.39.0 RNCMaskedView: :commit: d4ccf2bba163679c4550ce6ba0119604cd5e6379 :git: https://github.com/react-native-community/react-native-masked-view.git RNTAztecView: + :commit: c3c47584dd18fdafc171e0fa160780ec2db41050 :git: http://github.com/wordpress-mobile/gutenberg-mobile/ :submodules: true - :tag: v1.39.0 SPEC CHECKSUMS: 1PasswordExtension: f97cc80ae58053c331b2b6dc8843ba7103b33794 @@ -703,7 +703,7 @@ SPEC CHECKSUMS: Gridicons: 8e19276b20bb15d1fda1d4d0db96d066d170135b GTMAppAuth: 197a8dabfea5d665224aa00d17f164fc2248dab9 GTMSessionFetcher: 6f5c8abbab8a9bce4bb3f057e317728ec6182b10 - Gutenberg: eb317493db40786204035cc3bd1f8b29aadde744 + Gutenberg: 449231e24743741cb880e2ce3ae2779fd380d793 JTAppleCalendar: 932cadea40b1051beab10f67843451d48ba16c99 lottie-ios: 85ce835dd8c53e02509f20729fc7d6a4e6645a0a MediaEditor: 20cdeb46bdecd040b8bc94467ac85a52b53b193a @@ -747,7 +747,7 @@ SPEC CHECKSUMS: RNReanimated: 13f7a6a22667c4f00aac217bc66f94e8560b3d59 RNScreens: 6833ac5c29cf2f03eed12103140530bbd75b6aea RNSVG: 68a534a5db06dcbdaebfd5079349191598caef7b - RNTAztecView: 97919388e08911ad7908c8ab904780ac958e9c37 + RNTAztecView: 5705e00629b6742f7be48a708ae9b487151bbf8d Sentry: ab6c209f23700d1460691dbc90e19ed0a05d496b SimulatorStatusMagic: 28d4a9d1a500ac7cea0b2b5a43c1c6ddb40ba56c Sodium: 63c0ca312a932e6da481689537d4b35568841bdc @@ -773,6 +773,6 @@ SPEC CHECKSUMS: ZendeskSupportSDK: a87ab1e4badace92c75eb11dc77ede1e995b2adc ZIPFoundation: 249fa8890597086cd536bb2df5c9804d84e122b0 -PODFILE CHECKSUM: cf4946853e0d66f41d5e06692a8e3fbc588e94fc +PODFILE CHECKSUM: 5cd74c1c49b2540c29f06164ce7d5a368f4f8e4b COCOAPODS: 1.9.3 diff --git a/WordPress/Classes/Models/Blog.h b/WordPress/Classes/Models/Blog.h index 5a430f50e54e..9c74041a5b5a 100644 --- a/WordPress/Classes/Models/Blog.h +++ b/WordPress/Classes/Models/Blog.h @@ -13,6 +13,7 @@ NS_ASSUME_NONNULL_BEGIN @class Role; @class QuickStartTourState; @class UserSuggestion; +@class SiteSuggestion; @class PageTemplateCategory; extern NSString * const BlogEntityName; @@ -103,6 +104,7 @@ typedef NS_ENUM(NSInteger, SiteVisibility) { @property (nonatomic, strong, readwrite, nullable) NSSet *themes; @property (nonatomic, strong, readwrite, nullable) NSSet *media; @property (nonatomic, strong, readwrite, nullable) NSSet *userSuggestions; +@property (nonatomic, strong, readwrite, nullable) NSSet *siteSuggestions; @property (nonatomic, strong, readwrite, nullable) NSOrderedSet *menus; @property (nonatomic, strong, readwrite, nullable) NSOrderedSet *menuLocations; @property (nonatomic, strong, readwrite, nullable) NSSet *roles; diff --git a/WordPress/Classes/Models/SiteSuggestion+CoreDataClass.swift b/WordPress/Classes/Models/SiteSuggestion+CoreDataClass.swift new file mode 100644 index 000000000000..0d7905a31954 --- /dev/null +++ b/WordPress/Classes/Models/SiteSuggestion+CoreDataClass.swift @@ -0,0 +1,34 @@ +import Foundation +import CoreData + +extension CodingUserInfoKey { + static let managedObjectContext = CodingUserInfoKey(rawValue: "managedObjectContext")! +} + +enum DecoderError: Error { + case missingManagedObjectContext +} + +@objc(SiteSuggestion) +public class SiteSuggestion: NSManagedObject, Decodable { + enum CodingKeys: String, CodingKey { + case title = "title" + case siteURL = "siteurl" + case subdomain = "subdomain" + case blavatarURL = "blavatar" + } + + required convenience public init(from decoder: Decoder) throws { + guard let managedObjectContext = decoder.userInfo[CodingUserInfoKey.managedObjectContext] as? NSManagedObjectContext else { + throw DecoderError.missingManagedObjectContext + } + + self.init(context: managedObjectContext) + + let container = try decoder.container(keyedBy: CodingKeys.self) + self.title = try container.decode(String.self, forKey: .title) + self.siteURL = try container.decode(URL.self, forKey: .siteURL) + self.subdomain = try container.decode(String.self, forKey: .subdomain) + self.blavatarURL = try container.decode(URL.self, forKey: .blavatarURL) + } +} diff --git a/WordPress/Classes/Models/SiteSuggestion+CoreDataProperties.swift b/WordPress/Classes/Models/SiteSuggestion+CoreDataProperties.swift new file mode 100644 index 000000000000..5c9245936aba --- /dev/null +++ b/WordPress/Classes/Models/SiteSuggestion+CoreDataProperties.swift @@ -0,0 +1,17 @@ +import Foundation +import CoreData + + +extension SiteSuggestion { + + @nonobjc public class func fetchRequest() -> NSFetchRequest { + return NSFetchRequest(entityName: "SiteSuggestion") + } + + @NSManaged public var title: String? + @NSManaged public var siteURL: URL? + @NSManaged public var subdomain: String? + @NSManaged public var blavatarURL: URL? + @NSManaged public var blog: Blog? + +} diff --git a/WordPress/Classes/Services/XpostSuggestionService.swift b/WordPress/Classes/Services/XpostSuggestionService.swift new file mode 100644 index 000000000000..922b057378c9 --- /dev/null +++ b/WordPress/Classes/Services/XpostSuggestionService.swift @@ -0,0 +1,108 @@ +import Foundation + +/// A service to fetch and persist a list of sites that can be used for x-posting. +struct XpostSuggestionService { + + enum ServiceError: Error { + case missingAPI + case missingManagedObjectContext + case hostnameNotAvailable + case noResultsAvailable + } + + static var hasRequested = false + + /** + Fetch cached suggestions if available, otherwise from the network if the device is online. + + @param the blog/site to retrieve suggestions for + @param completion callback containing list of suggestions, or nil if unavailable + */ + static func suggestions(for blog: Blog, completion: @escaping (Result<[SiteSuggestion], Error>) -> Void) { + + if let results = retrievePersistedResults(for: blog), results.isEmpty == false { + completion(.success(results)) + } else if ReachabilityUtils.isInternetReachable() { + fetchAndPersistSuggestions(for: blog, completion: completion) + } else { + completion(.failure(ServiceError.noResultsAvailable)) + } + } + + private static func fetchAndPersistSuggestions(for blog: Blog, completion: @escaping (Result<[SiteSuggestion], Error>) -> Void) { + + guard !hasRequested else { return } + self.hasRequested = true + + guard let api = blog.wordPressComRestApi() else { + completion(.failure(ServiceError.missingAPI)) + return + } + + guard let managedObjectContext = blog.managedObjectContext else { + completion(.failure(ServiceError.missingManagedObjectContext)) + return + } + + guard let hostname = blog.hostname else { + completion(.failure(ServiceError.hostnameNotAvailable)) + return + } + + let urlString = "/wpcom/v2/sites/\(hostname)/xposts" + + api.GET(urlString, parameters: nil) { responseObject, httpResponse in + do { + let data = try JSONSerialization.data(withJSONObject: responseObject) + + try self.purgeExistingResults(for: blog, using: managedObjectContext) + + let siteSuggestions = try self.persist(data: data, to: blog, using: managedObjectContext) + completion(.success(siteSuggestions)) + } catch { + completion(.failure(error)) + } + + self.hasRequested = false + } failure: { error, _ in + completion(.failure(error)) + self.hasRequested = false + } + } + + private static func purgeExistingResults(for blog: Blog, using managedObjectContext: NSManagedObjectContext) throws { + blog.siteSuggestions?.forEach { siteSuggestion in + managedObjectContext.delete(siteSuggestion) + } + try managedObjectContext.save() + } + + private static func persist(data: Data, to blog: Blog, using managedObjectContext: NSManagedObjectContext) throws -> [SiteSuggestion] { + let decoder = JSONDecoder() + decoder.userInfo[CodingUserInfoKey.managedObjectContext] = managedObjectContext + let siteSuggestions = try decoder.decode([SiteSuggestion].self, from: data) + blog.siteSuggestions = Set(siteSuggestions) + try managedObjectContext.save() + return siteSuggestions + } + + private static func retrievePersistedResults(for blog: Blog) -> [SiteSuggestion]? { + guard let results = blog.siteSuggestions else { return nil } + return Array(results) + } +} + +extension XpostSuggestionService.ServiceError: CustomNSError { + static var errorDomain: String { return "XpostSuggestionService.ServiceError" } + + var errorCode: Int { return 0 } + + var errorUserInfo: [String : Any] { + switch self { + case .missingAPI: return [NSDebugDescriptionErrorKey: "Blog hostname not available"] + case .missingManagedObjectContext: return [NSDebugDescriptionErrorKey: "Managed object context not available"] + case .hostnameNotAvailable: return [NSDebugDescriptionErrorKey: "Blog hostname not available"] + case .noResultsAvailable: return [NSDebugDescriptionErrorKey: "The device is offline and there are no suggestions in the cache"] + } + } +} diff --git a/WordPress/Classes/ViewRelated/Comments/CommentViewController.m b/WordPress/Classes/ViewRelated/Comments/CommentViewController.m index 6fb923777a74..f12093271255 100644 --- a/WordPress/Classes/ViewRelated/Comments/CommentViewController.m +++ b/WordPress/Classes/ViewRelated/Comments/CommentViewController.m @@ -104,7 +104,7 @@ - (void)attachSuggestionsTableViewIfNeeded return; } - self.suggestionsTableView = [[SuggestionsTableView alloc] initWithSiteID:self.comment.blog.dotComID suggestionType:SuggestionTypeMention delegate:self]; + self.suggestionsTableView = [[SuggestionsTableView alloc] initWithSiteID:self.comment.blog.dotComID suggestionType:SuggestionTypeMentions delegate:self]; [self.suggestionsTableView setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.view addSubview:self.suggestionsTableView]; } diff --git a/WordPress/Classes/ViewRelated/Comments/FullScreenCommentReplyViewController.swift b/WordPress/Classes/ViewRelated/Comments/FullScreenCommentReplyViewController.swift index be83e5c66474..8aa7717c2d8b 100644 --- a/WordPress/Classes/ViewRelated/Comments/FullScreenCommentReplyViewController.swift +++ b/WordPress/Classes/ViewRelated/Comments/FullScreenCommentReplyViewController.swift @@ -69,7 +69,7 @@ public class FullScreenCommentReplyViewController: EditCommentViewController, Su } guard let siteID = siteID else { return } - let tableView = SuggestionsTableView(siteID: siteID, suggestionType: .mention, delegate: self) + let tableView = SuggestionsTableView(siteID: siteID, suggestionType: .mentions, delegate: self) tableView.useTransparentHeader = true tableView.translatesAutoresizingMaskIntoConstraints = false diff --git a/WordPress/Classes/ViewRelated/Gutenberg/GutenbergViewController.swift b/WordPress/Classes/ViewRelated/Gutenberg/GutenbergViewController.swift index 4b864b66213a..54952c999454 100644 --- a/WordPress/Classes/ViewRelated/Gutenberg/GutenbergViewController.swift +++ b/WordPress/Classes/ViewRelated/Gutenberg/GutenbergViewController.swift @@ -851,7 +851,13 @@ extension GutenbergViewController: GutenbergBridgeDelegate { func gutenbergDidRequestMention(callback: @escaping (Swift.Result) -> Void) { DispatchQueue.main.async(execute: { [weak self] in - self?.showSuggestions(type: .mention, callback: callback) + self?.showSuggestions(type: .mentions, callback: callback) + }) + } + + func gutenbergDidRequestXpost(callback: @escaping (Swift.Result) -> Void) { + DispatchQueue.main.async(execute: { [weak self] in + self?.showSuggestions(type: .xposts, callback: callback) }) } @@ -882,8 +888,10 @@ extension GutenbergViewController { } switch type { - case .mention: + case .mentions: guard SuggestionService.shared.shouldShowSuggestions(for: blog) else { return } + case .xposts: + break } previousFirstResponder = view.findFirstResponder() diff --git a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationDetailsViewController.swift b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationDetailsViewController.swift index 36c397a266e0..0a671d91494c 100644 --- a/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationDetailsViewController.swift +++ b/WordPress/Classes/ViewRelated/Notifications/Controllers/NotificationDetailsViewController.swift @@ -435,7 +435,7 @@ extension NotificationDetailsViewController { func setupSuggestionsView() { guard let siteID = note.metaSiteID else { return } - suggestionsTableView = SuggestionsTableView(siteID: siteID, suggestionType: .mention, delegate: self) + suggestionsTableView = SuggestionsTableView(siteID: siteID, suggestionType: .mentions, delegate: self) suggestionsTableView.translatesAutoresizingMaskIntoConstraints = false } diff --git a/WordPress/Classes/ViewRelated/Reader/ReaderCommentsViewController.m b/WordPress/Classes/ViewRelated/Reader/ReaderCommentsViewController.m index ce708f20e458..bd70cfee3691 100644 --- a/WordPress/Classes/ViewRelated/Reader/ReaderCommentsViewController.m +++ b/WordPress/Classes/ViewRelated/Reader/ReaderCommentsViewController.m @@ -385,7 +385,7 @@ - (void)configureSuggestionsTableView NSNumber *siteID = self.siteID; NSParameterAssert(siteID); - self.suggestionsTableView = [[SuggestionsTableView alloc] initWithSiteID:siteID suggestionType:SuggestionTypeMention delegate:self]; + self.suggestionsTableView = [[SuggestionsTableView alloc] initWithSiteID:siteID suggestionType:SuggestionTypeMentions delegate:self]; [self.suggestionsTableView setTranslatesAutoresizingMaskIntoConstraints:NO]; [self.view addSubview:self.suggestionsTableView]; } diff --git a/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.h b/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.h index 9aede401426c..08d87ea16a0b 100644 --- a/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.h +++ b/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.h @@ -1,7 +1,8 @@ #import typedef NS_CLOSED_ENUM(NSUInteger, SuggestionType) { - SuggestionTypeMention + SuggestionTypeMentions, + SuggestionTypeXposts }; @protocol SuggestionsTableViewDelegate; @@ -20,7 +21,7 @@ typedef NS_CLOSED_ENUM(NSUInteger, SuggestionType) { - (nonnull instancetype)initWithSiteID:(NSNumber *_Nullable)siteID suggestionType:(SuggestionType)suggestionType - delegate:(id _Nonnull)suggestionsDelegate; + delegate:(id _Nonnull)suggestionsDelegate NS_DESIGNATED_INITIALIZER; /** Enables or disables the SuggestionsTableView component. diff --git a/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.swift b/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.swift index 1ee7b4bbd4ca..82c93f4ceba9 100644 --- a/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.swift +++ b/WordPress/Classes/ViewRelated/Suggestions/SuggestionsTableView.swift @@ -3,7 +3,8 @@ import Foundation extension SuggestionType { var trigger: String { switch self { - case .mention: return "@" + case .mentions: return "@" + case .xposts: return "+" } } } @@ -17,43 +18,69 @@ extension SuggestionType { var suggestionTrigger: String { return suggestionType.trigger } + func siteSuggestions(for siteID: NSNumber, completion: @escaping ([SiteSuggestion]?) -> Void) { + let context = ContextManager.shared.mainContext + guard let blog = BlogService(managedObjectContext: context).blog(byBlogId: siteID) else { return } + + XpostSuggestionService.suggestions(for: blog) { result in + switch result { + case .success(let siteSuggestions): + completion(siteSuggestions) + case .failure: + completion(nil) + } + } + } + func predicate(for searchQuery: String) -> NSPredicate { switch suggestionType { - case .mention: + case .mentions: return NSPredicate(format: "(displayName contains[c] %@) OR (username contains[c] %@)", searchQuery, searchQuery) + case .xposts: + return NSPredicate(format: "(title contains[c] %@) OR (siteURL.absoluteString contains[c] %@)", searchQuery, searchQuery) } } func title(for suggestion: AnyObject) -> String? { let title: String? switch (suggestionType, suggestion) { - case (.mention, let suggestion as UserSuggestion): + case (.mentions, let suggestion as UserSuggestion): title = suggestion.username - default: title = nil + case (.xposts, let suggestion as SiteSuggestion): + title = suggestion.title + default: + return nil } return title.map { suggestionType.trigger.appending($0) } } func subtitle(for suggestion: AnyObject) -> String? { switch (suggestionType, suggestion) { - case (.mention, let suggestion as UserSuggestion): + case (.mentions, let suggestion as UserSuggestion): return suggestion.displayName - default: return nil + case (.xposts, let suggestion as SiteSuggestion): + return suggestion.siteURL?.absoluteString + default: + return nil } } private func imageURLForSuggestion(at indexPath: IndexPath) -> URL? { let suggestion = searchResults[indexPath.row] - switch (suggestionType, suggestion) { - case (.mention, let suggestion as UserSuggestion): + case (.mentions, let suggestion as UserSuggestion): return suggestion.imageURL - default: return nil + case (.xposts, let suggestion as SiteSuggestion): + return suggestion.blavatarURL + default: + return nil } } func loadImage(for suggestion: AnyObject, in cell: SuggestionsTableViewCell, at indexPath: IndexPath) { + cell.iconImageView.image = UIImage(named: "gravatar") + guard let imageURL = imageURLForSuggestion(at: indexPath) else { return } cell.imageDownloadHash = imageURL.hashValue @@ -65,27 +92,34 @@ extension SuggestionType { } } + private func suggestionText(for suggestion: Any) -> String? { + switch (suggestionType, suggestion) { + case (.mentions, let suggestion as UserSuggestion): + return suggestion.username + case (.xposts, let suggestion as SiteSuggestion): + return suggestion.title + default: return nil + } + } + func fetchSuggestions(for siteID: NSNumber) { - switch self.suggestionType { - case .mention: + switch suggestionType { + case .mentions: suggestions(for: siteID) { userSuggestions in self.suggestions = userSuggestions self.showSuggestions(forWord: self.searchText) } - } - } - - private func suggestionText(for suggestion: Any) -> String? { - switch (suggestionType, suggestion) { - case (.mention, let suggestion as UserSuggestion): - return suggestion.username - default: return nil + case .xposts: + siteSuggestions(for: siteID) { siteSuggestions in + self.suggestions = siteSuggestions + self.showSuggestions(forWord: self.searchText) + } + default: return; } } private func retrieveIcon(for imageURL: URL?, success: @escaping (UIImage?) -> Void) { let imageSize = CGSize(width: SuggestionsTableViewCellIconSize, height: SuggestionsTableViewCellIconSize) - if let image = cachedIcon(for: imageURL, with: imageSize) { success(image) } else { diff --git a/WordPress/Classes/WordPress.xcdatamodeld/.xccurrentversion b/WordPress/Classes/WordPress.xcdatamodeld/.xccurrentversion index 074c250d7d74..98aa5d24fe90 100644 --- a/WordPress/Classes/WordPress.xcdatamodeld/.xccurrentversion +++ b/WordPress/Classes/WordPress.xcdatamodeld/.xccurrentversion @@ -3,6 +3,6 @@ _XCCurrentVersionName - WordPress 102.xcdatamodel + WordPress 103.xcdatamodel diff --git a/WordPress/Classes/WordPress.xcdatamodeld/WordPress 103.xcdatamodel/contents b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 103.xcdatamodel/contents new file mode 100644 index 000000000000..514c763c57da --- /dev/null +++ b/WordPress/Classes/WordPress.xcdatamodeld/WordPress 103.xcdatamodel/contents @@ -0,0 +1,983 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/WordPress/WordPress.xcodeproj/project.pbxproj b/WordPress/WordPress.xcodeproj/project.pbxproj index 575d3f352863..ab6985a47090 100644 --- a/WordPress/WordPress.xcodeproj/project.pbxproj +++ b/WordPress/WordPress.xcodeproj/project.pbxproj @@ -1518,6 +1518,9 @@ B03B9236250BC5FD000A40AF /* Suggestion.swift in Sources */ = {isa = PBXBuildFile; fileRef = B03B9235250BC5FD000A40AF /* Suggestion.swift */; }; B0637527253E7CEC00FD45D2 /* SuggestionsTableView.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0637526253E7CEB00FD45D2 /* SuggestionsTableView.swift */; }; B0637543253E7E7A00FD45D2 /* GutenbergSuggestionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0637542253E7E7A00FD45D2 /* GutenbergSuggestionsViewController.swift */; }; + B06378B0253F637300FD45D2 /* XpostSuggestionService.swift in Sources */ = {isa = PBXBuildFile; fileRef = B06378AF253F637300FD45D2 /* XpostSuggestionService.swift */; }; + B06378C0253F639D00FD45D2 /* SiteSuggestion+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B06378BE253F639D00FD45D2 /* SiteSuggestion+CoreDataClass.swift */; }; + B06378C1253F639D00FD45D2 /* SiteSuggestion+CoreDataProperties.swift in Sources */ = {isa = PBXBuildFile; fileRef = B06378BF253F639D00FD45D2 /* SiteSuggestion+CoreDataProperties.swift */; }; B0AC50B4251E959B0039E022 /* CommentViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0AC50B3251E959B0039E022 /* CommentViewController.swift */; }; B0AC50DD251E96270039E022 /* ReaderCommentsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0AC50DC251E96270039E022 /* ReaderCommentsViewController.swift */; }; B0B68A9C252FA91E0001B28C /* UserSuggestion+CoreDataClass.swift in Sources */ = {isa = PBXBuildFile; fileRef = B0B68A9A252FA91E0001B28C /* UserSuggestion+CoreDataClass.swift */; }; @@ -4082,6 +4085,10 @@ B03B9235250BC5FD000A40AF /* Suggestion.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Suggestion.swift; sourceTree = ""; }; B0637526253E7CEB00FD45D2 /* SuggestionsTableView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = SuggestionsTableView.swift; path = Suggestions/SuggestionsTableView.swift; sourceTree = ""; }; B0637542253E7E7A00FD45D2 /* GutenbergSuggestionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = GutenbergSuggestionsViewController.swift; sourceTree = ""; }; + B06378AE253F619500FD45D2 /* WordPress 103.xcdatamodel */ = {isa = PBXFileReference; lastKnownFileType = wrapper.xcdatamodel; path = "WordPress 103.xcdatamodel"; sourceTree = ""; }; + B06378AF253F637300FD45D2 /* XpostSuggestionService.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = XpostSuggestionService.swift; sourceTree = ""; }; + B06378BE253F639D00FD45D2 /* SiteSuggestion+CoreDataClass.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SiteSuggestion+CoreDataClass.swift"; sourceTree = ""; }; + B06378BF253F639D00FD45D2 /* SiteSuggestion+CoreDataProperties.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "SiteSuggestion+CoreDataProperties.swift"; sourceTree = ""; }; B0AC50B3251E959B0039E022 /* CommentViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CommentViewController.swift; sourceTree = ""; }; B0AC50DC251E96270039E022 /* ReaderCommentsViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ReaderCommentsViewController.swift; sourceTree = ""; }; B0B68A9A252FA91E0001B28C /* UserSuggestion+CoreDataClass.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = "UserSuggestion+CoreDataClass.swift"; sourceTree = ""; }; @@ -5948,6 +5955,8 @@ E10290731F30615A00DAC588 /* Role.swift */, E6E27D611C6144DB0063F821 /* SharingButton.swift */, E6D170361EF9D8D10046D433 /* SiteInfo.swift */, + B06378BE253F639D00FD45D2 /* SiteSuggestion+CoreDataClass.swift */, + B06378BF253F639D00FD45D2 /* SiteSuggestion+CoreDataProperties.swift */, 5DED0E161B432E0400431FCD /* SourcePostAttribution.h */, 5DED0E171B432E0400431FCD /* SourcePostAttribution.m */, B03B9235250BC5FD000A40AF /* Suggestion.swift */, @@ -8379,6 +8388,7 @@ 57D66B99234BB206005A2D74 /* PostServiceRemoteFactory.swift */, 8BC12F732320181E004DDA72 /* PostService+MarkAsFailedAndDraftIfNeeded.swift */, 4631359024AD013F0017E65C /* PageCoordinator.swift */, + B06378AF253F637300FD45D2 /* XpostSuggestionService.swift */, 46E327D524E71B2F000944B3 /* Page Layouts */, ); path = Services; @@ -12525,6 +12535,7 @@ 738B9A5A21B85CF20005062B /* SiteCreationHeaderData.swift in Sources */, 594399931B45091000539E21 /* WPAuthTokenIssueSolver.m in Sources */, F16C35D623F33DE400C81331 /* PageAutoUploadMessageProvider.swift in Sources */, + B06378B0253F637300FD45D2 /* XpostSuggestionService.swift in Sources */, 8BDA5A6B247C2EAF00AB124C /* ReaderDetailViewController.swift in Sources */, 7E7B4CF820459E21001463D6 /* PersonHeaderCell.swift in Sources */, B03B9234250BC593000A40AF /* SuggestionService.swift in Sources */, @@ -12827,6 +12838,7 @@ 43FF64EF20DAA0840060A69A /* GravatarUploader.swift in Sources */, B5899ADE1B419C560075A3D6 /* NotificationSettingDetailsViewController.swift in Sources */, D8A3A5AA2069E53900992576 /* AztecMediaPickingCoordinator.swift in Sources */, + B06378C0253F639D00FD45D2 /* SiteSuggestion+CoreDataClass.swift in Sources */, 436D55DB210F862A00CEAA33 /* NibReusable.swift in Sources */, 98563DDD21BF30C40006F5E9 /* TabbedTotalsCell.swift in Sources */, 82FC61241FA8ADAD00A1757E /* ActivityTableViewCell.swift in Sources */, @@ -13420,6 +13432,7 @@ 176DEEE91D4615FE00331F30 /* WPSplitViewController.swift in Sources */, 400F4625201E74EE000CFD9E /* CollectionViewContainerRow.swift in Sources */, 9A8ECE0E2254A3260043C8DA /* JetpackConnectionWebViewController.swift in Sources */, + B06378C1253F639D00FD45D2 /* SiteSuggestion+CoreDataProperties.swift in Sources */, 4353BFB221A376BF0009CED3 /* UntouchableWindow.swift in Sources */, FF0AAE0A1A150A560089841D /* WPProgressTableViewCell.m in Sources */, D8A3A5B5206A4C7800992576 /* StockPhotosPicker.swift in Sources */, @@ -17409,6 +17422,7 @@ E125443B12BF5A7200D87A0A /* WordPress.xcdatamodeld */ = { isa = XCVersionGroup; children = ( + B06378AE253F619500FD45D2 /* WordPress 103.xcdatamodel */, 4625BC26253E285700C04AAD /* WordPress 102.xcdatamodel */, 327282732538BC0900C8076D /* WordPress 101.xcdatamodel */, B0DDC2EB252F7C4F002BAFB3 /* WordPress 100.xcdatamodel */, @@ -17512,7 +17526,7 @@ 8350E15911D28B4A00A7B073 /* WordPress.xcdatamodel */, E125443D12BF5A7200D87A0A /* WordPress 2.xcdatamodel */, ); - currentVersion = 4625BC26253E285700C04AAD /* WordPress 102.xcdatamodel */; + currentVersion = B06378AE253F619500FD45D2 /* WordPress 103.xcdatamodel */; name = WordPress.xcdatamodeld; path = Classes/WordPress.xcdatamodeld; sourceTree = "";