Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Add Hook to monitor network connectivity status #56861

Merged
merged 8 commits into from
Dec 11, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,10 @@ interface BlockTypeImpressionsCallback {
void onRequestBlockTypeImpressions(ReadableMap impressions);
}

interface ConnectionStatusCallback {
void onRequestConnectionStatus(boolean isConnected);
}

// Ref: https://github.com/facebook/react-native/blob/HEAD/Libraries/polyfills/console.js#L376
enum LogLevel {
TRACE(0),
Expand Down Expand Up @@ -183,4 +187,6 @@ void gutenbergDidRequestUnsupportedBlockFallback(ReplaceUnsupportedBlockCallback
void toggleUndoButton(boolean isDisabled);

void toggleRedoButton(boolean isDisabled);

void requestConnectionStatus(ConnectionStatusCallback connectionStatusCallback);
}
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import com.facebook.react.bridge.WritableNativeMap;
import com.facebook.react.modules.core.DeviceEventManagerModule;

import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.ConnectionStatusCallback;
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.MediaType;
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.OtherMediaOptionsReceivedCallback;
import org.wordpress.mobile.ReactNativeGutenbergBridge.GutenbergBridgeJS2Parent.FocalPointPickerTooltipShownCallback;
Expand Down Expand Up @@ -85,6 +86,8 @@ public class RNReactNativeGutenbergBridgeModule extends ReactContextBaseJavaModu

public static final String MAP_KEY_FEATURED_IMAGE_ID = "featuredImageId";

public static final String MAP_KEY_IS_CONNECTED = "isConnected";

private boolean mIsDarkMode;

public RNReactNativeGutenbergBridgeModule(ReactApplicationContext reactContext,
Expand Down Expand Up @@ -533,4 +536,18 @@ public void generateHapticFeedback() {
}
}
}

@ReactMethod
public void requestConnectionStatus(final Callback jsCallback) {
ConnectionStatusCallback connectionStatusCallback = requestConnectionStatusCallback(jsCallback);
mGutenbergBridgeJS2Parent.requestConnectionStatus(connectionStatusCallback);
}

private ConnectionStatusCallback requestConnectionStatusCallback(final Callback jsCallback) {
return new GutenbergBridgeJS2Parent.ConnectionStatusCallback() {
@Override public void onRequestConnectionStatus(boolean isConnected) {
jsCallback.invoke(isConnected);
}
};
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;

import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_IS_CONNECTED;
import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_ID;
import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_NEW_ID;
import static org.wordpress.mobile.ReactNativeGutenbergBridge.RNReactNativeGutenbergBridgeModule.MAP_KEY_MEDIA_FILE_UPLOAD_MEDIA_URL;
Expand Down Expand Up @@ -44,6 +45,8 @@ public interface JSEventEmitter {

private static final String EVENT_FEATURED_IMAGE_ID_NATIVE_UPDATED = "featuredImageIdNativeUpdated";

private static final String EVENT_CONNECTION_STATUS_CHANGE = "connectionStatusChange";

private static final String MAP_KEY_MEDIA_FILE_STATE = "state";
private static final String MAP_KEY_MEDIA_FILE_MEDIA_ACTION_PROGRESS = "progress";
private static final String MAP_KEY_MEDIA_FILE_MEDIA_SERVER_ID = "mediaServerId";
Expand Down Expand Up @@ -222,6 +225,12 @@ public void sendToJSFeaturedImageId(int mediaId) {
queueActionToJS(EVENT_FEATURED_IMAGE_ID_NATIVE_UPDATED, writableMap);
}

public void onConnectionStatusChange(boolean isConnected) {
WritableMap writableMap = new WritableNativeMap();
writableMap.putBoolean(MAP_KEY_IS_CONNECTED, isConnected);
queueActionToJS(EVENT_CONNECTION_STATUS_CHANGE, writableMap);
}

@Override public void onReplaceMediaFilesEditedBlock(String mediaFiles, String blockId) {
WritableMap writableMap = new WritableNativeMap();
writableMap.putString(MAP_KEY_REPLACE_BLOCK_HTML, mediaFiles);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ public class WPAndroidGlueCode {
private OnToggleUndoButtonListener mOnToggleUndoButtonListener;

private OnToggleRedoButtonListener mOnToggleRedoButtonListener;
private OnConnectionStatusEventListener mOnConnectionStatusEventListener;
private boolean mIsEditorMounted;

private String mContentHtml = "";
Expand Down Expand Up @@ -259,6 +260,10 @@ public interface OnToggleRedoButtonListener {
void onToggleRedoButton(boolean isDisabled);
}

public interface OnConnectionStatusEventListener {
boolean onRequestConnectionStatus();
}

public void mediaSelectionCancelled() {
mAppendsMultipleSelectedToSiblingBlocks = false;
}
Expand Down Expand Up @@ -594,6 +599,12 @@ public void toggleUndoButton(boolean isDisabled) {
public void toggleRedoButton(boolean isDisabled) {
mOnToggleRedoButtonListener.onToggleRedoButton(isDisabled);
}

@Override
public void requestConnectionStatus(ConnectionStatusCallback connectionStatusCallback) {
boolean isConnected = mOnConnectionStatusEventListener.onRequestConnectionStatus();
connectionStatusCallback.onRequestConnectionStatus(isConnected);
}
}, mIsDarkMode);

return Arrays.asList(
Expand Down Expand Up @@ -688,6 +699,7 @@ public void attachToContainer(ViewGroup viewGroup,
OnSendEventToHostListener onSendEventToHostListener,
OnToggleUndoButtonListener onToggleUndoButtonListener,
OnToggleRedoButtonListener onToggleRedoButtonListener,
OnConnectionStatusEventListener onConnectionStatusEventListener,
boolean isDarkMode) {
MutableContextWrapper contextWrapper = (MutableContextWrapper) mReactRootView.getContext();
contextWrapper.setBaseContext(viewGroup.getContext());
Expand All @@ -713,6 +725,7 @@ public void attachToContainer(ViewGroup viewGroup,
mOnSendEventToHostListener = onSendEventToHostListener;
mOnToggleUndoButtonListener = onToggleUndoButtonListener;
mOnToggleRedoButtonListener = onToggleRedoButtonListener;
mOnConnectionStatusEventListener = onConnectionStatusEventListener;

sAddCookiesInterceptor.setOnAuthHeaderRequestedListener(onAuthHeaderRequestedListener);

Expand Down Expand Up @@ -1149,6 +1162,10 @@ public void sendToJSFeaturedImageId(int mediaId) {
mDeferredEventEmitter.sendToJSFeaturedImageId(mediaId);
}

public void connectionStatusChange(boolean isConnected) {
mDeferredEventEmitter.onConnectionStatusChange(isConnected);
}

public void replaceUnsupportedBlock(String content, String blockId) {
if (mReplaceUnsupportedBlockCallback != null) {
mReplaceUnsupportedBlockCallback.replaceUnsupportedBlock(content, blockId);
Expand Down
48 changes: 48 additions & 0 deletions packages/react-native-bridge/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@
*/
import { NativeModules, NativeEventEmitter, Platform } from 'react-native';

/**
* WordPress dependencies
*/
import { useEffect, useState } from '@wordpress/element';

const { RNReactNativeGutenbergBridge } = NativeModules;
const isIOS = Platform.OS === 'ios';
const isAndroid = Platform.OS === 'android';
Expand Down Expand Up @@ -185,6 +190,49 @@ export function subscribeOnRedoPressed( callback ) {
return gutenbergBridgeEvents.addListener( 'onRedoPressed', callback );
}

export function useIsConnected() {
const [ isConnected, setIsConnected ] = useState( null );

useEffect( () => {
let isCurrent = true;

RNReactNativeGutenbergBridge.requestConnectionStatus(
( isBridgeConnected ) => {
if ( ! isCurrent ) {
return;
}

setIsConnected( isBridgeConnected );
}
);

return () => {
isCurrent = false;
};
}, [] );

useEffect( () => {
const subscription = subscribeConnectionStatus(
( { isConnected: isBridgeConnected } ) => {
setIsConnected( isBridgeConnected );
}
);

return () => {
subscription.remove();
};
}, [] );

return { isConnected };
}

function subscribeConnectionStatus( callback ) {
return gutenbergBridgeEvents.addListener(
'connectionStatusChange',
callback
);
}

/**
* Request media picker for the given media source.
*
Expand Down
5 changes: 5 additions & 0 deletions packages/react-native-bridge/ios/Gutenberg.swift
Original file line number Diff line number Diff line change
Expand Up @@ -210,6 +210,11 @@ public class Gutenberg: UIResponder {
bridgeModule.sendEventIfNeeded(.onRedoPressed, body: nil)
}

public func connectionStatusChange(isConnected: Bool) {
var data: [String: Any] = ["isConnected": isConnected]
bridgeModule.sendEventIfNeeded(.connectionStatusChange, body: data)
}

private func properties(from editorSettings: GutenbergEditorSettings?) -> [String : Any] {
var settingsUpdates = [String : Any]()
settingsUpdates["isFSETheme"] = editorSettings?.isFSETheme ?? false
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -283,6 +283,8 @@ public protocol GutenbergBridgeDelegate: AnyObject {
func gutenbergDidRequestToggleUndoButton(_ isDisabled: Bool)

func gutenbergDidRequestToggleRedoButton(_ isDisabled: Bool)

func gutenbergDidRequestConnectionStatus() -> Bool
}

// MARK: - Optional GutenbergBridgeDelegate methods
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,5 +42,6 @@ @interface RCT_EXTERN_MODULE(RNReactNativeGutenbergBridge, NSObject)
RCT_EXTERN_METHOD(generateHapticFeedback)
RCT_EXTERN_METHOD(toggleUndoButton:(BOOL)isDisabled)
RCT_EXTERN_METHOD(toggleRedoButton:(BOOL)isDisabled)
RCT_EXTERN_METHOD(requestConnectionStatus:(RCTResponseSenderBlock)callback)

@end
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,11 @@ public class RNReactNativeGutenbergBridge: RCTEventEmitter {
func toggleRedoButton(_ isDisabled: Bool) {
self.delegate?.gutenbergDidRequestToggleRedoButton(isDisabled)
}

@objc
func requestConnectionStatus(_ callback: @escaping RCTResponseSenderBlock) {
callback([self.delegate?.gutenbergDidRequestConnectionStatus() ?? true])
}
}

// MARK: - RCTBridgeModule delegate
Expand Down Expand Up @@ -450,6 +455,7 @@ extension RNReactNativeGutenbergBridge {
case showEditorHelp
case onUndoPressed
case onRedoPressed
case connectionStatusChange
}

public override func supportedEvents() -> [String]! {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -308,6 +308,11 @@ public void toggleRedoButton(boolean isDisabled) {
mainActivity.updateRedoItem(isDisabled);
}
}

@Override
public void requestConnectionStatus(ConnectionStatusCallback connectionStatusCallback) {
connectionStatusCallback.onRequestConnectionStatus(true);
}
}, isDarkMode());

return new DefaultReactNativeHost(this) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ extension GutenbergViewController: GutenbergBridgeDelegate {
}
}
}

func gutenbergDidRequestConnectionStatus() -> Bool {
return true
}
}

extension GutenbergViewController: GutenbergWebDelegate {
Expand Down
Loading