| // Copyright 2017 The Fuchsia Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| import 'dart:typed_data'; |
| |
| import 'package:fidl/fidl.dart' show InterfaceHandle; |
| import 'package:fidl_fuchsia_mem/fidl.dart' show Buffer; |
| import 'package:fidl_fuchsia_skia_skottie/fidl.dart' as skottie; |
| import 'package:fidl_fuchsia_sys/fidl.dart'; |
| import 'package:fidl_fuchsia_ui_app/fidl.dart' show ViewProviderProxy; |
| import 'package:fidl_fuchsia_ui_views/fidl_async.dart' |
| show ViewToken, ViewHolderToken; |
| import 'package:flutter/material.dart'; |
| import 'package:flutter/widgets.dart'; |
| import 'package:fuchsia_scenic_flutter/child_view.dart' show ChildView; |
| import 'package:fuchsia_scenic_flutter/child_view_connection.dart' |
| show ChildViewConnection; |
| import 'package:lib.app.dart/app.dart'; |
| import 'package:meta/meta.dart'; |
| import 'package:zircon/zircon.dart'; |
| |
| typedef LoadCallback = void Function( |
| skottie.Status status, skottie.Player player); |
| |
| /// A [Widget] that displays lottie animation in a scenic view. |
| class LottiePlayer extends StatefulWidget { |
| /// The JSON data of the animation as a string. |
| final String json; |
| |
| /// The background color. |
| final Color backgroundColor; |
| |
| /// Called after animation is loaded. |
| final LoadCallback onLoad; |
| |
| /// Loops the animation. Default [true]. |
| final bool loop; |
| |
| /// Starts playing the animation after loading. Default [true]. |
| final bool autoplay; |
| |
| /// Constructor. |
| const LottiePlayer({ |
| @required this.json, |
| this.backgroundColor = Colors.black, |
| this.loop = true, |
| this.autoplay = true, |
| Key key, |
| this.onLoad, |
| }) : super(key: key); |
| |
| @override |
| _LottiePlayerState createState() => _LottiePlayerState(); |
| } |
| |
| class _LottiePlayerState extends State<LottiePlayer> { |
| final ComponentControllerProxy _controller = ComponentControllerProxy(); |
| final skottie.LoaderProxy _loader = skottie.LoaderProxy(); |
| ChildViewConnection _connection; |
| |
| @override |
| void initState() { |
| super.initState(); |
| |
| _launchViewer(); |
| _loadViewer(); |
| } |
| |
| @override |
| void didUpdateWidget(LottiePlayer old) { |
| super.didUpdateWidget(old); |
| if (old.json == widget.json && |
| old.backgroundColor == widget.backgroundColor && |
| old.loop == widget.loop && |
| old.autoplay == widget.autoplay) { |
| return; |
| } |
| |
| _loadViewer(); |
| } |
| |
| @override |
| void dispose() { |
| _loader?.ctrl?.close(); |
| _controller?.ctrl?.close(); |
| _connection = null; |
| |
| super.dispose(); |
| } |
| |
| @override |
| Widget build(BuildContext context) => ChildView( |
| connection: _connection, |
| hitTestable: false, |
| focusable: false, |
| ); |
| |
| void _launchViewer() { |
| final startupContext = StartupContext.fromStartupInfo(); |
| final incomingServices = Services(); |
| |
| final launcher = LauncherProxy(); |
| connectToService(startupContext.environmentServices, launcher.ctrl); |
| launcher.createComponent( |
| LaunchInfo( |
| url: 'skottie_viewer', |
| directoryRequest: incomingServices.request(), |
| ), |
| _controller.ctrl.request(), |
| ); |
| launcher.ctrl.close(); |
| |
| final viewTokens = EventPairPair(); |
| assert(viewTokens.status == ZX.OK); |
| final viewHolderToken = ViewHolderToken(value: viewTokens.first); |
| final viewToken = ViewToken(value: viewTokens.second); |
| |
| final viewProvider = ViewProviderProxy(); |
| incomingServices.connectToService(viewProvider.ctrl); |
| viewProvider.createView(viewToken.value, null, null); |
| viewProvider.ctrl.close(); |
| |
| incomingServices |
| ..connectToService(_loader.ctrl) |
| ..close(); |
| |
| _connection = ChildViewConnection(viewHolderToken); |
| } |
| |
| void _loadViewer() { |
| final SizedVmo vmo = |
| SizedVmo.fromUint8List(Uint8List.fromList(widget.json.codeUnits)); |
| final options = skottie.Options( |
| backgroundColor: widget.backgroundColor.value, |
| loop: widget.loop, |
| autoplay: widget.autoplay, |
| ); |
| _loader.load(Buffer(vmo: vmo, size: vmo.size), options, |
| (skottie.Status status, InterfaceHandle<skottie.Player> player) { |
| widget.onLoad(status, skottie.PlayerProxy()..ctrl.bind(player)); |
| }); |
| } |
| } |