# Справочник Flutter SDK 0.24.0

Основной импорт — `package:gravity_sdk/gravity_sdk.dart`. Клиент — `GravitySDK.instance`. Полная документация типов: [API Reference опубликованного пакета](https://pub.dev/documentation/gravity_sdk/0.24.0/).

## Инициализация и настройки

```dart
Future<void> initialize({
  required String apiKey,
  required String section,
  ProductWidgetBuilder? productWidgetBuilder,
  GravityEventCallback? gravityEventCallback,
  GravityContentCallback? gravityContentCallback,
  LogLevel logLevel = LogLevel.info,
});

void setOptions({
  Options? options,
  ContentSettings? contentSettings,
  String? proxyUrl,
  bool? isFetchContentOnTrack,
  OfflineQueueSettings? offlineQueue,
  Duration? staleContentTimeout,
});
```

Это сигнатуры для справки, а не исполняемый фрагмент приложения. Значения по умолчанию и поведение параметров — [Конфигурация](./configuration.md).

## Идентификация и разрешения

| Сигнатура | Поведение |
|---|---|
| `void setUser(String userId, String sessionId)` | Задать внешний ID и управляемую приложением сессию |
| `Future<void> resetUser()` | Сбросить идентификацию и сессию; очередь не очищать |
| `Future<String?> getUserId()` | Прочитать серверный UID; может ждать инициализацию сессии |
| `void setUserIdListener(void Function(String? uid)? listener)` | Один listener изменений UID, `null` снимает |
| `Future<void> restoreUserId(String uid)` | Восстановить серверный UID; сбросить сессию и ручного пользователя |
| `void setNotificationPermissionStatus(NotificationPermissionStatus status)` | Задать `granted` / `denied` / `unknown` |

`getUserId()`, `setUserIdListener()` и `restoreUserId()` доступны до `initialize()`. Примеры и сценарии выхода: [Идентификация](./identity.md).

## Просмотры и события

```dart
Future<void> trackView({
  required BuildContext context,
  required PageContext pageContext,
});

Future<void> triggerEvent({
  required BuildContext context,
  required List<TriggerEvent> events,
  required PageContext pageContext,
});

Future<GravityDataResponse<ContentResponse>?> trackViewNoShow({
  required PageContext pageContext,
});

Future<GravityDataResponse<ContentResponse>?> triggerEventNoShow({
  required List<TriggerEvent> events,
  required PageContext pageContext,
});
```

Обычные методы могут показывать in-app; `NoShow` возвращает данные без UI. Флаг `isFetchContentOnTrack` применяется только к `NoShow`.

## Получение контента

Все методы ниже требуют `PageContext` и поддерживают необязательные `List<RtRule>? rules`:

| Метод и обязательный параметр | Возвращаемый тип |
|---|---|
| `getContentBySelector({required String selector, required PageContext pageContext, List<RtRule>? rules})` | `Future<ContentResponse>` |
| `getContentByCampaignId({required String campaignId, required PageContext pageContext, List<RtRule>? rules})` | `Future<ContentResponse>` |
| `getContentByGroup({required String group, required PageContext pageContext, List<RtRule>? rules})` | `Future<ContentResponse>` |
| `getContentBySelectorWithDetails({required String selector, required PageContext pageContext, List<RtRule>? rules})` | `Future<GravityDataResponse<ContentResponse>>` |
| `getContentByCampaignIdWithDetails({required String campaignId, required PageContext pageContext, List<RtRule>? rules})` | `Future<GravityDataResponse<ContentResponse>>` |

Методы `WithDetails` также вызывают глобальный `gravityContentCallback`. Ошибки запроса пробрасываются в вызывающий код.

В обычных selector-запросах SDK использует батчинг/дедупликацию совместимых конкурентных запросов. `WithDetails` обращается напрямую за полным JSON; не считайте его поведение по числу запросов идентичным обычному selector-методу.

## Ответы и переменные

| Тип/поле | Содержание |
|---|---|
| `GravityDataResponse<T>` | `T data` и `Map<String, dynamic> json` |
| `ContentResponse` | `User user` и `List<Campaign> data` |
| `Campaign` | `String? selector` и `List<CampaignVariation> payload` |
| `CampaignVariation` | `campaignId`, `experienceId`, `variationId`, `decisionId` и `List<CampaignContent> contents` |
| `CampaignContent` | `contentId`, `deliveryMethod`, `variables`, `products`, `events`, `placeholderId`, `custom`, `step` |
| `content.rawVariables` | `Map<String, dynamic>` с полным исходным объектом variables |
| `content.variables[key]` | `Object?`; без преобразования типа |
| `content.variables.valueOf<T>(key)` | `T?`; `null` при отсутствии или несовпадении типа |
| `Slot` | Карта `item`, `fallback`, `strId`, nullable `slotId` и product `events` |

`step == null` определяет корневой контент. Для engagement передавайте исходные объекты ответа, не DTO, собранные из отдельных идентификаторов.

## События TriggerEvent

У всех событий доступны `Map<String, String>? customProps` и `DateTime? eventTime`.

| Событие | Обязательные поля | Необязательные поля |
|---|---|---|
| `AddToCartEvent` | `double value`, `String productId`, `int quantity` | `currency`, `cart` |
| `RemoveFromCartEvent` | `value`, `productId`, `quantity` | `currency`, `cart` |
| `PurchaseEvent` | `String uniqueTransactionId`, `double value`, `List<CartItem> cart` | `currency` |
| `SyncCartEvent` | `double value` | `currency`, `cart` |
| `AddToWishlistEvent` | `double value`, `String productId` | — |
| `LoginEvent` / `SignUpEvent` | В конструкторе нет; сервер требует идентификатор | `hashedEmail`, `cuid`, `cuidType` |
| `CustomEvent` | `String type`, `String name` | `cuid`, `cuidType`, `cart` |

`CartItem` требует `String productId`, `int quantity` и `double itemPrice`. Примеры: [Контекст и события](./events.md).

## Engagement и tracking URL

```dart
void sendContentEngagement(ContentEngagement engagement);
void sendProductEngagement(ProductEngagement engagement);
Future<void> triggerTrackingUrl(String url);
```

Content engagement: `ContentImpressionEngagement`, `ContentVisibleImpressionEngagement`, `ContentClickEngagement`, `ContentCloseEngagement` — каждый принимает `(CampaignContent content, Campaign campaign)`.

Product engagement: `ProductClickEngagement`, `ProductVisibleImpressionEngagement` — принимают `(Slot slot, CampaignContent content, Campaign campaign)`.

`triggerTrackingUrl()` отправляет предоставленный URL, но не рисует UI и не сохраняет его в постоянной очереди. В SDK-интеграции предпочитайте типизированный engagement. [Кто отправляет аналитику](./campaigns.md#кто-отправляет-engagement).

## Callback

```dart
typedef GravityEventCallback = void Function(TrackingEvent event);
typedef GravityContentCallback =
    void Function(GravityDataResponse<ContentResponse> response);
```

`TrackingEvent` включает `ContentLoadEvent`, `ContentImpressionEvent`, `ContentVisibleImpressionEvent`, `ContentCloseEvent`, `CopyEvent`, `CancelEvent`, `FollowUrlEvent`, `FollowDeeplinkEvent`, `RequestPushEvent` и `ProductImpressionEvent`. События содержат `campaign` и соответствующие объекты контента/товара.

У `FollowUrlEvent` есть `url` и `FollowUrlType type` (`browser` или `webview`; по умолчанию `browser`); у `FollowDeeplinkEvent` — `deeplink`; у `CopyEvent` — `copiedValue`. Для ручного `ContentClickEngagement` отдельного click-callback нет.

## Виджеты и показ

| API | Основные параметры |
|---|---|
| `GravityInlineWidget` | Обязательные `selector`, `pageContext`; `placeholderId`, `width`, `height`, `showLoading = true`, `loadingWidget`, `backgroundColor`, `onLoaded`, `rules` |
| `GravityInlineListWidget` | Обязательные `group`, `pageContext`; `height`, `showLoading = true`, `loadingWidget`, `showIndicator = true`, цвета индикаторов |
| `GravityAnchor` | Обязательные `selector` и `builder`; необязательный `pageContext` |
| `ProductWidgetBuilder.build()` | Обязательные именованные `context`, `Slot product`, `CampaignContent content`, `Campaign campaign`; возвращает `Widget` |
| `fetchAnchorContent({required BuildContext context, required String selector, PageContext? pageContext})` | `Future<void>`; требует существующий якорь |

`GravityAnchorBuilder` — `Widget Function(BuildContext context, VoidCallback onReady)`. При отсутствии контекста у `fetchAnchorContent` используется `OTHER` с пустыми data/location. Для корректного таргетинга задавайте свой контекст.

`openStep()` используется встроенным рендерером для перехода к дополнительному контенту кампании. Для типовой интеграции форм и многошаговых кампаний вызывать его из приложения не требуется.

## Presentation lock

`void lockPresentation()`, `void unlockPresentation()`, `bool get isPresentationLocked` и `void setPresentationLockListener(void Function(bool locked)? listener)`.

Доступны до инициализации. Не блокируют inline, tooltip и собственный UI. [Поведение и серверные лимиты](./configuration.md#блокировка-автопоказа).

## Очередь

`Future<void> flushQueue()`, `Future<void> clearQueue()` и `Future<int> get pendingDeliveries` требуют инициализацию.

`OfflineQueueSettings`: `enabled = true`, `maxEntries = 500`, `maxAge = Duration(days: 7)`. [Поведение при ошибках](./offline.md).
