# iOS modal rich media

Starting from Pushwoosh SDK version 6.7.5, you have the ability to send **Modal Rich Media**.

We are introducing new **Modal Rich Media**, which can be customized. The new Modal Rich Media do not completely block the screen and can be positioned in different parts of the screen (top, bottom, and center).

> For more information on Rich Media pages, please refer to [our guide](/product/content/rich-media).

## Configuration

<Aside type="note">
 By default, the Pushwoosh iOS SDK supports displaying legacy rich media.
</Aside>

<Aside type="note">
If you plan to use modal rich media display as in-app messages in the Customer Journey Builder, make sure you have implemented the code shown below. See the [basic SDK integration](/developer/pushwoosh-sdk/ios-sdk/setting-up-pushwoosh-ios-sdk/basic-integration-guide/) for details.
</Aside>

```swift
//for silent push notifications
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {
    Pushwoosh.configure.handlePushReceived(userInfo)
    completionHandler(.noData)
}
```

### Option 1: Info.plist configuration

To enable the display of Modal Rich Media, set the parameter `Pushwoosh_RICH_MEDIA_STYLE` in your **info.plist** and assign it the value `MODAL_RICH_MEDIA`.

**Info.plist**:
```xml
<key>Pushwoosh_RICH_MEDIA_STYLE</key>
<string>MODAL_RICH_MEDIA</string>
```

### Option 2: Programmatic configuration (SDK 7.0.14+)

<Aside type="tip">
Available since Pushwoosh iOS SDK version **7.0.14**.
</Aside>

You can also configure the Rich Media presentation style programmatically in your AppDelegate:

<Tabs>
<TabItem label="Swift">
```swift
func application(_ application: UIApplication,
                 didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    // Set modal presentation style
    Pushwoosh.media.setRichMediaPresentationStyle(.modal)

    // Configure modal window appearance
    Pushwoosh.media.modalRichMedia.configure(
        position: .PWModalWindowPositionBottom,
        presentAnimation: .PWAnimationPresentFromBottom,
        dismissAnimation: .PWAnimationDismissDown
    )

    Pushwoosh.configure.registerForPushNotifications()
    return true
}
```
</TabItem>
<TabItem label="Objective-C">
```objective-c
- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    // Set modal presentation style
    [[Pushwoosh media] setRichMediaPresentationStyle:PWRichMediaPresentationStyleModal];

    // Configure modal window appearance
    [[[Pushwoosh media] modalRichMedia] configureWithPosition:PWModalWindowPositionBottom
                                             presentAnimation:PWAnimationPresentFromBottom
                                             dismissAnimation:PWAnimationDismissDown];

    [[Pushwoosh configure] registerForPushNotifications];
    return YES;
}
```
</TabItem>
</Tabs>

By default, Modal Rich Media will be displayed in the center of the screen with a bottom-to-top appearance animation.

<div style={{ display: "flex", justifyContent: "center" }}>
<video src="/ios-push-notifications-ios-modal-rich-media-1.webm" title="Example" autoplay loop muted playsinline width="300" />
</div>

### Modal Rich Media positioning

Modal Rich Media can be positioned in different locations on the screen.

```objective-c
/**
 Enum defining the possible positions for displaying a modal window.

 - `PWModalWindowPositionTop`: The modal window appears at the top of the screen, within the safe area.
 - `PWModalWindowPositionCenter`: The modal window appears at the center of the screen, within the safe area.
 - `PWModalWindowPositionBottom`: The modal window appears at the bottom of the screen, within the safe area.
 - `PWModalWindowPositionBottomSheet`: The modal window appears at the very bottom of the screen, ignoring the safe area.
 - `PWModalWindowPositionDefault`: The default position is the center of the screen, within the safe area.
 */
typedef NS_ENUM(NSInteger, ModalWindowPosition) {
    PWModalWindowPositionTop,       // Appears at the top of the screen (within safe area)
    PWModalWindowPositionCenter,    // Appears at the center of the screen (within safe area)
    PWModalWindowPositionBottom,    // Appears at the bottom of the screen (within safe area)
    PWModalWindowPositionBottomSheet, // Appears at the very bottom of the screen (ignores safe area)
    PWModalWindowPositionFullScreen, // Fullscreen, ignores safe area insets
    PWModalWindowPositionDefault    // Default position (center of the screen, within safe area)
};
```

The example below shows a Modal Rich Media displayed at the top of the screen.

<div style={{ display: "flex", justifyContent: "center" }}>
<video src="/ios-push-notifications-ios-modal-rich-media-2.webm" title="Example" autoplay loop muted playsinline width="300" />
</div>

Modal Rich Media show animations include:

```objective-c
typedef NS_ENUM(NSInteger, PresentModalWindowAnimation) {
    PWAnimationPresentFromBottom,
    PWAnimationPresentFromTop,
    PWAnimationPresentFromRight,
    PWAnimationPresentFromLeft,
    PWAnimationPresentNone
};
```

Modal Rich Media close animations include:

```objective-c
typedef NS_ENUM(NSInteger, DismissModalWindowAnimation) {
    PWAnimationDismissDown,
    PWAnimationDismissUp,
    PWAnimationDismissLeft,
    PWAnimationDismissRight,
    PWAnimationCurveEaseInOut,
    PWAnimationDismissNone,

    /**
     * Default dismiss animation is `PWAnimationCurveEaseInOut`
     */
    PWAnimationDismissDefault
};
```

The example below demonstrates displaying Modal Rich Media at the bottom of the screen with a left-to-right show animation and a rightward close animation:

<div style={{ display: "flex", justifyContent: "center" }}>
<video src="/ios-push-notifications-ios-modal-rich-media-3.webm" title="Example" autoplay loop muted playsinline width="300" />
</div>

### Additional parameters for Modal Rich Media

<Aside type="tip">
The following API is available since Pushwoosh iOS SDK version **7.0.14**.
</Aside>

Additional parameters for displaying Modal Rich Media include options like adding haptic feedback of type vibration, enabling swipe gestures, and setting an automatic close timer after a specified duration.

<Tabs>
<TabItem label="Swift">
```swift
// Haptic Feedback Type
Pushwoosh.media.modalRichMedia.setHapticFeedbackType(.PWHapticFeedbackLight)

// Swipe directions to dismiss
Pushwoosh.media.modalRichMedia.setDismissSwipeDirections([
    NSNumber(value: DismissSwipeDirection.PWSwipeDismissDown.rawValue),
    NSNumber(value: DismissSwipeDirection.PWSwipeDismissUp.rawValue)
])

// Set Rich Media corner radius
let topCorners = PWCornerTypeTopLeft.rawValue | PWCornerTypeTopRight.rawValue
Pushwoosh.media.modalRichMedia.setCornerType(CornerType(rawValue: topCorners), withRadius: 16)

// Close Modal Rich Media after N seconds
Pushwoosh.media.modalRichMedia.closeAfter(3)
```
</TabItem>
<TabItem label="Objective-C">
```objective-c
// Haptic Feedback Type
[[[Pushwoosh media] modalRichMedia] setHapticFeedbackType:PWHapticFeedbackLight];

// Swipe directions to dismiss
[[[Pushwoosh media] modalRichMedia] setDismissSwipeDirections:@[
    @(PWSwipeDismissDown),
    @(PWSwipeDismissUp)
]];

// Set Rich Media corner radius
CornerType topCorners = PWCornerTypeTopLeft | PWCornerTypeTopRight;
[[[Pushwoosh media] modalRichMedia] setCornerType:topCorners withRadius:16.0];

// Close Modal Rich Media after N seconds
[[[Pushwoosh media] modalRichMedia] closeAfter:3.0];
```
</TabItem>
</Tabs>

**Haptic Feedback Types:**

```objective-c
typedef NS_ENUM(NSInteger, HapticFeedbackType) {
    PWHapticFeedbackLight,         // Light vibration feedback
    PWHapticFeedbackMedium,        // Medium vibration feedback
    PWHapticFeedbackHard,          // Strong vibration feedback
    PWHapticFeedbackNone           // Vibration is off (default)
};
```

**Swipe Directions:**

```objective-c
typedef NS_ENUM(NSInteger, DismissSwipeDirection) {
    PWSwipeDismissDown,
    PWSwipeDismissUp,
    PWSwipeDismissLeft,
    PWSwipeDismissRight,
    PWSwipeDismissNone
};
```

## PWRichMediaPresentingDelegate

<Aside type="tip">
The delegate API via `Pushwoosh.media.modalRichMedia.delegate` is available since SDK version **7.0.14**.
</Aside>

To manage the queue of modal rich media, you need to implement the delegate methods of `PWRichMediaPresentingDelegate`.
When using this functionality, modal rich media are presented sequentially, and the next one will not be displayed until the user closes the current one. Once the user closes the presented rich media, the next one, which was part of a different push notification, will be shown.

<Tabs>
<TabItem label="Swift">
```swift
import UIKit
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate, PWRichMediaPresentingDelegate {

    var richMediaQueue: [PWRichMedia] = []
    var isPresenting = false

    func application(_ application: UIApplication,
                     didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        // Configure modal rich media
        Pushwoosh.media.setRichMediaPresentationStyle(.modal)
        Pushwoosh.media.modalRichMedia.configure(
            position: .PWModalWindowPositionBottom,
            presentAnimation: .PWAnimationPresentFromBottom,
            dismissAnimation: .PWAnimationDismissDown
        )

        // Set delegate
        Pushwoosh.media.modalRichMedia.delegate = self

        Pushwoosh.configure.registerForPushNotifications()
        return true
    }

    // MARK: - PWRichMediaPresentingDelegate

    func richMediaManager(_ richMediaManager: PWRichMediaManager, shouldPresent richMedia: PWRichMedia) -> Bool {
        if !richMediaQueue.contains(where: { $0 === richMedia }) {
            richMediaQueue.append(richMedia)
        }
        return !isPresenting
    }

    func richMediaManager(_ richMediaManager: PWRichMediaManager, didPresent richMedia: PWRichMedia) {
        isPresenting = true
    }

    func richMediaManager(_ richMediaManager: PWRichMediaManager, didClose richMedia: PWRichMedia) {
        isPresenting = false

        if let idx = richMediaQueue.firstIndex(where: { $0 === richMedia }) {
            richMediaQueue.remove(at: idx)
        }

        // Present next rich media in queue
        if let nextRichMedia = richMediaQueue.first {
            Pushwoosh.media.modalRichMedia.present(nextRichMedia)
        }
    }

    func richMediaManager(_ richMediaManager: PWRichMediaManager, presentingDidFailFor richMedia: PWRichMedia, withError error: Error) {
        richMediaManager(richMediaManager, didClose: richMedia)
    }
}
```
</TabItem>
<TabItem label="Objective-C">
```objective-c
#import "AppDelegate.h"
#import <PushwooshFramework/PushwooshFramework.h>

@interface AppDelegate () <PWRichMediaPresentingDelegate>

@property (nonatomic, strong) NSMutableArray<PWRichMedia *> *richMediaQueue;
@property (nonatomic, assign) BOOL isPresenting;

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
        didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    self.richMediaQueue = [NSMutableArray array];
    self.isPresenting = NO;

    // Configure modal rich media
    [[Pushwoosh media] setRichMediaPresentationStyle:PWRichMediaPresentationStyleModal];
    [[[Pushwoosh media] modalRichMedia] configureWithPosition:PWModalWindowPositionBottom
                                             presentAnimation:PWAnimationPresentFromBottom
                                             dismissAnimation:PWAnimationDismissDown];

    // Set delegate
    [[[Pushwoosh media] modalRichMedia] setDelegate:self];

    [[Pushwoosh configure] registerForPushNotifications];
    return YES;
}

#pragma mark - PWRichMediaPresentingDelegate

- (BOOL)richMediaManager:(PWRichMediaManager *)richMediaManager shouldPresentRichMedia:(PWRichMedia *)richMedia {
    if (![self.richMediaQueue containsObject:richMedia]) {
        [self.richMediaQueue addObject:richMedia];
    }
    return !self.isPresenting;
}

- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didPresentRichMedia:(PWRichMedia *)richMedia {
    self.isPresenting = YES;
}

- (void)richMediaManager:(PWRichMediaManager *)richMediaManager didCloseRichMedia:(PWRichMedia *)richMedia {
    self.isPresenting = NO;

    [self.richMediaQueue removeObject:richMedia];

    // Present next rich media in queue
    if (self.richMediaQueue.count > 0) {
        [[[Pushwoosh media] modalRichMedia] presentRichMedia:self.richMediaQueue.firstObject];
    }
}

- (void)richMediaManager:(PWRichMediaManager *)richMediaManager presentingDidFailForRichMedia:(PWRichMedia *)richMedia withError:(NSError *)error {
    [self richMediaManager:richMediaManager didCloseRichMedia:richMedia];
}

@end
```
</TabItem>
</Tabs>