mirror of
https://github.com/flutter/holobooth.git
synced 2025-05-17 21:36:00 +08:00

<!-- Thanks for contributing! Provide a description of your changes below and a general summary in the title Please look at the following checklist to ensure that your PR can be accepted quickly: --> ## Description Changes: - Bump min dart SDK to 2.19.0 - Bump Flutter version to 3.7.12 - Used Very Good Analysis 4.0.0 - Corrected new analyzer issues - Dart format ## Type of Change <!--- Put an `x` in all the boxes that apply: --> - [ ] ✨ New feature (non-breaking change which adds functionality) - [ ] 🛠️ Bug fix (non-breaking change which fixes an issue) - [ ] ❌ Breaking change (fix or feature that would cause existing functionality to change) - [ ] 🧹 Code refactor - [ ] ✅ Build configuration change - [ ] 📝 Documentation - [X] 🗑️ Chore
201 lines
5.7 KiB
Dart
201 lines
5.7 KiB
Dart
import 'package:camera/camera.dart';
|
|
import 'package:flutter/material.dart';
|
|
import 'package:flutter_bloc/flutter_bloc.dart';
|
|
import 'package:holobooth/convert/convert.dart';
|
|
import 'package:holobooth/l10n/l10n.dart';
|
|
import 'package:holobooth/share/share.dart';
|
|
import 'package:holobooth_ui/holobooth_ui.dart';
|
|
|
|
class DownloadButton extends StatefulWidget {
|
|
const DownloadButton({super.key, this.camera});
|
|
|
|
final CameraDescription? camera;
|
|
|
|
@override
|
|
State<DownloadButton> createState() => _DownloadButtonState();
|
|
}
|
|
|
|
class _DownloadButtonState extends State<DownloadButton> {
|
|
final layerLink = LayerLink();
|
|
|
|
void _showDownloadOptionsDialog() {
|
|
final downloadBloc = context.read<DownloadBloc>();
|
|
final url = context.read<ConvertBloc>().state.videoPath;
|
|
showDialog<void>(
|
|
context: context,
|
|
barrierColor: HoloBoothColors.transparent,
|
|
builder: (context) => BlocProvider.value(
|
|
value: downloadBloc,
|
|
child: DownloadOptionDialog(
|
|
layerLink: layerLink,
|
|
url: url,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
void _showErrorView(CameraDescription? camera) {
|
|
showAppDialog<void>(
|
|
context: context,
|
|
child: MultiBlocProvider(
|
|
providers: [
|
|
BlocProvider.value(value: context.read<ConvertBloc>()),
|
|
],
|
|
child: HoloBoothAlertDialog(
|
|
height: 300,
|
|
child: ConvertErrorView(
|
|
convertErrorOrigin: ConvertErrorOrigin.video,
|
|
camera: camera,
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
final l10n = context.l10n;
|
|
final downloadState = context.watch<DownloadBloc>().state;
|
|
final convertState = context.watch<ConvertBloc>().state;
|
|
final isLoading = (convertState.shareStatus == ShareStatus.waiting &&
|
|
convertState.shareType == ShareType.download) ||
|
|
downloadState.status == DownloadStatus.fetching;
|
|
|
|
return BlocListener<ConvertBloc, ConvertState>(
|
|
listenWhen: (previous, current) =>
|
|
previous.shareStatus != current.shareStatus,
|
|
listener: (context, state) {
|
|
if (state.shareStatus == ShareStatus.ready &&
|
|
state.shareType == ShareType.download) {
|
|
_showDownloadOptionsDialog();
|
|
}
|
|
},
|
|
child: CompositedTransformTarget(
|
|
link: layerLink,
|
|
child: GradientOutlinedButton(
|
|
loading: isLoading,
|
|
icon: const Icon(
|
|
Icons.file_download_rounded,
|
|
color: HoloBoothColors.white,
|
|
),
|
|
label: l10n.sharePageDownloadButtonText,
|
|
onPressed: () {
|
|
final convertStatus = context.read<ConvertBloc>().state.status;
|
|
if (convertStatus == ConvertStatus.videoCreated) {
|
|
_showDownloadOptionsDialog();
|
|
} else if (convertStatus == ConvertStatus.creatingVideo) {
|
|
context
|
|
.read<ConvertBloc>()
|
|
.add(const ShareRequested(ShareType.download));
|
|
} else if (convertStatus == ConvertStatus.errorGeneratingVideo) {
|
|
_showErrorView(widget.camera);
|
|
}
|
|
},
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DownloadOptionDialog extends StatelessWidget {
|
|
const DownloadOptionDialog({
|
|
required this.layerLink,
|
|
required this.url,
|
|
super.key,
|
|
});
|
|
|
|
final LayerLink layerLink;
|
|
final String url;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return CompositedTransformFollower(
|
|
link: layerLink,
|
|
offset: const Offset(0, 70),
|
|
child: Align(
|
|
alignment: Alignment.topLeft,
|
|
child: GradientFrame(
|
|
width: 200,
|
|
borderRadius: 12,
|
|
child: Column(
|
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
mainAxisSize: MainAxisSize.min,
|
|
children: [
|
|
DownloadAsAGifButton(
|
|
url: url,
|
|
),
|
|
DownloadAsAVideoButton(
|
|
url: url,
|
|
),
|
|
],
|
|
),
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DownloadAsAGifButton extends StatelessWidget {
|
|
const DownloadAsAGifButton({required this.url, super.key});
|
|
|
|
final String url;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return TextButton.icon(
|
|
style: TextButton.styleFrom(
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
context.read<DownloadBloc>().add(DownloadRequested.gif(url));
|
|
},
|
|
icon: ShaderMask(
|
|
shaderCallback: (bounds) {
|
|
return HoloBoothGradients.secondaryFour
|
|
.createShader(Offset.zero & bounds.size);
|
|
},
|
|
child: const Icon(Icons.download),
|
|
),
|
|
label: Text(
|
|
context.l10n.downloadOptionGif,
|
|
textHeightBehavior: const TextHeightBehavior(
|
|
applyHeightToFirstAscent: false,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|
|
|
|
class DownloadAsAVideoButton extends StatelessWidget {
|
|
const DownloadAsAVideoButton({required this.url, super.key});
|
|
|
|
final String url;
|
|
|
|
@override
|
|
Widget build(BuildContext context) {
|
|
return TextButton.icon(
|
|
style: TextButton.styleFrom(
|
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
|
),
|
|
onPressed: () {
|
|
Navigator.of(context).pop();
|
|
context.read<DownloadBloc>().add(DownloadRequested.video(url));
|
|
},
|
|
icon: ShaderMask(
|
|
shaderCallback: (bounds) {
|
|
return HoloBoothGradients.secondaryFour
|
|
.createShader(Offset.zero & bounds.size);
|
|
},
|
|
child: const Icon(Icons.download),
|
|
),
|
|
label: Text(
|
|
context.l10n.downloadOptionVideo,
|
|
textHeightBehavior: const TextHeightBehavior(
|
|
applyHeightToFirstAscent: false,
|
|
),
|
|
),
|
|
);
|
|
}
|
|
}
|