tss_video_glimpse 0.1.6 copy "tss_video_glimpse: ^0.1.6" to clipboard
tss_video_glimpse: ^0.1.6 copied to clipboard

Cross-platform Flutter package for video previews from network, assets, and Firebase Storage with smart caching.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:tss_video_glimpse/tss_video_glimpse.dart';

void main() {
  runApp(const TssVideoGlimpseExampleApp());
}

/// Comprehensive example app demonstrating all features of TSS Video Glimpse.
///
/// This app showcases:
/// - Network video previews
/// - Different quality settings
/// - Grid layouts
/// - Custom styling
/// - Error handling
/// - Controller usage
/// - Responsive design
class TssVideoGlimpseExampleApp extends StatelessWidget {
  /// Creates the example app.
  const TssVideoGlimpseExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'TSS Video Glimpse Examples',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(
          seedColor: Colors.deepPurple,
          brightness: Brightness.light,
        ),
        useMaterial3: true,
        cardTheme: const CardThemeData(
          elevation: 2,
          shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.all(Radius.circular(12)),
          ),
        ),
      ),
      home: const VideoGlimpseHomePage(),
    );
  }
}

/// Home page with navigation to different example screens
class VideoGlimpseHomePage extends StatelessWidget {
  const VideoGlimpseHomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('TSS Video Glimpse Examples'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildWelcomeCard(context),
          const SizedBox(height: 16),
          _buildExampleCard(
            context,
            title: 'Basic Examples',
            description: 'Simple video previews with different sources',
            icon: Icons.video_library,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const BasicExamplesPage(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Advanced Styling',
            description: 'Custom placeholders, error widgets, and styling',
            icon: Icons.palette,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const AdvancedStylingPage(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Grid Layouts',
            description: 'Video galleries and grid views',
            icon: Icons.grid_view,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const GridLayoutsPage(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Controller Usage',
            description: 'Advanced control with TssVideoGlimpseController',
            icon: Icons.control_camera,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const ControllerExamplePage(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'Quality Comparison',
            description: 'Compare different quality settings',
            icon: Icons.high_quality,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const QualityComparisonPage(),
              ),
            ),
          ),
          _buildExampleCard(
            context,
            title: 'YouTube Examples',
            description: 'YouTube video previews and playback',
            icon: Icons.play_circle_filled,
            onTap: () => Navigator.push(
              context,
              MaterialPageRoute(
                builder: (context) => const YoutubeExamplesPage(),
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildWelcomeCard(BuildContext context) {
    return Card(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(
                  Icons.video_collection,
                  size: 32,
                  color: Theme.of(context).colorScheme.primary,
                ),
                const SizedBox(width: 12),
                const Text(
                  'TSS Video Glimpse',
                  style: TextStyle(
                    fontSize: 24,
                    fontWeight: FontWeight.bold,
                  ),
                ),
              ],
            ),
            const SizedBox(height: 12),
            Text(
              'A powerful cross-platform Flutter package for generating stunning video previews.',
              style: TextStyle(
                fontSize: 14,
                color: Colors.grey.shade700,
              ),
            ),
            const SizedBox(height: 16),
            Wrap(
              spacing: 8,
              runSpacing: 8,
              children: [
                _buildFeatureChip(Icons.cloud, 'Network URLs'),
                _buildFeatureChip(Icons.folder, 'Local Assets'),
                _buildFeatureChip(Icons.cloud_upload, 'Firebase Storage'),
                _buildFeatureChip(Icons.cached, 'Smart Caching'),
                _buildFeatureChip(Icons.devices, 'Cross-Platform'),
              ],
            ),
          ],
        ),
      ),
    );
  }

  Widget _buildFeatureChip(IconData icon, String label) {
    return Chip(
      avatar: Icon(icon, size: 16),
      label: Text(label, style: const TextStyle(fontSize: 12)),
      padding: const EdgeInsets.symmetric(horizontal: 4),
    );
  }

  Widget _buildExampleCard(
    BuildContext context, {
    required String title,
    required String description,
    required IconData icon,
    required VoidCallback onTap,
  }) {
    return Card(
      child: ListTile(
        leading: Icon(
          icon,
          size: 32,
          color: Theme.of(context).colorScheme.primary,
        ),
        title: Text(
          title,
          style: const TextStyle(fontWeight: FontWeight.bold),
        ),
        subtitle: Text(description),
        trailing: const Icon(Icons.arrow_forward_ios, size: 16),
        onTap: onTap,
      ),
    );
  }
}

/// Basic examples page showing simple video previews
class BasicExamplesPage extends StatelessWidget {
  const BasicExamplesPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Basic Examples'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildSection(
            'Network Video',
            'Load video from a network URL with default settings',
            const TssVideoGlimpse(
              videoUrl:
                  'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
              width: double.infinity,
              height: 200,
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Different Aspect Ratio',
            'Video preview with 16:9 aspect ratio',
            const TssVideoGlimpse(
              videoUrl:
                  'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ElephantsDream.mp4',
              width: double.infinity,
              height: 250,
              fit: BoxFit.contain,
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Compact Preview',
            'Smaller preview for thumbnails',
            const Row(
              children: [
                Expanded(
                  child: TssVideoGlimpse(
                    videoUrl:
                        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
                    width: 150,
                    height: 100,
                  ),
                ),
                SizedBox(width: 12),
                Expanded(
                  child: TssVideoGlimpse(
                    videoUrl:
                        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4',
                    width: 150,
                    height: 100,
                  ),
                ),
              ],
            ),
          ),
          const SizedBox(height: 24),
          _buildInfoCard(),
        ],
      ),
    );
  }

  Widget _buildSection(String title, String description, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 4),
        Text(
          description,
          style: TextStyle(
            fontSize: 14,
            color: Colors.grey.shade600,
          ),
        ),
        const SizedBox(height: 12),
        child,
      ],
    );
  }

  Widget _buildInfoCard() {
    return Card(
      color: Colors.blue.shade50,
      child: const Padding(
        padding: EdgeInsets.all(16),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Row(
              children: [
                Icon(Icons.info_outline, color: Colors.blue),
                SizedBox(width: 8),
                Text(
                  'Pro Tip',
                  style: TextStyle(
                    fontSize: 16,
                    fontWeight: FontWeight.bold,
                    color: Colors.blue,
                  ),
                ),
              ],
            ),
            SizedBox(height: 8),
            Text(
              'Videos are automatically cached for faster loading on subsequent views. '
              'The default cache duration is 7 days, but you can customize it using the cacheMaxAge parameter.',
              style: TextStyle(fontSize: 14),
            ),
          ],
        ),
      ),
    );
  }
}

/// Advanced styling examples page
class AdvancedStylingPage extends StatelessWidget {
  const AdvancedStylingPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Advanced Styling'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildSection(
            'Custom Placeholder',
            'Beautiful gradient placeholder with custom loading indicator',
            TssVideoGlimpse(
              videoUrl:
                  'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
              width: double.infinity,
              height: 200,
              placeholder: Container(
                decoration: BoxDecoration(
                  gradient: LinearGradient(
                    begin: Alignment.topLeft,
                    end: Alignment.bottomRight,
                    colors: [
                      Colors.blue.shade300,
                      Colors.purple.shade300,
                    ],
                  ),
                  borderRadius: BorderRadius.circular(12),
                ),
                child: const Center(
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      CircularProgressIndicator(
                        valueColor: AlwaysStoppedAnimation<Color>(Colors.white),
                      ),
                      SizedBox(height: 12),
                      Text(
                        'Loading amazing content...',
                        style: TextStyle(
                          color: Colors.white,
                          fontSize: 14,
                          fontWeight: FontWeight.w500,
                        ),
                      ),
                    ],
                  ),
                ),
              ),
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Custom Error Widget',
            'Friendly error message with retry suggestion',
            TssVideoGlimpse(
              videoUrl: 'https://invalid-url-for-demo.com/video.mp4',
              width: double.infinity,
              height: 200,
              errorWidget: const Center(
                child: Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    SizedBox(height: 12),
                    Text(
                      'Oops! Video unavailable',
                      style: TextStyle(
                        fontSize: 16,
                        fontWeight: FontWeight.bold,
                      ),
                    ),
                    SizedBox(height: 4),
                    Text(
                      'Please check your connection',
                      style: TextStyle(fontSize: 12),
                    ),
                  ],
                ),
              ),
              onError: (error) {
                debugPrint('Video loading error: $error');
              },
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Rounded Corners',
            'Video preview with custom border radius',
            ClipRRect(
              borderRadius: BorderRadius.circular(20),
              child: const TssVideoGlimpse(
                videoUrl:
                    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4',
                width: double.infinity,
                height: 200,
                fit: BoxFit.cover,
              ),
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSection(String title, String description, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 4),
        Text(
          description,
          style: TextStyle(
            fontSize: 14,
            color: Colors.grey.shade600,
          ),
        ),
        const SizedBox(height: 12),
        child,
      ],
    );
  }
}

/// Grid layouts page showing video galleries
class GridLayoutsPage extends StatelessWidget {
  const GridLayoutsPage({super.key});

  static const videoUrls = [
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerBlazes.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerEscapes.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerFun.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerJoyrides.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/ForBiggerMeltdowns.mp4',
    'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/Sintel.mp4',
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Grid Layouts'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          const Text(
            '2-Column Grid',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.bold,
            ),
          ),
          const SizedBox(height: 12),
          GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 2,
              crossAxisSpacing: 12,
              mainAxisSpacing: 12,
              childAspectRatio: 16 / 9,
            ),
            itemCount: 4,
            itemBuilder: (context, index) {
              return ClipRRect(
                borderRadius: BorderRadius.circular(12),
                child: TssVideoGlimpse(
                  videoUrl: videoUrls[index],
                  width: double.infinity,
                  height: double.infinity,
                  fit: BoxFit.cover,
                  quality: TssVideoQuality.medium,
                ),
              );
            },
          ),
          const SizedBox(height: 24),
          const Text(
            '3-Column Grid',
            style: TextStyle(
              fontSize: 20,
              fontWeight: FontWeight.bold,
            ),
          ),
          const SizedBox(height: 12),
          GridView.builder(
            shrinkWrap: true,
            physics: const NeverScrollableScrollPhysics(),
            gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
              crossAxisCount: 3,
              crossAxisSpacing: 8,
              mainAxisSpacing: 8,
              childAspectRatio: 1,
            ),
            itemCount: 6,
            itemBuilder: (context, index) {
              return ClipRRect(
                borderRadius: BorderRadius.circular(8),
                child: TssVideoGlimpse(
                  videoUrl: videoUrls[index],
                  width: double.infinity,
                  height: double.infinity,
                  fit: BoxFit.cover,
                  quality: TssVideoQuality.low,
                ),
              );
            },
          ),
        ],
      ),
    );
  }
}

/// Controller example page showing advanced control
class ControllerExamplePage extends StatefulWidget {
  const ControllerExamplePage({super.key});

  @override
  State<ControllerExamplePage> createState() => _ControllerExamplePageState();
}

class _ControllerExamplePageState extends State<ControllerExamplePage> {
  late TssVideoGlimpseController _controller;
  bool _isInitialized = false;

  @override
  void initState() {
    super.initState();
    _controller = TssVideoGlimpseController(
      videoUrl:
          'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4',
      quality: TssVideoQuality.high,
    );
    _initializeController();
  }

  Future<void> _initializeController() async {
    final success = await _controller.initialize();
    if (mounted) {
      setState(() {
        _isInitialized = success;
      });
      if (!success) {
        ScaffoldMessenger.of(context).showSnackBar(
          SnackBar(
            content: Text('Failed to load video: ${_controller.error}'),
            backgroundColor: Colors.red,
          ),
        );
      }
    }
  }

  @override
  void dispose() {
    _controller.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('Controller Usage'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: Column(
        children: [
          Expanded(
            child: Center(
              child: Padding(
                padding: const EdgeInsets.all(16),
                child: TssVideoGlimpse.controller(
                  controller: _controller,
                  width: double.infinity,
                  height: 300,
                ),
              ),
            ),
          ),
          if (_isInitialized) ...[
            Padding(
              padding: const EdgeInsets.all(16),
              child: Column(
                children: [
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton.icon(
                        onPressed: () => _controller.play(),
                        icon: const Icon(Icons.play_arrow),
                        label: const Text('Play'),
                      ),
                      const SizedBox(width: 12),
                      ElevatedButton.icon(
                        onPressed: () => _controller.pause(),
                        icon: const Icon(Icons.pause),
                        label: const Text('Pause'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 12),
                  Row(
                    mainAxisAlignment: MainAxisAlignment.center,
                    children: [
                      ElevatedButton.icon(
                        onPressed: () =>
                            _controller.seekTo(const Duration(seconds: 0)),
                        icon: const Icon(Icons.skip_previous),
                        label: const Text('Start'),
                      ),
                      const SizedBox(width: 12),
                      ElevatedButton.icon(
                        onPressed: () =>
                            _controller.seekTo(const Duration(seconds: 10)),
                        icon: const Icon(Icons.forward_10),
                        label: const Text('10s'),
                      ),
                    ],
                  ),
                  const SizedBox(height: 16),
                  Card(
                    child: Padding(
                      padding: const EdgeInsets.all(16),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        children: [
                          const Text(
                            'Controller Info',
                            style: TextStyle(
                              fontSize: 16,
                              fontWeight: FontWeight.bold,
                            ),
                          ),
                          const SizedBox(height: 8),
                          Text('Source: ${_controller.sourceType.name}'),
                          Text('Quality: ${_controller.quality.name}'),
                          Text('Initialized: ${_controller.isInitialized}'),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ],
        ],
      ),
    );
  }
}

/// Quality comparison page
class QualityComparisonPage extends StatelessWidget {
  const QualityComparisonPage({super.key});

  @override
  Widget build(BuildContext context) {
    const videoUrl =
        'https://commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4';

    return Scaffold(
      appBar: AppBar(
        title: const Text('Quality Comparison'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildQualitySection(
            'Low Quality',
            'Faster loading, lower memory usage. Best for lists and grids.',
            const TssVideoGlimpse(
              videoUrl: videoUrl,
              width: double.infinity,
              height: 200,
              quality: TssVideoQuality.low,
            ),
          ),
          const SizedBox(height: 24),
          _buildQualitySection(
            'Medium Quality',
            'Balanced performance and quality. Default setting.',
            const TssVideoGlimpse(
              videoUrl: videoUrl,
              width: double.infinity,
              height: 200,
              quality: TssVideoQuality.medium,
            ),
          ),
          const SizedBox(height: 24),
          _buildQualitySection(
            'High Quality',
            'Best quality, higher memory usage. Best for detail views.',
            const TssVideoGlimpse(
              videoUrl: videoUrl,
              width: double.infinity,
              height: 200,
              quality: TssVideoQuality.high,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildQualitySection(String title, String description, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 4),
        Text(
          description,
          style: TextStyle(
            fontSize: 14,
            color: Colors.grey.shade600,
          ),
        ),
        const SizedBox(height: 12),
        child,
      ],
    );
  }
}

/// YouTube examples page
class YoutubeExamplesPage extends StatelessWidget {
  const YoutubeExamplesPage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('YouTube Examples'),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          _buildSection(
            'Standard YouTube Video',
            'Shows preview (no logo) and plays on tap',
            const TssVideoGlimpse(
              youtubeUrl: 'https://www.youtube.com/watch?v=dQw4w9WgXcQ',
              width: double.infinity,
              height: 200,
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Preview Only',
            'Shows preview but does not play video (Preview Only Mode)',
            const TssVideoGlimpse(
              youtubeUrl: 'https://www.youtube.com/watch?v=L_jWHffIx5E',
              width: double.infinity,
              height: 200,
              showPreviewOnly: true,
            ),
          ),
          const SizedBox(height: 24),
          _buildSection(
            'Shorts URL Support',
            'Works with YouTube Shorts URLs too',
            const TssVideoGlimpse(
              youtubeUrl: 'https://youtube.com/shorts/5qap5aO4i9A',
              width: 200,
              height: 350,
              fit: BoxFit.cover,
            ),
          ),
        ],
      ),
    );
  }

  Widget _buildSection(String title, String description, Widget child) {
    return Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      children: [
        Text(
          title,
          style: const TextStyle(
            fontSize: 20,
            fontWeight: FontWeight.bold,
          ),
        ),
        const SizedBox(height: 4),
        Text(
          description,
          style: TextStyle(
            fontSize: 14,
            color: Colors.grey.shade600,
          ),
        ),
        const SizedBox(height: 12),
        child,
      ],
    );
  }
}
2
likes
160
points
398
downloads

Publisher

verified publishertechsukras.com

Weekly Downloads

Cross-platform Flutter package for video previews from network, assets, and Firebase Storage with smart caching.

Repository

Topics

#video #preview #thumbnail #firebase #media

Documentation

API reference

License

MIT (license)

Dependencies

firebase_storage, flutter, flutter_cache_manager, http, omni_video_player, path_provider, webview_flutter_web, youtube_explode_dart, youtube_player_iframe

More

Packages that depend on tss_video_glimpse