viewer: open panorama
This commit is contained in:
parent
690d257375
commit
d40f32b11b
11 changed files with 253 additions and 92 deletions
|
@ -209,6 +209,12 @@ class Constants {
|
||||||
licenseUrl: 'https://github.com/flutter/packages/blob/master/packages/palette_generator/LICENSE',
|
licenseUrl: 'https://github.com/flutter/packages/blob/master/packages/palette_generator/LICENSE',
|
||||||
sourceUrl: 'https://github.com/flutter/packages/tree/master/packages/palette_generator',
|
sourceUrl: 'https://github.com/flutter/packages/tree/master/packages/palette_generator',
|
||||||
),
|
),
|
||||||
|
Dependency(
|
||||||
|
name: 'Panorama',
|
||||||
|
license: 'Apache 2.0',
|
||||||
|
licenseUrl: 'https://github.com/zesage/panorama/blob/master/LICENSE',
|
||||||
|
sourceUrl: 'https://github.com/zesage/panorama',
|
||||||
|
),
|
||||||
Dependency(
|
Dependency(
|
||||||
name: 'PDF for Dart and Flutter',
|
name: 'PDF for Dart and Flutter',
|
||||||
license: 'Apache 2.0',
|
license: 'Apache 2.0',
|
||||||
|
|
|
@ -2,6 +2,8 @@ import 'dart:ui';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
final _filter = ImageFilter.blur(sigmaX: 4, sigmaY: 4);
|
||||||
|
|
||||||
class BlurredRect extends StatelessWidget {
|
class BlurredRect extends StatelessWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
|
@ -11,7 +13,7 @@ class BlurredRect extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ClipRect(
|
return ClipRect(
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4),
|
filter: _filter,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -29,7 +31,7 @@ class BlurredRRect extends StatelessWidget {
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: BorderRadius.circular(borderRadius),
|
borderRadius: BorderRadius.circular(borderRadius),
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4),
|
filter: _filter,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@ -45,7 +47,7 @@ class BlurredOval extends StatelessWidget {
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return ClipOval(
|
return ClipOval(
|
||||||
child: BackdropFilter(
|
child: BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 4, sigmaY: 4),
|
filter: _filter,
|
||||||
child: child,
|
child: child,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
class AvesCircleBorder {
|
class AvesCircleBorder {
|
||||||
static BoxBorder build(BuildContext context) {
|
static const borderColor = Colors.white30;
|
||||||
final subPixel = MediaQuery.of(context).devicePixelRatio > 2;
|
|
||||||
return Border.all(
|
static double _borderWidth(BuildContext context) => MediaQuery.of(context).devicePixelRatio > 2 ? 0.5 : 1.0;
|
||||||
color: Colors.white30,
|
|
||||||
width: subPixel ? 0.5 : 1.0,
|
static Border build(BuildContext context) {
|
||||||
|
return Border.fromBorderSide(buildSide(context));
|
||||||
|
}
|
||||||
|
|
||||||
|
static BorderSide buildSide(BuildContext context) {
|
||||||
|
return BorderSide(
|
||||||
|
color: borderColor,
|
||||||
|
width: _borderWidth(context),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,8 @@ import 'package:aves/model/image_entry.dart';
|
||||||
import 'package:aves/model/settings/screen_on.dart';
|
import 'package:aves/model/settings/screen_on.dart';
|
||||||
import 'package:aves/model/settings/settings.dart';
|
import 'package:aves/model/settings/settings.dart';
|
||||||
import 'package:aves/model/source/collection_lens.dart';
|
import 'package:aves/model/source/collection_lens.dart';
|
||||||
import 'package:aves/utils/change_notifier.dart';
|
|
||||||
import 'package:aves/theme/durations.dart';
|
import 'package:aves/theme/durations.dart';
|
||||||
|
import 'package:aves/utils/change_notifier.dart';
|
||||||
import 'package:aves/widgets/collection/collection_page.dart';
|
import 'package:aves/widgets/collection/collection_page.dart';
|
||||||
import 'package:aves/widgets/fullscreen/entry_action_delegate.dart';
|
import 'package:aves/widgets/fullscreen/entry_action_delegate.dart';
|
||||||
import 'package:aves/widgets/fullscreen/image_page.dart';
|
import 'package:aves/widgets/fullscreen/image_page.dart';
|
||||||
|
@ -14,6 +14,7 @@ import 'package:aves/widgets/fullscreen/image_view.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
import 'package:aves/widgets/fullscreen/info/info_page.dart';
|
||||||
import 'package:aves/widgets/fullscreen/info/notifications.dart';
|
import 'package:aves/widgets/fullscreen/info/notifications.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/bottom.dart';
|
import 'package:aves/widgets/fullscreen/overlay/bottom.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/overlay/panorama.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/top.dart';
|
import 'package:aves/widgets/fullscreen/overlay/top.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/video.dart';
|
import 'package:aves/widgets/fullscreen/overlay/video.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
|
@ -223,22 +224,33 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
Widget bottomOverlay = ValueListenableBuilder<ImageEntry>(
|
Widget bottomOverlay = ValueListenableBuilder<ImageEntry>(
|
||||||
valueListenable: _entryNotifier,
|
valueListenable: _entryNotifier,
|
||||||
builder: (context, entry, child) {
|
builder: (context, entry, child) {
|
||||||
Widget videoOverlay;
|
if (entry == null) return SizedBox.shrink();
|
||||||
if (entry != null) {
|
|
||||||
final videoController = entry.isVideo ? _videoControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2 : null;
|
Widget extraBottomOverlay;
|
||||||
|
if (entry.isVideo) {
|
||||||
|
final videoController = _videoControllers.firstWhere((kv) => kv.item1 == entry.uri, orElse: () => null)?.item2;
|
||||||
if (videoController != null) {
|
if (videoController != null) {
|
||||||
videoOverlay = VideoControlOverlay(
|
extraBottomOverlay = VideoControlOverlay(
|
||||||
entry: entry,
|
entry: entry,
|
||||||
controller: videoController,
|
controller: videoController,
|
||||||
scale: _bottomOverlayScale,
|
scale: _bottomOverlayScale,
|
||||||
viewInsets: _frozenViewInsets,
|
|
||||||
viewPadding: _frozenViewPadding,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
} else if (entry.is360) {
|
||||||
|
extraBottomOverlay = PanoramaOverlay(
|
||||||
|
entry: entry,
|
||||||
|
scale: _bottomOverlayScale,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final child = Column(
|
final child = Column(
|
||||||
children: [
|
children: [
|
||||||
if (videoOverlay != null) videoOverlay,
|
if (extraBottomOverlay != null)
|
||||||
|
ExtraBottomOverlay(
|
||||||
|
viewInsets: _frozenViewInsets,
|
||||||
|
viewPadding: _frozenViewPadding,
|
||||||
|
child: extraBottomOverlay,
|
||||||
|
),
|
||||||
SlideTransition(
|
SlideTransition(
|
||||||
position: _bottomOverlayOffset,
|
position: _bottomOverlayOffset,
|
||||||
child: FullscreenBottomOverlay(
|
child: FullscreenBottomOverlay(
|
||||||
|
@ -255,7 +267,7 @@ class FullscreenBodyState extends State<FullscreenBody> with SingleTickerProvide
|
||||||
valueListenable: _overlayAnimationController,
|
valueListenable: _overlayAnimationController,
|
||||||
builder: (context, animation, child) {
|
builder: (context, animation, child) {
|
||||||
return Visibility(
|
return Visibility(
|
||||||
visible: entry != null && _overlayAnimationController.status != AnimationStatus.dismissed,
|
visible: _overlayAnimationController.status != AnimationStatus.dismissed,
|
||||||
child: child,
|
child: child,
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
|
|
@ -303,3 +303,35 @@ class _ShootingRow extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class ExtraBottomOverlay extends StatelessWidget {
|
||||||
|
final EdgeInsets viewInsets, viewPadding;
|
||||||
|
final Widget child;
|
||||||
|
|
||||||
|
const ExtraBottomOverlay({
|
||||||
|
Key key,
|
||||||
|
this.viewInsets,
|
||||||
|
this.viewPadding,
|
||||||
|
@required this.child,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
final mq = context.select<MediaQueryData, Tuple3<double, EdgeInsets, EdgeInsets>>((mq) => Tuple3(mq.size.width, mq.viewInsets, mq.viewPadding));
|
||||||
|
final mqWidth = mq.item1;
|
||||||
|
final mqViewInsets = mq.item2;
|
||||||
|
final mqViewPadding = mq.item3;
|
||||||
|
|
||||||
|
final viewInsets = this.viewInsets ?? mqViewInsets;
|
||||||
|
final viewPadding = this.viewPadding ?? mqViewPadding;
|
||||||
|
final safePadding = (viewInsets + viewPadding).copyWith(bottom: 8) + EdgeInsets.symmetric(horizontal: 8.0);
|
||||||
|
|
||||||
|
return Padding(
|
||||||
|
padding: safePadding,
|
||||||
|
child: SizedBox(
|
||||||
|
width: mqWidth - safePadding.horizontal,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -8,7 +8,12 @@ class OverlayButton extends StatelessWidget {
|
||||||
final Animation<double> scale;
|
final Animation<double> scale;
|
||||||
final Widget child;
|
final Widget child;
|
||||||
|
|
||||||
const OverlayButton({Key key, this.scale, this.child}) : super(key: key);
|
const OverlayButton({
|
||||||
|
Key key,
|
||||||
|
@required this.scale,
|
||||||
|
@required this.child,
|
||||||
|
}) : assert(scale != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
|
@ -30,3 +35,45 @@ class OverlayButton extends StatelessWidget {
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class OverlayTextButton extends StatelessWidget {
|
||||||
|
final Animation<double> scale;
|
||||||
|
final String text;
|
||||||
|
final VoidCallback onPressed;
|
||||||
|
|
||||||
|
const OverlayTextButton({
|
||||||
|
Key key,
|
||||||
|
@required this.scale,
|
||||||
|
@required this.text,
|
||||||
|
this.onPressed,
|
||||||
|
}) : assert(scale != null),
|
||||||
|
super(key: key);
|
||||||
|
|
||||||
|
static const _borderRadius = 123.0;
|
||||||
|
static final _minSize = MaterialStateProperty.all<Size>(Size(kMinInteractiveDimension, kMinInteractiveDimension));
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return SizeTransition(
|
||||||
|
sizeFactor: scale,
|
||||||
|
child: BlurredRRect(
|
||||||
|
borderRadius: _borderRadius,
|
||||||
|
child: OutlinedButton(
|
||||||
|
onPressed: onPressed,
|
||||||
|
style: ButtonStyle(
|
||||||
|
backgroundColor: MaterialStateProperty.all<Color>(kOverlayBackgroundColor),
|
||||||
|
foregroundColor: MaterialStateProperty.all<Color>(Colors.white),
|
||||||
|
overlayColor: MaterialStateProperty.all<Color>(Colors.white.withOpacity(0.12)),
|
||||||
|
minimumSize: _minSize,
|
||||||
|
side: MaterialStateProperty.all<BorderSide>(AvesCircleBorder.buildSide(context)),
|
||||||
|
shape: MaterialStateProperty.all<OutlinedBorder>(RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(_borderRadius)),
|
||||||
|
)),
|
||||||
|
// shape: MaterialStateProperty.all<OutlinedBorder>(CircleBorder()),
|
||||||
|
),
|
||||||
|
child: Text(text.toUpperCase()),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
37
lib/widgets/fullscreen/overlay/panorama.dart
Normal file
37
lib/widgets/fullscreen/overlay/panorama.dart
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
|
import 'package:aves/widgets/fullscreen/panorama_page.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
|
class PanoramaOverlay extends StatelessWidget {
|
||||||
|
final ImageEntry entry;
|
||||||
|
final Animation<double> scale;
|
||||||
|
|
||||||
|
const PanoramaOverlay({
|
||||||
|
Key key,
|
||||||
|
@required this.entry,
|
||||||
|
@required this.scale,
|
||||||
|
}) : super(key: key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Row(
|
||||||
|
children: [
|
||||||
|
Spacer(),
|
||||||
|
OverlayTextButton(
|
||||||
|
scale: scale,
|
||||||
|
text: 'Open Panorama',
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.push(
|
||||||
|
context,
|
||||||
|
MaterialPageRoute(
|
||||||
|
settings: RouteSettings(name: PanoramaPage.routeName),
|
||||||
|
builder: (context) => PanoramaPage(entry: entry),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
)
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -10,22 +10,17 @@ import 'package:aves/widgets/common/fx/borders.dart';
|
||||||
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
import 'package:aves/widgets/fullscreen/overlay/common.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
|
import 'package:flutter_ijkplayer/flutter_ijkplayer.dart';
|
||||||
import 'package:provider/provider.dart';
|
|
||||||
import 'package:tuple/tuple.dart';
|
|
||||||
|
|
||||||
class VideoControlOverlay extends StatefulWidget {
|
class VideoControlOverlay extends StatefulWidget {
|
||||||
final ImageEntry entry;
|
final ImageEntry entry;
|
||||||
final Animation<double> scale;
|
|
||||||
final IjkMediaController controller;
|
final IjkMediaController controller;
|
||||||
final EdgeInsets viewInsets, viewPadding;
|
final Animation<double> scale;
|
||||||
|
|
||||||
const VideoControlOverlay({
|
const VideoControlOverlay({
|
||||||
Key key,
|
Key key,
|
||||||
@required this.entry,
|
@required this.entry,
|
||||||
@required this.controller,
|
@required this.controller,
|
||||||
@required this.scale,
|
@required this.scale,
|
||||||
this.viewInsets,
|
|
||||||
this.viewPadding,
|
|
||||||
}) : super(key: key);
|
}) : super(key: key);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
@ -99,63 +94,48 @@ class VideoControlOverlayState extends State<VideoControlOverlay> with SingleTic
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final mq = context.select<MediaQueryData, Tuple3<double, EdgeInsets, EdgeInsets>>((mq) => Tuple3(mq.size.width, mq.viewInsets, mq.viewPadding));
|
return StreamBuilder<IjkStatus>(
|
||||||
final mqWidth = mq.item1;
|
stream: controller.ijkStatusStream,
|
||||||
final mqViewInsets = mq.item2;
|
builder: (context, snapshot) {
|
||||||
final mqViewPadding = mq.item3;
|
// do not use stream snapshot because it is obsolete when switching between videos
|
||||||
|
final status = controller.ijkStatus;
|
||||||
final viewInsets = widget.viewInsets ?? mqViewInsets;
|
return TooltipTheme(
|
||||||
final viewPadding = widget.viewPadding ?? mqViewPadding;
|
data: TooltipTheme.of(context).copyWith(
|
||||||
final safePadding = (viewInsets + viewPadding).copyWith(bottom: 8) + EdgeInsets.symmetric(horizontal: 8.0);
|
preferBelow: false,
|
||||||
|
),
|
||||||
return Padding(
|
child: Row(
|
||||||
padding: safePadding,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
child: SizedBox(
|
children: status == IjkStatus.error
|
||||||
width: mqWidth - safePadding.horizontal,
|
? [
|
||||||
child: StreamBuilder<IjkStatus>(
|
OverlayButton(
|
||||||
stream: controller.ijkStatusStream,
|
scale: scale,
|
||||||
builder: (context, snapshot) {
|
child: IconButton(
|
||||||
// do not use stream snapshot because it is obsolete when switching between videos
|
icon: Icon(AIcons.openInNew),
|
||||||
final status = controller.ijkStatus;
|
onPressed: () => AndroidAppService.open(entry.uri, entry.mimeTypeAnySubtype),
|
||||||
return TooltipTheme(
|
tooltip: 'Open',
|
||||||
data: TooltipTheme.of(context).copyWith(
|
),
|
||||||
preferBelow: false,
|
),
|
||||||
),
|
]
|
||||||
child: Row(
|
: [
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
Expanded(
|
||||||
children: status == IjkStatus.error
|
child: _buildProgressBar(),
|
||||||
? [
|
),
|
||||||
OverlayButton(
|
SizedBox(width: 8),
|
||||||
scale: scale,
|
OverlayButton(
|
||||||
child: IconButton(
|
scale: scale,
|
||||||
icon: Icon(AIcons.openInNew),
|
child: IconButton(
|
||||||
onPressed: () => AndroidAppService.open(entry.uri, entry.mimeTypeAnySubtype),
|
icon: AnimatedIcon(
|
||||||
tooltip: 'Open',
|
icon: AnimatedIcons.play_pause,
|
||||||
),
|
progress: _playPauseAnimation,
|
||||||
),
|
),
|
||||||
]
|
onPressed: _playPause,
|
||||||
: [
|
tooltip: isPlaying ? 'Pause' : 'Play',
|
||||||
Expanded(
|
),
|
||||||
child: _buildProgressBar(),
|
),
|
||||||
),
|
],
|
||||||
SizedBox(width: 8),
|
),
|
||||||
OverlayButton(
|
);
|
||||||
scale: scale,
|
});
|
||||||
child: IconButton(
|
|
||||||
icon: AnimatedIcon(
|
|
||||||
icon: AnimatedIcons.play_pause,
|
|
||||||
progress: _playPauseAnimation,
|
|
||||||
),
|
|
||||||
onPressed: _playPause,
|
|
||||||
tooltip: isPlaying ? 'Pause' : 'Play',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildProgressBar() {
|
Widget _buildProgressBar() {
|
||||||
|
|
30
lib/widgets/fullscreen/panorama_page.dart
Normal file
30
lib/widgets/fullscreen/panorama_page.dart
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
import 'package:aves/image_providers/uri_image_provider.dart';
|
||||||
|
import 'package:aves/model/image_entry.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:panorama/panorama.dart';
|
||||||
|
|
||||||
|
class PanoramaPage extends StatelessWidget {
|
||||||
|
static const routeName = '/fullscreen/panorama';
|
||||||
|
|
||||||
|
final ImageEntry entry;
|
||||||
|
|
||||||
|
const PanoramaPage({@required this.entry});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return Scaffold(
|
||||||
|
body: Panorama(
|
||||||
|
child: Image(
|
||||||
|
image: UriImage(
|
||||||
|
uri: entry.uri,
|
||||||
|
mimeType: entry.mimeType,
|
||||||
|
rotationDegrees: entry.rotationDegrees,
|
||||||
|
isFlipped: entry.isFlipped,
|
||||||
|
expectedContentLength: entry.sizeBytes,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
resizeToAvoidBottomInset: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
14
pubspec.lock
14
pubspec.lock
|
@ -283,6 +283,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.0"
|
version: "2.0.0"
|
||||||
|
flutter_cube:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: flutter_cube
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.6"
|
||||||
flutter_driver:
|
flutter_driver:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description: flutter
|
description: flutter
|
||||||
|
@ -585,6 +592,13 @@ packages:
|
||||||
url: "https://pub.dartlang.org"
|
url: "https://pub.dartlang.org"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.3"
|
version: "0.2.3"
|
||||||
|
panorama:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: panorama
|
||||||
|
url: "https://pub.dartlang.org"
|
||||||
|
source: hosted
|
||||||
|
version: "0.0.2"
|
||||||
path:
|
path:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|
18
pubspec.yaml
18
pubspec.yaml
|
@ -1,26 +1,19 @@
|
||||||
name: aves
|
name: aves
|
||||||
description: Aves is a gallery and metadata explorer app, built for Android.
|
description: Aves is a gallery and metadata explorer app, built for Android.
|
||||||
|
|
||||||
# The following line prevents the package from being accidentally published to
|
|
||||||
# pub.dev using `pub publish`. This is preferred for private packages.
|
|
||||||
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
publish_to: 'none' # Remove this line if you wish to publish to pub.dev
|
||||||
|
|
||||||
# The following defines the version and build number for your application.
|
|
||||||
# A version number is three numbers separated by dots, like 1.2.43
|
|
||||||
# followed by an optional build number separated by a +.
|
|
||||||
# Both the version and the builder number may be overridden in flutter
|
|
||||||
# build by specifying --build-name and --build-number, respectively.
|
|
||||||
# In Android, build-name is used as versionName while build-number used as versionCode.
|
|
||||||
# Read more about Android versioning at https://developer.android.com/studio/publish/versioning
|
|
||||||
# In iOS, build-name is used as CFBundleShortVersionString while build-number used as CFBundleVersion.
|
|
||||||
# Read more about iOS versioning at
|
|
||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
|
||||||
version: 1.2.8+34
|
version: 1.2.8+34
|
||||||
|
|
||||||
# brendan-duncan/image (as of v2.1.19):
|
# brendan-duncan/image (as of v2.1.19):
|
||||||
# - does not support TIFF with JPEG compression (issue #184)
|
# - does not support TIFF with JPEG compression (issue #184)
|
||||||
# - TIFF tile decoding is not public (issue #258)
|
# - TIFF tile decoding is not public (issue #258)
|
||||||
|
|
||||||
|
# dnfield/flutter_svg (as of v0.19.1):
|
||||||
|
# - `Could not parse "currentColor" as a color`: https://github.com/dnfield/flutter_svg/issues/31
|
||||||
|
# - no <style> support: https://github.com/dnfield/flutter_svg/issues/105
|
||||||
|
# - inconsistent % unit support: https://github.com/dnfield/flutter_svg/issues/110
|
||||||
|
|
||||||
# video_player (as of v0.10.8+2, backed by ExoPlayer):
|
# video_player (as of v0.10.8+2, backed by ExoPlayer):
|
||||||
# - does not support content URIs (by default, but trivial by fork)
|
# - does not support content URIs (by default, but trivial by fork)
|
||||||
# - does not support AVI/XVID, AC3
|
# - does not support AVI/XVID, AC3
|
||||||
|
@ -77,6 +70,7 @@ dependencies:
|
||||||
overlay_support:
|
overlay_support:
|
||||||
package_info:
|
package_info:
|
||||||
palette_generator:
|
palette_generator:
|
||||||
|
panorama:
|
||||||
pdf:
|
pdf:
|
||||||
pedantic:
|
pedantic:
|
||||||
percent_indicator:
|
percent_indicator:
|
||||||
|
|
Loading…
Reference in a new issue