diff --git a/CHANGELOG.md b/CHANGELOG.md
index 479bf76..88a13b0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,63 +1,4 @@
-## 1.0.0
-- chore: bump minimum Dart SDK version to 3.7
-- chore: bump `extended_image` to `^10.0.1`
-- chore: bump `provider` to `^6.1.5+1`
-
-## 0.1.2
-
-- fix: the endless loop can still happen if you switch between tabs quickly and time it perfectly while still loading gifs.
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.1.1...0.1.2)
-
-## 0.1.1
-
-- fix: if you switch tabs very quickly before the initial gif fetch then you will get stuck in an endless loop and crash the app.
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.1.0...0.1.1)
-
-## 0.1.0
-
-- feat: Integrate [tenor_dart's](https://pub.dev/packages/tenor_dart) new `TenorResult.source` parameter to track which tab the GIF was selected from for analytics
-- fix: not being able to scroll down to load more on tablets or when using display zoom on iPad
-- refactor: `TenorViewEmojis`, `TenorViewGifs`, `TenorViewStickers` and `TenorTabView` now have a `gifsPerRow` parameter instead of `mediaWidth` to be more explicit and support a wider range of devices
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.0.5...0.1.0)
-
-## 0.0.5
-
-- fix: error when only one tab is passed in
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.0.4...0.0.5)
-
-## 0.0.4
-
-- feature: add `coverAppBar` _(false)_ to disable calculations preventing bottom sheet from covering AppBar
-- refactor: expose `animationStyle` as a parameter of `TenorStyle`
-- refactor: expose `initialExtent` as a parameter of `showAsBottomSheet()`, defaults to `maxExtent` if not used
-- refactor: expose `snapSizes` as a parameter of `showAsBottomSheet()`
-- refactor: expose `useSafeArea` as a parameter of `showAsBottomSheet()`
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.0.3...0.0.4)
-
-## 0.0.3
-
-- chore: write tests
-- chore: updated/added examples and broke them up for a better experience
-- fix: category was displaying `searchTerm` and now it's displaying `name` as that is localized from Tenor
- - added `stripHashtag` _(true)_ to `TenorCategoryStyle` so you can display a hashtag before each category name if you'd like _(comes like that from Tenor)_
-- fix: issue where featured category could not be localized
-- refactor: expose `keyboardDismissBehavior` as a parameter of `showAsBottomSheet()`
-- refactor: expose `searchFieldHintText` as a parameter of `showAsBottomSheet()` to make localization easier
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.0.2...0.0.3)
-
-## 0.0.2
-
-- chore: write tests
-- refactor: support `tenor_dart` changes
-
-[All Code Changes](https://github.com/Flyclops/tenor_flutter/compare/0.0.1...0.0.2)
-
## 0.0.1
-- Initial version
+- refactor: [klipy_flutter](https://pub.dev/packages/klipy_flutter) so that it supports the KLIPY API via their [migration docs](https://docs.klipy.com/migrate-from-tenor).
+- BREAKING: `contentFilter` has been removed and can be set via the [Partner Panel](https://docs.klipy.com/migrate-from-tenor/content-filtering)
\ No newline at end of file
diff --git a/README.md b/README.md
index 5506d23..697ad9a 100644
--- a/README.md
+++ b/README.md
@@ -1,85 +1,84 @@
-# Tenor Flutter
+# KLIPY Flutter
-
-
-
-
-
+
+
+
+
+
-This package integrates [Tenor GIF search](https://tenor.com/) into [Flutter](https://flutter.dev/) by utilizing the [tenor_dart](https://pub.dev/packages/tenor_dart) package to communicate directly with the [Tenor API V2](https://developers.google.com/tenor/guides/quickstart) via [http](https://pub.dev/packages/http).
+This package integrates [KLIPY GIF search](https://klipy.com/) into [Flutter](https://flutter.dev/) by utilizing the [klipy_dart](https://pub.dev/packages/klipy_dart) package to communicate directly with the [KLIPY API](https://docs.klipy.com/getting-started) via [http](https://pub.dev/packages/http). We are currently using the [migration from Tenor](https://docs.klipy.com/migrate-from-tenor) option but plan to build this package out to be feature complete with the KLIPY API.
-The package currently provides an opinionated yet customizable UI experience for searching and selecting from a list of GIFs/Stickers from the Tenor GIF search API.
+The package currently provides an opinionated yet customizable UI experience for searching and selecting from a list of GIFs/Stickers from the KLIPY GIF search API.
-
+
-Show some ❤️ and star the repo to support this package.
+Show some ❤️ and star the repo to support this package.
## What to know
-- In order to start using Tenor Flutter you must obtain an API key by registering your project with [Tenor](https://developers.google.com/tenor/guides/quickstart).
-- Tenor requires proper [attribution](https://developers.google.com/tenor/guides/attribution) for projects using their API. This package enables "Powered By Tenor" and "Search Tenor" by default. You are only required to have one.
+- In order to start using KLIPY Dart you must obtain an API key by registering your project with [KLIPY](https://docs.klipy.com/getting-started).
+- KLIPY requires proper [attribution](https://docs.klipy.com/attribution) for projects using their API. This package does not handle the attribution process, so you will need to take care of it yourself.
-## Obtaining Tenor API v2 key
+## Obtaining KLIPY API key
-1. Log in to the [Google Cloud Console](https://console.cloud.google.com)
-2. Create a [new project](https://console.cloud.google.com/projectcreate)
-3. Go to the Google Cloud Marketplace and find the [Tenor API](https://console.cloud.google.com/marketplace/product/google/tenor.googleapis.com)
-4. Click `Enable` to activate it
-5. In the navigation menu, go to the `APIs & Services` tab and select [Credentials](https://console.cloud.google.com/apis/credentials)
-6. Click `+ Create Credentials` and choose `API key`
-7. Copy the generated API key
-8. Provide this API key as a parameter to `Tenor(apiKey: 'YOUR_API_KEY')`
+1. Log in to the [partner panel](https://partner.klipy.com)
+2. Add a [new platform](https://partner.klipy.com/api-keys)
+3. Click `Create Key`
+4. Copy the generated API key
+5. Provide this API key as a parameter to `KlipyClient(apiKey: 'YOUR_API_KEY')`
## Usage
### Installation
```
-flutter pub add tenor_flutter
+flutter pub add klipy_flutter
```
-Having trouble? Read the pub.dev installation page.
+Having trouble? Read the pub.dev installation page.
### Import
Import the package into the dart file where it will be used:
```
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
```
### Initialize
-You must pass in a valid `apiKey` provided by [Tenor](https://developers.google.com/tenor/guides/quickstart). It's **strongly recommended** to also pass in a `clientKey` as this will help you distinguish which project is making the requests.
+You must pass in a valid `apiKey` provided by [KLIPY](https://docs.klipy.com/getting-started).
+
+If you would like to distinguish between projects/devices then consider creating seperate [API keys](https://partner.klipy.com/api-keys) under the same platform.
```
-final tenorClient = Tenor(apiKey: 'YOUR_API_KEY', clientKey: 'YOUR_PROJECT_NAME');
+final klipyClient = KlipyClient(apiKey: 'YOUR_API_KEY');
```
## Example
-For more elaborate examples feel free to check out [example/lib/main.dart](https://github.com/Flyclops/tenor_flutter/blob/main/example/lib/main.dart).
+For more elaborate examples feel free to check out [example/lib/main.dart](https://github.com/Flyclops/klipy_flutter/blob/main/example/lib/main.dart).
Here's how to display the UI as a bottom sheet and then print the user's selection. If `null` is returned, it means the user closed the sheet without choosing a GIF.
```
-final tenorClient = Tenor(apiKey: 'YOUR_API_KEY', clientKey: 'YOUR_PROJECT_NAME');
-final TenorResult? result = await tenorClient.showAsBottomSheet(context: context);
+final klipyClient = KlipyClient(apiKey: 'YOUR_API_KEY');
+final KlipyResultObject? result = await klipyClient.showAsBottomSheet(context: context);
print(result?.media.tinyGif?.url);
```
## Don't need the UI?
-If you're seeking a solution that allows for full customization without the need of dependencies then consider [Tenor Dart](https://github.com/Flyclops/tenor_dart).
+If you're seeking a solution that allows for full customization without the need of dependencies then consider [KLIPY Dart](https://github.com/Flyclops/klipy_dart).
## Sponsors
- 
|
- 
|
+ 
|
+ 
|
Flyclops is a independent mobile games studio specializing in casual multi-player games, both asynchronous turn-based, and real-time. Flyclops’s games have been played by millions across the globe. |
@@ -90,14 +89,14 @@ If you're seeking a solution that allows for full customization without the need
## What's next?
- Documentation
-- Tests _([Contributions](https://github.com/Flyclops/tenor_flutter/blob/main/CONTRIBUTING.md) welcome)_ ^\_^
+- Tests _([Contributions](https://github.com/Flyclops/klipy_flutter/blob/main/CONTRIBUTING.md) welcome)_ ^\_^
- Further improvements
## Contributing
-If you read this far then you are awesome! There are a multiple ways in which you can [contribute](https://github.com/Flyclops/tenor_flutter/blob/main/CONTRIBUTING.md):
+If you read this far then you are awesome! There are a multiple ways in which you can [contribute](https://github.com/Flyclops/klipy_flutter/blob/main/CONTRIBUTING.md):
-- Pick up any issue marked with "[good first issue](https://github.com/flyclops/tenor_flutter/issues?q=is:open+is:issue+label:%22good+first+issue%22)"
+- Pick up any issue marked with "[good first issue](https://github.com/flyclops/klipy_flutter/issues?q=is:open+is:issue+label:%22good+first+issue%22)"
- Propose any feature, enhancement
- Report a bug
- Fix a bug
diff --git a/assets/media_watermark.png b/assets/media_watermark.png
new file mode 100644
index 0000000..9bafc25
Binary files /dev/null and b/assets/media_watermark.png differ
diff --git a/assets/powered_by_dark.png b/assets/powered_by_dark.png
index 9f084f0..294e47c 100644
Binary files a/assets/powered_by_dark.png and b/assets/powered_by_dark.png differ
diff --git a/assets/powered_by_light.png b/assets/powered_by_light.png
index 86b6a4f..3198bb6 100644
Binary files a/assets/powered_by_light.png and b/assets/powered_by_light.png differ
diff --git a/example/README.md b/example/README.md
index 56af23f..bebc0e3 100644
--- a/example/README.md
+++ b/example/README.md
@@ -1,3 +1,3 @@
-# Tenor Flutter Example
+# KLIPY Flutter Example
-If you want to test this example create a `.env` file located at `example/.env` with your [Tenor API](https://developers.google.com/tenor/guides/quickstart) key `TENOR_API_KEY=PUT_YOUR_KEY_HERE` and then run `example/lib/main.dart`.
+If you want to test this example create a `.env` file located at `example/.env` with your [KLIPY API](https://docs.klipy.com/getting-started) key `KLIPY_API_KEY=PUT_YOUR_KEY_HERE` and then run `example/lib/main.dart`.
diff --git a/example/assets/demo.gif b/example/assets/demo.gif
index 5e0a07b..00db346 100644
Binary files a/example/assets/demo.gif and b/example/assets/demo.gif differ
diff --git a/example/assets/domino_logo_github.png b/example/assets/domino_logo_github.png
index 8b27928..acd7ea3 100644
Binary files a/example/assets/domino_logo_github.png and b/example/assets/domino_logo_github.png differ
diff --git a/example/assets/flyclops_logo_github.png b/example/assets/flyclops_logo_github.png
index a24c69e..7a56c57 100644
Binary files a/example/assets/flyclops_logo_github.png and b/example/assets/flyclops_logo_github.png differ
diff --git a/example/lib/examples/dark_theme.dart b/example/lib/examples/dark_theme.dart
index 91a7eaa..b70b93c 100644
--- a/example/lib/examples/dark_theme.dart
+++ b/example/lib/examples/dark_theme.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
class DarkTheme extends StatefulWidget {
const DarkTheme({super.key});
@@ -10,10 +10,10 @@ class DarkTheme extends StatefulWidget {
}
class DarkThemeState extends State {
- // replace apiKey with an api key provided by Tenor > https://developers.google.com/tenor/guides/quickstart
- var tenor = Tenor(apiKey: FlutterConfig.get('TENOR_API_KEY'));
+ // replace apiKey with an api key provided by KLIPY > https://docs.klipy.com/getting-started
+ var klipyClient = KlipyClient(apiKey: FlutterConfig.get('KLIPY_API_KEY'));
// define a result that we can display later
- TenorResult? selectedResult;
+ KlipyResultObject? selectedResult;
@override
Widget build(BuildContext context) {
@@ -44,11 +44,11 @@ class DarkThemeState extends State {
FloatingActionButton(
backgroundColor: Colors.black,
onPressed: () async {
- final result = await tenor.showAsBottomSheet(
+ final result = await klipyClient.showAsBottomSheet(
context: context,
- style: TenorStyle(
+ style: KlipyStyle(
color: const Color(0xFF2b2d31),
- searchFieldStyle: const TenorSearchFieldStyle(
+ searchFieldStyle: const KlipySearchFieldStyle(
fillColor: Color(0xFF1e1f22),
hintStyle: TextStyle(
color: Color(0xFFb5bac1),
@@ -61,10 +61,10 @@ class DarkThemeState extends State {
fontWeight: FontWeight.normal,
),
),
- attributionStyle: const TenorAttributionStyle(
+ attributionStyle: const KlipyAttributionStyle(
brightnes: Brightness.dark,
),
- tabBarStyle: TenorTabBarStyle(
+ tabBarStyle: KlipyTabBarStyle(
decoration: BoxDecoration(
color: const Color(0xFF1e1f22),
border: Border.all(
@@ -85,7 +85,7 @@ class DarkThemeState extends State {
unselectedLabelColor: const Color(0xFFb5bac1),
labelColor: Colors.white,
),
- selectedCategoryStyle: const TenorSelectedCategoryStyle(
+ selectedCategoryStyle: const KlipySelectedCategoryStyle(
icon: Icon(
Icons.arrow_back_ios_new,
size: 15,
@@ -97,35 +97,35 @@ class DarkThemeState extends State {
fontWeight: FontWeight.normal,
),
),
- tabViewStyle: const TenorTabViewStyle(
+ tabViewStyle: const KlipyTabViewStyle(
mediaBackgroundColor: Color(0xFF404249),
),
),
tabs: [
- TenorTab(
+ KlipyTab(
name: 'Emojis',
- view: TenorViewEmojis(
- client: tenor,
- style: const TenorTabViewStyle(
+ view: KlipyViewEmojis(
+ client: klipyClient,
+ style: const KlipyTabViewStyle(
mediaBackgroundColor: Color(0xFF404249),
),
),
),
- TenorTab(
+ KlipyTab(
name: 'GIFs',
- view: TenorViewGifs(
- client: tenor,
- style: const TenorTabViewStyle(
+ view: KlipyViewGifs(
+ client: klipyClient,
+ style: const KlipyTabViewStyle(
mediaBackgroundColor: Color(0xFF404249),
),
featuredCategory: '📈 Featured22',
),
),
- TenorTab(
+ KlipyTab(
name: 'Stickers',
- view: TenorViewStickers(
- client: tenor,
- style: const TenorTabViewStyle(
+ view: KlipyViewStickers(
+ client: klipyClient,
+ style: const KlipyTabViewStyle(
mediaBackgroundColor: Color(0xFF404249),
),
),
diff --git a/example/lib/examples/localization.dart b/example/lib/examples/localization.dart
index d521fcc..0c8d590 100644
--- a/example/lib/examples/localization.dart
+++ b/example/lib/examples/localization.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
class Localization extends StatefulWidget {
const Localization({super.key});
@@ -10,14 +10,14 @@ class Localization extends StatefulWidget {
}
class LocalizationState extends State {
- // replace apiKey with an api key provided by Tenor > https://developers.google.com/tenor/guides/quickstart
- var tenor = Tenor(
- apiKey: FlutterConfig.get('TENOR_API_KEY'),
+ // replace apiKey with an api key provided by KLIPY > https://docs.klipy.com/getting-started
+ var klipyClient = KlipyClient(
+ apiKey: FlutterConfig.get('KLIPY_API_KEY'),
country: 'es',
locale: 'es_ES',
);
// define a result that we can display later
- TenorResult? selectedResult;
+ KlipyResultObject? selectedResult;
@override
Widget build(BuildContext context) {
@@ -47,27 +47,27 @@ class LocalizationState extends State {
children: [
FloatingActionButton(
onPressed: () async {
- final result = await tenor.showAsBottomSheet(
+ final result = await klipyClient.showAsBottomSheet(
context: context,
- searchFieldHintText: 'Buscar Tenor',
+ searchFieldHintText: 'Buscar KLIPY',
tabs: [
- TenorTab(
+ KlipyTab(
name: 'Caritas',
- view: TenorViewEmojis(
- client: tenor,
+ view: KlipyViewEmojis(
+ client: klipyClient,
),
),
- TenorTab(
+ KlipyTab(
name: 'Fotos',
- view: TenorViewGifs(
- client: tenor,
+ view: KlipyViewGifs(
+ client: klipyClient,
featuredCategory: '📈 Destacada',
),
),
- TenorTab(
+ KlipyTab(
name: 'Pegatinas',
- view: TenorViewStickers(
- client: tenor,
+ view: KlipyViewStickers(
+ client: klipyClient,
),
),
],
diff --git a/example/lib/main.dart b/example/lib/main.dart
index 38b0f1a..03374c3 100644
--- a/example/lib/main.dart
+++ b/example/lib/main.dart
@@ -1,8 +1,8 @@
import 'package:flutter/material.dart';
import 'package:flutter_config/flutter_config.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
-import 'package:tenor_flutter_example/examples/dark_theme.dart';
-import 'package:tenor_flutter_example/examples/localization.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
+import 'package:klipy_flutter_example/examples/dark_theme.dart';
+import 'package:klipy_flutter_example/examples/localization.dart';
void main() async {
// only used to load api key from .env file, not required
@@ -18,7 +18,7 @@ class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
- title: 'Tenor Flutter Demo',
+ title: 'KLIPY Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
@@ -35,27 +35,28 @@ class MyHomePage extends StatefulWidget {
}
class _MyHomePageState extends State {
- // replace apiKey with an api key provided by Tenor > https://developers.google.com/tenor/guides/quickstart
- var tenor = Tenor(apiKey: FlutterConfig.get('TENOR_API_KEY'));
+ // replace apiKey with an api key provided by KLIPY > https://docs.klipy.com/getting-started
+ var klipyClient = KlipyClient(apiKey: FlutterConfig.get('KLIPY_API_KEY'));
// define a result that we can display later
- TenorResult? selectedResult;
+ KlipyResultObject? selectedResult;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
backgroundColor: Theme.of(context).colorScheme.inversePrimary,
- title: const Text('Tenor Flutter Demo'),
+ title: const Text('KLIPY Flutter Demo'),
),
body: _exampleBody(),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: [
- // A default implementation of tenor flutter. Displays the gif picker
+ // A default implementation of klipy flutter. Displays the gif picker
// as a bottom sheet and then updates the selectedResult in state.
FloatingActionButton(
onPressed: () async {
- final result = await tenor.showAsBottomSheet(context: context);
+ final result =
+ await klipyClient.showAsBottomSheet(context: context);
setState(() {
selectedResult = result;
});
@@ -68,7 +69,7 @@ class _MyHomePageState extends State {
);
}
- // Additional examples, see: https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples
+ // Additional examples, see: https://github.com/Flyclops/klipy_flutter/tree/main/example/lib/examples
Widget _exampleBody() {
final selectedGif = selectedResult?.media.tinyGif ??
selectedResult?.media.tinyGifTransparent;
@@ -87,12 +88,12 @@ class _MyHomePageState extends State {
alignment: WrapAlignment.center,
spacing: 8,
children: [
- // https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples/dark_theme.dart
+ // https://github.com/Flyclops/klipy_flutter/tree/main/example/lib/examples/dark_theme.dart
ElevatedButton(
onPressed: () => push(const DarkTheme()),
child: const Text('Dark Theme'),
),
- // https://github.com/Flyclops/tenor_flutter/tree/main/example/lib/examples/localization.dart
+ // https://github.com/Flyclops/klipy_flutter/tree/main/example/lib/examples/localization.dart
ElevatedButton(
onPressed: () => push(const Localization()),
child: const Text('Localization'),
@@ -106,10 +107,12 @@ class _MyHomePageState extends State {
mainAxisAlignment: MainAxisAlignment.center,
children: [
selectedResult != null && selectedGif != null
- ? Image.network(
- selectedGif.url,
- width: selectedGif.dimensions.width,
- height: selectedGif.dimensions.height,
+ ? KlipyMediaWidget(
+ media: Image.network(
+ selectedGif.url,
+ width: selectedGif.dimensions.width,
+ height: selectedGif.dimensions.height,
+ ),
)
: const Text('No GIF selected'),
selectedGif != null
diff --git a/example/pubspec.yaml b/example/pubspec.yaml
index 0b50a34..7317123 100644
--- a/example/pubspec.yaml
+++ b/example/pubspec.yaml
@@ -1,19 +1,18 @@
-name: tenor_flutter_example
-description: "An example of how to use Tenor Flutter"
+name: klipy_flutter_example
+description: "An example of how to use KLIPY Flutter"
publish_to: "none"
-
-version: 1.0.0+1
+version: 1.0.0
environment:
sdk: ">=3.2.6 <4.0.0"
dependencies:
+ cupertino_icons: ^1.0.2
flutter:
sdk: flutter
flutter_config: ^2.0.2
- tenor_flutter:
+ klipy_flutter:
path: ../
- cupertino_icons: ^1.0.2
dev_dependencies:
flutter_test:
diff --git a/lib/klipy_flutter.dart b/lib/klipy_flutter.dart
new file mode 100644
index 0000000..207be10
--- /dev/null
+++ b/lib/klipy_flutter.dart
@@ -0,0 +1,15 @@
+// hide KlipyClient from klipy_dart so we can extend it later
+export 'package:klipy_dart/klipy_dart.dart' hide KlipyClient;
+
+export 'src/components/attribution.dart' show KlipyAttributionStyle;
+export 'src/components/drag_handle.dart' show KlipyDragHandleStyle;
+export 'src/components/media_widget.dart' show KlipyMediaWidget;
+export 'src/components/search_field.dart'
+ show KlipySelectedCategoryStyle, KlipySearchFieldStyle;
+export 'src/components/tab_bar.dart' show KlipyTabBarStyle;
+export 'src/components/tab_view_emojis.dart';
+export 'src/components/tab_view_gifs.dart';
+export 'src/components/tab_view_stickers.dart';
+export 'src/components/tab_view.dart' show KlipyTabView, KlipyTabViewStyle;
+export 'src/klipy_client.dart';
+export 'src/models/models.dart';
diff --git a/lib/src/components/attribution.dart b/lib/src/components/attribution.dart
index 8787431..20157f4 100644
--- a/lib/src/components/attribution.dart
+++ b/lib/src/components/attribution.dart
@@ -1,59 +1,51 @@
import 'package:flutter/material.dart';
-class TenorAttributionStyle {
+class KlipyAttributionStyle {
final Brightness brightnes;
final double height;
final EdgeInsets padding;
- const TenorAttributionStyle({
+ const KlipyAttributionStyle({
this.brightnes = Brightness.light,
- this.height = 15,
- this.padding = const EdgeInsets.symmetric(
- vertical: 8,
- ),
+ this.height = 20,
+ this.padding = const EdgeInsets.symmetric(vertical: 8),
});
}
-class TenorAttribution extends StatelessWidget {
- final TenorAttributionStyle style;
+class KlipyAttribution extends StatelessWidget {
+ final KlipyAttributionStyle style;
- const TenorAttribution({
- this.style = const TenorAttributionStyle(),
+ const KlipyAttribution({
+ this.style = const KlipyAttributionStyle(),
super.key,
});
@override
Widget build(BuildContext context) {
+ String logoPath =
+ style.brightnes == Brightness.light
+ ? 'powered_by_dark.png'
+ : 'powered_by_light.png';
return Padding(
// If safe area is required, add it.
- padding: MediaQuery.of(context).padding.bottom > 0
- ? style.padding.copyWith(
- bottom: MediaQuery.of(context).padding.bottom,
- )
- : style.padding,
+ padding:
+ MediaQuery.of(context).padding.bottom > 0
+ ? style.padding.copyWith(
+ bottom: MediaQuery.of(context).padding.bottom,
+ )
+ : style.padding,
child: Center(
- child: _logo(context),
- ),
- );
- }
-
- Widget _logo(BuildContext context) {
- String logoPath = style.brightnes == Brightness.light
- ? 'powered_by_dark.png'
- : 'powered_by_light.png';
-
- return Container(
- height: style.height,
- decoration: BoxDecoration(
- image: DecorationImage(
- fit: BoxFit.fitHeight,
- image: AssetImage(
+ child: Container(
+ alignment: Alignment.center,
+ width: double.infinity,
+ child: Image.asset(
'assets/$logoPath',
- package: 'tenor_flutter',
+ package: 'klipy_flutter',
+ height: style.height,
+ fit: BoxFit.contain,
),
),
),
- width: double.infinity,
);
}
}
diff --git a/lib/src/components/category.dart b/lib/src/components/category.dart
index 766d43f..77b5289 100644
--- a/lib/src/components/category.dart
+++ b/lib/src/components/category.dart
@@ -1,8 +1,8 @@
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
-import 'package:tenor_dart/tenor_dart.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorCategoryStyle {
+class KlipyCategoryStyle {
/// Allows you to set a fallback decoration for people to see if the image loads slow or fails.
final Decoration decoration;
@@ -12,7 +12,7 @@ class TenorCategoryStyle {
/// Color that shows between the category text and image.
final Color imageOverlayColor;
- /// Tenor returns "#" back with the category name, this will strip it.
+ /// KLIPY returns "#" back with the category name, this will strip it.
final bool stripHashtag;
/// Control how the category text looks.
@@ -21,10 +21,8 @@ class TenorCategoryStyle {
/// Used to stop text from touching the edges when `FittedBox` kicks in.
final EdgeInsets padding;
- const TenorCategoryStyle({
- this.decoration = const BoxDecoration(
- color: Color(0xFFBEB9AC),
- ),
+ const KlipyCategoryStyle({
+ this.decoration = const BoxDecoration(color: Color(0xFFBEB9AC)),
this.height = 100,
this.imageOverlayColor = const Color.fromRGBO(0, 0, 0, 0.5),
this.padding = const EdgeInsets.all(8),
@@ -37,29 +35,29 @@ class TenorCategoryStyle {
});
}
-class TenorCategoryWidget extends StatelessWidget {
- final TenorCategory? category;
- final Function(TenorCategory)? onTap;
- final TenorCategoryStyle style;
+class KlipyCategoryWidget extends StatelessWidget {
+ final KlipyCategoryObject? category;
+ final Function(KlipyCategoryObject)? onTap;
+ final KlipyCategoryStyle style;
- const TenorCategoryWidget({
+ const KlipyCategoryWidget({
this.category,
this.onTap,
- this.style = const TenorCategoryStyle(),
+ this.style = const KlipyCategoryStyle(),
super.key,
});
@override
Widget build(BuildContext context) {
// for promotion
- final tenorCategory = category;
- final tenorCategoryImage = tenorCategory?.image;
+ final klipyCategory = category;
+ final klipyCategoryImage = klipyCategory?.image;
// early out
- if (tenorCategory == null) return const SizedBox.shrink();
+ if (klipyCategory == null) return const SizedBox.shrink();
return GestureDetector(
- onTap: () => onTap?.call(tenorCategory),
+ onTap: () => onTap?.call(klipyCategory),
child: Container(
height: style.height,
decoration: style.decoration,
@@ -67,9 +65,9 @@ class TenorCategoryWidget extends StatelessWidget {
child: Stack(
fit: StackFit.expand,
children: [
- if (tenorCategoryImage != null && tenorCategoryImage.isNotEmpty)
+ if (klipyCategoryImage != null && klipyCategoryImage.isNotEmpty)
ExtendedImage.network(
- tenorCategoryImage,
+ klipyCategoryImage,
cache: true,
gaplessPlayback: true,
fit: BoxFit.cover,
@@ -81,9 +79,9 @@ class TenorCategoryWidget extends StatelessWidget {
child: FittedBox(
fit: BoxFit.fitWidth,
child: Text(
- style.stripHashtag && tenorCategory.name.startsWith('#')
- ? tenorCategory.name.substring(1)
- : tenorCategory.name,
+ style.stripHashtag && klipyCategory.name.startsWith('#')
+ ? klipyCategory.name.substring(1)
+ : klipyCategory.name,
style: style.textStyle,
),
),
diff --git a/lib/src/components/components.dart b/lib/src/components/components.dart
index cc9a5aa..ea0eb16 100644
--- a/lib/src/components/components.dart
+++ b/lib/src/components/components.dart
@@ -1,11 +1,12 @@
export 'attribution.dart';
export 'category.dart';
export 'drag_handle.dart';
+export 'media_widget.dart';
export 'search_field.dart';
export 'selectable_gif.dart';
export 'sheet.dart';
export 'tab_bar.dart';
-export 'tab_view.dart';
export 'tab_view_emojis.dart';
export 'tab_view_gifs.dart';
export 'tab_view_stickers.dart';
+export 'tab_view.dart';
diff --git a/lib/src/components/drag_handle.dart b/lib/src/components/drag_handle.dart
index 64fb529..5b79e14 100644
--- a/lib/src/components/drag_handle.dart
+++ b/lib/src/components/drag_handle.dart
@@ -1,31 +1,27 @@
import 'package:flutter/material.dart';
-class TenorDragHandleStyle {
+class KlipyDragHandleStyle {
final Decoration decoration;
final double height;
final EdgeInsets margin;
final double width;
- const TenorDragHandleStyle({
+ const KlipyDragHandleStyle({
this.decoration = const BoxDecoration(
color: Color(0xFF8A8A86),
- borderRadius: BorderRadius.all(
- Radius.circular(100),
- ),
+ borderRadius: BorderRadius.all(Radius.circular(100)),
),
this.height = 4,
- this.margin = const EdgeInsets.symmetric(
- vertical: 8,
- ),
+ this.margin = const EdgeInsets.symmetric(vertical: 8),
this.width = 134,
});
}
-class TenorDragHandle extends StatelessWidget {
- final TenorDragHandleStyle _style;
+class KlipyDragHandle extends StatelessWidget {
+ final KlipyDragHandleStyle _style;
- const TenorDragHandle({
- TenorDragHandleStyle style = const TenorDragHandleStyle(),
+ const KlipyDragHandle({
+ KlipyDragHandleStyle style = const KlipyDragHandleStyle(),
super.key,
}) : _style = style;
diff --git a/lib/src/components/media_widget.dart b/lib/src/components/media_widget.dart
new file mode 100644
index 0000000..60f113f
--- /dev/null
+++ b/lib/src/components/media_widget.dart
@@ -0,0 +1,26 @@
+import 'package:flutter/material.dart';
+import 'package:flutter/widgets.dart';
+
+class KlipyMediaWidget extends StatelessWidget {
+ final Widget media;
+
+ const KlipyMediaWidget({required this.media, super.key});
+
+ @override
+ Widget build(BuildContext context) {
+ return Stack(
+ children: [
+ media,
+ Positioned(
+ bottom: 2,
+ left: 2,
+ child: Image.asset(
+ 'assets/media_watermark.png',
+ package: 'klipy_flutter',
+ height: 10,
+ ),
+ ),
+ ],
+ );
+ }
+}
diff --git a/lib/src/components/search_field.dart b/lib/src/components/search_field.dart
index 1da9c00..e6ff8c9 100644
--- a/lib/src/components/search_field.dart
+++ b/lib/src/components/search_field.dart
@@ -2,12 +2,12 @@
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
-import 'package:tenor_flutter/src/providers/app_bar_provider.dart';
-import 'package:tenor_flutter/src/providers/sheet_provider.dart';
-import 'package:tenor_flutter/src/utilities/debouncer.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
+import 'package:klipy_flutter/src/providers/app_bar_provider.dart';
+import 'package:klipy_flutter/src/providers/sheet_provider.dart';
+import 'package:klipy_flutter/src/utilities/debouncer.dart';
-class TenorSelectedCategoryStyle {
+class KlipySelectedCategoryStyle {
final double height;
final EdgeInsets padding;
final Icon? icon;
@@ -16,12 +16,9 @@ class TenorSelectedCategoryStyle {
/// The space between icon and text.
final double spaceBetween;
- const TenorSelectedCategoryStyle({
+ const KlipySelectedCategoryStyle({
this.height = 52,
- this.padding = const EdgeInsets.only(
- left: 14,
- top: 1,
- ),
+ this.padding = const EdgeInsets.only(left: 14, top: 1),
this.icon = const Icon(
Icons.arrow_back_ios_new,
size: 15,
@@ -36,12 +33,12 @@ class TenorSelectedCategoryStyle {
});
}
-class TenorSearchFieldStyle {
+class KlipySearchFieldStyle {
final Color fillColor;
final TextStyle textStyle;
final TextStyle hintStyle;
- const TenorSearchFieldStyle({
+ const KlipySearchFieldStyle({
this.fillColor = Colors.white,
this.hintStyle = const TextStyle(
color: Color(0xFF8A8A86),
@@ -57,34 +54,34 @@ class TenorSearchFieldStyle {
}
/// If you want to style this just pass in your own via the `searchFieldWidget` parameter.
-class TenorSearchField extends StatefulWidget {
+class KlipySearchField extends StatefulWidget {
// Scroll Controller
final ScrollController scrollController;
final TextEditingController? searchFieldController;
final Widget? searchFieldWidget;
- final TenorSelectedCategoryStyle selectedCategoryStyle;
- final TenorSearchFieldStyle style;
+ final KlipySelectedCategoryStyle selectedCategoryStyle;
+ final KlipySearchFieldStyle style;
final String hintText;
final AnimationStyle? animationStyle;
- const TenorSearchField({
+ const KlipySearchField({
super.key,
required this.hintText,
required this.scrollController,
this.animationStyle,
this.searchFieldController,
this.searchFieldWidget,
- this.selectedCategoryStyle = const TenorSelectedCategoryStyle(),
- this.style = const TenorSearchFieldStyle(),
+ this.selectedCategoryStyle = const KlipySelectedCategoryStyle(),
+ this.style = const KlipySearchFieldStyle(),
});
@override
- State createState() => _TenorSearchFieldState();
+ State createState() => _KlipySearchFieldState();
}
-class _TenorSearchFieldState extends State {
- late TenorAppBarProvider _appBarProvider;
- late TenorSheetProvider _sheetProvider;
+class _KlipySearchFieldState extends State {
+ late KlipyAppBarProvider _appBarProvider;
+ late KlipySheetProvider _sheetProvider;
late TextEditingController _textEditingController;
final FocusNode _focus = FocusNode();
@@ -94,22 +91,19 @@ class _TenorSearchFieldState extends State {
_focus.addListener(() => _onFocusChange(widget.animationStyle));
// AppBar Provider
- _appBarProvider = Provider.of(context, listen: false);
+ _appBarProvider = Provider.of(context, listen: false);
// Listen query
_appBarProvider.addListener(_listenerQuery);
// Set Texfield Controller
- _textEditingController = widget.searchFieldController ??
- TextEditingController(
- text: _appBarProvider.queryText,
- );
+ _textEditingController =
+ widget.searchFieldController ??
+ TextEditingController(text: _appBarProvider.queryText);
WidgetsBinding.instance.addPostFrameCallback((_) {
// Establish the debouncer
- final debouncer = TenorDebouncer(
- delay: _appBarProvider.debounce,
- );
+ final debouncer = KlipyDebouncer(delay: _appBarProvider.debounce);
// Listener TextField
_textEditingController.addListener(() {
@@ -125,8 +119,8 @@ class _TenorSearchFieldState extends State {
@override
void didChangeDependencies() {
- _sheetProvider = Provider.of(context);
- _appBarProvider = Provider.of(context);
+ _sheetProvider = Provider.of(context);
+ _appBarProvider = Provider.of(context);
super.didChangeDependencies();
}
@@ -218,7 +212,8 @@ class _TenorSearchFieldState extends State {
padding: const EdgeInsets.all(8),
child: Icon(
Icons.clear,
- color: widget.style.hintStyle.color ??
+ color:
+ widget.style.hintStyle.color ??
const Color(0xFF8A8A86),
size: 20,
),
@@ -241,7 +236,7 @@ class _TenorSearchFieldState extends State {
_sheetProvider.scrollController.animateTo(
_sheetProvider.maxExtent,
duration:
- animationStyle?.duration ?? tenorDefaultAnimationStyle.duration!,
+ animationStyle?.duration ?? klipyDefaultAnimationStyle.duration!,
curve: animationStyle?.curve ?? Curves.linear,
);
}
diff --git a/lib/src/components/selectable_gif.dart b/lib/src/components/selectable_gif.dart
index 44bce1d..e533bba 100644
--- a/lib/src/components/selectable_gif.dart
+++ b/lib/src/components/selectable_gif.dart
@@ -1,13 +1,13 @@
import 'package:extended_image/extended_image.dart';
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorSelectableGif extends StatelessWidget {
+class KlipySelectableGif extends StatelessWidget {
final Color backgroundColor;
- final Function(TenorResult)? onTap;
- final TenorResult result;
+ final Function(KlipyResultObject)? onTap;
+ final KlipyResultObject result;
- const TenorSelectableGif({
+ const KlipySelectableGif({
required this.result,
this.backgroundColor = Colors.transparent,
this.onTap,
diff --git a/lib/src/components/sheet.dart b/lib/src/components/sheet.dart
index bb6b47a..7af7206 100644
--- a/lib/src/components/sheet.dart
+++ b/lib/src/components/sheet.dart
@@ -1,28 +1,27 @@
// ignore_for_file: implementation_imports
import 'package:flutter/material.dart';
+import 'package:klipy_flutter/src/components/attribution.dart';
+import 'package:klipy_flutter/src/components/drag_handle.dart';
+import 'package:klipy_flutter/src/components/search_field.dart';
+import 'package:klipy_flutter/src/components/tab_bar.dart';
+import 'package:klipy_flutter/src/models/attribution.dart';
+import 'package:klipy_flutter/src/models/tab.dart';
+import 'package:klipy_flutter/src/providers/providers.dart';
+import 'package:klipy_flutter/src/klipy_client.dart';
import 'package:provider/provider.dart';
-import 'package:tenor_flutter/src/components/attribution.dart';
-
-import 'package:tenor_flutter/src/components/drag_handle.dart';
-import 'package:tenor_flutter/src/components/search_field.dart';
-import 'package:tenor_flutter/src/components/tab_bar.dart';
-import 'package:tenor_flutter/src/models/attribution.dart';
-import 'package:tenor_flutter/src/models/tab.dart';
-import 'package:tenor_flutter/src/providers/providers.dart';
-import 'package:tenor_flutter/src/tenor.dart';
-
-class TenorSheet extends StatefulWidget {
- final TenorAttributionType attributionType;
+
+class KlipySheet extends StatefulWidget {
+ final KlipyAttributionType attributionType;
final bool coverAppBar;
final int initialTabIndex;
final TextEditingController? searchFieldController;
final String searchFieldHintText;
final Widget? searchFieldWidget;
- final TenorStyle style;
+ final KlipyStyle style;
final List? snapSizes;
- final List tabs;
+ final List tabs;
- const TenorSheet({
+ const KlipySheet({
required this.attributionType,
required this.coverAppBar,
required this.searchFieldHintText,
@@ -36,21 +35,21 @@ class TenorSheet extends StatefulWidget {
});
@override
- State createState() => _TenorSheetState();
+ State createState() => _KlipySheetState();
}
-class _TenorSheetState extends State
+class _KlipySheetState extends State
with SingleTickerProviderStateMixin {
late TabController tabController;
- late TenorSheetProvider sheetProvider;
- late TenorTabProvider tabProvider;
+ late KlipySheetProvider sheetProvider;
+ late KlipyTabProvider tabProvider;
late final bool canShowTabs;
@override
void initState() {
super.initState();
- tabProvider = Provider.of(context, listen: false);
+ tabProvider = Provider.of(context, listen: false);
canShowTabs = widget.tabs.length > 1;
if (canShowTabs) {
@@ -70,7 +69,7 @@ class _TenorSheetState extends State
@override
void didChangeDependencies() {
- sheetProvider = Provider.of(context, listen: false);
+ sheetProvider = Provider.of(context, listen: false);
super.didChangeDependencies();
}
@@ -132,8 +131,9 @@ class _TenorSheetState extends State
onNotification: (notification) {
// Fix a weird bug where the sheet doesn't snap to the minExtent
// Ends in something like 0.5000000000000001 instead of 0.5
- final extent =
- double.parse(notification.extent.toStringAsPrecision(15));
+ final extent = double.parse(
+ notification.extent.toStringAsPrecision(15),
+ );
if (extent == sheetProvider.minExtent) {
sheetProvider.scrollController.jumpTo(sheetProvider.minExtent);
}
@@ -143,13 +143,15 @@ class _TenorSheetState extends State
controller: sheetProvider.scrollController,
expand: false,
// just in case we calculate a smaller maxChildSize than initialChildSize
- initialChildSize: sheetProvider.initialExtent > maxChildSize
- ? maxChildSize
- : sheetProvider.initialExtent,
+ initialChildSize:
+ sheetProvider.initialExtent > maxChildSize
+ ? maxChildSize
+ : sheetProvider.initialExtent,
maxChildSize: maxChildSize,
- minChildSize: sheetProvider.minExtent > maxChildSize
- ? maxChildSize
- : sheetProvider.minExtent,
+ minChildSize:
+ sheetProvider.minExtent > maxChildSize
+ ? maxChildSize
+ : sheetProvider.minExtent,
snap: true,
snapSizes: widget.snapSizes,
builder: (context, scrollController) {
@@ -164,16 +166,14 @@ class _TenorSheetState extends State
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
- const TenorDragHandle(
- style: TenorDragHandleStyle(),
- ),
+ const KlipyDragHandle(style: KlipyDragHandleStyle()),
if (canShowTabs)
- TenorTabBar(
+ KlipyTabBar(
style: widget.style.tabBarStyle,
tabController: tabController,
tabs: widget.tabs.map((tab) => tab.name).toList(),
),
- TenorSearchField(
+ KlipySearchField(
animationStyle: widget.style.animationStyle,
hintText: widget.searchFieldHintText,
scrollController: scrollController,
@@ -184,32 +184,33 @@ class _TenorSheetState extends State
style: widget.style.searchFieldStyle,
),
Expanded(
- child: (canShowTabs)
- ? TabBarView(
- controller: tabController,
- children: widget.tabs
- .map(
- (tab) => MultiProvider(
- providers: [
- Provider(
- create: (context) => constraints,
- ),
- Provider(
- create: (context) => tab,
- ),
- ],
- child: tab.view,
- ),
- )
- .toList(),
- )
- : widget.tabs.first.view,
+ child:
+ (canShowTabs)
+ ? TabBarView(
+ controller: tabController,
+ children:
+ widget.tabs
+ .map(
+ (tab) => MultiProvider(
+ providers: [
+ Provider(
+ create:
+ (context) => constraints,
+ ),
+ Provider(
+ create: (context) => tab,
+ ),
+ ],
+ child: tab.view,
+ ),
+ )
+ .toList(),
+ )
+ : widget.tabs.first.view,
),
if (widget.attributionType ==
- TenorAttributionType.poweredBy)
- TenorAttribution(
- style: widget.style.attributionStyle,
- ),
+ KlipyAttributionType.poweredBy)
+ KlipyAttribution(style: widget.style.attributionStyle),
],
),
),
diff --git a/lib/src/components/tab_bar.dart b/lib/src/components/tab_bar.dart
index c3cdb0a..4c78fd3 100644
--- a/lib/src/components/tab_bar.dart
+++ b/lib/src/components/tab_bar.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-class TenorTabBarStyle {
+class KlipyTabBarStyle {
final Decoration decoration;
final Decoration indicator;
final Color labelColor;
@@ -14,18 +14,12 @@ class TenorTabBarStyle {
final Color unselectedLabelColor;
final TextStyle unselectedLabelStyle;
- const TenorTabBarStyle({
+ const KlipyTabBarStyle({
this.decoration = const BoxDecoration(
color: Color(0xFFEDE7D7),
border: Border.symmetric(
- horizontal: BorderSide(
- color: Color(0xFFEDE7D7),
- width: 2,
- ),
- vertical: BorderSide(
- color: Color(0xFFEDE7D7),
- width: 2,
- ),
+ horizontal: BorderSide(color: Color(0xFFEDE7D7), width: 2),
+ vertical: BorderSide(color: Color(0xFFEDE7D7), width: 2),
),
borderRadius: BorderRadius.all(Radius.circular(8)),
),
@@ -63,10 +57,7 @@ class TenorTabBarStyle {
fontWeight: FontWeight.bold,
),
this.height = 30,
- this.margin = const EdgeInsets.only(
- left: 8,
- right: 8,
- ),
+ this.margin = const EdgeInsets.only(left: 8, right: 8),
this.unselectedLabelColor = const Color(0xFF3B3B3B),
this.unselectedLabelStyle = const TextStyle(
decoration: TextDecoration.none,
@@ -76,15 +67,15 @@ class TenorTabBarStyle {
});
}
-class TenorTabBar extends StatelessWidget {
+class KlipyTabBar extends StatelessWidget {
final TabController tabController;
final List tabs;
- final TenorTabBarStyle style;
+ final KlipyTabBarStyle style;
- const TenorTabBar({
+ const KlipyTabBar({
required this.tabController,
required this.tabs,
- this.style = const TenorTabBarStyle(),
+ this.style = const KlipyTabBarStyle(),
super.key,
});
diff --git a/lib/src/components/tab_view.dart b/lib/src/components/tab_view.dart
index 004324f..7bb2dbf 100644
--- a/lib/src/components/tab_view.dart
+++ b/lib/src/components/tab_view.dart
@@ -4,76 +4,75 @@ import 'package:extended_image/extended_image.dart';
import 'package:flutter_staggered_grid_view/flutter_staggered_grid_view.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';
-import 'package:tenor_flutter/src/components/components.dart';
-import 'package:tenor_flutter/src/providers/app_bar_provider.dart';
-import 'package:tenor_flutter/src/providers/tab_provider.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/components/components.dart';
+import 'package:klipy_flutter/src/providers/app_bar_provider.dart';
+import 'package:klipy_flutter/src/providers/tab_provider.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
const featuredCategoryPath = '##trending-gifs';
-class TenorTabViewStyle {
+class KlipyTabViewStyle {
final Color mediaBackgroundColor;
- const TenorTabViewStyle({
- this.mediaBackgroundColor = Colors.white,
- });
+ const KlipyTabViewStyle({this.mediaBackgroundColor = Colors.white});
}
-class TenorTabView extends StatefulWidget {
+class KlipyTabView extends StatefulWidget {
final Widget Function(BuildContext, Widget?)? builder;
- final TenorCategoryStyle categoryStyle;
- final Tenor client;
+ final KlipyCategoryStyle categoryStyle;
+ final KlipyClient client;
final String featuredCategory;
final int gifsPerRow;
final bool? keepAliveTabView;
- final Future Function(
+ final Future Function(
String queryText,
String? pos,
int limit,
- TenorCategory? category,
- )? onLoad;
- final Function(TenorResult? gif)? onSelected;
+ KlipyCategoryObject? category,
+ )?
+ onLoad;
+ final Function(KlipyResultObject? gif)? onSelected;
final bool showCategories;
- final TenorTabViewStyle style;
+ final KlipyTabViewStyle style;
- const TenorTabView({
+ const KlipyTabView({
required this.client,
this.builder,
- this.categoryStyle = const TenorCategoryStyle(),
+ this.categoryStyle = const KlipyCategoryStyle(),
String? featuredCategory,
int? gifsPerRow,
this.keepAliveTabView,
this.onLoad,
this.onSelected,
this.showCategories = false,
- this.style = const TenorTabViewStyle(),
+ this.style = const KlipyTabViewStyle(),
super.key,
- }) : featuredCategory = featuredCategory ?? '📈 Featured',
- gifsPerRow = gifsPerRow ?? 3;
+ }) : featuredCategory = featuredCategory ?? '📈 Featured',
+ gifsPerRow = gifsPerRow ?? 3;
@override
- State createState() => _TenorTabViewState();
+ State createState() => _KlipyTabViewState();
}
-class _TenorTabViewState extends State
+class _KlipyTabViewState extends State
with AutomaticKeepAliveClientMixin {
@override
bool get wantKeepAlive => widget.keepAliveTabView ?? true;
// Tab Provider
- late TenorTabProvider _tabProvider;
+ late KlipyTabProvider _tabProvider;
// Scroll Controller
late final ScrollController _scrollController;
// AppBar Provider
- late TenorAppBarProvider _appBarProvider;
+ late KlipyAppBarProvider _appBarProvider;
// Collection
- TenorResponse? _collection;
+ KlipyResponse? _collection;
// List of gifs
- List _list = [];
+ List _list = [];
// Direction
final Axis _scrollDirection = Axis.vertical;
@@ -87,13 +86,13 @@ class _TenorTabViewState extends State
// Offset
String? offset;
- List _categories = [];
+ List _categories = [];
- /// The Tenor client so we can use the API.
- late final Tenor client;
+ /// The KLIPY client so we can use the API.
+ late final KlipyClient client;
/// The current tabs data.
- late final TenorTab tab;
+ late final KlipyTab tab;
/// The limit of gifs to request per load.
late int requestLimit;
@@ -105,13 +104,13 @@ class _TenorTabViewState extends State
client = widget.client;
// Which tab are we?
- tab = context.read();
+ tab = context.read();
// We should update this whenever the size changes eventually
requestLimit = _calculateLimit();
// AppBar Provider
- _appBarProvider = Provider.of(context, listen: false);
+ _appBarProvider = Provider.of(context, listen: false);
_appBarProvider.addListener(_appBarProviderListener);
// Scroll Controller
@@ -119,7 +118,7 @@ class _TenorTabViewState extends State
_scrollController.addListener(_scrollControllerListener);
// Tab Provider
- _tabProvider = Provider.of(context, listen: false);
+ _tabProvider = Provider.of(context, listen: false);
_tabProvider.addListener(_tabProviderListener);
WidgetsBinding.instance.addPostFrameCallback((_) {
@@ -146,9 +145,7 @@ class _TenorTabViewState extends State
Widget build(BuildContext context) {
super.build(context);
if (_list.isEmpty && _categories.isEmpty) {
- return const Center(
- child: CircularProgressIndicator(),
- );
+ return const Center(child: CircularProgressIndicator());
}
if (_appBarProvider.queryText.isEmpty &&
@@ -168,7 +165,7 @@ class _TenorTabViewState extends State
final category = _categories[idx];
return ClipRRect(
borderRadius: BorderRadius.circular(8),
- child: TenorCategoryWidget(
+ child: KlipyCategoryWidget(
style: widget.categoryStyle,
category: category,
onTap: (selectedCategory) {
@@ -185,13 +182,11 @@ class _TenorTabViewState extends State
},
itemCount: _categories.length,
mainAxisSpacing: 8,
- // Add safe area padding if `TenorAttributionType.poweredBy` is disabled
+ // Add safe area padding if `KlipyAttributionType.poweredBy` is disabled
padding:
- _tabProvider.attributionType == TenorAttributionType.poweredBy
- ? null
- : EdgeInsets.only(
- bottom: MediaQuery.of(context).padding.bottom,
- ),
+ _tabProvider.attributionType == KlipyAttributionType.poweredBy
+ ? EdgeInsets.zero
+ : const EdgeInsets.only(bottom: 0),
scrollDirection: _scrollDirection,
),
),
@@ -206,24 +201,24 @@ class _TenorTabViewState extends State
crossAxisCount: widget.gifsPerRow,
crossAxisSpacing: 8,
keyboardDismissBehavior: _appBarProvider.keyboardDismissBehavior,
- itemBuilder: (ctx, idx) => ClipRRect(
- borderRadius: BorderRadius.circular(8),
- child: TenorSelectableGif(
- backgroundColor: widget.style.mediaBackgroundColor,
- onTap: (selectedResult) => _selectedGif(
- selectedResult,
+ itemBuilder:
+ (ctx, idx) => ClipRRect(
+ borderRadius: BorderRadius.circular(8),
+ child: KlipySelectableGif(
+ backgroundColor: widget.style.mediaBackgroundColor,
+ onTap: (selectedResult) => _selectedGif(selectedResult),
+ result: _list[idx],
+ ),
),
- result: _list[idx],
- ),
- ),
itemCount: _list.length,
mainAxisSpacing: 8,
- // Add safe area padding if `TenorAttributionType.poweredBy` is disabled
- padding: _tabProvider.attributionType == TenorAttributionType.poweredBy
- ? null
- : EdgeInsets.only(
- bottom: MediaQuery.of(context).padding.bottom,
- ),
+ // Add safe area padding if `KlipyAttributionType.poweredBy` is disabled
+ padding:
+ _tabProvider.attributionType == KlipyAttributionType.poweredBy
+ ? null
+ : EdgeInsets.only(
+ bottom: MediaQuery.of(context).padding.bottom,
+ ),
scrollDirection: _scrollDirection,
),
);
@@ -232,8 +227,8 @@ class _TenorTabViewState extends State
// Estimate the request limit based on the visible area. Doesn't need to be precise.
// This function assumes all gifs are 1:1 aspect ratio for simplicity.
int _calculateLimit() {
- // Tenor has a hard limit of 50 per request
- const int tenorRequestLimit = 50;
+ // KLIPY has a hard limit of 50 per request
+ const int klipyRequestLimit = 50;
// Call this here so we get updated constraints in case of size change
final constraints = context.read();
// The width of each gif (estimated)
@@ -242,9 +237,9 @@ class _TenorTabViewState extends State
final gifRowCount = (constraints.maxHeight / gifWidth).round();
// Based on estimates, how many gifs can we fit into the TabView
final calculatedRequestLimit = widget.gifsPerRow * gifRowCount;
- // If the limit is greater than Tenor's hard limit, cap it
- return calculatedRequestLimit > tenorRequestLimit
- ? tenorRequestLimit
+ // If the limit is greater than KLIPY's hard limit, cap it
+ return calculatedRequestLimit > klipyRequestLimit
+ ? klipyRequestLimit
: calculatedRequestLimit;
}
@@ -278,13 +273,13 @@ class _TenorTabViewState extends State
Future _loadCatagories() async {
try {
- final fromTenor = await client.categories();
+ final fromKlipy = await client.categories();
final featuredGifResponse = await client.featured(limit: 1);
final featuredGif = featuredGifResponse?.results.first;
if (featuredGif != null) {
- fromTenor.insert(
+ fromKlipy.insert(
0,
- TenorCategory(
+ KlipyCategoryObject(
image: featuredGif.media.tinyGif?.url ?? '',
name: widget.featuredCategory,
path: featuredCategoryPath,
@@ -294,7 +289,7 @@ class _TenorTabViewState extends State
}
setState(() {
- _categories = fromTenor;
+ _categories = fromKlipy;
});
} catch (e) {
//
@@ -354,9 +349,9 @@ class _TenorTabViewState extends State
_isLoading = false;
});
}
- } on TenorNetworkException {
+ } on KlipyNetworkException {
_isLoading = false;
- } on TenorApiException {
+ } on KlipyApiException {
_isLoading = false;
} catch (e) {
_isLoading = false;
@@ -369,27 +364,23 @@ class _TenorTabViewState extends State
}
// Return selected gif
- void _selectedGif(TenorResult gif) {
+ void _selectedGif(KlipyResultObject gif) {
try {
- // https://developers.google.com/tenor/guides/endpoints#register-share
+ // https://docs.klipy.com/migrate-from-tenor/register-share
client.registerShare(gif.id, search: _appBarProvider.queryText);
} catch (e) {
// do nothing if it fails
}
// return result to the consumer
- Navigator.pop(
- context,
- gif.copyWith(
- source: _tabProvider.selectedTab.name,
- ),
- );
+ Navigator.pop(context, gif.copyWith(source: _tabProvider.selectedTab.name));
}
// if you scroll within a threshhold of the bottom of the screen, load more gifs
void _scrollControllerListener() {
// trending-gifs, etc
- final customCategorySelected = _appBarProvider.selectedCategory != null &&
+ final customCategorySelected =
+ _appBarProvider.selectedCategory != null &&
_appBarProvider.queryText == '';
if (customCategorySelected ||
diff --git a/lib/src/components/tab_view_emojis.dart b/lib/src/components/tab_view_emojis.dart
index e2d94e1..3ab9dfe 100644
--- a/lib/src/components/tab_view_emojis.dart
+++ b/lib/src/components/tab_view_emojis.dart
@@ -1,22 +1,22 @@
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/utilities/is_tablet.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/utilities/is_tablet.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorViewEmojis extends StatelessWidget {
- final Tenor client;
+class KlipyViewEmojis extends StatelessWidget {
+ final KlipyClient client;
final int? gifsPerRow;
- final TenorTabViewStyle style;
+ final KlipyTabViewStyle style;
- const TenorViewEmojis({
+ const KlipyViewEmojis({
required this.client,
this.gifsPerRow,
- this.style = const TenorTabViewStyle(),
+ this.style = const KlipyTabViewStyle(),
super.key,
});
@override
Widget build(BuildContext context) {
- return TenorTabView(
+ return KlipyTabView(
client: client,
gifsPerRow: gifsPerRow ?? (isTablet(context) ? 8 : 9),
keepAliveTabView: true,
@@ -24,7 +24,7 @@ class TenorViewEmojis extends StatelessWidget {
if (queryText.isNotEmpty) {
return await client.search(
'$queryText emoji',
- mediaFilter: const [TenorMediaFormat.tinyGifTransparent],
+ mediaFilter: const [KlipyMediaFormat.tinyGifTransparent],
pos: pos,
limit: limit,
sticker: true,
@@ -32,7 +32,7 @@ class TenorViewEmojis extends StatelessWidget {
} else {
return await client.search(
'emoji',
- mediaFilter: const [TenorMediaFormat.tinyGifTransparent],
+ mediaFilter: const [KlipyMediaFormat.tinyGifTransparent],
pos: pos,
limit: limit,
sticker: true,
diff --git a/lib/src/components/tab_view_gifs.dart b/lib/src/components/tab_view_gifs.dart
index 7985eb4..403eb3e 100644
--- a/lib/src/components/tab_view_gifs.dart
+++ b/lib/src/components/tab_view_gifs.dart
@@ -1,27 +1,27 @@
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/components/tab_view.dart';
-import 'package:tenor_flutter/src/utilities/is_tablet.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/components/tab_view.dart';
+import 'package:klipy_flutter/src/utilities/is_tablet.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorViewGifs extends StatelessWidget {
- final Tenor client;
+class KlipyViewGifs extends StatelessWidget {
+ final KlipyClient client;
final String? featuredCategory;
final int? gifsPerRow;
final bool showCategories;
- final TenorTabViewStyle style;
+ final KlipyTabViewStyle style;
- const TenorViewGifs({
+ const KlipyViewGifs({
required this.client,
this.featuredCategory,
this.gifsPerRow,
this.showCategories = true,
- this.style = const TenorTabViewStyle(),
+ this.style = const KlipyTabViewStyle(),
super.key,
});
@override
Widget build(BuildContext context) {
- return TenorTabView(
+ return KlipyTabView(
client: client,
featuredCategory: featuredCategory,
gifsPerRow: gifsPerRow ?? (isTablet(context) ? 3 : 2),
@@ -29,29 +29,19 @@ class TenorViewGifs extends StatelessWidget {
showCategories: showCategories,
onLoad: (queryText, pos, limit, category) async {
if (queryText.isNotEmpty) {
- return await client.search(
- queryText,
- pos: pos,
- limit: limit,
- );
+ return await client.search(queryText, pos: pos, limit: limit);
} else {
if (showCategories) {
// if a trending is selected, seatch them up
if (category?.path == featuredCategoryPath) {
- return await client.featured(
- pos: pos,
- limit: limit,
- );
+ return await client.featured(pos: pos, limit: limit);
}
// don't hit the api since we already have the categories
return null;
}
// ask for new featured gifs since categories are disabled
- return await client.featured(
- pos: pos,
- limit: limit,
- );
+ return await client.featured(pos: pos, limit: limit);
}
},
style: style,
diff --git a/lib/src/components/tab_view_stickers.dart b/lib/src/components/tab_view_stickers.dart
index bf857b5..1586356 100644
--- a/lib/src/components/tab_view_stickers.dart
+++ b/lib/src/components/tab_view_stickers.dart
@@ -1,22 +1,22 @@
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/utilities/is_tablet.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/utilities/is_tablet.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorViewStickers extends StatelessWidget {
- final Tenor client;
+class KlipyViewStickers extends StatelessWidget {
+ final KlipyClient client;
final int? gifsPerRow;
- final TenorTabViewStyle style;
+ final KlipyTabViewStyle style;
- const TenorViewStickers({
+ const KlipyViewStickers({
required this.client,
this.gifsPerRow,
- this.style = const TenorTabViewStyle(),
+ this.style = const KlipyTabViewStyle(),
super.key,
});
@override
Widget build(BuildContext context) {
- return TenorTabView(
+ return KlipyTabView(
client: client,
gifsPerRow: gifsPerRow ?? (isTablet(context) ? 6 : 5),
keepAliveTabView: true,
@@ -24,14 +24,14 @@ class TenorViewStickers extends StatelessWidget {
if (queryText.isNotEmpty) {
return await client.search(
queryText,
- mediaFilter: const [TenorMediaFormat.tinyGifTransparent],
+ mediaFilter: const [KlipyMediaFormat.tinyGifTransparent],
pos: pos,
limit: limit,
sticker: true,
);
} else {
return await client.featured(
- mediaFilter: const [TenorMediaFormat.tinyGifTransparent],
+ mediaFilter: const [KlipyMediaFormat.tinyGifTransparent],
pos: pos,
limit: limit,
sticker: true,
diff --git a/lib/src/klipy_client.dart b/lib/src/klipy_client.dart
new file mode 100644
index 0000000..b36a1c4
--- /dev/null
+++ b/lib/src/klipy_client.dart
@@ -0,0 +1,159 @@
+import 'package:flutter/material.dart';
+import 'package:klipy_dart/klipy_dart.dart' as klipy_dart;
+import 'package:klipy_flutter/klipy_flutter.dart';
+import 'package:klipy_flutter/src/components/components.dart';
+import 'package:klipy_flutter/src/providers/providers.dart';
+import 'package:provider/provider.dart';
+
+const klipyDefaultAnimationStyle = AnimationStyle(
+ duration: Duration(milliseconds: 250),
+ reverseDuration: Duration(milliseconds: 200),
+);
+
+class KlipyStyle {
+ final AnimationStyle? animationStyle;
+ final KlipyAttributionStyle attributionStyle;
+
+ /// Background color of the sheet.
+ final Color color;
+ final KlipyDragHandleStyle dragHandleStyle;
+ final String? fontFamily;
+ final KlipySearchFieldStyle searchFieldStyle;
+ final KlipySelectedCategoryStyle selectedCategoryStyle;
+
+ /// Shape for the sheet.
+ final ShapeBorder shape;
+ final KlipyTabBarStyle tabBarStyle;
+ final KlipyTabViewStyle tabViewStyle;
+
+ const KlipyStyle({
+ this.animationStyle,
+ this.attributionStyle = const KlipyAttributionStyle(),
+ this.color = const Color(0xFFF9F8F2),
+ this.dragHandleStyle = const KlipyDragHandleStyle(),
+ this.fontFamily,
+ this.searchFieldStyle = const KlipySearchFieldStyle(),
+ this.selectedCategoryStyle = const KlipySelectedCategoryStyle(),
+ this.shape = const RoundedRectangleBorder(
+ borderRadius: BorderRadius.vertical(top: Radius.circular(8)),
+ ),
+ this.tabBarStyle = const KlipyTabBarStyle(),
+ this.tabViewStyle = const KlipyTabViewStyle(),
+ });
+}
+
+class KlipyClient extends klipy_dart.KlipyClient {
+ const KlipyClient({
+ required super.apiKey,
+ super.client = const klipy_dart.KlipyHttpClient(),
+ super.country = 'US',
+ super.locale = 'en_US',
+ super.networkTimeout = const Duration(seconds: 5),
+ });
+
+ /// Shows a bottom sheet modal that allows you to select a KLIPY media object for use.
+ ///
+ /// If you pass in a `searchFieldWidget` you must also pass in a `searchFieldController`. The controller will automatically be disposed of.
+ ///
+ /// You must have valid [KLIPY attribution](https://docs.klipy.com/attribution) in order to use this within your app.
+ Future showAsBottomSheet({
+ required BuildContext context,
+ KlipyAttributionType attributionType = KlipyAttributionType.poweredBy,
+ // Whether to cover the app bar with the bottom sheet.
+ bool coverAppBar = false,
+ Duration debounce = const Duration(milliseconds: 300),
+ double? initialExtent,
+ int initialTabIndex = 1,
+ ScrollViewKeyboardDismissBehavior keyboardDismissBehavior =
+ ScrollViewKeyboardDismissBehavior.manual,
+ double maxExtent = 1,
+ double minExtent = 0.7,
+ String queryText = '',
+ TextEditingController? searchFieldController,
+ String searchFieldHintText = 'Search KLIPY',
+ Widget? searchFieldWidget,
+ // A list of target sizes that the showModalBottomSheet should snap to.
+ // The [minChildSize] and [maxChildSize] are implicitly included in snap sizes and do not need to be specified here.
+ List? snapSizes,
+ KlipyStyle style = const KlipyStyle(),
+ List? tabs,
+ bool useSafeArea = true,
+ }) {
+ final tabsToDisplay =
+ tabs ??
+ [
+ KlipyTab(
+ name: 'Emojis',
+ view: KlipyViewEmojis(client: this, style: style.tabViewStyle),
+ ),
+ KlipyTab(
+ name: 'GIFs',
+ view: KlipyViewGifs(client: this, style: style.tabViewStyle),
+ ),
+ KlipyTab(
+ name: 'Stickers',
+ view: KlipyViewStickers(client: this, style: style.tabViewStyle),
+ ),
+ ];
+
+ return showModalBottomSheet(
+ clipBehavior: Clip.antiAlias,
+ context: context,
+ isScrollControlled: true,
+ shape: style.shape,
+ sheetAnimationStyle: style.animationStyle ?? klipyDefaultAnimationStyle,
+ useSafeArea: useSafeArea,
+ builder: (context) {
+ return DefaultTextStyle.merge(
+ style: TextStyle(fontFamily: style.fontFamily),
+ child: Padding(
+ padding: EdgeInsets.only(
+ // move the sheet up when the keyboard is shown
+ bottom: MediaQuery.of(context).viewInsets.bottom,
+ ),
+ child: MultiProvider(
+ providers: [
+ ChangeNotifierProvider(
+ create:
+ (context) => KlipyAppBarProvider(
+ queryText,
+ debounce,
+ keyboardDismissBehavior: keyboardDismissBehavior,
+ ),
+ ),
+ ChangeNotifierProvider(
+ create:
+ (context) => KlipySheetProvider(
+ initialExtent: initialExtent,
+ maxExtent: maxExtent,
+ minExtent: minExtent,
+ scrollController: DraggableScrollableController(),
+ ),
+ ),
+ ChangeNotifierProvider(
+ create:
+ (context) => KlipyTabProvider(
+ attributionType: attributionType,
+ client: this,
+ selectedTab: tabsToDisplay[initialTabIndex],
+ ),
+ ),
+ ],
+ child: KlipySheet(
+ attributionType: attributionType,
+ coverAppBar: coverAppBar,
+ initialTabIndex: initialTabIndex,
+ searchFieldController: searchFieldController,
+ searchFieldHintText: searchFieldHintText,
+ searchFieldWidget: searchFieldWidget,
+ snapSizes: snapSizes,
+ style: style,
+ tabs: tabsToDisplay,
+ ),
+ ),
+ ),
+ );
+ },
+ );
+ }
+}
diff --git a/lib/src/models/attribution.dart b/lib/src/models/attribution.dart
index 92411e2..7cbd2fa 100644
--- a/lib/src/models/attribution.dart
+++ b/lib/src/models/attribution.dart
@@ -1,13 +1,12 @@
-/// It is your responsibility to display attribution via atleast one of the following methods.
+/// To ensure a consistent and high-quality experience across all platforms, applications using the KLIPY API must include clear attribution.
+/// - Display a visible “Powered by KLIPY” mark wherever KLIPY content is shown.
+/// - Set “Search KLIPY” as the default placeholder text in the search input field.
///
-/// https://developers.google.com/tenor/guides/attribution
-enum TenorAttributionType {
+/// More information https://docs.klipy.com/attribution
+enum KlipyAttributionType {
/// Use this attribution during the GIF browsing experience.
poweredBy,
- /// Use this attribution as the placeholder text in your search box. If you have your own SearchFieldWidget and intend to use this attribution you must implement it yourself.
- searchTenor,
-
- /// Use this attribution in the footer of a shared GIF. Must be implemented yourself.
- viaTenor,
+ /// Use this attribution to hide poweredBy. It's your responsibility to provide the correct attribution.
+ none,
}
diff --git a/lib/src/models/tab.dart b/lib/src/models/tab.dart
index 6065c93..c90dfb1 100644
--- a/lib/src/models/tab.dart
+++ b/lib/src/models/tab.dart
@@ -1,11 +1,8 @@
import 'package:flutter/material.dart';
-class TenorTab {
+class KlipyTab {
final String name;
final Widget view;
- const TenorTab({
- required this.name,
- required this.view,
- });
+ const KlipyTab({required this.name, required this.view});
}
diff --git a/lib/src/providers/app_bar_provider.dart b/lib/src/providers/app_bar_provider.dart
index 327ad19..2bc85b6 100644
--- a/lib/src/providers/app_bar_provider.dart
+++ b/lib/src/providers/app_bar_provider.dart
@@ -1,12 +1,12 @@
import 'package:flutter/widgets.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorAppBarProvider with ChangeNotifier {
+class KlipyAppBarProvider with ChangeNotifier {
final ScrollViewKeyboardDismissBehavior keyboardDismissBehavior;
String _queryText = '';
String get queryText => _queryText;
- TenorCategory? _selectedCategory;
+ KlipyCategoryObject? _selectedCategory;
Duration _debounce = Duration.zero;
Duration get debounce => _debounce;
@@ -20,19 +20,19 @@ class TenorAppBarProvider with ChangeNotifier {
notifyListeners();
}
- TenorAppBarProvider(
+ KlipyAppBarProvider(
String queryText,
Duration debounce, {
required this.keyboardDismissBehavior,
- TenorCategory? selectedCategory,
- }) : _selectedCategory = selectedCategory,
- super() {
+ KlipyCategoryObject? selectedCategory,
+ }) : _selectedCategory = selectedCategory,
+ super() {
_queryText = queryText;
_debounce = debounce;
}
- TenorCategory? get selectedCategory => _selectedCategory;
- set selectedCategory(TenorCategory? newCategory) {
+ KlipyCategoryObject? get selectedCategory => _selectedCategory;
+ set selectedCategory(KlipyCategoryObject? newCategory) {
_selectedCategory = newCategory;
notifyListeners();
}
diff --git a/lib/src/providers/sheet_provider.dart b/lib/src/providers/sheet_provider.dart
index 5aaf2d9..2e7bc65 100644
--- a/lib/src/providers/sheet_provider.dart
+++ b/lib/src/providers/sheet_provider.dart
@@ -1,17 +1,17 @@
import 'package:flutter/material.dart';
-class TenorSheetProvider extends ChangeNotifier {
+class KlipySheetProvider extends ChangeNotifier {
final double minExtent;
final double maxExtent;
final double initialExtent;
- TenorSheetProvider({
+ KlipySheetProvider({
required DraggableScrollableController scrollController,
required this.minExtent,
required this.maxExtent,
double? initialExtent,
- }) : initialExtent = initialExtent ?? maxExtent,
- _scrollController = scrollController;
+ }) : initialExtent = initialExtent ?? maxExtent,
+ _scrollController = scrollController;
DraggableScrollableController _scrollController;
diff --git a/lib/src/providers/tab_provider.dart b/lib/src/providers/tab_provider.dart
index e85bb01..46459ed 100644
--- a/lib/src/providers/tab_provider.dart
+++ b/lib/src/providers/tab_provider.dart
@@ -1,19 +1,19 @@
import 'package:flutter/widgets.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class TenorTabProvider with ChangeNotifier {
- TenorAttributionType attributionType;
- Tenor client;
- TenorTab _selectedTab;
+class KlipyTabProvider with ChangeNotifier {
+ KlipyAttributionType attributionType;
+ KlipyClient client;
+ KlipyTab _selectedTab;
- TenorTabProvider({
+ KlipyTabProvider({
required this.attributionType,
required this.client,
- required TenorTab selectedTab,
+ required KlipyTab selectedTab,
}) : _selectedTab = selectedTab;
- TenorTab get selectedTab => _selectedTab;
- set selectedTab(TenorTab selectedTab) {
+ KlipyTab get selectedTab => _selectedTab;
+ set selectedTab(KlipyTab selectedTab) {
_selectedTab = selectedTab;
notifyListeners();
}
diff --git a/lib/src/tenor.dart b/lib/src/tenor.dart
deleted file mode 100644
index 5593942..0000000
--- a/lib/src/tenor.dart
+++ /dev/null
@@ -1,171 +0,0 @@
-import 'package:flutter/material.dart';
-import 'package:provider/provider.dart';
-import 'package:tenor_dart/tenor_dart.dart' as tenor_dart;
-
-import 'package:tenor_flutter/src/components/components.dart';
-import 'package:tenor_flutter/src/providers/providers.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
-
-const tenorDefaultAnimationStyle = AnimationStyle(
- duration: Duration(milliseconds: 250),
- reverseDuration: Duration(milliseconds: 200),
-);
-
-class TenorStyle {
- final AnimationStyle? animationStyle;
- final TenorAttributionStyle attributionStyle;
-
- /// Background color of the sheet.
- final Color color;
- final TenorDragHandleStyle dragHandleStyle;
- final String? fontFamily;
- final TenorSearchFieldStyle searchFieldStyle;
- final TenorSelectedCategoryStyle selectedCategoryStyle;
-
- /// Shape for the sheet.
- final ShapeBorder shape;
- final TenorTabBarStyle tabBarStyle;
- final TenorTabViewStyle tabViewStyle;
-
- const TenorStyle({
- this.animationStyle,
- this.attributionStyle = const TenorAttributionStyle(),
- this.color = const Color(0xFFF9F8F2),
- this.dragHandleStyle = const TenorDragHandleStyle(),
- this.fontFamily,
- this.searchFieldStyle = const TenorSearchFieldStyle(),
- this.selectedCategoryStyle = const TenorSelectedCategoryStyle(),
- this.shape = const RoundedRectangleBorder(
- borderRadius: BorderRadius.vertical(
- top: Radius.circular(8),
- ),
- ),
- this.tabBarStyle = const TenorTabBarStyle(),
- this.tabViewStyle = const TenorTabViewStyle(),
- });
-}
-
-class Tenor extends tenor_dart.Tenor {
- const Tenor({
- required super.apiKey,
- super.client = const tenor_dart.TenorHttpClient(),
- super.clientKey,
- super.contentFilter = TenorContentFilter.off,
- super.country = 'US',
- super.locale = 'en_US',
- super.networkTimeout = const Duration(seconds: 5),
- });
-
- /// Shows a bottom sheet modal that allows you to select a Tenor media object for use.
- ///
- /// If you pass in a `searchFieldWidget` you must also pass in a `searchFieldController`. The controller will automatically be disposed of.
- ///
- /// You must have one valid form of [Tenor attribution](https://developers.google.com/tenor/guides/attribution) in order to use this within your app.
- Future showAsBottomSheet({
- required BuildContext context,
- TenorAttributionType attributionType = TenorAttributionType.poweredBy,
- // Whether to cover the app bar with the bottom sheet.
- bool coverAppBar = false,
- Duration debounce = const Duration(milliseconds: 300),
- double? initialExtent,
- int initialTabIndex = 1,
- ScrollViewKeyboardDismissBehavior keyboardDismissBehavior =
- ScrollViewKeyboardDismissBehavior.manual,
- double maxExtent = 1,
- double minExtent = 0.7,
- String queryText = '',
- TextEditingController? searchFieldController,
- String searchFieldHintText = 'Search Tenor',
- Widget? searchFieldWidget,
- // A list of target sizes that the showModalBottomSheet should snap to.
- // The [minChildSize] and [maxChildSize] are implicitly included in snap sizes and do not need to be specified here.
- List? snapSizes,
- TenorStyle style = const TenorStyle(),
- List? tabs,
- bool useSafeArea = true,
- }) {
- final tabsToDisplay = tabs ??
- [
- TenorTab(
- name: 'Emojis',
- view: TenorViewEmojis(
- client: this,
- style: style.tabViewStyle,
- ),
- ),
- TenorTab(
- name: 'GIFs',
- view: TenorViewGifs(
- client: this,
- style: style.tabViewStyle,
- ),
- ),
- TenorTab(
- name: 'Stickers',
- view: TenorViewStickers(
- client: this,
- style: style.tabViewStyle,
- ),
- ),
- ];
-
- return showModalBottomSheet(
- clipBehavior: Clip.antiAlias,
- context: context,
- isScrollControlled: true,
- shape: style.shape,
- sheetAnimationStyle: style.animationStyle ?? tenorDefaultAnimationStyle,
- useSafeArea: useSafeArea,
- builder: (context) {
- return DefaultTextStyle.merge(
- style: TextStyle(
- fontFamily: style.fontFamily,
- ),
- child: Padding(
- padding: EdgeInsets.only(
- // move the sheet up when the keyboard is shown
- bottom: MediaQuery.of(context).viewInsets.bottom,
- ),
- child: MultiProvider(
- providers: [
- ChangeNotifierProvider(
- create: (context) => TenorAppBarProvider(
- queryText,
- debounce,
- keyboardDismissBehavior: keyboardDismissBehavior,
- ),
- ),
- ChangeNotifierProvider(
- create: (context) => TenorSheetProvider(
- initialExtent: initialExtent,
- maxExtent: maxExtent,
- minExtent: minExtent,
- scrollController: DraggableScrollableController(),
- ),
- ),
- ChangeNotifierProvider(
- create: (context) => TenorTabProvider(
- attributionType: attributionType,
- client: this,
- selectedTab: tabsToDisplay[initialTabIndex],
- ),
- ),
- ],
- child: TenorSheet(
- attributionType: attributionType,
- coverAppBar: coverAppBar,
- initialTabIndex: initialTabIndex,
- searchFieldController: searchFieldController,
- searchFieldHintText: searchFieldHintText,
- searchFieldWidget: searchFieldWidget,
- snapSizes: snapSizes,
- style: style,
- tabs: tabsToDisplay,
- ),
- ),
- ),
- );
- },
- );
- }
-}
diff --git a/lib/src/utilities/debouncer.dart b/lib/src/utilities/debouncer.dart
index 50fcfc2..c5a2943 100644
--- a/lib/src/utilities/debouncer.dart
+++ b/lib/src/utilities/debouncer.dart
@@ -1,12 +1,11 @@
import 'dart:async';
-class TenorDebouncer {
+class KlipyDebouncer {
final Duration _delay;
Timer? _timer;
- TenorDebouncer({
- Duration delay = const Duration(milliseconds: 300),
- }) : _delay = delay;
+ KlipyDebouncer({Duration delay = const Duration(milliseconds: 300)})
+ : _delay = delay;
void call(void Function() callback) {
_timer?.cancel();
diff --git a/lib/tenor_flutter.dart b/lib/tenor_flutter.dart
deleted file mode 100644
index 47355c5..0000000
--- a/lib/tenor_flutter.dart
+++ /dev/null
@@ -1,15 +0,0 @@
-// hide Tenor so we can extend it
-export 'package:tenor_dart/tenor_dart.dart' hide Tenor;
-
-export 'src/tenor.dart';
-
-export 'src/components/attribution.dart' show TenorAttributionStyle;
-export 'src/components/drag_handle.dart' show TenorDragHandleStyle;
-export 'src/components/search_field.dart'
- show TenorSelectedCategoryStyle, TenorSearchFieldStyle;
-export 'src/components/tab_bar.dart' show TenorTabBarStyle;
-export 'src/components/tab_view.dart' show TenorTabView, TenorTabViewStyle;
-export 'src/components/tab_view_emojis.dart';
-export 'src/components/tab_view_gifs.dart';
-export 'src/components/tab_view_stickers.dart';
-export 'src/models/models.dart';
diff --git a/pubspec.yaml b/pubspec.yaml
index 07335b3..315ada8 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -1,11 +1,13 @@
-name: tenor_flutter
-version: 1.0.0
-description: An opinionated yet customizable Flutter package for searching and selecting from a list of GIFs/Stickers from the Tenor GIF search API.
+name: klipy_flutter
+version: 0.0.1
+description: An opinionated yet customizable Flutter package for searching and selecting from a list of GIFs/Stickers from the KLIPY GIF search API.
homepage: https://github.com/flyclops
-repository: https://github.com/flyclops/tenor_flutter
+repository: https://github.com/flyclops/klipy_flutter
topics:
- gif
+ - klipy
- tenor
+ - giphy
environment:
sdk: ">=3.7.0 <4.0.0"
@@ -16,7 +18,7 @@ dependencies:
provider: ^6.1.5+1
flutter_staggered_grid_view: ^0.7.0
extended_image: ^10.0.1
- tenor_dart: ^0.0.4
+ klipy_dart: ^0.0.1
dev_dependencies:
flutter_test:
diff --git a/test/components/attribution_test.dart b/test/components/attribution_test.dart
index 110455d..d52903a 100644
--- a/test/components/attribution_test.dart
+++ b/test/components/attribution_test.dart
@@ -1,20 +1,19 @@
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/components/components.dart';
+import 'package:klipy_flutter/src/components/components.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('Attribution Widget >', () {
- testWidgets('Make sure safe area overwrites any previous padding',
- (tester) async {
+ testWidgets('Make sure safe area overwrites any previous padding', (
+ tester,
+ ) async {
await tester.pumpWidget(
const MediaQuery(
- data: MediaQueryData(
- padding: EdgeInsets.only(bottom: 10),
- ),
- child: TenorAttribution(
- style: TenorAttributionStyle(padding: EdgeInsets.all(8)),
+ data: MediaQueryData(padding: EdgeInsets.only(bottom: 10)),
+ child: KlipyAttribution(
+ style: KlipyAttributionStyle(padding: EdgeInsets.all(8)),
),
),
);
diff --git a/test/components/category_test.dart b/test/components/category_test.dart
index da0cf43..6c35e46 100644
--- a/test/components/category_test.dart
+++ b/test/components/category_test.dart
@@ -1,22 +1,20 @@
-import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/components/components.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:flutter/material.dart';
+import 'package:klipy_flutter/src/components/components.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('Category Widget >', () {
testWidgets('If category is null, find nothing', (tester) async {
- await tester.pumpWidget(
- const TenorCategoryWidget(),
- );
+ await tester.pumpWidget(const KlipyCategoryWidget());
expect(find.byType(GestureDetector), findsNothing);
});
testWidgets('Keep hashtag', (tester) async {
- final tenorCategoryTest = TenorCategory(
+ final klipyCategoryTest = KlipyCategoryObject(
name: '#test',
searchTerm: 'test search term',
path: 'path/to/category',
@@ -26,11 +24,9 @@ void main() {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
- child: TenorCategoryWidget(
- category: tenorCategoryTest,
- style: const TenorCategoryStyle(
- stripHashtag: false,
- ),
+ child: KlipyCategoryWidget(
+ category: klipyCategoryTest,
+ style: const KlipyCategoryStyle(stripHashtag: false),
),
),
);
@@ -40,7 +36,7 @@ void main() {
});
testWidgets('Strip hashtag', (tester) async {
- final tenorCategoryTest = TenorCategory(
+ final klipyCategoryTest = KlipyCategoryObject(
name: '#test',
searchTerm: 'test search term',
path: 'path/to/category',
@@ -50,11 +46,9 @@ void main() {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
- child: TenorCategoryWidget(
- category: tenorCategoryTest,
- style: const TenorCategoryStyle(
- stripHashtag: true,
- ),
+ child: KlipyCategoryWidget(
+ category: klipyCategoryTest,
+ style: const KlipyCategoryStyle(stripHashtag: true),
),
),
);
@@ -68,7 +62,7 @@ void main() {
bool hasTapped = false;
// category to populate with
- final tenorCategoryTest = TenorCategory(
+ final klipyCategoryTest = KlipyCategoryObject(
name: 'test',
searchTerm: 'test search term',
path: 'path/to/category',
@@ -79,10 +73,10 @@ void main() {
await tester.pumpWidget(
Directionality(
textDirection: TextDirection.ltr,
- child: TenorCategoryWidget(
- category: tenorCategoryTest,
- onTap: (tenorCategory) {
- expect(tenorCategory, tenorCategoryTest);
+ child: KlipyCategoryWidget(
+ category: klipyCategoryTest,
+ onTap: (klipyCategory) {
+ expect(klipyCategory, klipyCategoryTest);
hasTapped = true;
},
),
diff --git a/test/tenor_test.dart b/test/klipy_client_test.dart
similarity index 65%
rename from test/tenor_test.dart
rename to test/klipy_client_test.dart
index fb02679..a0cc1a7 100644
--- a/test/tenor_test.dart
+++ b/test/klipy_client_test.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
-import 'package:tenor_flutter/src/components/components.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/components/components.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
import 'package:flutter_test/flutter_test.dart';
import 'mocks/mocks.dart';
@@ -8,18 +8,18 @@ import 'mocks/mocks.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
- group('Tenor >', () {
- const tenorClient = Tenor(apiKey: '12345');
+ group('KlipyClient >', () {
+ const klipyClient = KlipyClient(apiKey: '12345');
test('Make sure it is the right type', () {
- expect(tenorClient, isA());
+ expect(klipyClient, isA());
});
});
testWidgets('Make sure bottom sheet opens and closes', (tester) async {
- final tenorClient = Tenor(
+ final klipyClient = KlipyClient(
apiKey: '12345',
- client: MockTenorHttpClient(),
+ client: MockKlipyHttpClient(),
);
late BuildContext savedContext;
@@ -36,17 +36,17 @@ void main() {
);
// show bottom sheet
- tenorClient.showAsBottomSheet(context: savedContext);
+ klipyClient.showAsBottomSheet(context: savedContext);
await tester.pump();
// make sure it opens by finding a widget
- expect(find.byType(TenorSheet), findsOneWidget);
+ expect(find.byType(KlipySheet), findsOneWidget);
// close bottom sheet
await tester.tapAt(const Offset(20.0, 20.0));
await tester.pumpAndSettle();
// make sure it closes by finding no widgets
- expect(find.byType(TenorSheet), findsNothing);
+ expect(find.byType(KlipySheet), findsNothing);
});
}
diff --git a/test/mocks/mocks.dart b/test/mocks/mocks.dart
index da657e1..2c02f99 100644
--- a/test/mocks/mocks.dart
+++ b/test/mocks/mocks.dart
@@ -1,4 +1,4 @@
import 'package:mocktail/mocktail.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
-class MockTenorHttpClient extends Mock implements TenorHttpClient {}
+class MockKlipyHttpClient extends Mock implements KlipyHttpClient {}
diff --git a/test/providers/app_bar_provider_test.dart b/test/providers/app_bar_provider_test.dart
index b78b429..9f78f6e 100644
--- a/test/providers/app_bar_provider_test.dart
+++ b/test/providers/app_bar_provider_test.dart
@@ -1,22 +1,22 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:tenor_flutter/src/providers/providers.dart';
-import 'package:tenor_flutter/tenor_flutter.dart';
+import 'package:klipy_flutter/src/providers/providers.dart';
+import 'package:klipy_flutter/klipy_flutter.dart';
void main() {
const testQuery = 'some search query';
const testDuration = Duration(milliseconds: 500);
const testKeyboardDismissBehavior = ScrollViewKeyboardDismissBehavior.onDrag;
- final testCategory = TenorCategory(
+ final testCategory = KlipyCategoryObject(
image: 'test image',
name: 'test name',
path: 'test path',
searchTerm: 'test seach term',
);
- group('TenorAppBarProvider >', () {
+ group('KlipyAppBarProvider >', () {
test('Initializes as expected', () async {
- final provider = TenorAppBarProvider(
+ final provider = KlipyAppBarProvider(
testQuery,
testDuration,
keyboardDismissBehavior: testKeyboardDismissBehavior,
@@ -30,7 +30,7 @@ void main() {
test('Can set queryText', () async {
const updatedQuery = 'updated query';
- final provider = TenorAppBarProvider(
+ final provider = KlipyAppBarProvider(
testQuery,
testDuration,
keyboardDismissBehavior: testKeyboardDismissBehavior,
@@ -44,7 +44,7 @@ void main() {
});
test('Can set selectedCategory', () async {
- final provider = TenorAppBarProvider(
+ final provider = KlipyAppBarProvider(
testQuery,
testDuration,
keyboardDismissBehavior: testKeyboardDismissBehavior,
@@ -58,7 +58,7 @@ void main() {
});
test('Resets selectedCategory when queryText cleared', () async {
- final provider = TenorAppBarProvider(
+ final provider = KlipyAppBarProvider(
testQuery,
testDuration,
keyboardDismissBehavior: testKeyboardDismissBehavior,
diff --git a/test/providers/sheet_provider_test.dart b/test/providers/sheet_provider_test.dart
index 2a5469d..e717f42 100644
--- a/test/providers/sheet_provider_test.dart
+++ b/test/providers/sheet_provider_test.dart
@@ -1,6 +1,6 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:tenor_flutter/src/providers/providers.dart';
+import 'package:klipy_flutter/src/providers/providers.dart';
void main() {
const testMinExtent = 0.7;
@@ -8,9 +8,9 @@ void main() {
const testMaxExtent = 0.9;
final testScrollController = DraggableScrollableController();
- group('TenorSheetProvider >', () {
+ group('KlipySheetProvider >', () {
test('Initializes as expected', () async {
- final provider = TenorSheetProvider(
+ final provider = KlipySheetProvider(
maxExtent: testMaxExtent,
minExtent: testMinExtent,
initialExtent: tesInitialExtent,
@@ -25,7 +25,7 @@ void main() {
test('Can set scrollController', () async {
final updatedScrollController = DraggableScrollableController();
- final provider = TenorSheetProvider(
+ final provider = KlipySheetProvider(
maxExtent: testMaxExtent,
minExtent: testMinExtent,
scrollController: testScrollController,
diff --git a/test/utilities/debouncer_test.dart b/test/utilities/debouncer_test.dart
index 778460f..af0c6bb 100644
--- a/test/utilities/debouncer_test.dart
+++ b/test/utilities/debouncer_test.dart
@@ -1,52 +1,48 @@
-import 'package:tenor_flutter/src/utilities/debouncer.dart';
+import 'package:klipy_flutter/src/utilities/debouncer.dart';
import 'package:flutter_test/flutter_test.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('Debouncer >', () {
- test('Make sure the callback is called after the right amount of time',
- () async {
- final debouncer = TenorDebouncer(
- delay: const Duration(
- seconds: 1,
- ),
- );
+ test(
+ 'Make sure the callback is called after the right amount of time',
+ () async {
+ final debouncer = KlipyDebouncer(delay: const Duration(seconds: 1));
- bool callbackCalled = false;
+ bool callbackCalled = false;
- debouncer.call(() {
- callbackCalled = true;
- });
+ debouncer.call(() {
+ callbackCalled = true;
+ });
- expect(callbackCalled, false);
+ expect(callbackCalled, false);
- await Future.delayed(const Duration(seconds: 1), () {});
+ await Future.delayed(const Duration(seconds: 1), () {});
- expect(callbackCalled, true);
- });
+ expect(callbackCalled, true);
+ },
+ );
});
- test('Make sure that dispose ends the timer and does not run the callback',
- () async {
- final debouncer = TenorDebouncer(
- delay: const Duration(
- seconds: 1,
- ),
- );
+ test(
+ 'Make sure that dispose ends the timer and does not run the callback',
+ () async {
+ final debouncer = KlipyDebouncer(delay: const Duration(seconds: 1));
- bool callbackCalled = false;
+ bool callbackCalled = false;
- debouncer.call(() {
- callbackCalled = true;
- });
+ debouncer.call(() {
+ callbackCalled = true;
+ });
- expect(callbackCalled, false);
+ expect(callbackCalled, false);
- debouncer.dispose();
+ debouncer.dispose();
- await Future.delayed(const Duration(seconds: 1), () {});
+ await Future.delayed(const Duration(seconds: 1), () {});
- expect(callbackCalled, false);
- });
+ expect(callbackCalled, false);
+ },
+ );
}
diff --git a/test/utilities/is_tablet_test.dart b/test/utilities/is_tablet_test.dart
index bc9e8be..0780742 100644
--- a/test/utilities/is_tablet_test.dart
+++ b/test/utilities/is_tablet_test.dart
@@ -1,18 +1,17 @@
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
-import 'package:tenor_flutter/src/utilities/is_tablet.dart';
+import 'package:klipy_flutter/src/utilities/is_tablet.dart';
void main() {
TestWidgetsFlutterBinding.ensureInitialized();
group('isTablet >', () {
- testWidgets('true when iPad Pro (12.9-inch) (5th generation)',
- (tester) async {
+ testWidgets('true when iPad Pro (12.9-inch) (5th generation)', (
+ tester,
+ ) async {
await tester.pumpWidget(
MediaQuery(
- data: const MediaQueryData(
- size: Size(1192.0, 1558.0),
- ),
+ data: const MediaQueryData(size: Size(1192.0, 1558.0)),
child: MaterialApp(
home: Builder(
builder: (context) {
@@ -28,9 +27,7 @@ void main() {
testWidgets('false when iPhone 17 Pro', (tester) async {
await tester.pumpWidget(
MediaQuery(
- data: const MediaQueryData(
- size: Size(402.0, 874.0),
- ),
+ data: const MediaQueryData(size: Size(402.0, 874.0)),
child: MaterialApp(
home: Builder(
builder: (context) {