snap_reels 2.3.3 copy "snap_reels: ^2.3.3" to clipboard
snap_reels: ^2.3.3 copied to clipboard

A powerful, customizable Flutter widget for creating TikTok/Instagram-style vertical video reels with advanced features like caching, analytics, and rich interactions.

2.3.3 #

Bug Fixes #

  • Streaming-видео зависало через 1–2 секунды без восстановления. libavformat по умолчанию не переподключается при transient HTTP error / keep-alive close. Перед player.open() теперь выставляется набор streaming-tunables: demuxer-lavf-o=reconnect=1,reconnect_streamed=1,reconnect_on_network_error=1,reconnect_delay_max=2, network-timeout=30, hwdec=auto-safe, force-seekable=yes, cache=yes,cache-secs=10, demuxer-readahead-secs=20. См. media-kit/media-kit#959.

2.3.2 #

Bug Fixes #

  • Видео зависало через 1–2 секунды после старта на release-сборке AndroidVideo widget из media_kit_video рендерился только после первого декодированного кадра (_hasFirstFrame), до этого момента в дереве стоял SizedBox.shrink(). Surface texture для libmpv создаётся вместе с widget'ом, поэтому в release-сборках с быстрым AOT-стартом плеер мог инициализироваться раньше, чем Flutter добавлял Video в дерево, и libmpv оставался без render sink — декодирование первого буфера проходило, дальше playback зависал. Лечилось ручным переходом приложения в background и обратно (Flutter перерисовывал дерево, surface наконец привязывался). Теперь Video всегда в дереве с момента первого build, thumbnail рисуется поверх и скрывается на первом кадре. Соответствует описанию media-kit/media-kit#909.

2.3.1 #

Доводка фичи thumbnail-кэша из 2.3.0: prefetch соседних thumbnail-ов параллельно с видео, hook на host-side fallback URL при сбое первичной загрузки, переиспользование cache-записи между двумя URL'ами одного ресурса.

Bug Fixes #

  • Thumbnail соседних reels не предзагружался — в 2.3.0 CacheManager инициализировался, но _preloadAdjacentVideos тянул в декодер только видео; thumbnail-картинки качались строго в момент mount'а CachedThumbnail. На свайпе пользователь видел fallback-плейсхолдер пока шёл сетевой запрос. Теперь _PreloadManagerMixin параллельно с видео делает fire-and-forget CacheManager.downloadAndCache для thumbnail'ов в окне [currentIndex − thumbnailPreloadBehind; currentIndex + thumbnailPreloadAhead]. Дефолт +5/-2 покрывает типичный burst-свайп без перегрузки disk LRU.
  • Невозможно было обработать сбой загрузки thumbnail на стороне host'аCachedThumbnail молча падал в fallback widget'у при network/decode error, без шанса на ретрай через альтернативный URL. Добавлены ReelConfig.thumbnailProxyUrlBuilder (String? Function(ReelModel)) и ReelConfig.thumbnailLoadTimeout (default 3 сек): если первичный URL не отдал первый кадр за таймаут или упал — CachedThumbnail пересоздаёт future с URL'ом из билдера. Билдер получает ReelModel, чтобы host-приложение могло строить URL по reel.id (например, через свой бэкенд) без парсинга и URL-encode'а оригинала.
  • Повторное открытие просмотренного reel заново уходило на сеть — если первичная загрузка прошла через thumbnailProxyUrlBuilder, cache_index хранил запись только под fallback-ключом. На повторном mount'е _resolvePath(primaryUrl) отдавал cache miss и снова уходил в fallback. Теперь после успеха на fallback URL CachedThumbnail зовёт новый CacheManager.linkCachedUrl(primary, fallback), который создаёт alias-запись на тот же filePath. Повторный mount отдаёт картинку синхронно из памяти.

New API #

  • ReelConfig.thumbnailProxyUrlBuilderString? Function(ReelModel reel)?, default null. Возврат null сохраняет первичный URL.
  • ReelConfig.thumbnailLoadTimeoutDuration, default 3s. Без эффекта когда thumbnailProxyUrlBuilder не задан.
  • PreloadConfig.thumbnailPreloadAhead / thumbnailPreloadBehindint, default 5 / 2. 0/0 отключает prefetch thumbnails полностью.
  • CacheManager.linkCachedUrl(aliasUrl, existingUrl) — создаёт вторую запись в cache index, ссылающуюся на тот же filePath. Файл не копируется.

Breaking Changes #

  • CachedThumbnail конструктор: параметр url: String заменён на reel: ReelModel. Виджету теперь нужен полный ReelModel, чтобы передать его в proxyUrlBuilder. Если в host-приложении использовался CachedThumbnail(url: ..., fallback: ...) напрямую (вне ReelVideoPlayer) — заменить на CachedThumbnail(reel: ..., fallback: ...). Внутри пакета все вызовы (reel_video_player, reel_error_overlay) обновлены.

2.3.0 #

New Features #

  • ReelConfig.httpClient — необязательное поле Dio?, пробрасываемое в CacheManager.initialize(). Позволяет переиспользовать HTTP-клиент хост-приложения (например, с NativeAdapter + CronetEngine), чтобы делить connection pool, TLS session cache и interceptors при prefetch видео и thumbnails.
  • ReelConfig.errorDialogBuilder — кастомизация full-screen error-попапа в overlay. Билдер получает ReelModel текущего reel'а, errorMessage и два колбэка (onRetry, onCancel) — host-приложение может полностью заменить UI на свой дизайн и показать контекст (например, thumbnail) о каком именно видео идёт речь.
  • ReelConfig.bufferingBuilder — кастомизация индикатора буферизации в overlay. Билдер возвращает произвольный виджет вместо дефолтного CircularProgressIndicator с надписью «Buffering...».
  • Новые публичные виджетыReelErrorOverlay и ReelBufferingIndicator вынесены из reel_overlay.dart как переиспользуемые building blocks; билдеры выше вызывают их или пользовательский UI.
  • ReelConfig.thumbnailFallbackBuilder — кастомный виджет-заглушка вместо чёрного Container когда thumbnailUrl пустой или загрузка упала. Билдер получает ReelModel, поэтому host-приложение может показать content-specific placeholder (градиент, иконку, лого, инициалы).
  • Thumbnail идёт через CacheManager — новый внутренний виджет CachedThumbnail заменил Image.network в ReelVideoPlayer. Теперь thumbnail-запросы используют тот же Dio (с native-адаптером/Cronet при соответствующей настройке host-приложения), попадают в общий connection pool и сохраняются на диск по LRU. Ошибки скачивания и декодирования попадают в debugPrint для диагностики.
  • Настраиваемые tap targets без влияния на визуал — пять новых полей в ReelConfig: actionMinTapTargetSize (дефолт 44 — равно прошлому поведению с padding: EdgeInsets.all(8) вокруг 28pt иконки), actionIconSize (дефолт 28), likeButtonSize (дефолт 32), actionSpacing (дефолт 16), hashtagMinTapTargetSize (дефолт 0 — hit area равна тексту, как было). actionMinTapTargetSize и hashtagMinTapTargetSize задают минимальный размер кликабельной области через Container(constraints:, alignment: center) + HitTestBehavior.opaque — визуальный размер иконки/текста при этом не меняется. Дефолты сохраняют обратную совместимость — потребители могут поднять значения до 48/56 для Apple HIG / Material accessibility compliance или плотных UX. Затронутые элементы: action buttons (comment/share/bookmark/download/more) в reel_actions.dart и hashtag-чипы в reel_overlay.dart. Остальные tappable-элементы overlay (bottom-controls IconButton'ы, retry в inline error, Material-диалоги) уже имеют 48pt tap-таргеты встроенно.

Bug Fixes #

  • Инициализация CacheManager — починен латентный баг: поля _dio и _config были объявлены как late и никогда не присваивались, а _isInitialized был final bool = false. Из-за этого любой вызов downloadAndCache реально ничего не кэшировал (ошибки глушились Future.microtask). Теперь CacheManager.instance.initialize() вызывается из ReelController.initialize() с параметрами из ReelConfig, идемпотентен и корректно выставляет _isInitialized.
  • Порядок проверок в ReelController.initialize — валидация пустого списка reels перенесена до вызова MediaKit.ensureInitialized(). Пустой SnapReels(reels: []) больше не требует наличия libmpv на хосте.
  • Thumbnail не перекрывается чёрным Video — до первого декодированного кадра ReelVideoPlayer теперь держит Video скрытым (подписка на player.stream.width). Раньше media_kit рендерил solid-black background поверх thumbnail всё время буферизации и после ошибки.
  • Buffering… больше не рисуется поверх error-диалога — overlay использует if/else if: при hasError == true buffering-индикатор не показывается, даже если стрим буферизации продолжает тикать.

Dependencies #

  • Удалён share_plus — был заявлен в pubspec.yaml, но нигде не использовался в коде пакета.
  • wakelock_plus ^1.5.1 → ^1.6.0 (транзитивно тянет win32 ^6.0.0 и package_info_plus ^10).
  • device_info_plus ^12.4.0 → ^13.0.0 (API потребителя без изменений, только win32 bump и повышенные минимумы SDK).
  • Environment поднят до Dart ^3.10.0, Flutter >=3.38.1 — требование device_info_plus 13.1.0 / wakelock_plus 1.6.0. На flutter 3.41.5 (текущая в CI GameReel) — работает без замечаний.

Maintenance #

  • Добавлен unit-тест cache_manager_test.dart: проверяет идемпотентность initialize() и работоспособность публичного API после инициализации (отсутствие LateInitializationError).
  • В CachedThumbnail.errorBuilder заменены __ на _ (новый lint unnecessary_underscores в Dart ≥3.10).

2.2.0 #

New Features #

  • showHashtags в ReelConfig — управляет отображением хештегов под описанием. По умолчанию true (обратная совместимость). При false блок #hashtag полностью скрывается.

Bug Fixes #

  • SafeArea в контекстном меню_showMoreOptions() bottom sheet теперь обёрнут в SafeArea(top: false). На устройствах с gesture navigation bar (Samsung A54 и др.) нижние пункты меню больше не перекрываются системной панелью.

Maintenance #

  • Обновлены зависимости: connectivity_plus ^7.1.1, lottie ^3.3.3, lints ^6.1.0.

2.1.3 #

Bug Fixes #

  • Фикс "No active player with ID" — при передаче внешнего уже инициализированного ReelController в SnapReels, виджет больше не вызывает initialize() повторно. Двойная инициализация вызывала _resetPool() во время активного preload, что приводило к fatal-ошибке StateError: Bad state: No active player with ID 1 из media_kit.
  • Guard в _preloadVideo и _initializeCurrentVideo — добавлена проверка на пустой пул и disposed-состояние перед работой с Player'ами, предотвращая краш при race condition.

Maintenance #

  • Замена устаревшего flutter_lints на lints: ^5.1.1 (в пакете и в example).
  • Обновлены зависимости: connectivity_plus ^7.1.0, device_info_plus ^12.4.0, share_plus ^12.0.2, mockito ^5.6.4, build_runner ^2.13.1.

2.1.2 #

New Features #

  • contentBottomPadding в ReelConfig — отступ снизу для overlay-контента (автор, лайки, actions). Позволяет поднять контент над tab bar или другими элементами UI.
  • showProgressIndicator теперь работает — параметр существовал в config, но не применялся в overlay. Теперь при false прогресс-бар скрывается, а контент опускается на его место.

2.1.1 #

Performance #

  • Адаптивный размер пула — размер Player-пула теперь определяется автоматически по классу устройства: low — 2, medium — 3, high — 4. На мощных устройствах (Android SDK 31+, iPhone 11+) предзагружаются до 2 видео вперёд.

2.1.0 #

⚠️ Breaking Changes #

  • Миграция на media_kitvideo_player заменён на media_kit + media_kit_video + media_kit_libs_video. Пакет video_player больше не используется. Приложение должно вызвать MediaKit.ensureInitialized() до использования (вызывается автоматически в ReelController.initialize()).
  • Не работает на Android-эмуляторе — media_kit не поддерживает рендеринг текстур на эмуляторе. Тестирование — только на реальных устройствах.

Performance #

  • Player Pool (3 слота) — вместо create/dispose цикла на каждый свайп теперь используется фиксированный пул из 3 Player'ов (prev/current/next). При переключении видео вызывается player.open() на существующем Player'е — hardware-декодер переиспользуется без пересоздания. Устраняет исчерпание пула декодеров и GC-давление при быстром скролле.
  • Slot recycling — при свайпе самый дальний слот автоматически переиспользуется для preload следующего видео. Без dispose/recreate нативных ресурсов.

Architecture #

  • Декомпозиция reel_controller.dart — 770 строк разбиты на 5 part-файлов:
    • _reel_state_mixin.dart — реактивное состояние и геттеры
    • _video_lifecycle_mixin.dart — пул Player'ов, slot assignment, stream-подписки
    • _preload_manager_mixin.dart — preload через slot recycling
    • _playback_mixin.dart — play/pause/volume/seek
    • reel_controller.dart — тонкий оркестратор

Bug Fixes #

  • Фикс гонки _isVideoInitializing — отменённые инициализации (serial mismatch) больше не сбрасывают _isVideoInitializing в finally, что исправляет баг с незагрузкой видео при быстром свайпе через 4-5 страниц.
  • Фикс race condition при реинициализации — пул создаётся один раз, при повторных initialize() выполняется _resetPool() (stop + clear assignments) вместо dispose/recreate, исключая ошибку "Player has been disposed".

Maintenance #

  • Убран video_player из зависимостей.
  • Убран хардкод User-Agent из cache_manager.dart.
  • Убраны VideoPlayerController-методы из cache_manager.dart и streaming_service.dart — пул управляет Player'ами самостоятельно.
  • streaming_service.dart упрощён до resolveStreamingUrl() — только выбор формата (HLS/DASH/MP4), без создания контроллеров.
  • reel_progress_indicator.dart переведён с ValueListenableBuilder<VideoPlayerValue> на Obx с currentPosition/totalDuration.
  • reel_overlay.dart — убраны прямые обращения к VideoPlayerController, используются Rx-геттеры.

2.0.0 #

⚠️ Breaking Changes #

  • AwesomeReels переименован в SnapReels — главный виджет теперь называется SnapReels. Замените все вхождения AwesomeReels(...) на SnapReels(...) в вашем коде.

Deprecations #

  • StreamingConfig.enableAdaptiveBitrate помечен @Deprecated — параметр не имел эффекта и будет удалён в v3.0.0. Просто уберите его из кода.

Performance #

  • SHA-256 cache keys: хэш кэша теперь вычисляется через SHA-256 вместо url.hashCode. Устраняет коллизии и недетерминированность на web-платформе.
  • URL normalization: CDN-токены (token, sig, expires, auth и др.) вырезаются перед хэшированием — одно видео с разными токенами авторизации больше не дублируется в кэше.
  • Memory pressure handling: при системном сигнале нехватки памяти все preloaded контроллеры диспоузятся, memory-кэш очищается. Предотвращает OOM-kill на устройствах с 2–3 GB RAM.
  • Adaptive preload: на слабых устройствах (Android SDK < 28, iPhone < 11 поколения) preloadAhead автоматически снижается до 1, preloadBehind до 0 — экономия ~2 hw-декодеров.
  • Preload prioritization: next preload выполняется первым (await), prev — fire-and-forget, так как 80% скроллов идут вниз.
  • Debounced preload: при быстром скролле preload промежуточных страниц пропускается (debounce 200 мс) — нет лишних init/dispose циклов.
  • Serial-based init cancellation: каждый onPageChanged присваивает уникальный serial; если до конца инициализации страница сменилась снова — инициализация отменяется и контроллер диспоузится. Устраняет баг: после 4-5 быстрых свайпов видео не воспроизводилось, показывался только thumbnail.

Maintenance #

  • Добавлена зависимость crypto: ^3.0.6 для SHA-256.
  • Файл reel_config.dart декомпозирован: CacheConfig/PreloadConfigcache_config.dart, StreamingConfigstreaming_config.dart, VideoPlayerConfigvideo_player_config.dart, ProgressIndicatorConfigprogress_config.dart. Публичное API не изменилось.
  • CacheItem и CacheStats вынесены в models/cache_item.dart.
  • Добавлен DeviceClassifier (utils/device_classifier.dart) с классификацией устройств: low / medium / high.
  • User-Agent изменён с AwesomeReels/1.0.0 на SnapReels/1.3.0.

1.2.0 #

New Features #

  • peekNext() method on ReelController — animate a partial scroll to preview the next reel and snap back, useful for onboarding hints

1.1.0 #

New Features #

  • Thumbnail preview: show thumbnailUrl as background image while video loads, replacing black screen with a smooth visual transition

1.0.0 #

Fork & Rename #

New Features #

  • appendReels() method on ReelController — append new reels without reinitializing the controller
  • onReportTap, onBlockTap, onCopyLinkTap callbacks in ReelConfig with customizable labels (reportLabel, blockLabel, copyLinkLabel)
  • showCommentButton parameter in ReelConfig — conditionally show/hide comment button

Bug Fixes #

  • Fixed hardware video decoder exhaustion: dispose far-away preloaded VideoPlayerControllers during scroll, keeping max 3 alive (previous, current, next)

Maintenance #

  • Updated share_plus to ^12.0.0, connectivity_plus to ^7.0.0, device_info_plus to ^12.0.0, wakelock_plus to ^1.4.0
  • Replaced deprecated activeColor with activeThumbColor in example app
  • Fixed string interpolation in ReelModel.toString()

0.0.5 #

🎨 Example App Redesign #

  • Modern blue-gradient theme for Home and Playground screens
  • New gradient feature cards, decorative orbs, and improved typography
  • Refreshed buttons and section cards with professional look-and-feel

🔧 Core Playback Improvements #

  • Ensure only a single video plays at a time when switching reels
  • Pause and detach previous controller on page change and controller switch
  • Preloaded controllers are initialized paused to prevent background audio
  • Pause off-screen reels via visibility detection

🐛 Fixes #

  • Mitigated black-screen-with-audio by guarding rendering until valid video size
  • Cleaned up controller listeners on dispose/switch
  • Replaced deprecated Color.withOpacity with Color.withValues

0.0.4 #

  • Updated README.md to reflect new features and usage examples

0.0.3 #

⚠️ Breaking Changes #

  • Multi-Format Video Support: Plugin now supports HLS, MPEG-DASH, and MP4 video sources. This may require changes to your video URLs and backend delivery.
  • New Event Callbacks: Added onPress and onLongPress event callbacks for advanced interaction handling. Update your widget usage to handle these events if needed.

🎯 Major Progress Bar Overhaul #

  • Perfect Seeking Logic: Complete redesign of video seeking functionality

    • Tap anywhere on progress bar for instant seeking
    • Smooth drag-to-seek with real-time preview
    • Release-to-seek mechanism for better user control
    • Maintains playback state correctly (pause during drag, resume after)
  • Enhanced Draggable Thumb: Professional circular progress indicator

    • Animated circular dot that grows during interaction
    • Proper positioning using LayoutBuilder for accuracy
    • Visual feedback with shadows, borders, and smooth animations
    • 60px hit area for much easier touch interaction
  • Live Thumbnail Preview: Instagram/TikTok-style seeking preview

    • Shows preview window above progress bar during drag
    • Displays current time position in real-time
    • Smart positioning to stay within screen bounds
    • Elegant animations with scale and opacity effects
  • Production-Ready Video Controller: Robust video management system

    • Index-based controller tracking instead of unreliable ID-based system
    • Preloading and caching for instant video transitions
    • Enhanced error handling with retry logic
    • Optimized memory management and disposal

🎨 UI/UX Improvements #

  • Better Visual Design: Light grey progress bar background for improved visibility
  • Responsive Touch Areas: Increased hit areas with HitTestBehavior.opaque for better responsiveness
  • Smooth Animations: Multiple animation controllers for professional feel
  • Performance Optimizations: Efficient ValueListenableBuilder and LayoutBuilder usage

🚀 Crash Prevention & Stability #

  • Removed All Loading Indicators: Eliminated stuck "loading..." states
  • Robust Error Recovery: Comprehensive error handling prevents crashes
  • Controller Lifecycle Management: Proper initialization and disposal
  • Video State Tracking: Accurate playback state management

🔧 Technical Improvements #

  • Flutter Analyze Clean: Fixed all critical errors and warnings
  • Memory Optimizations: Efficient animation controller management
  • Gesture Detection: Enhanced touch responsiveness and interaction
  • Code Quality: Improved error handling and state management

🗑️ Removed #

  • Loading Indicators: Removed all loading widgets that caused UI blocks
  • Deprecated Dependencies: Updated to use withValues() instead of deprecated withOpacity()
  • Complex Progress Classes: Simplified to essential, optimized components

🐛 Bug Fixes #

  • Fixed thumb not moving during progress bar interaction
  • Resolved thumbnail preview not showing during seek
  • Improved drag sensitivity and touch responsiveness
  • Fixed video controller initialization timing issues
  • Corrected progress calculation and positioning bugs

0.0.2 #

🚀 New Features #

  • Long-press Controls: Added long-press to pause/play functionality with proper state tracking
  • Intelligent Retry System: Enhanced video loading with exponential backoff and automatic cache clearing on failures
  • Configuration Enhancements: Added new ReelConfig options:
    • bookmarkInMoreMenu - Move bookmark button to more menu (default: true)
    • downloadInMoreMenu - Move download button to more menu (default: true)
    • followButtonColor - Configurable follow button color (default: white)
    • followingButtonColor - Color when user is following (default: white70)
  • Improved UI Organization: Better button placement with configurable more menu options
  • Enhanced Comment System: Redesigned comment bottom sheet with improved UI and keyboard handling
  • Live Preview Playground: Added mini reels player in playground screen for real-time configuration testing

🔧 Improvements #

  • Follow Button Styling: Updated to use configurable colors instead of fixed accent color
  • Error Handling: Better retry logic with cache management for failed video loads
  • Comment Interface: Removed external dialog dependency, improved native comment experience
  • Code Organization: Cleaned up duplicate imports and optimized widget structure

🗑️ Removed #

  • Premium Features: Removed premium-only features to maintain open-source nature
  • External Dependencies: Reduced reliance on external dialog packages

🐛 Bug Fixes #

  • Fixed loading overlay persistence issues
  • Improved video state management during long-press interactions
  • Better handling of video controller lifecycle

0.0.1 #

  • Initial release: TikTok/Instagram-style vertical video reels widget with caching, analytics, and rich interactions.
3
likes
150
points
381
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A powerful, customizable Flutter widget for creating TikTok/Instagram-style vertical video reels with advanced features like caching, analytics, and rich interactions.

Repository (GitHub)
View/report issues
Contributing

License

MIT (license)

Dependencies

connectivity_plus, crypto, device_info_plus, dio, flutter, font_awesome_flutter, get, iconly, like_button, lottie, media_kit, media_kit_libs_video, media_kit_video, path_provider, visibility_detector, wakelock_plus

More

Packages that depend on snap_reels