Mobile SDK для Flutter на iOS
Проверенная пара: shopstory_player_flutter 0.2.0-preview.3 и ShopStoryPlayerSDK 0.2.0-preview.2. Документированный baseline — Flutter 3.24.5 / Dart 3.5.4, iOS 15+ и Xcode 16+. Android adapter в эту поставку не входит.
Установить adapter
Получите read-only доступ к Flutter и native пакетам. В pubspec.yaml добавьте Git dependency с URL из выданной инструкции и ref: 0.2.0-preview.3. Сохраните pubspec.lock и native lockfile.
Для Flutter 3.24 используется CocoaPods; точный native pin указан в инструкции adapter. Для проекта с включённым Swift Package Manager используйте настройки из той же версии. Не меняйте способ подключения всего приложения ради примера.
После установки выполните flutter pub get и сборку iOS. Доступ к приватным зависимостям должен работать и на машине разработчика, и в CI.
Запустить starter
Скачать Flutter starter. README содержит команды генерации iOS host, подключения локальной копии adapter и запуска с --dart-define. Проект не содержит клиентских идентификаторов.
Передайте выданные applicationId и тестовый feedProductId. Для товара с видео должен появиться SDK preview; его нажатие открывает player. Товар без видео оставляет обычную PDP. Product action открывает PDP приложения, а не подтверждает корзину.
Подключить приложение
final shopStory = ShopStoryPlayerFlutter.instance;
var shopStoryConfigured = false;
if (shopStory.isSupportedPlatform) {
try {
await shopStory.configure(applicationId: applicationId);
shopStoryConfigured = true;
} catch (error, stackTrace) {
FlutterError.reportError(
FlutterErrorDetails(exception: error, stack: stackTrace),
);
}
}
final observer = ShopStoryNavigatorObserver(
surfaceForRoute: mapRouteToShopStorySurface,
);
Future<ShopStoryProductActionResult> openNativeProduct(
ShopStoryProductAction action,
) async {
final id = action.payload.feedProductId;
if (id == null || id.trim().isEmpty) {
return const ShopStoryProductActionFailed(
ShopStoryProductActionFailureReason.invalidPayload,
);
}
final accepted = await openProductByFeedId(id);
return accepted
? const ShopStoryProductActionOpenedProduct()
: const ShopStoryProductActionFailed(
ShopStoryProductActionFailureReason.operationFailed,
);
}
final productActionRegistration = shopStoryConfigured
? shopStory.registerProductActionHandlers(
onOpenProduct: openNativeProduct,
onAddProduct: openNativeProduct,
)
: null;
MaterialApp(
navigatorObservers: shopStoryConfigured ? [observer] : [],
home: const AppRoot(),
);
final productScreen = shopStoryConfigured
? ShopStoryProductDetailScope(
feedProductId: product.feedProductId,
child: ProductDetailView(product: product),
)
: ProductDetailView(product: product);
Один root Navigator должен использовать observer. Для declarative router, tabs и nested navigator передавайте текущую поверхность из существующего state owner через setCurrentSurface.
До открытия ShopStory UI зарегистрируйте обработчики в integration root. В примере оба действия открывают нативную PDP: у onAddProduct нет автоматического перехода через onOpenProduct. Если поступившее действие не имеет обработчика, адаптер отклоняет его.
openProductByFeedId принадлежит приложению и возвращает true, когда router принял переход. Не ожидайте закрытия открытой страницы: например, Future из Navigator.push завершается после возврата с неё. Возвращайте ShopStoryProductActionOpenedProduct после принятого перехода. Для прямой корзины замените onAddProduct отдельным обработчиком и возвращайте ShopStoryProductActionSucceeded только после подтверждения cart-команды. Регистрацию удерживает root owner; при его освобождении вызовите productActionRegistration?.dispose().
Следующий шаг
Проверьте lifecycle и выпуск и аналитику приложения.