From 40c8b31fc2b87e21b06f3267953cf9703cfd160a Mon Sep 17 00:00:00 2001 From: David Calhoun Date: Thu, 31 Aug 2023 11:36:26 -0400 Subject: [PATCH 1/8] refactor: Separate MediaUploader constants export This allows the MediaUploader component file to export only React components, which enables hot module reloading. --- .../src/components/index.native.js | 4 ++-- .../media-placeholder/index.native.js | 12 ++++++------ .../src/components/media-upload/constants.js | 15 +++++++++++++++ .../components/media-upload/index.native.js | 19 +++++++++---------- .../media-upload/test/index.native.js | 4 ++-- 5 files changed, 34 insertions(+), 20 deletions(-) create mode 100644 packages/block-editor/src/components/media-upload/constants.js diff --git a/packages/block-editor/src/components/index.native.js b/packages/block-editor/src/components/index.native.js index a6ab6bb76d048..1f675daaa8ca1 100644 --- a/packages/block-editor/src/components/index.native.js +++ b/packages/block-editor/src/components/index.native.js @@ -38,13 +38,13 @@ export { } from './rich-text'; export { default as MediaReplaceFlow } from './media-replace-flow'; export { default as MediaPlaceholder } from './media-placeholder'; +export { default as MediaUpload } from './media-upload'; export { - default as MediaUpload, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_AUDIO, MEDIA_TYPE_ANY, -} from './media-upload'; +} from './media-upload/constants'; export { default as MediaUploadProgress, MEDIA_UPLOAD_STATE_UPLOADING, diff --git a/packages/block-editor/src/components/media-placeholder/index.native.js b/packages/block-editor/src/components/media-placeholder/index.native.js index dd36feae1e415..938c01e92b4ed 100644 --- a/packages/block-editor/src/components/media-placeholder/index.native.js +++ b/packages/block-editor/src/components/media-placeholder/index.native.js @@ -8,12 +8,6 @@ import { sentenceCase } from 'change-case'; * WordPress dependencies */ import { __, sprintf } from '@wordpress/i18n'; -import { - MediaUpload, - MEDIA_TYPE_IMAGE, - MEDIA_TYPE_VIDEO, - MEDIA_TYPE_AUDIO, -} from '@wordpress/block-editor'; import { usePreferredColorSchemeStyle } from '@wordpress/compose'; import { cloneElement, useCallback, useRef } from '@wordpress/element'; import { Icon, plusCircleFilled } from '@wordpress/icons'; @@ -23,6 +17,12 @@ import { Icon, plusCircleFilled } from '@wordpress/icons'; */ import styles from './styles.scss'; import { useBlockEditContext } from '../block-edit/context'; +import MediaUpload from '../media-upload'; +import { + MEDIA_TYPE_IMAGE, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_AUDIO, +} from '../media-upload/constants'; const isMediaEqual = ( media1, media2 ) => media1.id === media2.id || media1.url === media2.url; diff --git a/packages/block-editor/src/components/media-upload/constants.js b/packages/block-editor/src/components/media-upload/constants.js new file mode 100644 index 0000000000000..2697be40e562c --- /dev/null +++ b/packages/block-editor/src/components/media-upload/constants.js @@ -0,0 +1,15 @@ +/** + * WordPress dependencies + */ +import { __ } from '@wordpress/i18n'; + +export const MEDIA_TYPE_IMAGE = 'image'; +export const MEDIA_TYPE_VIDEO = 'video'; +export const MEDIA_TYPE_AUDIO = 'audio'; +export const MEDIA_TYPE_ANY = 'any'; + +export const OPTION_TAKE_VIDEO = __( 'Take a Video' ); +export const OPTION_TAKE_PHOTO = __( 'Take a Photo' ); +export const OPTION_TAKE_PHOTO_OR_VIDEO = __( 'Take a Photo or Video' ); +export const OPTION_INSERT_FROM_URL = __( 'Insert from URL' ); +export const OPTION_WORDPRESS_MEDIA_LIBRARY = __( 'WordPress Media Library' ); diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index e7c7b840f5aba..2e0f4961df73d 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -28,16 +28,15 @@ import { store as blockEditorStore } from '@wordpress/block-editor'; import { compose } from '@wordpress/compose'; import { withSelect } from '@wordpress/data'; -export const MEDIA_TYPE_IMAGE = 'image'; -export const MEDIA_TYPE_VIDEO = 'video'; -export const MEDIA_TYPE_AUDIO = 'audio'; -export const MEDIA_TYPE_ANY = 'any'; - -export const OPTION_TAKE_VIDEO = __( 'Take a Video' ); -export const OPTION_TAKE_PHOTO = __( 'Take a Photo' ); -export const OPTION_TAKE_PHOTO_OR_VIDEO = __( 'Take a Photo or Video' ); -export const OPTION_INSERT_FROM_URL = __( 'Insert from URL' ); -export const OPTION_WORDPRESS_MEDIA_LIBRARY = __( 'WordPress Media Library' ); +/** + * Internal dependencies + */ +import { + MEDIA_TYPE_IMAGE, + MEDIA_TYPE_VIDEO, + MEDIA_TYPE_AUDIO, + MEDIA_TYPE_ANY, +} from './constants'; const URL_MEDIA_SOURCE = 'URL'; diff --git a/packages/block-editor/src/components/media-upload/test/index.native.js b/packages/block-editor/src/components/media-upload/test/index.native.js index 75268aef6de68..b856cb0388de1 100644 --- a/packages/block-editor/src/components/media-upload/test/index.native.js +++ b/packages/block-editor/src/components/media-upload/test/index.native.js @@ -14,8 +14,8 @@ import { requestMediaPicker } from '@wordpress/react-native-bridge'; /** * Internal dependencies */ +import { MediaUpload } from '../index'; import { - MediaUpload, MEDIA_TYPE_IMAGE, MEDIA_TYPE_VIDEO, MEDIA_TYPE_AUDIO, @@ -23,7 +23,7 @@ import { OPTION_TAKE_PHOTO, OPTION_INSERT_FROM_URL, OPTION_WORDPRESS_MEDIA_LIBRARY, -} from '../index'; +} from '../constants'; const MEDIA_URL = 'http://host.media.type'; const MEDIA_ID = 123; From 19af0c1254e2ddf792e946a3f55709e4626bedce Mon Sep 17 00:00:00 2001 From: David Calhoun Date: Thu, 31 Aug 2023 12:52:44 -0400 Subject: [PATCH 2/8] feat: Insert from URL leverages a bottom sheet The usage of iOS `UIAlertController` via `react-native-prompt-android` resulted in an obscured alert on small devices in landscape orientation as there was not enough vertical space between the keyboard and the top of the editor view. Replacing the usage of alerts with the existing bottom sheet avoids the obscured UI. --- package-lock.json | 11 --- .../components/media-upload/index.native.js | 80 ++++++++++++------- .../android/react-native-bridge/build.gradle | 1 - .../android/app/build.gradle | 1 - packages/react-native-editor/package.json | 1 - 5 files changed, 50 insertions(+), 44 deletions(-) diff --git a/package-lock.json b/package-lock.json index bff840a51828d..b3cad8cc5ac75 100644 --- a/package-lock.json +++ b/package-lock.json @@ -46294,11 +46294,6 @@ "react-native": ">=0.65.0" } }, - "node_modules/react-native-prompt-android": { - "version": "1.0.0-wp-4", - "resolved": "https://raw.githubusercontent.com/wordpress-mobile/react-native-prompt-android/v1.0.0-wp-4/react-native-prompt-android-1.0.0-wp-4.tgz", - "integrity": "sha512-brKcM8Uh1If+PVPV2lDjCifBYgm/BqtkVuSEE6SA6nVw1gCYFpj6GRQ4tUDKVo4+zI8436DTifVl/3QwlM9aJg==" - }, "node_modules/react-native-reanimated": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.17.0.tgz", @@ -56261,7 +56256,6 @@ "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", - "react-native-prompt-android": "https://raw.githubusercontent.com/wordpress-mobile/react-native-prompt-android/v1.0.0-wp-4/react-native-prompt-android-1.0.0-wp-4.tgz", "react-native-reanimated": "2.17.0", "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.6.3", @@ -68704,7 +68698,6 @@ "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", - "react-native-prompt-android": "https://raw.githubusercontent.com/wordpress-mobile/react-native-prompt-android/v1.0.0-wp-4/react-native-prompt-android-1.0.0-wp-4.tgz", "react-native-reanimated": "2.17.0", "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.6.3", @@ -94268,10 +94261,6 @@ "react-native-animatable": "1.3.3" } }, - "react-native-prompt-android": { - "version": "https://raw.githubusercontent.com/wordpress-mobile/react-native-prompt-android/v1.0.0-wp-4/react-native-prompt-android-1.0.0-wp-4.tgz", - "integrity": "sha512-brKcM8Uh1If+PVPV2lDjCifBYgm/BqtkVuSEE6SA6nVw1gCYFpj6GRQ4tUDKVo4+zI8436DTifVl/3QwlM9aJg==" - }, "react-native-reanimated": { "version": "2.17.0", "resolved": "https://registry.npmjs.org/react-native-reanimated/-/react-native-reanimated-2.17.0.tgz", diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 2e0f4961df73d..28111e9004315 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -3,14 +3,17 @@ */ import { Platform } from 'react-native'; -import prompt from 'react-native-prompt-android'; - /** * WordPress dependencies */ import { Component, React } from '@wordpress/element'; import { __ } from '@wordpress/i18n'; -import { Picker } from '@wordpress/components'; +import { + BottomSheet, + PanelBody, + Picker, + TextControl, +} from '@wordpress/components'; import { getOtherMediaOptions, requestMediaPicker, @@ -51,6 +54,8 @@ export class MediaUpload extends Component { this.onPickerSelect = this.onPickerSelect.bind( this ); this.getAllSources = this.getAllSources.bind( this ); this.state = { + url: '', + showURLInput: false, otherMediaOptions: [], }; } @@ -203,31 +208,10 @@ export class MediaUpload extends Component { } onPickerSelect( value ) { - const { - allowedTypes = [], - onSelect, - onSelectURL, - multiple = false, - } = this.props; + const { allowedTypes = [], onSelect, multiple = false } = this.props; if ( value === URL_MEDIA_SOURCE ) { - prompt( - __( 'Type a URL' ), // title - undefined, // message - [ - { - text: __( 'Cancel' ), - style: 'cancel', - }, - { - text: __( 'Apply' ), - onPress: onSelectURL, - }, - ], // Buttons. - 'plain-text', // type - undefined, // defaultValue - 'url' // keyboardType - ); + this.setState( { showURLInput: true } ); return; } @@ -305,13 +289,49 @@ export class MediaUpload extends Component { /> ); - return this.props.render( { - open: this.onPickerPresent, - getMediaOptions, - } ); + return ( + <> + { + if ( this.state.url !== '' ) { + this.props.onSelectURL( this.state.url ); + } + this.setState( { showURLInput: false, url: '' } ); + } } + onChange={ ( url ) => { + this.setState( { url } ); + } } + value={ this.state.url } + /> + { this.props.render( { + open: this.onPickerPresent, + getMediaOptions, + } ) } + + ); } } +function URLInput( props ) { + return ( + + + + + + ); +} + export default compose( [ withSelect( ( select ) => { const { capabilities } = select( blockEditorStore ).getSettings(); diff --git a/packages/react-native-bridge/android/react-native-bridge/build.gradle b/packages/react-native-bridge/android/react-native-bridge/build.gradle index 4c7882ad0ffdb..8ea42babee505 100644 --- a/packages/react-native-bridge/android/react-native-bridge/build.gradle +++ b/packages/react-native-bridge/android/react-native-bridge/build.gradle @@ -90,7 +90,6 @@ dependencies { implementation "com.facebook.react:react-android:$rnVersion" implementation "com.github.wordpress-mobile:react-native-video:${extractPackageVersion(packageJson, 'react-native-video', 'dependencies')}" implementation "com.github.wordpress-mobile:react-native-slider:${extractPackageVersion(packageJson, '@react-native-community/slider', 'dependencies')}" - implementation "com.github.wordpress-mobile:react-native-prompt-android:${extractPackageVersion(packageJson, 'react-native-prompt-android', 'dependencies')}" // Published by `wordpress-mobile/react-native-libraries-publisher` // See the documentation for this value in `build.gradle.kts` of `wordpress-mobile/react-native-libraries-publisher` diff --git a/packages/react-native-editor/android/app/build.gradle b/packages/react-native-editor/android/app/build.gradle index 5bbb6e560a491..ecb63589bcf1c 100644 --- a/packages/react-native-editor/android/app/build.gradle +++ b/packages/react-native-editor/android/app/build.gradle @@ -142,7 +142,6 @@ dependencies { implementation "com.github.wordpress-mobile:react-native-video:${extractPackageVersion(packageJson, 'react-native-video', 'dependencies')}" implementation "com.github.wordpress-mobile:react-native-slider:${extractPackageVersion(packageJson, '@react-native-community/slider', 'dependencies')}" - implementation "com.github.wordpress-mobile:react-native-prompt-android:${extractPackageVersion(packageJson, 'react-native-prompt-android', 'dependencies')}" // Published by `wordpress-mobile/react-native-libraries-publisher` // See the documentation for this value in `build.gradle.kts` of `wordpress-mobile/react-native-libraries-publisher` diff --git a/packages/react-native-editor/package.json b/packages/react-native-editor/package.json index a84aba86afc54..531d02b9c7fad 100644 --- a/packages/react-native-editor/package.json +++ b/packages/react-native-editor/package.json @@ -63,7 +63,6 @@ "react-native-get-random-values": "1.4.0", "react-native-linear-gradient": "2.7.3", "react-native-modal": "13.0.1", - "react-native-prompt-android": "https://raw.githubusercontent.com/wordpress-mobile/react-native-prompt-android/v1.0.0-wp-4/react-native-prompt-android-1.0.0-wp-4.tgz", "react-native-reanimated": "2.17.0", "react-native-safe-area": "^0.5.0", "react-native-safe-area-context": "4.6.3", From db7d4bfc249aa94961d6fa0943c81a665133fe1d Mon Sep 17 00:00:00 2001 From: David Calhoun Date: Thu, 31 Aug 2023 13:31:01 -0400 Subject: [PATCH 3/8] refactor: Remove lingering react-native-prompt-android references This package is no longer installed or used. These referenced caused build errors. --- .../org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java | 2 -- .../app/src/main/java/com/gutenberg/MainApplication.java | 3 --- 2 files changed, 5 deletions(-) diff --git a/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java b/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java index 0e8962cc70482..69adb653211da 100644 --- a/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java +++ b/packages/react-native-bridge/android/react-native-bridge/src/main/java/org/wordpress/mobile/WPAndroidGlue/WPAndroidGlueCode.java @@ -73,7 +73,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.TimeUnit; -import im.shimo.react.prompt.RNPromptPackage; import okhttp3.OkHttpClient; @@ -618,7 +617,6 @@ public ReactInstanceManager getReactInstanceManager(ReactApplicationContext reac return mReactInstanceManager; } }, - new RNPromptPackage(), new RNCWebViewPackage(), new ClipboardPackage(), new FastImageViewPackage(), diff --git a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java index ba01cffb2943c..d718b34f25db3 100644 --- a/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java +++ b/packages/react-native-editor/android/app/src/main/java/com/gutenberg/MainApplication.java @@ -51,8 +51,6 @@ import java.util.List; import java.util.ArrayList; -import im.shimo.react.prompt.RNPromptPackage; - public class MainApplication extends Application implements ReactApplication, GutenbergBridgeInterface { private static final String TAG = "MainApplication"; @@ -334,7 +332,6 @@ protected List getPackages() { new ReanimatedPackage(), new SafeAreaContextPackage(), new RNScreensPackage(), - new RNPromptPackage(), new RNCWebViewPackage(), new ClipboardPackage(), new FastImageViewPackage(), From 6d77e74946c5ea217e2035232942357d5d4a2359 Mon Sep 17 00:00:00 2001 From: David Calhoun Date: Thu, 31 Aug 2023 13:31:34 -0400 Subject: [PATCH 4/8] feat: Enable automatic focus of Insert from URL input This felt appropriate given this input is displayed for a user immediately after tapping "Insert from URL." Thus, the user likely expects a focused input and presented keyboard. --- .../block-editor/src/components/media-upload/index.native.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 28111e9004315..0a7e8c48a2ef9 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -322,6 +322,8 @@ function URLInput( props ) { > Date: Thu, 31 Aug 2023 13:40:33 -0400 Subject: [PATCH 5/8] feat: Adjust URL input content alignment Align with content layout with that found in other existing bottom sheets. --- .../block-editor/src/components/media-upload/index.native.js | 3 ++- .../src/components/media-upload/style.native.scss | 4 ++++ 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 packages/block-editor/src/components/media-upload/style.native.scss diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 0a7e8c48a2ef9..924930352e019 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -40,6 +40,7 @@ import { MEDIA_TYPE_AUDIO, MEDIA_TYPE_ANY, } from './constants'; +import styles from './style.scss'; const URL_MEDIA_SOURCE = 'URL'; @@ -320,7 +321,7 @@ function URLInput( props ) { isVisible={ props.isVisible } onClose={ props.onClose } > - + Date: Thu, 31 Aug 2023 20:28:52 -0400 Subject: [PATCH 6/8] test: Add bottom sheet test ID Used for tests in the gutenberg-mobile repository. --- packages/components/src/mobile/bottom-sheet/index.native.js | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/components/src/mobile/bottom-sheet/index.native.js b/packages/components/src/mobile/bottom-sheet/index.native.js index 4ef8614279404..11918782f4dfb 100644 --- a/packages/components/src/mobile/bottom-sheet/index.native.js +++ b/packages/components/src/mobile/bottom-sheet/index.native.js @@ -527,6 +527,7 @@ class BottomSheet extends Component { panResponder.panHandlers.onMoveShouldSetResponderCapture } onAccessibilityEscape={ this.onCloseBottomSheet } + testID="bottom-sheet" { ...rest } > Date: Fri, 1 Sep 2023 08:20:22 -0400 Subject: [PATCH 7/8] docs: Add change log entry --- packages/react-native-editor/CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/packages/react-native-editor/CHANGELOG.md b/packages/react-native-editor/CHANGELOG.md index 9864fc38d04cc..34f9b0248cd17 100644 --- a/packages/react-native-editor/CHANGELOG.md +++ b/packages/react-native-editor/CHANGELOG.md @@ -10,6 +10,7 @@ For each user feature we should also add a importance categorization label to i --> ## Unreleased +- [*] Fix the obscurred "Insert from URL" input for media blocks when using a device in landscape orientation. [#54096] ## 1.103.0 - [**] Replace third-party dependency react-native-hsv-color-picker with first-party code [#53329] From db66c34a8f9a7032466e9f93db025b79d9df6470 Mon Sep 17 00:00:00 2001 From: David Calhoun Date: Tue, 5 Sep 2023 09:21:01 -0400 Subject: [PATCH 8/8] feat: Insert from URL input presents URL-centric keyboard --- .../block-editor/src/components/media-upload/index.native.js | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/packages/block-editor/src/components/media-upload/index.native.js b/packages/block-editor/src/components/media-upload/index.native.js index 924930352e019..97fa69d49a4ec 100644 --- a/packages/block-editor/src/components/media-upload/index.native.js +++ b/packages/block-editor/src/components/media-upload/index.native.js @@ -325,6 +325,10 @@ function URLInput( props ) {