v_story_viewer 1.0.2 copy "v_story_viewer: ^1.0.2" to clipboard
v_story_viewer: ^1.0.2 copied to clipboard

Flutter package for WhatsApp/Instagram-style story viewing with gestures, caching, and cross-platform support.

v_story_viewer #

A production-ready Flutter package for displaying WhatsApp/Instagram-style stories with intuitive gesture controls, smart media caching, and extensive customization options. Built for performance with 60 FPS animations and full cross-platform support.

📸 Showcase #

Story Viewer Demo 1 Story Viewer Demo 2

pub package License Flutter

✨ Key Features #

  • 📱 Multiple Media Types - Images, videos, text, and custom widgets
  • 🎮 Intuitive Gestures - Tap to navigate, swipe to dismiss, long press to pause
  • ⚡ High Performance - 60 FPS animations with efficient caching
  • 🎨 Fully Customizable - Themes, headers, footers, and custom content
  • 🌍 Cross-Platform - iOS, Android, Web, macOS, Windows, Linux
  • 🔄 Smart Caching - Automatic media caching with offline support
  • 🌐 Internationalization - RTL support and multi-language ready

📋 Roadmap (Upcoming Features) #

  • 🎙️ Voice Stories - Support for audio/voice recordings as stories
  • Video trimming capabilities
  • Advanced filters and effects
  • Story analytics and metrics

📦 Installation #

Add to your pubspec.yaml:

dependencies:
  v_story_viewer: ^1.0.0

Then run:

flutter pub get

🚀 Quick Start #

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

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Story Viewer Demo',
      home: const StoryViewerScreen(),
    );
  }
}

class StoryViewerScreen extends StatelessWidget {
  const StoryViewerScreen({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    final storyGroups = [
      VStoryGroup(
        id: 'user1',
        user: VStoryUser(
          name: 'John Doe',
          profileUrl: 'https://example.com/profile1.jpg',
          verified: true,
        ),
        stories: [
          VImageStory(
            id: 'story1',
            url: 'https://example.com/image1.jpg',
            duration: const Duration(seconds: 5),
            caption: 'Beautiful sunset 🌅',
          ),
          VVideoStory(
            id: 'story2',
            url: 'https://example.com/video1.mp4',
            caption: 'Amazing moments 🎥',
          ),
        ],
      ),
      VStoryGroup(
        id: 'user2',
        user: VStoryUser(
          name: 'Jane Smith',
          profileUrl: 'https://example.com/profile2.jpg',
        ),
        stories: [
          VTextStory(
            id: 'story3',
            text: 'Hello World! 👋',
            backgroundColor: Colors.blue,
            duration: const Duration(seconds: 3),
          ),
        ],
      ),
    ];

    return Scaffold(
      body: VStoryViewer(
        storyGroups: storyGroups,
        onComplete: () => Navigator.pop(context),
      ),
    );
  }
}

📖 Story Types #

Image Stories #

Display images from various sources:

// Network URL
VImageStory(
  id: 'img1',
  url: 'https://example.com/image.jpg',
  duration: const Duration(seconds: 5),
  caption: 'Optional caption',
)

// Asset
VImageStory(
  id: 'img2',
  url: 'assets/images/story.jpg',
  duration: const Duration(seconds: 5),
)

// Local file
VImageStory(
  id: 'img3',
  url: '/path/to/image.jpg',
  duration: const Duration(seconds: 5),
)

Video Stories #

Play videos automatically:

VVideoStory(
  id: 'vid1',
  url: 'https://example.com/video.mp4',
  caption: 'Video story',
  autoPlay: true,
  muted: false,
)

Text Stories #

Create text-based stories:

VTextStory(
  id: 'txt1',
  text: 'Hello World!',
  backgroundColor: Colors.blue,
  textStyle: const TextStyle(
    fontSize: 32,
    color: Colors.white,
    fontWeight: FontWeight.bold,
  ),
  duration: const Duration(seconds: 5),
)

Custom Stories #

Display any Flutter widget:

VCustomStory(
  id: 'custom1',
  duration: const Duration(seconds: 5),
  builder: (context) => Center(
    child: Column(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        const Icon(Icons.star, size: 100, color: Colors.yellow),
        const SizedBox(height: 20),
        const Text(
          'Custom Content',
          style: TextStyle(fontSize: 24, color: Colors.white),
        ),
      ],
    ),
  ),
)

🎮 Gesture Controls #

Built-in WhatsApp-style gestures:

Gesture Action
Tap left Previous story
Tap right Next story
Swipe down Dismiss viewer
Swipe left/right Navigate between groups
Double tap Send reaction
Long press Pause story

Customize gesture behavior:

VStoryViewer(
  storyGroups: storyGroups,
  gestureConfig: VGestureConfig(
    leftTapZoneWidth: 0.4,      // 40% of screen
    rightTapZoneWidth: 0.6,     // 60% of screen
    enableVerticalSwipe: true,
    enableHorizontalSwipe: true,
    enableDoubleTap: true,
    enableLongPress: true,
  ),
)

🎛️ Programmatic Control #

Use VStoryController for programmatic control:

final controller = VStoryController();

// Playback control
controller.play();
controller.pause();
controller.stop();
controller.reset();

// Navigation
controller.nextStory();
controller.previousStory();
controller.jumpToStory(groupIndex: 0, storyIndex: 2);

// Listen to changes
controller.addListener(() {
  print('Current state: ${controller.state}');
});

// Cleanup
controller.dispose();

Use the controller with VStoryViewer:

VStoryViewer(
  storyGroups: storyGroups,
  controller: controller,
  onComplete: () => Navigator.pop(context),
)

🎨 Customization #

Theme Configuration #

VStoryViewer(
  storyGroups: storyGroups,
  theme: VStoryTheme(
    progressBarStyle: VProgressBarStyle(
      activeColor: Colors.white,
      inactiveColor: Colors.white30,
      height: 2.0,
    ),
    headerStyle: VHeaderStyle(
      backgroundColor: Colors.black26,
      textStyle: const TextStyle(color: Colors.white),
    ),
    footerStyle: VFooterStyle(
      backgroundColor: Colors.black54,
      textStyle: const TextStyle(color: Colors.white),
    ),
  ),
)
VStoryViewer(
  storyGroups: storyGroups,
  headerBuilder: (context, group, story) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Row(
        children: [
          CircleAvatar(
            backgroundImage: NetworkImage(group.user.profileUrl ?? ''),
          ),
          const SizedBox(width: 12),
          Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Text(group.user.name),
              Text(
                'Just now',
                style: Theme.of(context).textTheme.caption,
              ),
            ],
          ),
        ],
      ),
    );
  },
  footerBuilder: (context, group, story) {
    return Padding(
      padding: const EdgeInsets.all(16),
      child: Text(
        story.caption ?? '',
        style: const TextStyle(color: Colors.white),
      ),
    );
  },
)

Reply System #

VStoryViewer(
  storyGroups: storyGroups,
  replyConfig: VReplyConfig(
    enabled: true,
    placeholder: 'Reply to story...',
    maxLength: 280,
    onReply: (message, storyId) {
      // Handle reply
      print('Reply: $message to story: $storyId');
    },
  ),
)

Reaction System #

VStoryViewer(
  storyGroups: storyGroups,
  reactionConfig: VReactionConfig(
    enabled: true,
    reactions: ['❤️', '😂', '😮', '😢', '👏', '🔥'],
    onReaction: (emoji, storyId) {
      // Handle reaction
      print('Reaction: $emoji on story: $storyId');
    },
  ),
)

📡 Event Callbacks #

Track story viewer events:

VStoryViewer(
  storyGroups: storyGroups,
  onStoryChanged: (groupIndex, storyIndex) {
    print('Story changed: group $groupIndex, story $storyIndex');
  },
  onGroupChanged: (groupIndex) {
    print('Group changed: $groupIndex');
  },
  onComplete: () {
    print('All stories viewed');
    Navigator.pop(context);
  },
  onDispose: () {
    print('Viewer disposed');
  },
)

🌍 Localization & RTL #

VStoryViewer(
  storyGroups: storyGroups,
  locale: const Locale('ar'),           // Arabic
  textDirection: TextDirection.rtl,      // Right-to-left
)

Supported languages: English, Arabic, Spanish, and more.

💾 Caching #

The package automatically uses flutter_cache_manager for efficient media caching:

// Use default cache manager (automatic)
VStoryViewer(
  storyGroups: storyGroups,
)

// Or provide custom cache manager
import 'package:flutter_cache_manager/flutter_cache_manager.dart';

class CustomCacheManager extends BaseCacheManager {
  static const key = 'customStoryCache';
  CustomCacheManager() : super(key);
}

VStoryViewer(
  storyGroups: storyGroups,
  cacheManager: CustomCacheManager(),
)

📋 API Reference #

Core Classes #

VStoryViewer

Main widget for displaying stories.

Properties:

  • storyGroups: List<VStoryGroup> - Story groups to display
  • controller: VStoryController? - Optional controller for programmatic control
  • onComplete: VoidCallback? - Called when all stories complete
  • onDispose: VoidCallback? - Called when widget disposed
  • onStoryChanged: Function(int, int)? - Called on story change
  • onGroupChanged: Function(int)? - Called on group change
  • theme: VStoryTheme? - Customize appearance
  • gestureConfig: VGestureConfig? - Configure gestures
  • replyConfig: VReplyConfig? - Enable replies
  • reactionConfig: VReactionConfig? - Enable reactions
  • headerBuilder: Function? - Custom header widget
  • footerBuilder: Function? - Custom footer widget
  • locale: Locale? - Language/region setting
  • textDirection: TextDirection? - RTL/LTR support

VStoryController

Programmatic control over story playback.

Methods:

  • play() - Resume playback
  • pause() - Pause playback
  • stop() - Stop playback
  • reset() - Reset to start
  • nextStory() - Go to next story
  • previousStory() - Go to previous story
  • jumpToStory({required int groupIndex, required int storyIndex}) - Jump to specific story
  • addListener(VoidCallback) - Listen to state changes
  • dispose() - Cleanup resources

Data Models #

VStoryGroup

VStoryGroup({
  required String id,
  required VStoryUser user,
  required List<VBaseStory> stories,
})

VStoryUser

VStoryUser({
  required String name,
  String? profileUrl,
  bool verified = false,
})

Story Types

  • VImageStory - Display images from network, assets, or files
  • VVideoStory - Play videos with auto-play and controls
  • VTextStory - Text with custom background and styling
  • VCustomStory - Any Flutter widget as story content

Configuration Classes #

  • VStoryTheme - Progress bar, header, and footer styling
  • VGestureConfig - Gesture behavior customization
  • VReplyConfig - Reply system setup
  • VReactionConfig - Reaction emoji configuration

For detailed API documentation, see API_REFERENCE.md.

🔧 Troubleshooting #

Videos not playing #

Ensure the video URL is accessible and in a supported format (MP4, WebM). Check platform permissions for video playback.

Images not loading #

Verify image URLs are correct and accessible. For local files, ensure paths are absolute. For assets, check pubspec.yaml configuration.

Gestures not responding #

Verify gestureConfig properties are correctly set. Ensure the device has proper touch capabilities.

Performance issues #

  • Reduce story count per session
  • Use cached URLs instead of streaming
  • Enable caching with flutter_cache_manager
  • Use const constructors for static stories

Memory leaks #

Always dispose the controller when done:

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

📱 Platform Support #

Platform Status
iOS ✅ Fully supported
Android ✅ Fully supported
Web ✅ Fully supported
macOS ✅ Fully supported
Windows ✅ Fully supported
Linux ✅ Fully supported

📋 Requirements #

  • Flutter: >=3.0.0
  • Dart: ^3.9.0

📦 Dependencies #

  • flutter_cache_manager: ^3.4.1 - Media caching
  • video_player: ^2.10.0 - Video playback
  • cached_network_image: ^3.4.1 - Image caching
  • v_platform: ^2.1.4 - Cross-platform file handling

📚 Examples #

Complete examples are available in the example directory:

  • Basic story viewer
  • Multiple story types
  • Custom themes and styling
  • Reply and reaction systems
  • Programmatic navigation
  • Error handling

Run the example:

cd example
flutter run

🤝 Contributing #

Contributions are welcome! Please see CONTRIBUTING.md for guidelines.

📄 License #

MIT License - See LICENSE file for details.

🎯 Need Help? #

✍️ Author #

Created and maintained by Hatem Ragap


Made with ❤️ for the Flutter community

4
likes
0
points
194
downloads

Publisher

verified publishervchatsdk.com

Weekly Downloads

Flutter package for WhatsApp/Instagram-style story viewing with gestures, caching, and cross-platform support.

Repository (GitHub)
View/report issues

Documentation

Documentation

License

unknown (license)

Dependencies

cached_network_image, crypto, emoji_picker_flutter, event_bus, flutter, flutter_cache_manager, gal, intl, permission_handler, share_plus, shared_preferences, step_progress, v_platform, video_player

More

Packages that depend on v_story_viewer