pipouch 0.0.1
pipouch: ^0.0.1 copied to clipboard
A comprehensive collection of Flutter helpers, extensions, functions, and reusable widgets to accelerate your app development.
PiPouch #
A comprehensive collection of essential Flutter helpers, extensions, functions, and reusable widgets designed to accelerate your app development and promote cleaner, more efficient code. From robust API response handling to versatile data formatting and UI enhancements, PiPouch equips you with ready-to-use solutions.
✨ Why PiPouch? #
Developing Flutter apps often involves writing repetitive boilerplate code, handling common tasks, or creating similar UI components. PiPouch aims to streamline your workflow by providing a curated set of tested and ready-to-use utilities, allowing you to focus on your app's unique features rather than reinventing the wheel.
With PiPouch, you get:
- ⚡️ Increased Productivity: Reduce development time by leveraging pre-built solutions for common scenarios.
- 🧼 Cleaner Codebase: Utilize powerful extensions for
String,num,DateTime,File,Color,Duration, andIterableto write more concise and readable code. - 🌐 Robust API Handling: Simplify network response checks and error localization with dedicated extensions.
- 🎨 Flexible UI Enhancements: Apply common styles and layouts to any widget with handy
Widgetextensions. - ⚙️ Common Utilities: A collection of functions to handle everyday tasks efficiently.
🚀 Getting Started #
1. Add PiPouch to your pubspec.yaml #
dependencies:
flutter:
sdk: flutter
pipouch: ^1.0.0 # Use the latest version from pub.dev
# If you are using Dio for networking, ensure it's also in your dependencies:
dio: ^5.0.0 # Or your current Dio version
shimmer: ^3.0.0 # Required for PiButton's shimmer loading type
Then, run flutter pub get in your terminal.
2. Import PiPouch #
import 'package:pipouch/pipouch.dart';
// You might also need specific imports depending on what you use:
// import 'package:pipouch/utils/localization/pi_abs_localization.dart'; // If you're extending localization
// import 'package:pipouch/utils/localization/pi_dio_error_localization.dart'; // For specific error localization
📖 Usage Examples #
Here are some quick examples to get you started with PiPouch's powerful utilities.
API Response Handling (Response Extension) #
Simplify checking API response statuses and getting localized messages. Requires dio package.
import 'package:dio/dio.dart';
import 'package:pipouch/pipouch.dart'; // Make sure to import
Future<void> handleResponse(Response response) async {
if (response.isSuccess) {
print('Request was successful!');
print('Message: ${response.statusCodeMessage()}'); // Default locale 'id_ID'
} else if (response.isTokenExpired) {
print('Token Expired! Please re-authenticate.');
print('Message: ${response.statusCodeMessage('en_US')}'); // Specify locale
} else if (response.isNotFound) {
print('Resource not found!');
} else {
print('An error occurred: ${response.statusCodeMessage()}');
}
}
// Example usage with Dio
// try {
// final dio = Dio();
// final response = await dio.get('[https://api.example.com/data](https://api.example.com/data)');
// handleResponse(response);
// } on DioException catch (e) {
// if (e.response != null) {
// handleResponse(e.response!);
// } else {
// print('Network Error: ${e.message}');
// }
// }
Data Type Extensions #
num Extensions
Format numbers into currency or short forms.
import 'package:pipouch/pipouch.dart';
print(100000.toShortK); // Output: 100K
print(75500.toShortK); // Output: 75K
print(100000.toRupiah); // Output: Rp 100.000
print(75500.toRupiahNoSymbol); // Output: 75.000
String Extensions
Extensive utilities for string manipulation, conversion, and validation.
import 'package:pipouch/pipouch.dart';
import 'dart:ui'; // For Locale
// Null or Empty check
String? text = null;
print(text.isEmptyOrNull); // Output: true
text = '';
print(text.isEmptyOrNull); // Output: true
print('Hello'.isEmptyOrNull); // Output: false
print(''.toEmptyNullReplacement(replacement: 'N/A')); // Output: N/A
// Capitalization
print('hello world'.toCapitalize()); // Output: Hello world
print('this is a title'.toTitleCase()); // Output: This Is A Title
print('another example'.extCapitalizeFirstLetter()); // Output: Another example
print('final check'.toCapitalizeTitle()); // Output: Final Check
// Phone number formatting
print('08123456789'.toCCPhoneNumber()); // Output: 628123456789 (default 'id' locale)
print('08123456789'.toCCPhoneNumber(locale: const Locale('en'))); // Output: 18123456789
// Type conversion
print('123'.toInt); // Output: 123
print('123.45'.toDouble); // Output: 123.45
print('true'.toBoolean); // Output: true
// Date/Time conversion & formatting
final String dateString = '2023-01-20';
final DateTime dateTime = dateString.toDateTime(); // Output: 2023-01-20 00:00:00.000
print(dateString.toFormattedDate(outputDateFormat: 'dd MMMMître')); // Output: 20 Januari 2023
print('2023-01-20 15:30:00'.toDateLocale()); // Output: 20-01-2023 - 15:30
// String utilities
print('testāḥ'.toReplaceSpecialChar()); // Output: testah
print('L0RD'.replaceLetterToNumber); // Output: L0RD (example showing how letters are replaced)
print('01245678'.replaceNumberToLetter); // Output: OIZASGTB
print('John Doe'.toInitialWord()); // Output: JD
// File type checks
print('image.jpg'.isImage); // Output: true
print('animation.json'.isLottie); // Output: true
DateTime Extensions
Format dates and calculate time differences.
import 'package:pipouch/pipouch.dart';
import 'dart:ui'; // For Locale
final DateTime myDate = DateTime(2023, 1, 15, 10, 30);
print(myDate.toFormattedString(outputDateFormat: 'dd/MM/yyyy')); // Output: 15/01/2023
print(myDate.toTimeString()); // Output: 10:30
print(myDate.toDateStringDDMMMMYYYY()); // Output: 15 Januari 2023
// Time Ago (requires localization setup)
final DateTime fiveMinutesAgo = DateTime.now().subtract(const Duration(minutes: 5));
print(fiveMinutesAgo.toTimeAgo(locale: const Locale('en'))); // Output: 5 minutes ago
final DateTime twoDaysAgo = DateTime.now().subtract(const Duration(days: 2));
print(twoDaysAgo.toTimeAgo(locale: const Locale('id'))); // Output: 2 hari lalu
File Extensions
Get file properties like size and Base64 encoding.
import 'dart:io';
import 'package:pipouch/pipouch.dart';
// Example: (Assuming 'my_file.txt' exists and is accessible)
// final File myFile = File('path/to/my_file.txt');
// print('Size in KB: ${myFile.toSizeInKB} KB');
// print('Size in MB: ${myFile.toSizeInMB} MB');
// print('Base64: ${myFile.toBase64?.substring(0, 30)}...'); // Print first 30 chars
Color Extensions
Determine if a color is light or dark based on its greyscale value.
import 'package:flutter/material.dart';
import 'package:pipouch/pipouch.dart';
const Color darkColor = Colors.black;
const Color lightColor = Colors.white;
const Color midColor = Colors.blue;
print(darkColor.isDark); // Output: true
print(lightColor.isLight); // Output: true
print(midColor.isDark); // Output: (depends on blue shade, likely false)
Duration Extensions
Format durations into human-readable remaining time.
import 'package:flutter/material.dart';
import 'package:pipouch/pipouch.dart';
const Duration twentyMinutes = Duration(minutes: 20);
print(twentyMinutes.toRemaining(const Locale('en'))); // Output: 20 minutes
const Duration threeHoursTenMinutes = Duration(hours: 3, minutes: 10);
print(threeHoursTenMinutes.toRemaining(const Locale('id'))); // Output: 3 jam 10 menit
const Duration oneSecond = Duration(seconds: 1);
print(oneSecond.toRemaining(const Locale('en'))); // Output: 1 second (if no hours/minutes)
Iterable Extension
Adds mapIndexed method, useful for mapping with an index.
import 'package:pipouch/pipouch.dart';
final List<String> items = ['apple', 'banana', 'cherry'];
final List<String> indexedItems = items.mapIndexed((item, index) {
return '$index: $item';
}).toList();
print(indexedItems); // Output: [0: apple, 1: banana, 2: cherry]
Widget Extensions (Widget Extension) #
Apply common visual effects and layouts concisely to any widget.
import 'package:flutter/material.dart';
import 'package:pipouch/pipouch.dart';
// Example: Apply margin, border radius, and shimmer effect
Widget myContent = Container(
width: 100,
height: 100,
color: Colors.grey[300],
);
Widget styledWidget = myContent
.shimmer() // Add shimmer effect
.borderRadius(all: 12.0) // Apply border radius to all corners
.margin(all: 16.0) // Apply margin on all sides
.backgroundColor(color: Colors.lightBlue); // Add a background color
// To use in your build method:
// Scaffold(
// body: Center(
// child: styledWidget,
// ),
// );
// Example: inner shadow
Widget shadowContainer = Container(
width: 150,
height: 50,
color: Colors.white,
child: const Center(child: Text('With Inner Shadow')),
).innerShadow(shadowColor: Colors.black.withOpacity(0.1)); // Apply inner shadow
// Example: Semantics for accessibility
Widget accessibleText = const Text('Click me').semantics('my_button_text'); // Add semantics
Custom Widgets #
PiButton
A highly customizable button widget with various styles, shapes, sizes, and states. It supports different types (filled, outlined, label), loading indicators (circular, shimmer), and a wide range of visual customizations.
Parameters:
onTap:void Function()?- Callback when the button is tapped.onDoubleTap:void Function()?- Callback for double-tap events.onLongPress:void Function()?- Callback for long-press events.label:String?- The text displayed on the button.iconPreffix:Widget?- An optional icon before the label.iconSuffix:Widget?- An optional icon after the label.shape:PiButtonShape- Defines the button's shape (e.g.,SQUARE,ROUNDED,CIRCLE).color:PiButtonColor- Defines the semantic color of the button (e.g.,PRIMARY,DANGER,SUCCESS).size:PiButtonSize- Defines the button's size (e.g.,SMALL,MEDIUM,LARGE).state:PiButtonState- Defines the button's interactive state (e.g.,IDLE,DISABLE,LOADING).layout:PiButtonLayout- Defines how the button fills space (WRAPorFULL).type:PiButtonType- Defines the button's visual style (e.g.,FILLED,OUTLINED,LABEL).loadingType:PiButtonLoadingType- Specifies the visual style of the loading indicator (CIRCULAR,SHIMMER).- Customization (Optional):
textStyle,backgroundColor,foregroundColor,borderRadius,horizontalPadding,verticalPadding,loadingIconColor,loadingIconStrokeWidth,loadingRadius,iconPreffixColor,iconSuffixColor,splashColor,height,width,borderWidth.
Enums:
PiButtonShape:SQUARE,ROUNDED,ROUNDED_FULL,CIRCLE.PiButtonColor:PRIMARY,SECONDARY,SUCCESS,WARNING,INFO,DANGER,DISABLE.PiButtonSize:SMALL,MEDIUM,LARGE.PiButtonState:IDLE,SUCCESS,DISABLE,LOADING.PiButtonLayout:WRAP,FULL.PiButtonType:FILLED,OUTLINED,LABEL.PiButtonLoadingType:CIRCULAR,SHIMMER.
Usage Examples:
import 'package:flutter/material.dart';
import 'package:pipouch/pipouch.dart';
// ... inside a StatelessWidget or StatefulWidget's build method
Column(
spacing: 8, // Assuming Column.spacing is available or replaced with SizedBox
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
const Text("Button By Size"),
PiButton(onTap: () {}, label: "Login", size: PiButtonSize.LARGE),
PiButton(onTap: () {}, label: "Login", size: PiButtonSize.MEDIUM),
PiButton(onTap: () {}, label: "Login", size: PiButtonSize.SMALL),
const Text("Button By Size & Shape"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
shape: PiButtonShape.CIRCLE,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.SMALL,
shape: PiButtonShape.ROUNDED_FULL,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
shape: PiButtonShape.ROUNDED,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
shape: PiButtonShape.SQUARE,
),
const Text("Button By Size & Layout"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
layout: PiButtonLayout.FULL, // Occupies full width
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.SMALL,
layout: PiButtonLayout.WRAP, // Wraps content
),
const Text("Button By Size & State"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
state: PiButtonState.LOADING, // Shows loading indicator
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
state: PiButtonState.DISABLE, // Button is disabled
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.SMALL,
state: PiButtonState.IDLE, // Normal state
),
const Text("Button By Size & Loading Type"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
state: PiButtonState.LOADING,
loadingType: PiButtonLoadingType.CIRCULAR, // Circular progress indicator
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
state: PiButtonState.LOADING,
loadingType: PiButtonLoadingType.SHIMMER, // Shimmer effect
),
const Text("Button By Size & Type"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
type: PiButtonType.FILLED, // Solid background
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.OUTLINED, // Bordered
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.LABEL, // Text-only, no background/border
),
const Text("Button By Size, Type & Color"),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
type: PiButtonType.FILLED,
color: PiButtonColor.PRIMARY,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.OUTLINED,
color: PiButtonColor.SECONDARY,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.LABEL,
color: PiButtonColor.SUCCESS,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
type: PiButtonType.FILLED,
color: PiButtonColor.INFO,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.OUTLINED,
color: PiButtonColor.DANGER,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.MEDIUM,
type: PiButtonType.LABEL,
color: PiButtonColor.WARNING,
),
PiButton(
onTap: () {},
label: "Login",
size: PiButtonSize.LARGE,
type: PiButtonType.FILLED,
color: PiButtonColor.DISABLE,
),
],
)
🤝 Contributing #
We welcome contributions! If you have a useful helper, extension, function, or widget that fits the scope of PiPouch, feel free to:
- Fork the repository.
- Create a new branch (
git checkout -b feature/your-feature-name). - Make your changes and write tests.
- Commit your changes (
git commit -m 'feat: Add amazing new feature'). - Push to the branch (
git push origin feature/your-feature-name). - Open a Pull Request.
Please ensure your code adheres to Flutter's Effective Dart guidelines and includes appropriate documentation comments.
🐛 Issues and Feedback #
Encountered a bug? Have a feature request? Please open an issue on our GitHub Issue Tracker.
📜 License #
PiPouch is released under the MIT License.
Copyright © 2025 [Rafi Fitra Alamsyah/PiPo]. All rights reserved.