snap_reels 2.3.3
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-сборке Android —
Videowidget из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-forgetCacheManager.downloadAndCacheдля thumbnail'ов в окне[currentIndex − thumbnailPreloadBehind; currentIndex + thumbnailPreloadAhead]. Дефолт+5/-2покрывает типичный burst-свайп без перегрузки disk LRU. - Невозможно было обработать сбой загрузки thumbnail на стороне host'а —
CachedThumbnailмолча падал вfallbackwidget'у при 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 URLCachedThumbnailзовёт новыйCacheManager.linkCachedUrl(primary, fallback), который создаёт alias-запись на тот жеfilePath. Повторный mount отдаёт картинку синхронно из памяти.
New API #
ReelConfig.thumbnailProxyUrlBuilder—String? Function(ReelModel reel)?, defaultnull. Возвратnullсохраняет первичный URL.ReelConfig.thumbnailLoadTimeout—Duration, default3s. Без эффекта когдаthumbnailProxyUrlBuilderне задан.PreloadConfig.thumbnailPreloadAhead/thumbnailPreloadBehind—int, default5/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-controlsIconButton'ы, 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 == truebuffering-индикатор не показывается, даже если стрим буферизации продолжает тикать.
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 потребителя без изменений, толькоwin32bump и повышенные минимумы 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заменены__на_(новый lintunnecessary_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_kit —
video_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/seekreel_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:
nextpreload выполняется первым (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/PreloadConfig→cache_config.dart,StreamingConfig→streaming_config.dart,VideoPlayerConfig→video_player_config.dart,ProgressIndicatorConfig→progress_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 onReelController— animate a partial scroll to preview the next reel and snap back, useful for onboarding hints
1.1.0 #
New Features #
- Thumbnail preview: show
thumbnailUrlas background image while video loads, replacing black screen with a smooth visual transition
1.0.0 #
Fork & Rename #
- Forked from flutter_awesome_reels by wailashraf71
- Published as
snap_reels— maintained independently
New Features #
appendReels()method onReelController— append new reels without reinitializing the controlleronReportTap,onBlockTap,onCopyLinkTapcallbacks inReelConfigwith customizable labels (reportLabel,blockLabel,copyLinkLabel)showCommentButtonparameter inReelConfig— 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_plusto ^12.0.0,connectivity_plusto ^7.0.0,device_info_plusto ^12.0.0,wakelock_plusto ^1.4.0 - Replaced deprecated
activeColorwithactiveThumbColorin 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
onPressandonLongPressevent 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.opaquefor better responsiveness - Smooth Animations: Multiple animation controllers for professional feel
- Performance Optimizations: Efficient
ValueListenableBuilderandLayoutBuilderusage
🚀 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 deprecatedwithOpacity() - 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.