binSaed / flutter_cached_pdfview

Enhanced PDF view for Flutter.
https://pub.dev/packages/flutter_cached_pdfview
MIT License
121 stars 70 forks source link

store current page to restore and navigate to latest page which we read #35

Closed pishguy closed 3 years ago

pishguy commented 3 years ago

is any solution store current page and navigate that to restore?

you suppose we need to read pdf from latest page which we see and read it

binSaed commented 3 years ago

you need to use shared preference

   PDF(
           defaultPage: //get page from sharedPreference
           onPageChanged: (page, total) {
            //save page to sharedPreference
             },
          ).cachedFromUrl('http://africau.edu/images/default/sample.pdf')
pishguy commented 3 years ago

@AbdOoSaed so reading from shared preference can be navigate to that?

pishguy commented 3 years ago

@AbdOoSaed

I can't set latest read page could you see this implementation please?

class _ShowPdfFromUrlState extends State<ShowPdfFromUrl> {
  final Completer<PDFViewController> _pdfViewController = Completer<PDFViewController>();
  final ValueNotifier<int> _pageCount = ValueNotifier<int>(0);
  final ValueNotifier<int> _currentPage = ValueNotifier<int>(1);
  Preference<int> _pdfPageIndex;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    _pdfPageIndex = Provider.of<ApplicationSettings>(context).pdfPageIndex ?? 0;

    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Icon(Icons.picture_as_pdf),
            Expanded(
              child: Text(
                ' - ${widget.productName}',
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
              ),
            ),
          ],
        ),
      ),
      body: PreferenceBuilder(
        preference: _pdfPageIndex,
        builder: (context, int pageIndex) {
          return Stack(
            children: [
              PDF(
                onPageChanged: (page, total) {
                  _pageCount.value = total;
                  _currentPage.value = page == 0 ? 1 : page;
                  _pdfPageIndex.setValue(_currentPage.value);
                  print('CURRENT PAGE: ${_currentPage.value}');
                },
                onViewCreated: (PDFViewController pdfViewController) async {
                  _pdfViewController.complete(pdfViewController);
                  _pageCount.value = await pdfViewController.getPageCount();
                  print('SAVED PAGE: ${_pdfPageIndex.getValue()}');

                  pdfViewController.setPage(_pdfPageIndex.getValue());

                  /* this code don't work too */
                  //pdfViewController.setPage(30);

                },
              ).cachedFromUrl(
                '${widget.pdfUrl}',
                placeholder: (progress) => Center(child: Text('Yükleniyor $progress %')),
                errorWidget: (error) {
                  return Container(
                    width: double.infinity,
                    height: double.infinity,
                    child: Center(
                        child: Column(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Text('PDF hatası indiriliyor'),
                        Padding(
                          padding: const EdgeInsets.only(top: 16.0),
                          child: OutlineButton(
                            onPressed: () {
                              setState(() {});
                            },
                            child: Text('lütfen tekrar deneyin'),
                          ),
                        ),
                      ],
                    )),
                  );
                },
              ),
              Positioned(
                top: 8.0,
                left: 8.0,
                child: ValueListenableBuilder2<int, int>(
                  _pageCount,
                  _currentPage,
                  builder: (_, count, current, __) {
                    return Container(
                      padding: EdgeInsets.all(8.0),
                      decoration: BoxDecoration(
                        borderRadius: BorderRadius.circular(8.0),
                        color: Colors.black,
                      ),
                      child: Text(
                        '$current / ($count)',
                        style: TextStyle(
                          color: Colors.white,
                        ),
                      ),
                    );
                  },
                ),
              ),
            ],
          );
        },
      ),
    );
  }
}

class ValueListenableBuilder2<A, B> extends StatelessWidget {
  ValueListenableBuilder2(
    this.first,
    this.second, {
    Key key,
    this.builder,
    this.child,
  }) : super(key: key);

  final ValueListenable<A> first;
  final ValueListenable<B> second;
  final Widget child;
  final Widget Function(BuildContext context, A a, B b, Widget child) builder;

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<A>(
      valueListenable: first,
      builder: (_, a, __) {
        return ValueListenableBuilder<B>(
          valueListenable: second,
          builder: (context, b, __) {
            return builder(context, a, b, child);
          },
        );
      },
    );
  }
}

save and restore work fine but .setPage doesn't work:

I/flutter (21057): SAVED PAGE: 9
I/flutter (21057): CURRENT PAGE: 0
pishguy commented 3 years ago

@AbdOoSaed

or this implemented code

class _ShowPdfFromUrlState extends State<ShowPdfFromUrl> {
  final Completer<PDFViewController> _pdfViewController = Completer<PDFViewController>();
  final ValueNotifier<int> _pageCount = ValueNotifier<int>(0);
  final ValueNotifier<int> _currentPage = ValueNotifier<int>(1);
  Preference<int> _pdfPageIndex;

  @override
  void didChangeDependencies() {
    super.didChangeDependencies();
  }

  @override
  Widget build(BuildContext context) {
    _pdfPageIndex = Provider.of<ApplicationSettings>(context).pdfPageIndex ?? 0;

    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Image.asset(
              'assets/images/acrobat.png',
              width: 40.0,
            ),
            Expanded(
              child: Text(
                ' - ${widget.productName}',
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
              ),
            ),
          ],
        ),
      ),
      body: Stack(
        children: [
          PDF(
            onPageChanged: (page, total) {
              _pageCount.value = total;
              _currentPage.value = page;
              _pdfPageIndex.setValue(_currentPage.value);
              print('CURRENT PAGE: ${_currentPage.value}');
              print('SAVED PAGE: ${_pdfPageIndex.getValue()}');
            },
            onViewCreated: (PDFViewController pdfViewController) async {
              _pdfViewController.complete(pdfViewController);
              _pageCount.value = await pdfViewController.getPageCount();
            },
          ).cachedFromUrl(
            '${widget.pdfUrl}',
            placeholder: (progress) => Center(child: Text('Yükleniyor $progress %')),
            errorWidget: (error) {
              return Container(
                width: double.infinity,
                height: double.infinity,
                child: Center(
                    child: Column(
                      mainAxisSize: MainAxisSize.max,
                      mainAxisAlignment: MainAxisAlignment.start,
                      crossAxisAlignment: CrossAxisAlignment.center,
                      children: [
                        Text('PDF hatası indiriliyor'),
                        Padding(
                          padding: const EdgeInsets.only(top: 16.0),
                          child: OutlineButton(
                            onPressed: () {
                              setState(() {});
                            },
                            child: Text('lütfen tekrar deneyin'),
                          ),
                        ),
                      ],
                    )),
              );
            },
          ),
          FutureBuilder<PDFViewController>(
            future: _pdfViewController.future,
            builder: (_, AsyncSnapshot<PDFViewController> snapshot) {
              if (snapshot.hasData && snapshot.data != null) {
                final PDFViewController pdfController = snapshot.data;
                pdfController.setPage(_pdfPageIndex.getValue());
                return Positioned(
                  top: 8.0,
                  left: 8.0,
                  child: ValueListenableBuilder2<int, int>(
                    _pageCount,
                    _currentPage,
                    builder: (_, count, current, __) {
                      return Container(
                        padding: EdgeInsets.all(8.0),
                        decoration: BoxDecoration(
                          borderRadius: BorderRadius.circular(8.0),
                          color: Colors.black,
                        ),
                        child: Text(
                          '$current / ($count)',
                          style: TextStyle(
                            color: Colors.white,
                          ),
                        ),
                      );
                    },
                  ),
                );
              } else {
                return Container();
              }
            },
          ),
        ],
      ),
    );
  }
}
ramsmart-inno commented 3 years ago

how to get the current page and total page count from cached URL?

pishguy commented 3 years ago

@ramsmart-inno

Full Code:

import 'dart:async';
import 'package:hive_flutter/hive_flutter.dart';
import 'package:caferilik/core/database/cache_ebook.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:flutter_cached_pdfview/flutter_cached_pdfview.dart';
import 'package:hive/hive.dart';

class ShowPdfFromUrl extends StatefulWidget {
  final String pdfUrl;
  final String productName;

  ShowPdfFromUrl({@required this.pdfUrl, @required this.productName});

  @override
  _ShowPdfFromUrlState createState() => _ShowPdfFromUrlState();
}

class _ShowPdfFromUrlState extends State<ShowPdfFromUrl> {
  final Completer<PDFViewController> _pdfViewController = Completer<PDFViewController>();
  final StreamController<String> _pageCountController = StreamController<String>();
  final TextEditingController _controller = TextEditingController();
  Box cacheEbook;
  int cachedIndex = 0;

  @override
  void initState() {
    super.initState();
    cacheEbook = Hive.box('cache_ebook');
    cachedIndex = cacheEbook.values.toList().indexWhere((ebook) => ebook.productName == widget.productName);
    if (cachedIndex < 0) {
      var _c = CacheEbook()
        ..productName = widget.productName
        ..currentPage = 0;
      cacheEbook.add(_c);
      cachedIndex = cacheEbook.length - 1;
    }
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Row(
          mainAxisAlignment: MainAxisAlignment.start,
          crossAxisAlignment: CrossAxisAlignment.center,
          children: [
            Image.asset(
              'assets/images/acrobat.png',
              width: 40.0,
            ),
            Expanded(
              child: Text(
                ' ${widget.productName}',
                overflow: TextOverflow.ellipsis,
                maxLines: 1,
              ),
            ),
          ],
        ),
      ),
      body: Stack(
        children: [
          PDF(
            onPageChanged: (page, total) {
              //_pageCount.value = total;
              //_currentPage.value = page;
              //_pdfPageIndex.setValue(_currentPage.value);
              //print('CURRENT PAGE: ${_currentPage.value}');
              //print('SAVED PAGE: ${_pdfPageIndex.getValue()}');

              if (page > 0) {
                var _c = CacheEbook()
                  ..productName = widget.productName
                  ..currentPage = page;
                cacheEbook.putAt(cachedIndex, _c);
              }
            },
            onViewCreated: (PDFViewController pdfViewController) async {
              _pdfViewController.complete(pdfViewController);
              //_pageCount.value = await pdfViewController.getPageCount();
            },
          ).cachedFromUrl(
            '${widget.pdfUrl}',
            placeholder: (progress) => Center(child: Text('Yükleniyor $progress %')),
            errorWidget: (error) {
              return Container(
                width: double.infinity,
                height: double.infinity,
                child: Center(
                    child: Column(
                  mainAxisSize: MainAxisSize.max,
                  mainAxisAlignment: MainAxisAlignment.start,
                  crossAxisAlignment: CrossAxisAlignment.center,
                  children: [
                    Text('PDF hatası indiriliyor'),
                    Padding(
                      padding: const EdgeInsets.only(top: 16.0),
                      child: OutlineButton(
                        onPressed: () {
                          setState(() {});
                        },
                        child: Text('lütfen tekrar deneyin'),
                      ),
                    ),
                  ],
                )),
              );
            },
          ),
          Align(
            alignment: Alignment.bottomCenter,
            child: FutureBuilder<PDFViewController>(
              future: _pdfViewController.future,
              builder: (_, AsyncSnapshot<PDFViewController> snapshot) {
                final PDFViewController pdfController = snapshot.data;

                return Card(
                  margin: EdgeInsets.zero,
                  child: BottomAppBar(
                    shape: const CircularNotchedRectangle(),
                    child: Container(
                      height: kBottomNavigationBarHeight,
                      child: Row(
                        mainAxisSize: MainAxisSize.max,
                        mainAxisAlignment: MainAxisAlignment.center,
                        children: <Widget>[
                          SizedBox(
                            width: 16.0,
                          ),
                          IconButton(
                              icon: Icon(Icons.add),
                              onPressed: () async {
                                final int currentPage = await pdfController.getCurrentPage() + 1;
                                final int numberOfPages = await pdfController.getPageCount();
                                if (numberOfPages > currentPage) {
                                  await pdfController.setPage(currentPage);
                                  var _c = CacheEbook()
                                    ..productName = widget.productName
                                    ..currentPage = currentPage;
                                  cacheEbook.putAt(cachedIndex, _c);
                                }
                              }),
                          SizedBox(
                            width: 16.0,
                          ),
                          IconButton(
                              icon: Icon(Icons.remove),
                              onPressed: () async {
                                final int currentPage = await pdfController.getCurrentPage() - 1;
                                if (currentPage >= 0) {
                                  await pdfController.setPage(currentPage);
                                  var _c = CacheEbook()
                                    ..productName = widget.productName
                                    ..currentPage = currentPage;
                                  cacheEbook.putAt(cachedIndex, _c);
                                }
                              }),
                          SizedBox(
                            width: 16.0,
                          ),
                          /*Expanded(
                              child: TextFormField(
                            controller: _controller,
                            decoration: InputDecoration(hintText: 'Page Number'),
                          )),
                          SizedBox(
                            width: 16.0,
                          ),*/

                          Spacer(),
                          ValueListenableBuilder(
                            valueListenable: cacheEbook.listenable(),
                            builder: (context, Box box, child) {
                              return RaisedButton(
                                onPressed: () async => await pdfController.setPage(box.getAt(cachedIndex).currentPage),
                                child: Row(
                                  mainAxisAlignment: MainAxisAlignment.center,
                                  crossAxisAlignment: CrossAxisAlignment.center,
                                  children: <Widget>[
                                    Text('Kitap Ayracı (${box.getAt(cachedIndex).currentPage})'),
                                    Icon(Icons.double_arrow),
                                  ],
                                ),
                              );
                            },
                          ),
                          SizedBox(
                            width: 16.0,
                          ),
                        ],
                      ),
                    ),
                  ),
                );
              },
            ),
          )
        ],
      ),
    );
  }

  @override
  void dispose() {
    _pageCountController.close();
    super.dispose();
  }
}

class ValueListenableBuilder2<A, B> extends StatelessWidget {
  ValueListenableBuilder2(
    this.first,
    this.second, {
    Key key,
    this.builder,
    this.child,
  }) : super(key: key);

  final ValueListenable<A> first;
  final ValueListenable<B> second;
  final Widget child;
  final Widget Function(BuildContext context, A a, B b, Widget child) builder;

  @override
  Widget build(BuildContext context) {
    return ValueListenableBuilder<A>(
      valueListenable: first,
      builder: (_, a, __) {
        return ValueListenableBuilder<B>(
          valueListenable: second,
          builder: (context, b, __) {
            return builder(context, a, b, child);
          },
        );
      },
    );
  }
}