Skip to content

Commit

Permalink
support null-safety close #6
Browse files Browse the repository at this point in the history
  • Loading branch information
robert-virkus committed Mar 10, 2021
1 parent 615b5a0 commit c175ca7
Show file tree
Hide file tree
Showing 12 changed files with 105 additions and 113 deletions.
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
## [1.0.0] - 2021-03-10
* Support null-safefty
* Use open source [native_pdf_view](https://pub.dev/packages/native_pdf_view) package instead of commercial package
* Improved video controls

## [0.2.0] - 2021-02-02
* A `MediaProvider` can now also have a description that can be useful when sharing the media to other apps.
* The hero animation now works also for text media.
Expand Down
2 changes: 1 addition & 1 deletion lib/enough_media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,6 @@ export 'preview/all_preview.dart';
export 'widget_registry.dart';

export 'package:flutter_sound_lite/flutter_sound.dart';
export 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
export 'package:native_pdf_view/native_pdf_view.dart';
export 'package:video_player/video_player.dart';
export 'package:chewie/chewie.dart';
11 changes: 5 additions & 6 deletions lib/interactive/audio_interactive_media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,22 @@ import '../media_provider.dart';
class AudioInteractiveMedia extends StatefulWidget {
final MediaProvider mediaProvider;
AudioInteractiveMedia({
Key key,
@required this.mediaProvider,
Key? key,
required this.mediaProvider,
}) : super(key: key);

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

class _AudioInteractiveMediaState extends State<AudioInteractiveMedia> {
String name;
FlutterSoundPlayer audioPlayer;
Track track;
late String name;
late Track track;

@override
void initState() {
final provider = widget.mediaProvider;
name = provider.name ?? '<unknown>';
name = provider.name;
if (provider is MemoryMediaProvider) {
track = Track(dataBuffer: provider.data, trackTitle: name);
} else if (provider is UrlMediaProvider) {
Expand Down
2 changes: 1 addition & 1 deletion lib/interactive/image_interactive_media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import 'package:photo_view/photo_view.dart';
/// Displays zoomable images
class ImageInteractiveMedia extends StatelessWidget {
final MediaProvider mediaProvider;
const ImageInteractiveMedia({Key key, @required this.mediaProvider})
const ImageInteractiveMedia({Key? key, required this.mediaProvider})
: super(key: key);

@override
Expand Down
88 changes: 40 additions & 48 deletions lib/interactive/pdf_interactive_media.dart
Original file line number Diff line number Diff line change
@@ -1,76 +1,68 @@
import 'package:enough_media/media_provider.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:native_pdf_view/native_pdf_view.dart';

/// Displays PDFs
class PdfInteractiveMedia extends StatefulWidget {
final MediaProvider mediaProvider;
PdfInteractiveMedia({Key key, @required this.mediaProvider})
PdfInteractiveMedia({Key? key, required this.mediaProvider})
: super(key: key);

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

class _PdfInteractiveMediaState extends State<PdfInteractiveMedia> {
PdfViewerController pdfViewerController;
OverlayEntry overlayEntry;
late PdfController pdfController;

@override
void initState() {
pdfViewerController = PdfViewerController();
pdfController = PdfController(document: initDocument(widget.mediaProvider));
super.initState();
}

@override
Widget build(BuildContext context) {
final provider = widget.mediaProvider;
Future<PdfDocument> initDocument(final MediaProvider provider) {
if (provider is MemoryMediaProvider) {
return SfPdfViewer.memory(
provider.data,
controller: pdfViewerController,
onTextSelectionChanged: onTextSelectionChanged,
);
} else if (provider is UrlMediaProvider) {
return SfPdfViewer.network(
provider.url,
controller: pdfViewerController,
onTextSelectionChanged: onTextSelectionChanged,
);
return PdfDocument.openData(provider.data);
// } else if (provider is UrlMediaProvider) {
// provider.url
// );
} else if (provider is AssetMediaProvider) {
return SfPdfViewer.asset(
provider.assetName,
controller: pdfViewerController,
onTextSelectionChanged: onTextSelectionChanged,
);
return PdfDocument.openAsset(provider.assetName);
} else {
throw StateError('Unsupported media provider $provider');
}
}

void onTextSelectionChanged(PdfTextSelectionChangedDetails details) {
if (details.selectedText == null && overlayEntry != null) {
overlayEntry.remove();
overlayEntry = null;
} else if (details.selectedText != null && overlayEntry == null) {
final OverlayState overlayState = Overlay.of(context);
overlayEntry = OverlayEntry(
builder: (context) => Positioned(
top: details.globalSelectedRegion.center.dy - 55,
left: details.globalSelectedRegion.bottomLeft.dx,
child: RaisedButton(
child: Text('Copy', style: TextStyle(fontSize: 17)),
onPressed: () {
Clipboard.setData(ClipboardData(text: details.selectedText));
pdfViewerController.clearSelection();
},
color: Colors.white,
elevation: 10,
),
),
);
overlayState.insert(overlayEntry);
}
@override
Widget build(BuildContext context) {
return PdfView(
controller: pdfController,
);
}

// void onTextSelectionChanged(PdfTextSelectionChangedDetails details) {
// if (details.selectedText == null && overlayEntry != null) {
// overlayEntry.remove();
// overlayEntry = null;
// } else if (details.selectedText != null && overlayEntry == null) {
// final OverlayState overlayState = Overlay.of(context);
// overlayEntry = OverlayEntry(
// builder: (context) => Positioned(
// top: details.globalSelectedRegion.center.dy - 55,
// left: details.globalSelectedRegion.bottomLeft.dx,
// child: RaisedButton(
// child: Text('Copy', style: TextStyle(fontSize: 17)),
// onPressed: () {
// Clipboard.setData(ClipboardData(text: details.selectedText));
// pdfViewerController.clearSelection();
// },
// color: Colors.white,
// elevation: 10,
// ),
// ),
// );
// overlayState.insert(overlayEntry);
// }
// }
}
18 changes: 7 additions & 11 deletions lib/interactive/video_interactive_media.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,17 @@ import '../media_provider.dart';

class VideoInteractiveMedia extends StatefulWidget {
final MediaProvider mediaProvider;
VideoInteractiveMedia({Key key, this.mediaProvider}) : super(key: key);
VideoInteractiveMedia({Key? key, required this.mediaProvider})
: super(key: key);

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

class _VideoInteractiveMediaState extends State<VideoInteractiveMedia> {
VideoPlayerController _videoController;
ChewieController _chewieController;
Future<VideoPlayerController> _loader;
late VideoPlayerController _videoController;
late ChewieController _chewieController;
late Future<VideoPlayerController> _loader;

@override
void initState() {
Expand All @@ -26,10 +27,8 @@ class _VideoInteractiveMediaState extends State<VideoInteractiveMedia> {
}

void dispose() {
if (_videoController != null) {
_videoController.dispose();
_chewieController.dispose();
}
_videoController.dispose();
_chewieController.dispose();
super.dispose();
}

Expand Down Expand Up @@ -81,12 +80,9 @@ class _VideoInteractiveMediaState extends State<VideoInteractiveMedia> {
case ConnectionState.waiting:
case ConnectionState.active:
return Center(child: CircularProgressIndicator());
break;
case ConnectionState.done:
return buildVideo();
break;
}
return Text('loading video...');
},
);
}
Expand Down
10 changes: 5 additions & 5 deletions lib/interactive_media_widget.dart
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,18 @@ import 'package:flutter/material.dart';
class InteractiveMediaWidget extends StatelessWidget {
final MediaProvider mediaProvider;
final bool useRegistry;
final Object heroTag;
final Object? heroTag;
const InteractiveMediaWidget({
Key key,
@required this.mediaProvider,
Key? key,
required this.mediaProvider,
this.useRegistry = false,
this.heroTag,
}) : super(key: key);

@override
Widget build(BuildContext context) {
if (heroTag != null) {
return Hero(tag: heroTag, child: _buildMedia());
return Hero(tag: heroTag!, child: _buildMedia());
}
return _buildMedia();
}
Expand All @@ -27,7 +27,7 @@ class InteractiveMediaWidget extends StatelessWidget {
if (useRegistry) {
final registry = WidgetRegistry();
if (registry.resolveInteractive != null) {
final resolved = registry.resolveInteractive(provider);
final resolved = registry.resolveInteractive!(provider);
if (resolved != null) {
return resolved;
}
Expand Down
12 changes: 6 additions & 6 deletions lib/media_provider.dart
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,10 @@ class MediaProvider {
final String mediaType;

/// The size in bytes, if known
final int size;
final int? size;

/// Description, can be useful when sharing this media
final String description;
final String? description;

/// Creates a new media provider with the given [name], [mediaType] like application/pdf, [size] in bytes and [description].
MediaProvider(this.name, this.mediaType, this.size, {this.description});
Expand Down Expand Up @@ -46,7 +46,7 @@ class UrlMediaProvider extends MediaProvider {
/// Creates a new URL media provider with the given [name], [mediaType] and [url].
/// Optionally specify the [size] in bytes and the [description].
UrlMediaProvider(String name, String mediaType, this.url,
{int size, String description})
{int? size, String? description})
: super(name, mediaType, size, description: description);
}

Expand All @@ -58,7 +58,7 @@ class MemoryMediaProvider extends MediaProvider {
/// Creates a new meemory media provider with the given [name], [mediaType] and [data].
/// Optionally specify the [description].
MemoryMediaProvider(String name, String mediaType, this.data,
{String description})
{String? description})
: super(name, mediaType, data.length, description: description);
}

Expand All @@ -70,13 +70,13 @@ class AssetMediaProvider extends MediaProvider {
/// Creates a new asset media provider with the given [name], [mediaType] and [assetName].
/// Optionally specify the [size] in bytes and the [description].
AssetMediaProvider(String name, String mediaType, this.assetName,
{String description})
{String? description})
: super(name, mediaType, null, description: description);
}

class TextMediaProvider extends MediaProvider {
final String text;
TextMediaProvider(String name, String mediaType, this.text,
{String description})
{String? description})
: super(name, mediaType, null, description: description);
}
8 changes: 4 additions & 4 deletions lib/preview/image_preview.dart
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import 'package:flutter/material.dart';
class ImagePreview extends StatelessWidget {
final MediaProvider mediaProvider;
final BoxFit fit;
final double width;
final double height;
final double? width;
final double? height;
const ImagePreview(
{Key key,
@required this.mediaProvider,
{Key? key,
required this.mediaProvider,
this.fit = BoxFit.cover,
this.width,
this.height})
Expand Down
Loading

0 comments on commit c175ca7

Please sign in to comment.