# Модальные Rich Media для tvOS

Начиная с версии Pushwoosh SDK 6.11.0, у вас есть возможность отправлять **модальные Rich Media** на устройства tvOS (Apple TV).

Модальные Rich Media для tvOS предоставляют интерактивное отображение контента на основе HTML, оптимизированное для навигации с помощью пульта Apple TV. Rich Media можно настраивать, изменяя их положение, анимацию и поддержку навигации фокусом.

<video src="/tv_os_rich_media.webm" title="Пример Rich Media для tvOS" autoplay loop muted playsinline />

<Aside type="caution">
Стандартные push-уведомления не поддерживаются в tvOS. Apple TV не отображает традиционные баннеры или оповещения push-уведомлений. С помощью модуля PushwooshTVOS можно отображать только Rich Media контент, доставляемый через тихие push-уведомления.
</Aside>

> Для получения дополнительной информации о страницах Rich Media, пожалуйста, обратитесь к [нашему руководству](/ru/product/content/rich-media).

## Установка

Модуль PushwooshTVOS является необязательным и может быть интегрирован в ваш проект tvOS с помощью Swift Package Manager или CocoaPods.

### Swift Package Manager

Добавьте пакет Pushwoosh в ваш проект tvOS:

1. В Xcode выберите **File** → **Add Package Dependencies...**
2. Введите URL репозитория: `https://github.com/Pushwoosh/Pushwoosh-XCFramework`
3. Выберите последнюю версию
4. Добавьте следующие фреймворки в вашу цель tvOS:
   * **PushwooshFramework**
   * **PushwooshCore**
   * **PushwooshBridge**
   * **PushwooshLiveActivities**
   * **PushwooshTVOS**

### CocoaPods

Добавьте в ваш Podfile:

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

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

Затем выполните:

```bash
pod install
```

## Базовая интеграция

### 1. Настройте Pushwoosh в вашем AppDelegate

Импортируйте необходимые модули и настройте Pushwoosh с вашим кодом приложения:

```swift
import UIKit
import PushwooshTVOS
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

        // Configure Pushwoosh with your app code
        Pushwoosh.TVoS.setAppCode("XXXXX-XXXXX")

        // Register for push notifications
        Pushwoosh.TVoS.registerForTvPushNotifications()

        return true
    }
}
```

### 2. Обработайте регистрацию токена устройства

Реализуйте обработчик токена устройства для регистрации устройства в 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. Обработайте входящие push-уведомления

Обработайте входящие push-уведомления с Rich Media контентом:

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

    // Handle push notification and display rich media if present
    if Pushwoosh.TVoS.handleTVOSPush(userInfo: userInfo) {
        completionHandler(.newData)
    } else {
        completionHandler(.noData)
    }
}
```

<Aside type="note">
tvOS поддерживает только тихие push-уведомления с флагом `content-available: 1`. При отправке push-уведомлений на устройства Apple TV через Pushwoosh убедитесь, что:
- Флаг «content-available» включен в полезной нагрузке вашего push-уведомления
- Rich Media контент включен в уведомление
</Aside>

## Конфигурация Rich Media

### Позиционирование

Модальные Rich Media для tvOS можно разместить в пяти местах на экране:

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

// Left side of the screen
Pushwoosh.TVoS.configureRichMediaWith(position: .left, presentAnimation: .fromLeft, dismissAnimation: .toLeft)

// Right side of the screen
Pushwoosh.TVoS.configureRichMediaWith(position: .right, presentAnimation: .fromRight, dismissAnimation: .toRight)

// Top of the screen
Pushwoosh.TVoS.configureRichMediaWith(position: .top, presentAnimation: .fromTop, dismissAnimation: .toTop)

// Bottom of the screen
Pushwoosh.TVoS.configureRichMediaWith(position: .bottom, presentAnimation: .fromBottom, dismissAnimation: .toBottom)
```

Доступные варианты позиционирования:

```swift
enum PWTVOSRichMediaPosition {
    case center     // Content positioned at the center of the screen (default)
    case left       // Content positioned at the left side of the screen
    case right      // Content positioned at the right side of the screen
    case top        // Content positioned at the top of the screen
    case bottom     // Content positioned at the bottom of the screen
}
```

### Анимации появления

Управляйте тем, как Rich Media контент появляется на экране:

```swift
enum PWTVOSRichMediaPresentAnimation {
    case none        // No animation, content appears immediately (default)
    case fromTop     // Content slides in from the top of the screen
    case fromBottom  // Content slides in from the bottom of the screen
    case fromLeft    // Content slides in from the left side of the screen
    case fromRight   // Content slides in from the right side of the screen
}
```

### Анимации скрытия

Управляйте тем, как Rich Media контент исчезает с экрана:

```swift
enum PWTVOSRichMediaDismissAnimation {
    case none       // No animation, content disappears immediately (default)
    case toTop      // Content slides out to the top of the screen
    case toBottom   // Content slides out to the bottom of the screen
    case toLeft     // Content slides out to the left side of the screen
    case toRight    // Content slides out to the right side of the screen
}
```

### Примеры конфигурации

Настройте Rich Media так, чтобы они появлялись слева с анимацией:

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

Настройте Rich Media так, чтобы они появлялись внизу с анимацией скольжения:

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

Настройте Rich Media так, чтобы они появлялись по центру без анимации:

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

## Конфигурация кнопки закрытия

По умолчанию кнопка «Закрыть» отображается внизу презентаций Rich Media. При необходимости эту кнопку можно скрыть:

```swift
// Hide the system Close button
Pushwoosh.TVoS.configureCloseButton(false)
```

<Aside type="caution">
Если вы скроете кнопку «Закрыть», убедитесь, что ваш HTML-контент Rich Media содержит кнопку с действием `closeInApp`, чтобы пользователи могли закрыть контент:

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

## Навигация фокусом для Apple TV

tvOS SDK автоматически управляет навигацией фокусом для пульта Apple TV. Интерактивные элементы (кнопки, ссылки) в вашем HTML-контенте Rich Media будут доступны для фокусировки с помощью пульта Apple TV.

### Поведение фокуса

- Фокусируемые элементы автоматически обнаруживаются в HTML-контенте
- Пользователи могут перемещаться между элементами с помощью крестовины на пульте Apple TV
- Элемент, находящийся в фокусе, получает визуальное выделение
- Пользователи могут активировать сфокусированные элементы, нажав центральную кнопку на пульте
- Системная кнопка «Закрыть» (если она видна) также является частью навигации фокусом

### Рекомендации по созданию HTML-контента

При создании HTML-контента для Rich Media в tvOS:

1. Используйте стандартные интерактивные HTML-элементы: `<button>`, `<a>`, `<input />`
2. Обеспечьте достаточное расстояние между интерактивными элементами для четкого обозначения фокуса
3. Протестируйте свой контент в симуляторе Apple TV, чтобы проверить навигацию фокусом
4. Рассмотрите возможность использования более крупных областей касания по сравнению с iOS (рекомендуемая минимальная ширина 250pt)

## Полный пример интеграции

Вот полный пример, демонстрирующий все функции:

```swift
import UIKit
import PushwooshTVOS
import PushwooshFramework

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

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

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

        // Configure rich media appearance
        Pushwoosh.TVoS.configureRichMediaWith(
            position: .center,
            presentAnimation: .fromBottom,
            dismissAnimation: .toTop
        )

        // Show close button (default)
        Pushwoosh.TVoS.configureCloseButton(true)

        // Register for push notifications
        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)
        }
    }
}
```

## Устранение неполадок

### Проблемы с навигацией фокусом

Если навигация фокусом не работает должным образом:

1. Убедитесь, что ваш HTML-контент использует стандартные интерактивные элементы (`<button>`, `<a>`)
2. Протестируйте в симуляторе Apple TV, чтобы проверить поведение фокуса
3. Убедитесь, что интерактивные элементы имеют достаточный размер и расстояние между собой
4. Проверьте, что ваш HTML/CSS не мешает состояниям фокуса

## Пример на реальном устройстве

Вот как Rich Media выглядит на реальном устройстве Apple TV:

![Rich Media для tvOS на Apple TV](/tv_os_simulator.webp)

На скриншоте показан Rich Media контент, отображаемый на Apple TV с:
- Пользовательский HTML-макет с градиентными фонами
- Интерактивные кнопки, оптимизированные для пульта Apple TV
- Поддержка навигации фокусом для всех интерактивных элементов

## Ссылки

- [Исходный код iOS SDK](https://github.com/Pushwoosh/pushwoosh-ios-sdk)
- [Рекомендации по человеческому интерфейсу tvOS](https://developer.apple.com/design/human-interface-guidelines/tvos)
- [Создание Rich Media контента](/ru/product/content/rich-media)