# Rich media modal para tvOS

A partir de la versión 6.11.0 del SDK de Pushwoosh, tienes la capacidad de enviar **Rich Media Modal** a dispositivos tvOS (Apple TV).

El Rich Media Modal para tvOS proporciona una visualización de contenido interactivo basado en HTML, optimizado para la navegación con el control remoto de Apple TV. El rich media se puede personalizar con diferentes posiciones, animaciones y soporte para la navegación por foco.

<video src="/tv_os_rich_media.webm" title="Ejemplo de Rich Media para tvOS" autoplay loop muted playsinline />

<Aside type="caution">
Las notificaciones push estándar no son compatibles con tvOS. Apple TV no muestra banners o alertas de notificaciones push tradicionales. Solo el contenido Rich Media entregado a través de notificaciones push silenciosas puede mostrarse utilizando el módulo PushwooshTVOS.
</Aside>

> Para más información sobre las páginas Rich Media, por favor consulta [nuestra guía](/es/product/content/rich-media).

## Instalación

El módulo PushwooshTVOS es opcional y puede integrarse en tu proyecto de tvOS utilizando Swift Package Manager o CocoaPods.

### Swift Package Manager

Añade el paquete Pushwoosh a tu proyecto de tvOS:

1. En Xcode, selecciona **File** → **Add Package Dependencies...**
2. Introduce la URL del repositorio: `https://github.com/Pushwoosh/Pushwoosh-XCFramework`
3. Selecciona la última versión
4. Añade los siguientes frameworks a tu target de tvOS:
   * **PushwooshFramework**
   * **PushwooshCore**
   * **PushwooshBridge**
   * **PushwooshLiveActivities**
   * **PushwooshTVOS**

### CocoaPods

Añade a tu Podfile:

```ruby
target 'YourTvOSApp' do
  platform :tvos, '13.0'

  pod 'PushwooshXCFramework'
  pod 'PushwooshXCFramework/PushwooshTVOS'
end
```

Luego ejecuta:

```bash
pod install
```

## Integración básica

### 1. Configura Pushwoosh en tu AppDelegate

Importa los módulos necesarios y configura Pushwoosh con el código de tu aplicación:

```swift
import UIKit
import PushwooshTVOS
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

        // Configura Pushwoosh con el código de tu aplicación
        Pushwoosh.TVoS.setAppCode("XXXXX-XXXXX")

        // Regístrate para recibir notificaciones push
        Pushwoosh.TVoS.registerForTvPushNotifications()

        return true
    }
}
```

### 2. Maneja el registro del token del dispositivo

Implementa el manejador de token del dispositivo para registrar el dispositivo con Pushwoosh:

```swift
func application(_ application: UIApplication, didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
    Pushwoosh.TVoS.registerForTvPushNotifications(withToken: deviceToken) { error in
        if let error = error {
            print("Failed to register: \(error)")
        } else {
            print("Successfully registered for push notifications")
        }
    }
}

func application(_ application: UIApplication, didFailToRegisterForRemoteNotificationsWithError error: Error) {
    Pushwoosh.TVoS.handleTvPushRegistrationFailure(error)
}
```

### 3. Maneja las notificaciones push entrantes

Procesa las notificaciones push entrantes con contenido rich media:

```swift
func application(_ application: UIApplication,
                 didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                 fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

    // Maneja la notificación push y muestra el rich media si está presente
    if Pushwoosh.TVoS.handleTVOSPush(userInfo: userInfo) {
        completionHandler(.newData)
    } else {
        completionHandler(.noData)
    }
}
```

<Aside type="note">
tvOS solo admite notificaciones push silenciosas con la bandera `content-available: 1`. Al enviar notificaciones push a dispositivos Apple TV a través de Pushwoosh, asegúrate de:
- Habilitar la bandera "content-available" en la carga útil de tu notificación push
- Incluir contenido Rich Media en la notificación
</Aside>

## Configuración de Rich Media

### Posicionamiento

El Rich Media Modal para tvOS se puede posicionar en cinco ubicaciones en la pantalla:

```swift
// Posición central (por defecto)
Pushwoosh.TVoS.configureRichMediaWith(position: .center, presentAnimation: .none, dismissAnimation: .none)

// Lado izquierdo de la pantalla
Pushwoosh.TVoS.configureRichMediaWith(position: .left, presentAnimation: .fromLeft, dismissAnimation: .toLeft)

// Lado derecho de la pantalla
Pushwoosh.TVoS.configureRichMediaWith(position: .right, presentAnimation: .fromRight, dismissAnimation: .toRight)

// Parte superior de la pantalla
Pushwoosh.TVoS.configureRichMediaWith(position: .top, presentAnimation: .fromTop, dismissAnimation: .toTop)

// Parte inferior de la pantalla
Pushwoosh.TVoS.configureRichMediaWith(position: .bottom, presentAnimation: .fromBottom, dismissAnimation: .toBottom)
```

Opciones de posición disponibles:

```swift
enum PWTVOSRichMediaPosition {
    case center     // Contenido posicionado en el centro de la pantalla (por defecto)
    case left       // Contenido posicionado en el lado izquierdo de la pantalla
    case right      // Contenido posicionado en el lado derecho de la pantalla
    case top        // Contenido posicionado en la parte superior de la pantalla
    case bottom     // Contenido posicionado en la parte inferior de la pantalla
}
```

### Animaciones de presentación

Controla cómo aparece el contenido rich media en la pantalla:

```swift
enum PWTVOSRichMediaPresentAnimation {
    case none        // Sin animación, el contenido aparece inmediatamente (por defecto)
    case fromTop     // El contenido se desliza desde la parte superior de la pantalla
    case fromBottom  // El contenido se desliza desde la parte inferior de la pantalla
    case fromLeft    // El contenido se desliza desde el lado izquierdo de la pantalla
    case fromRight   // El contenido se desliza desde el lado derecho de la pantalla
}
```

### Animaciones de cierre

Controla cómo desaparece el contenido rich media de la pantalla:

```swift
enum PWTVOSRichMediaDismissAnimation {
    case none       // Sin animación, el contenido desaparece inmediatamente (por defecto)
    case toTop      // El contenido se desliza hacia la parte superior de la pantalla
    case toBottom   // El contenido se desliza hacia la parte inferior de la pantalla
    case toLeft     // El contenido se desliza hacia el lado izquierdo de la pantalla
    case toRight    // El contenido se desliza hacia el lado derecho de la pantalla
}
```

### Ejemplos de configuración

Configura el rich media para que aparezca en el lado izquierdo con animaciones:

```swift
Pushwoosh.TVoS.configureRichMediaWith(
    position: .left,
    presentAnimation: .fromBottom,
    dismissAnimation: .toLeft
)
```

Configura el rich media para que aparezca en la parte inferior con animaciones de deslizamiento:

```swift
Pushwoosh.TVoS.configureRichMediaWith(
    position: .bottom,
    presentAnimation: .fromBottom,
    dismissAnimation: .toBottom
)
```

Configura el rich media para que aparezca centrado sin animaciones:

```swift
Pushwoosh.TVoS.configureRichMediaWith(
    position: .center,
    presentAnimation: .none,
    dismissAnimation: .none
)
```

## Configuración del botón de cerrar

Por defecto, se muestra un botón de Cerrar en la parte inferior de las presentaciones de rich media. Puedes ocultar este botón si es necesario:

```swift
// Ocultar el botón de Cerrar del sistema
Pushwoosh.TVoS.configureCloseButton(false)
```

<Aside type="caution">
Si ocultas el botón de Cerrar, asegúrate de que tu contenido HTML de rich media incluya un botón con la acción `closeInApp` para permitir a los usuarios descartar el contenido:

```html
<button onclick="closeInApp()">Cerrar</button>
```
</Aside>

## Navegación por foco para Apple TV

El SDK de tvOS gestiona automáticamente la navegación por foco para el control remoto de Apple TV. Los elementos interactivos (botones, enlaces) en tu contenido HTML de rich media serán enfocables utilizando el control remoto de Apple TV.

### Comportamiento del foco

- Los elementos enfocables se detectan automáticamente en el contenido HTML
- Los usuarios pueden navegar entre elementos utilizando el panel direccional del control remoto de Apple TV
- El elemento actualmente enfocado recibe un resaltado visual
- Los usuarios pueden activar los elementos enfocados presionando el botón central del control remoto
- El botón de Cerrar del sistema (cuando está visible) también forma parte de la navegación por foco

### Mejores prácticas para el contenido HTML

Al crear contenido HTML para rich media de tvOS:

1. Usa elementos HTML interactivos estándar: `<button>`, `<a>`, `<input />`
2. Asegúrate de que haya suficiente espacio entre los elementos interactivos para una indicación clara del foco
3. Prueba tu contenido con el simulador de Apple TV para verificar la navegación por foco
4. Considera usar áreas de toque más grandes en comparación con iOS (se recomienda un ancho mínimo de 250pt)

## Ejemplo de integración completa

Aquí tienes un ejemplo completo que muestra todas las características:

```swift
import UIKit
import PushwooshTVOS
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

        // Configura Pushwoosh
        Pushwoosh.TVoS.setAppCode("XXXXX-XXXXX")

        // Configura la apariencia del rich media
        Pushwoosh.TVoS.configureRichMediaWith(
            position: .center,
            presentAnimation: .fromBottom,
            dismissAnimation: .toTop
        )

        // Muestra el botón de cerrar (por defecto)
        Pushwoosh.TVoS.configureCloseButton(true)

        // Regístrate para recibir notificaciones push
        Pushwoosh.TVoS.registerForTvPushNotifications()

        return true
    }

    func application(_ application: UIApplication,
                     didRegisterForRemoteNotificationsWithDeviceToken deviceToken: Data) {
        Pushwoosh.TVoS.registerForTvPushNotifications(withToken: deviceToken) { error in
            if let error = error {
                print("Failed to register: \(error)")
            } else {
                print("Successfully registered")
            }
        }
    }

    func application(_ application: UIApplication,
                     didFailToRegisterForRemoteNotificationsWithError error: Error) {
        Pushwoosh.TVoS.handleTvPushRegistrationFailure(error)
    }

    func application(_ application: UIApplication,
                     didReceiveRemoteNotification userInfo: [AnyHashable: Any],
                     fetchCompletionHandler completionHandler: @escaping (UIBackgroundFetchResult) -> Void) {

        if Pushwoosh.TVoS.handleTVOSPush(userInfo: userInfo) {
            completionHandler(.newData)
        } else {
            completionHandler(.noData)
        }
    }
}
```

## Solución de problemas

### Problemas de navegación por foco

Si la navegación por foco no funciona correctamente:

1. Verifica que tu contenido HTML utilice elementos interactivos estándar (`<button>`, `<a>`)
2. Prueba en el simulador de Apple TV para verificar el comportamiento del foco
3. Asegúrate de que los elementos interactivos tengan suficiente tamaño y espaciado
4. Comprueba que tu HTML/CSS no interfiera con los estados de foco

## Ejemplo en un dispositivo real

Así es como se ve el rich media en un dispositivo Apple TV real:

![Rich Media de tvOS en un Apple TV](/tv_os_simulator.webp)

La captura de pantalla muestra el contenido rich media en un Apple TV con:
- Diseño HTML personalizado con fondos degradados
- Botones interactivos optimizados para el control remoto de Apple TV
- Soporte de navegación por foco para todos los elementos interactivos

## Referencias

- [Código Fuente del SDK de iOS](https://github.com/Pushwoosh/pushwoosh-ios-sdk)
- [Guías de Interfaz Humana de tvOS](https://developer.apple.com/design/human-interface-guidelines/tvos)
- [Creación de Contenido Rich Media](/es/product/content/rich-media)