Genesys Cloud - Developer Community!

 View Only

Sign Up

  • 1.  Mobile Messenger SDK 2.2.0 – Present custom image viewer above Messenger UI after URL click

    Posted 20 days ago

    Hi Genesys Developer Community,

    We are integrating the Genesys Mobile Messenger SDK 2.2.0 into a React Native application through native wrappers.

    We have a requirement where image hyperlinks sent in chat should open inside our application instead of launching the external browser.

    We have already identified URL click handling/interception points, but we are now running into a UI layering problem.


    Problem:

    When an image URL is tapped, we attempt to notify React Native and display a React Native modal/image viewer.

    However, the Messenger UI is rendered as a native full-screen layer above the React Native view hierarchy.


    As a result:

    • React Native modal opens behind Messenger UI

    • React Native modal is hidden/not visible

    • User never sees the image viewer


    Questions:

    1. Is there a supported way to present custom UI above the Messenger UI after a URL click event?

    2. When handling URL clicks, is the recommended approach to:

      • open a native dialog/view controller/activity directly from the URL click callback

      • or dismiss/minimize Messenger and then return control to the host app?

    3. Are there any SDK APIs intended for custom content presentation after URL clicks?

    4. Has anyone implemented an in-app image viewer for chat image links using the Mobile Messenger SDK?

    5. If Messenger is presented modally/full-screen, what is the recommended mechanism for showing host-application UI in response to a URL click?


    Current Architecture:

    • React Native host application

    • Genesys Mobile Messenger SDK 2.2.0

    • Messenger UI presented using the native SDK UI

    • Image URL taps detected in native code

    Environment:

    Android:

    • com.genesys.cloud:core:2.2.0

    • com.genesys.cloud:chatintegration:2.2.0

    • com.genesys.cloud:ui:2.2.0

    iOS:

    • GenesysCloudMessenger 2.2.0

    • GenesysCloudMessengerTransport 2.13.0

    Any guidance or examples would be greatly appreciated.

    Thank you!


    #MobileMessenger

    ------------------------------
    James Smith
    ------------------------------


  • 2.  RE: Mobile Messenger SDK 2.2.0 – Present custom image viewer above Messenger UI after URL click

    Posted 15 days ago

    Hi James, thanks for raising this issue. Our devs will investigate provided logs and come back to you with their findings.



    ------------------------------
    Anton Afanasiev
    Manager, Mobile Development
    ------------------------------



  • 3.  RE: Mobile Messenger SDK 2.2.0 – Present custom image viewer above Messenger UI after URL click

    Posted 13 days ago

    Hello James,

    First of all let me answer your questions:

    1. Is there a supported way to present custom UI above the Messenger UI after a URL click event?

      Model presentations (including full-screen) above the Messenger UI are possible using regular RN/iOS/Android APIs, our SDK does not provide any additional API for this, but it should not be required.

    2. When handling URL clicks, is the recommended approach to:

      • open a native dialog/view controller/activity directly from the URL click callback

      • or dismiss/minimize Messenger and then return control to the host app?
        You do not need to minimize the SDK UI, you should be able to display above it any other screen, however you can also minimize the UI if that what you want. I don't recommend completely terminating the chat session, as that could degrade end-user experience.

    3. Are there any SDK APIs intended for custom content presentation after URL clicks?

      No, this can be achieved using regular platform (RN/iOS/Android) APIs.

    4. Has anyone implemented an in-app image viewer for chat image links using the Mobile Messenger SDK?

      As a PoC to validate my answer I implemented it now, you can find below a summary of what I needed to implement to achieve this.

    5. If Messenger is presented modally/full-screen, what is the recommended mechanism for showing host-application UI in response to a URL click?

      You can present another screen modally/full-screen above the chat UI using standard platform APIs.

    While we promise React Native compatibility with our SDK, we are not able to provide in-depth react native support. In order to validate your issue I created a simple react native host app for our SDK, and added a similar in-app image viewer to what you described. I was able to get it working. 

    You can wire this up by combining the didClickLink delegate on the iOS side with an RCTRootView for the custom viewer. The key is that the chat is presented as a UIKit modal, so a plain JS <Modal> won't render above it - the viewer has to be presented by UIKit too, with React Native content hosted inside.

    Here's the shape of what worked for us on Messenger SDK 2.2.0 + RN 0.73.

    1. Implement didClickLink: on your ChatControllerDelegate

    In your native module, detect image URLs by pathExtension and forward them to JS via an event. For everything else, fall back to the default behavior so non-image links still open in Safari.

    - (BOOL)isImageURLString:(NSString *)urlString {
        NSString *ext = [NSURL URLWithString:urlString].pathExtension.lowercaseString;
        return [@[@"jpg", @"jpeg", @"png"] containsObject:ext];
    }
    
    - (void)didClickLink:(NSString *)url {
        if ([self isImageURLString:url]) {
            [self sendEventWithName:@"onMessengerImageLink" body:@{@"url": url}];
            return;
        }
        NSURL *parsed = [NSURL URLWithString:url];
        if (parsed) {
            [[UIApplication sharedApplication] openURL:parsed options:@{} completionHandler:nil];
        }
    }
    

    Using pathExtension is nice because it tolerates query strings and fragments (image.jpg?w=400#x).

    2. Expose presentImageViewer / dismissImageViewer from native

    The viewer is hosted in an RCTRootView, wrapped in a UIViewController, and presented from the topmost presented VC. Walking up the presentedViewController chain is what gets the viewer above the chat's nav controller.

    RCT_EXPORT_METHOD(presentImageViewer:(NSString *)imageUrl) {
        RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:self.bridge
                                                         moduleName:@"ImageViewer"
                                                  initialProperties:@{@"imageUrl": imageUrl}];
        rootView.backgroundColor = [UIColor clearColor];
    
        UIViewController *vc = [[UIViewController alloc] init];
        vc.view = rootView;
        vc.modalPresentationStyle = UIModalPresentationOverFullScreen;
        self.imageViewerController = vc;
    
        UIViewController *top = [UIApplication sharedApplication].keyWindow.rootViewController;
        while (top.presentedViewController) { top = top.presentedViewController; }
        [top presentViewController:vc animated:YES completion:nil];
    }
    
    RCT_EXPORT_METHOD(dismissImageViewer) {
        UIViewController *vc = self.imageViewerController;
        self.imageViewerController = nil;
        [vc dismissViewControllerAnimated:YES completion:nil];
    }
    

    Make sure your module inherits from RCTEventEmitter so it can send onMessengerImageLink, and that methodQueue returns dispatch_get_main_queue() because both present and dismiss need to be on the main thread.

    3. Register the viewer as a separate RN component

    In index.js, register an ImageViewer component alongside your app entry. This lets RCTRootView instantiate it by name.

    import {AppRegistry} from 'react-native';
    import App from './src/App';
    import ImageViewer from './src/ImageViewer';
    import {name as appName} from './app.json';
    
    AppRegistry.registerComponent(appName, () => App);
    AppRegistry.registerComponent('ImageViewer', () => ImageViewer);
    

    The component itself is just an Image + a close button that calls back into native:

    const ImageViewer = ({imageUrl}) => (
      <View style={{flex: 1, backgroundColor: '#000'}}>
        <SafeAreaView style={{flex: 1}}>
          <TouchableOpacity onPress={() => GenesysCloud.dismissImageViewer()}>
            <Text style={{color: '#fff'}}>Close</Text>
          </TouchableOpacity>
          <Image source={{uri: imageUrl}} style={{flex: 1}} resizeMode="contain" />
        </SafeAreaView>
      </View>
    );
    

    4. Tie it together in your app

    Listen for the event and trigger the viewer:

    const sub = new NativeEventEmitter(NativeModules.GenesysCloud)
      .addListener('onMessengerImageLink', ({url}) => {
        GenesysCloud.presentImageViewer(url);
      });
    

    Important note

    If you try to open the viewer with a JS <Modal> instead of an RCTRootView, you'll see it render below the chat. That's because the SDK presents UINavigationController on top of the React Native root view controller, and a JS Modal still belongs to that same RN root. Going through RCTRootView + presentViewController: is what gets you the correct z-order.

    Please let us know if you were able to implement the functionality based on this.



    ------------------------------
    Andras Solyom
    Senior Mobile Software Engineer - iOS
    ------------------------------