PDF Bookshelf Viewer

A beautiful Flutter package that displays PDFs in a bookshelf-style list with realistic page-turning animations and modern loading capabilities.

pub package pub points Flutter Platform License

✨ Features

📚 Bookshelf-Style Display

  • Beautiful wooden shelf design with realistic textures
  • 3D book appearance with shadows and depth
  • Customizable books per shelf
  • Auto-generated book colors based on titles

📖 Page-Turning Animation

  • Realistic 3D page flip effect
  • Smooth animations with gesture support
  • Tap left/right to navigate pages
  • Page indicator display

🌐 Multiple PDF Sources

  • Network URLs: Download PDFs from any HTTP/HTTPS URL
  • Firebase Storage: Integrate with Firebase Cloud Storage
  • App Assets: Bundle PDFs with your app
  • Local Files: Load PDFs from device storage

⚡ Modern Features

  • Automatic Caching: Downloaded PDFs are cached for offline access
  • Download Progress: Real-time progress indicators
  • Error Handling: Graceful error states with retry functionality
  • Offline Support: Access cached PDFs without internet
  • Cache Management: Clear cache and monitor storage usage

📦 Installation

Add this to your package's pubspec.yaml file:

dependencies:
  pdf_bookshelf_viewer: ^0.1.5

Then run:

flutter pub get

🚀 Quick Start

Basic Example

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

class MyBookshelf extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final books = [
      PdfBook(
        title: 'Flutter Guide',
        source: PdfSource.network('https://example.com/flutter.pdf'),
        author: 'John Doe',
      ),
      PdfBook(
        title: 'Dart Basics',
        source: PdfSource.asset('assets/pdfs/dart.pdf'),
        author: 'Jane Smith',
      ),
    ];

    return Scaffold(
      appBar: AppBar(title: Text('My Bookshelf')),
      body: BookshelfView(
        books: books,
        onBookTap: (book) {
          Navigator.push(
            context,
            MaterialPageRoute(
              builder: (context) => PdfPageFlipViewer(
                pdfSource: book.source,
                title: book.title,
              ),
            ),
          );
        },
      ),
    );
  }
}

📖 Usage Examples

Loading PDFs from Different Sources

1. Network URL

PdfBook(
  title: 'My Document',
  source: PdfSource.network('https://example.com/document.pdf'),
)

2. Network URL with Headers

PdfBook(
  title: 'Protected Document',
  source: PdfSource.network(
    'https://api.example.com/document.pdf',
    headers: {'Authorization': 'Bearer YOUR_TOKEN'},
  ),
)

3. Firebase Storage

// Make sure to initialize Firebase first
PdfBook(
  title: 'Firebase PDF',
  source: PdfSource.firebase('pdfs/document.pdf'),
)

// With custom bucket
PdfBook(
  title: 'Custom Bucket PDF',
  source: PdfSource.firebase(
    'pdfs/document.pdf',
    bucket: 'gs://your-custom-bucket',
  ),
)

4. App Assets

// Add PDF to pubspec.yaml assets first
PdfBook(
  title: 'Bundled PDF',
  source: PdfSource.asset('assets/pdfs/guide.pdf'),
)

5. Local File

PdfBook(
  title: 'Local Document',
  source: PdfSource.file('/path/to/local/file.pdf'),
)

Customizing the Bookshelf

BookshelfView(
  books: books,
  onBookTap: _handleBookTap,
  booksPerShelf: 4,  // Number of books per row
  shelfHeight: 220,   // Height of each shelf
  backgroundColor: Color(0xFFD4A574),  // Custom wood color
)

PDF Viewer Options

PdfPageFlipViewer(
  pdfSource: PdfSource.network('https://example.com/doc.pdf'),
  title: 'Document Title',
  initialPage: 0,      // Start at first page
  forceRefresh: false, // Set true to ignore cache
)

Cache Management

final pdfLoader = PdfLoaderService();

// Get cache size
final cacheSize = await pdfLoader.getCacheSize();
print('Cache size: ${cacheSize / (1024 * 1024)} MB');

// Clear all cache
await pdfLoader.clearCache();

// Remove specific PDF from cache
await pdfLoader.removeCachedPdf('https://example.com/document.pdf');

Manual PDF Loading with Progress

final pdfLoader = PdfLoaderService();

final localPath = await pdfLoader.loadPdf(
  PdfSource.network('https://example.com/large-document.pdf'),
  onProgress: (progress) {
    print('Download progress: ${(progress * 100).toStringAsFixed(0)}%');
  },
  forceRefresh: false, // Use cached version if available
);

print('PDF saved at: $localPath');

Lazy Loading Source

You can provide books without a source and load it when the user taps on the book:

BookshelfView(
  books: [
    PdfBook(
      title: 'Lazy Book',
      // source is optional
      pageCount: 150,
      dimensions: '20x30 cm',
    ),
  ],
  onObtainSource: (book) async {
    // Fetch source asynchronously
    await Future.delayed(Duration(seconds: 1));
    return PdfSource.network('https://example.com/${book.title}.pdf');
  },
)

🎨 Components

PdfBook Model

Represents a PDF book with metadata:

PdfBook(
  title: 'Book Title',        // Required
  source: PdfSource.network(...), // Required
  author: 'Author Name',      // Optional
  coverImage: 'cover.png',    // Optional
PdfBook(
  title: 'Book Title',        // Required
  source: PdfSource.network(...), // Optional
  author: 'Author Name',      // Optional
  coverImage: 'cover.png',    // Optional
  description: 'Description', // Optional
  pageCount: 120,             // Optional
  dimensions: '15 x 22 cm',   // Optional
  weight: '0.5 kg',           // Optional
)

PdfSource

Defines where to load the PDF from:

  • PdfSource.network(url, {headers}) - HTTP/HTTPS URL
  • PdfSource.firebase(path, {bucket}) - Firebase Storage
  • PdfSource.asset(path) - App assets
  • PdfSource.file(path) - Local file system

BookshelfView Widget

Displays books in a bookshelf layout:

Parameter Type Default Description
books List<PdfBook> required List of books to display
onBookTap Function(PdfBook)? null Callback when book is tapped
onObtainSource Future<PdfSource?> Function(PdfBook)? null Callback to lazy load source
booksPerShelf int 3 Books per shelf row
shelfHeight double 200 Height of each shelf
backgroundColor Color Wood color Background color

PdfPageFlipViewer Widget

PDF viewer with page-turning animation:

Parameter Type Default Description
pdfSource PdfSource required PDF source
title String? null Title in app bar
initialPage int 0 Starting page number
forceRefresh bool false Ignore cache

🔧 Firebase Setup

To use Firebase Storage:

  1. Add Firebase to your Flutter app
  2. Initialize Firebase in main.dart:
import 'package:firebase_core/firebase_core.dart';

void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp();
  runApp(MyApp());
}
  1. Configure Firebase Storage rules
  2. Use PdfSource.firebase() to load PDFs

📱 Platform Support

Platform Support Notes
Android ✅ Full All features supported
iOS ✅ Full All features supported
Web ⚠️ Limited PDF rendering may vary
Desktop ⚠️ Limited Experimental support

🎯 Requirements

  • Flutter SDK: >=3.0.0
  • Dart SDK: >=3.0.0

📸 Screenshots

Coming soon

🤝 Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

📄 License

This project is licensed under the MIT License - see the LICENSE file for details.

🙏 Credits

📚 Example App

Run the example app to see all features in action:

cd example
flutter run

The example demonstrates:

  • Loading PDFs from network URLs
  • Firebase Storage integration
  • Asset-bundled PDFs
  • Cache management
  • Error handling and retry
  • Download progress indicators

👨‍💻 Author

Developed by TechSukras

🐛 Issues

If you encounter any issues, please file them on the GitHub issue tracker.

Libraries

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