// Copyright 2014 The Flutter 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 'package:flutter/material.dart';

class AnimationWithMicrotasks extends StatefulWidget {
  const AnimationWithMicrotasks({Key? key}) : super(key: key);

  @override
  State<AnimationWithMicrotasks> createState() => _AnimationWithMicrotasksState();
}

class _AnimationWithMicrotasksState extends State<AnimationWithMicrotasks> {
  final _ChunkedWork work = _ChunkedWork();

  @override
  void initState() {
    super.initState();
    work.start();
  }

  @override
  void dispose() {
    work.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return const Scaffold(
      backgroundColor: Colors.grey,
      body: Center(
        child: SizedBox(
          width: 200,
          height: 100,
          child: LinearProgressIndicator(),
        ),
      ),
    );
  }
}

class _ChunkedWork {
  bool _canceled = false;

  Future<void> start() async {
    // Run 100 pieces of synchronous work.
    // Chunked up to allow frames to be drawn.
    for (int i = 0; i < 100; ++i) {
      _chunkedSynchronousWork();
    }
  }

  void cancel() {
    _canceled = true;
  }

  Future<void> _chunkedSynchronousWork() async {
    while (!_canceled) {
      // Yield to the event loop to let engine draw frames.
      await Future<void>.delayed(Duration.zero);

      // Perform synchronous computation for 1 ms.
      _syncComputationFor(const Duration(milliseconds: 1));
    }
  }

  void _syncComputationFor(Duration duration) {
    final Stopwatch sw = Stopwatch()..start();
    while (!_canceled && sw.elapsed < duration) {}
  }
}
