pdf_bookshelf_viewer 0.1.5 copy "pdf_bookshelf_viewer: ^0.1.5" to clipboard
pdf_bookshelf_viewer: ^0.1.5 copied to clipboard

A Flutter package for displaying PDFs in a beautiful bookshelf-style list with realistic page-turning animations.

example/lib/main.dart

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

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

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PDF Bookshelf Viewer Demo',
      theme: ThemeData(primarySwatch: Colors.brown, useMaterial3: true),
      home: const BookshelfScreen(),
    );
  }
}

class BookshelfScreen extends StatefulWidget {
  const BookshelfScreen({super.key});

  @override
  State<BookshelfScreen> createState() => _BookshelfScreenState();
}

class _BookshelfScreenState extends State<BookshelfScreen> {
  List<PdfBook> books = [];
  bool isLoading = true;

  @override
  void initState() {
    super.initState();
    _loadSampleBooks();
  }

  Future<void> _loadSampleBooks() async {
    // Create sample PDF books from different sources
    final sampleBooks = [
      // Example: PDF from network URL
      PdfBook(
        title: 'Flutter Basics',
        source: PdfSource.network(
          'https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf',
        ),
        author: 'John Doe',
        description: 'Learn the fundamentals of Flutter development',
      ),

      // Example: PDF from Firebase Storage (requires Firebase setup)
      // Uncomment and configure Firebase to use
      // PdfBook(
      //   title: 'Dart Programming',
      //   source: PdfSource.firebase('pdfs/dart_programming.pdf'),
      //   author: 'Jane Smith',
      //   description: 'Master Dart programming language',
      // ),

      // Example: PDF from assets (add PDF files to assets/pdfs/)
      PdfBook(
        title: 'Mobile Design',
        source: PdfSource.asset('assets/pdfs/sample.pdf'),
        author: 'Bob Johnson',
        description: 'Best practices for mobile UI/UX design',
      ),

      // Example: Another network PDF
      PdfBook(
        title: 'State Management',
        source: PdfSource.network(
          'https://www.africau.edu/images/default/sample.pdf',
        ),
        author: 'Alice Williams',
        description: 'Managing state in Flutter applications',
      ),

      // Example: PDF with custom headers
      PdfBook(
        title: 'Advanced Flutter',
        source: PdfSource.network(
          'https://www.clickdimensions.com/links/TestPDFfile.pdf',
          headers: {'Authorization': 'Bearer token'},
        ),
        author: 'Charlie Brown',
        description: 'Advanced Flutter techniques and patterns',
      ),

      // Example: Local file (if you have a PDF file path)
      // PdfBook(
      //   title: 'Testing Guide',
      //   source: PdfSource.file('/path/to/local/file.pdf'),
      //   author: 'David Lee',
      //   description: 'Comprehensive guide to testing Flutter apps',
      // ),
    ];

    setState(() {
      books = sampleBooks;
      isLoading = false;
    });
  }

  void _openBook(PdfBook book) {
    // Use cross-platform viewer (works on all platforms)
    _openCrossPlatformViewer(book);

    // TODO: Advanced and Basic viewers need refactoring for pdfx
    // Uncomment when migration is complete
    /*
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Choose Viewer'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            ListTile(
              leading: const Icon(Icons.devices),
              title: const Text('Cross-Platform Viewer'),
              subtitle: const Text('Works on all platforms'),
              onTap: () {
                Navigator.pop(context);
                _openCrossPlatformViewer(book);
              },
            ),
            ListTile(
              leading: const Icon(Icons.auto_stories),
              title: const Text('Advanced Viewer'),
              subtitle: const Text('With curl animation (mobile only)'),
              onTap: () {
                Navigator.pop(context);
                _openAdvancedViewer(book);
              },
            ),
            ListTile(
              leading: const Icon(Icons.book),
              title: const Text('Basic Viewer'),
              subtitle: const Text('Simple page flip (mobile only)'),
              onTap: () {
                Navigator.pop(context);
                _openBasicViewer(book);
              },
            ),
          ],
        ),
      ),
    );
    */
  }

  bool _useImprovedCurl = true;

  void _openCrossPlatformViewer(PdfBook book) {
    Navigator.push(
      context,
      MaterialPageRoute(
        builder: (context) => CrossPlatformPdfViewer(
          pdfSource: book.source!,
          title: book.title,
          enablePageFlip: _useImprovedCurl,
          settings: const ReaderSettings(
            enableTwoPageMode:
                false, // Page flip usually works best with single page view
            immersiveModeEnabled: true,
          ),
        ),
      ),
    );
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('My Bookshelf'),
        centerTitle: true,
        elevation: 0,
        actions: [
          Row(
            children: [
              const Text('Curl'),
              Switch(
                value: _useImprovedCurl,
                onChanged: (value) {
                  setState(() {
                    _useImprovedCurl = value;
                  });
                },
              ),
            ],
          ),
          IconButton(
            icon: const Icon(Icons.info_outline),
            onPressed: () => _showInfoDialog(),
            tooltip: 'About',
          ),
        ],
      ),
      body: isLoading
          ? const Center(child: CircularProgressIndicator())
          : books.isEmpty
          ? const Center(
              child: Text(
                'No books available',
                textAlign: TextAlign.center,
                style: TextStyle(fontSize: 16),
              ),
            )
          : BookshelfView(
              books: books,
              onBookTap: _openBook,
              booksPerShelf: 3,
              shelfHeight: 200,
            ),
      floatingActionButton: FloatingActionButton(
        onPressed: _showCacheInfo,
        tooltip: 'Cache Info',
        child: const Icon(Icons.storage),
      ),
    );
  }

  void _showInfoDialog() {
    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('PDF Sources'),
        content: const SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            mainAxisSize: MainAxisSize.min,
            children: [
              Text(
                'This demo shows PDFs from different sources:',
                style: TextStyle(fontWeight: FontWeight.bold),
              ),
              SizedBox(height: 12),
              Text('📡 Network URLs'),
              Text('🔥 Firebase Storage'),
              Text('📦 App Assets'),
              Text('📁 Local Files'),
              SizedBox(height: 12),
              Text('Features:', style: TextStyle(fontWeight: FontWeight.bold)),
              SizedBox(height: 8),
              Text('✓ Automatic caching'),
              Text('✓ Download progress'),
              Text('✓ Offline support'),
              Text('✓ Page flip animation'),
              Text('✓ Error handling with retry'),
            ],
          ),
        ),
        actions: [
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }

  Future<void> _showCacheInfo() async {
    final loader = PdfLoaderService();
    final cacheSize = await loader.getCacheSize();
    final cacheSizeMB = (cacheSize / (1024 * 1024)).toStringAsFixed(2);

    if (!mounted) return;

    showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: const Text('Cache Information'),
        content: Column(
          mainAxisSize: MainAxisSize.min,
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            Text('Cache Size: $cacheSizeMB MB'),
            const SizedBox(height: 16),
            const Text(
              'Cached PDFs are stored locally for offline access and faster loading.',
            ),
          ],
        ),
        actions: [
          TextButton(
            onPressed: () async {
              await loader.clearCache();
              if (!context.mounted) return;
              Navigator.pop(context);
              ScaffoldMessenger.of(
                context,
              ).showSnackBar(const SnackBar(content: Text('Cache cleared')));
            },
            child: const Text('Clear Cache'),
          ),
          TextButton(
            onPressed: () => Navigator.pop(context),
            child: const Text('Close'),
          ),
        ],
      ),
    );
  }
}
1
likes
160
points
309
downloads

Publisher

verified publishertechsukras.com

Weekly Downloads

A Flutter package for displaying PDFs in a beautiful bookshelf-style list with realistic page-turning animations.

Homepage

Documentation

API reference

License

MIT (license)

Dependencies

cached_network_image, dio, firebase_core, firebase_storage, flutter, http, path_provider, pdfx, shared_preferences, vector_math

More

Packages that depend on pdf_bookshelf_viewer