Skip to content

Commit

Permalink
Merge pull request #3 from thecodexhub/feat/freeze-unfreeze
Browse files Browse the repository at this point in the history
feat: add freeze, unfreeze methods to pause and resume animation
  • Loading branch information
thecodexhub authored Nov 22, 2023
2 parents 5889045 + 7849976 commit 4cb686b
Show file tree
Hide file tree
Showing 10 changed files with 207 additions and 16 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
## 0.2.0

- feat: add freeze and unfreeze methods on controller to pause and resume animation
- docs(README): update documentation on freeze and unfreeze method
- docs(example): update example app with the freeze and unfreeze method showcases

## 0.1.1

- chore(deps): bump to flutter version 3.16.0
Expand Down
21 changes: 16 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-purple.svg)](https://opensource.org/licenses/MIT)
[![Package Version](https://img.shields.io/pub/v/typethis.svg)](https://pub.dev/packages/typethis)

A flutter package that aims to simplify versatile typing animation with reset functionality.
A flutter package that aims to simplify versatile typing animation with reset, freeze and unfreeze functionality.

## Create a TypeThis widget

Expand All @@ -27,9 +27,23 @@ final typeThisWidget = TypeThis(
typeThisWidget.controller.reset();
```

## Freeze (pause) the animation

```dart
// Call the `freeze()` method on controller to freeze/pause the typing animation.
typeThisWidget.controller.freeze();
```

## Unfreeze (resume) the animation

```dart
// Call the `unfreeze()` method on controller to unfreeze/resume the typing animation.
typeThisWidget.controller.unfreeze();
```

## Demo

[![Demo](screenshots/typethis.gif)](https://github.com/thecodexhub/typethis)
[![Demo](demo/typethis.gif)](https://github.com/thecodexhub/typethis)

## License

Expand All @@ -38,9 +52,6 @@ The project is released under the [MIT License](LICENSE). Learn more about it, [
---

<p align="center">
<a href="https://github.com/thecodexhub">
<img width="75px" src="https://avatars.githubusercontent.com/u/56641059?v=4" alt="thecodexhub">
</a>
<p align="center">
Developed and Maintained with 💜 by <a href="https://github.com/thecodexhub">thecodexhub</a>
</p>
Expand Down
Binary file added demo/typethis.gif
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
19 changes: 10 additions & 9 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import 'package:example/widgets/widgets.dart';
import 'package:flutter/material.dart';
import 'package:typethis/typethis.dart';

Expand All @@ -13,24 +14,24 @@ class MyApp extends StatelessWidget {
final typeThisWidget = TypeThis(
string: 'Hi there! How are you doing?',
speed: 100,
style: const TextStyle(fontSize: 20),
style: const TextStyle(fontSize: 18),
);

return MaterialApp(
title: 'Flutter TypeThis Demo',
theme: ThemeData(
primarySwatch: Colors.deepPurple,
),
theme: ThemeData(primarySwatch: Colors.deepPurple),
home: Scaffold(
appBar: AppBar(
title: const Text('TypeThis Example'),
backgroundColor: Colors.grey[200],
),
body: Center(
child: typeThisWidget,
),
floatingActionButton: FloatingActionButton(
onPressed: () => typeThisWidget.controller.reset(),
child: const Icon(Icons.refresh),
child: CustomDecoratedBox(
typeThisWidget: typeThisWidget,
onResetPressed: () => typeThisWidget.controller.reset(),
onFreezePressed: () => typeThisWidget.controller.freeze(),
onUnfreezePressed: () => typeThisWidget.controller.unfreeze(),
),
),
),
);
Expand Down
104 changes: 104 additions & 0 deletions example/lib/widgets/custom_decorated_box.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
import 'package:flutter/material.dart';

class CustomDecoratedBox extends StatelessWidget {
const CustomDecoratedBox({
super.key,
required this.typeThisWidget,
required this.onResetPressed,
required this.onFreezePressed,
required this.onUnfreezePressed,
});
final Widget typeThisWidget;
final VoidCallback onResetPressed;
final VoidCallback onFreezePressed;
final VoidCallback onUnfreezePressed;

@override
Widget build(BuildContext context) {
return Container(
constraints: const BoxConstraints(maxWidth: 550),
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
const SizedBox(height: 24),
const _BuildDocumentation(),
const SizedBox(height: 24),
Container(
height: 60,
width: double.infinity,
padding: const EdgeInsets.symmetric(
vertical: 8,
horizontal: 16,
),
decoration: BoxDecoration(
borderRadius: BorderRadius.circular(16),
color: Colors.grey[200],
),
child: typeThisWidget,
),
const SizedBox(height: 24),
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
OutlinedButton.icon(
onPressed: onResetPressed,
icon: const Icon(Icons.refresh),
label: const Text('Reset'),
),
const SizedBox(width: 12),
OutlinedButton.icon(
onPressed: onFreezePressed,
icon: const Icon(Icons.pause),
label: const Text('Freeze'),
),
const SizedBox(width: 12),
OutlinedButton.icon(
onPressed: onUnfreezePressed,
icon: const Icon(Icons.play_arrow),
label: const Text('Unfreeze'),
),
],
),
],
),
);
}
}

class _BuildDocumentation extends StatelessWidget {
const _BuildDocumentation();

@override
Widget build(BuildContext context) {
return const Text.rich(
TextSpan(
style: TextStyle(fontSize: 16),
children: [
TextSpan(
text: '• reset() : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(
text: 'Resets the typing animation.',
),
TextSpan(
text: '\n• freeze() : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(
text: 'Freezes / pauses the typing animation.',
),
TextSpan(
text: '\n• unfreeze() : ',
style: TextStyle(fontWeight: FontWeight.bold),
),
TextSpan(
text: 'Resumes the typing animation.',
),
],
),
);
}
}
1 change: 1 addition & 0 deletions example/lib/widgets/widgets.dart
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export 'custom_decorated_box.dart';
28 changes: 28 additions & 0 deletions lib/src/typethis_controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,34 @@ class TypeThisController with ChangeNotifier {
_startTimerAndNotify();
}

/// Freezes the typing animation.
///
/// ```dart
/// // Extract the [TypeThis] widget into a separate variable.
/// final typeThisWidget = TypeThis(
/// string: 'Hi there! How are you doing?',
/// speed: 50,
/// style: TextStyle(fontSize: 18, color: Colors.black),
/// );
///
/// // Freezes the animation
/// typeThisWidget.controller.freeze();
/// ```
void freeze() {
timer?.cancel();
}

/// Unfreezes the typing animation, means the animation resumes
/// from where it was frozen last time.
void unfreeze() {
// for safety, if unfreeze() is called without freeze() being called
// previously.
timer?.cancel();
if (_steps != _maxBoundLength) {
_startTimerAndNotify();
}
}

@override
void dispose() {
timer?.cancel();
Expand Down
4 changes: 2 additions & 2 deletions pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
name: typethis
description: A flutter package that aims to simplify versatile typing animation with reset functionality.
description: A flutter package that aims to simplify versatile typing animation with reset, freeze and unfreeze functionality.
repository: https://github.com/thecodexhub/typethis
issue_tracker: https://github.com/thecodexhub/typethis/issues
homepage: https://github.com/thecodexhub/typethis
documentation: https://github.com/thecodexhub/typethis

version: 0.1.1
version: 0.2.0

environment:
sdk: ">=3.1.3 <4.0.0"
Expand Down
Binary file removed screenshots/typethis.gif
Binary file not shown.
40 changes: 40 additions & 0 deletions test/typethis_controller_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -66,5 +66,45 @@ void main() {
expect(secondTimer?.isActive, false);
expect(controller.timer?.isActive, true);
});

test('freeze method freezes the controller', () async {
final controller = TypeThisController(
const Duration(milliseconds: 100),
5,
);
final previousTimer = controller.timer;

expect(previousTimer?.isActive, true);

await Future.delayed(const Duration(milliseconds: 350));
controller.freeze();

expect(controller.timer?.isActive, false);
expect(controller.steps, equals(3));
});

test(
'unfreeze method resumes the controller from freezing point',
() async {
final controller = TypeThisController(
const Duration(milliseconds: 100),
7,
);
final previousTimer = controller.timer;

expect(previousTimer?.isActive, true);

await Future.delayed(const Duration(milliseconds: 350));
controller.freeze();

expect(controller.steps, equals(3));

controller.unfreeze();
await Future.delayed(const Duration(milliseconds: 250));

expect(controller.timer?.isActive, true);
expect(controller.steps, equals(5));
},
);
});
}

0 comments on commit 4cb686b

Please sign in to comment.