baiomy 0.0.1
baiomy: ^0.0.1 copied to clipboard
built once, used everywhere.
๐ Baiomy #
Built once, used everywhere.
A powerful, all-in-one Flutter toolkit for local storage, password encryption, Egyptian ID parsing, input validation, utilities, and widgets โ all behind a single import.
import 'package:baiomy/baiomy.dart';
๐ฆ What's Inside #
| Module | Classes / APIs |
|---|---|
| ๐๏ธ Local Storage | BaiomySharedPrefs ยท BaiomySecureStorage ยท StorageException |
| ๐ Password Encryption | BaiomyPasswordEncryption ยท PasswordHasher ยท EncryptedPayload ยท HashedPassword ยท CryptoException |
| ๐ Egyptian ID Parser | BaiomyEgyptianIdParser |
| ๐งฉ Extensions | BuildContextExtension ยท FormAutoScroll ยท EmailValidator ยท PasswordValidator ยท NotesValidator ยท DomainValidator |
| ๐ ๏ธ Utils | BaiomyInputFormatters ยท inputDecoration() |
| ๐จ Widgets | AppToasts ยท AvatarGlow ยท ConditionalBuilder ยท CustomSizedBox ยท CustomValueListenable ยท LoadingItem |
๐ฅ Installation #
dependencies:
baiomy:
git:
url: https://github.com/mohamedelbaiomy/baiomy.git
flutter pub get
โก Setup โ once in main.dart #
import 'package:baiomy/baiomy.dart';
void main() async {
WidgetsFlutterBinding.ensureInitialized();
// Required before using BaiomySharedPrefs
await BaiomySharedPrefs.instance.init();
// Required before using BaiomyPasswordEncryption
BaiomyPasswordEncryption.instance.configure(keyPhrase: 'your-secret-phrase');
runApp(const MyApp());
}
๐๏ธ Local Storage #
BaiomySharedPrefs #
Non-sensitive data โ settings, flags, UI state. Backed by SharedPreferences.
Reads are synchronous after init().
final prefs = BaiomySharedPrefs.instance;
// โโ Write โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await prefs.setString('theme', 'dark');
await prefs.setInt('launch_count', 1);
await prefs.setBool('onboarding_done', value: true);
await prefs.setDouble('font_size', 16.0);
await prefs.setStringList('tags', ['flutter', 'dart']);
await prefs.setObject('config', {'lang': 'en', 'theme': 'dark'});
// โโ Read โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
final theme = prefs.getString('theme', defaultValue: 'light');
final count = prefs.getInt('launch_count', defaultValue: 0);
final done = prefs.getBool('onboarding_done');
final size = prefs.getDouble('font_size');
final tags = prefs.getStringList('tags');
final config = prefs.getObject('config'); // Map<String, dynamic>?
// โโ Update (key must already exist, throws otherwise) โโโโโโโโโโโโโโโโโโ
await prefs.updateString('theme', 'light');
await prefs.updateInt('launch_count', 2);
await prefs.updateBool('onboarding_done', newValue: false);
await prefs.updateDouble('font_size', 18.0);
await prefs.patchObject('config', {'theme': 'light'}); // partial update
// โโ Remove โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await prefs.remove('theme');
await prefs.clear(); // โ ๏ธ wipes everything
// โโ Utility โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
prefs.containsKey('theme'); // bool
prefs.getKeys(); // Set<String>
prefs.get('theme'); // dynamic
BaiomySecureStorage #
Sensitive data โ tokens, passwords, PII. Encrypted at rest via platform
Keychain (iOS) / Keystore (Android). All reads are async.
final secure = BaiomySecureStorage.instance;
// โโ Write โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await secure.setString('access_token', 'eyJhbGci...');
await secure.setBool('biometrics_enabled', value: true);
await secure.setInt('user_id', 42);
await secure.setDouble('score', 9.5);
await secure.setObject('session', {'expires_at': 1700000000});
// โโ Read โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
final token = await secure.getString('access_token');
final enabled = await secure.getBool('biometrics_enabled');
final uid = await secure.getInt('user_id');
final session = await secure.getObject('session');
// โโ Update (key must already exist, throws otherwise) โโโโโโโโโโโโโโโโโโ
await secure.updateString('access_token', 'newToken');
await secure.updateBool('biometrics_enabled', newValue: false);
await secure.updateInt('user_id', 99);
await secure.updateDouble('score', 10.0);
await secure.patchObject('session', {'scope': 'read write'});
// โโ Remove โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await secure.remove('access_token');
await secure.removeMany(['access_token', 'session']); // batch
await secure.clear(); // โ ๏ธ wipes everything
// โโ Utility โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
await secure.containsKey('access_token'); // Future<bool>
await secure.getKeys(); // Future<Set<String>>
await secure.getAll(); // Future<Map<String, String>>
๐ Password Encryption #
Which one should I use? #
Need to recover the original password later? โ BaiomyPasswordEncryption (AES-256 two-way)
Just need to verify it at login? โ PasswordHasher (PBKDF2 one-way)
BaiomyPasswordEncryption โ Two-way AES-256-CBC #
Encrypts any string and lets you get the original value back. Every encrypt call produces a different ciphertext even for the same input because a fresh random IV is generated each time.
Configure once in main():
BaiomyPasswordEncryption.instance.configure(keyPhrase: 'your-secret-phrase');
Encrypt & store in Firestore:
final payload = BaiomyPasswordEncryption.instance.encrypt(passwordController.text);
// payload.combined โ "ivBase64:ciphertextBase64" โ store this
// payload.iv โ IV used, Base64-encoded
// payload.cipherText โ encrypted value, Base64-encoded
await FirebaseFirestore.instance.collection('users').doc(uid).set({
'password': payload.combined,
});
Decrypt โ recover the original:
final doc = await FirebaseFirestore.instance.collection('users').doc(uid).get();
final pass = BaiomyPasswordEncryption.instance.decrypt(doc['password'] as String);
Convenience โ encrypt directly to a string:
final stored = BaiomyPasswordEncryption.instance.encryptToString(passwordController.text);
Validate a stored value:
BaiomyPasswordEncryption.instance.isValidPayload(stored); // bool
PasswordHasher โ One-way PBKDF2-HMAC-SHA256 #
Best for login systems where you never need the original password back. Uses 310,000 iterations (OWASP 2023) + a unique 32-byte random salt. Uses constant-time comparison to prevent timing attacks. The original password cannot be recovered โ ever.
Hash on registration:
final hashed = PasswordHasher.instance.hash(passwordController.text);
// hashed.combined โ "310000:saltBase64:hashBase64" โ store this
// hashed.hash โ derived key, Base64-encoded
// hashed.salt โ random salt, Base64-encoded
// hashed.iterations โ 310000
await FirebaseFirestore.instance.collection('users').doc(uid).set({
'passwordHash': hashed.combined,
});
Verify on login:
final doc = await FirebaseFirestore.instance.collection('users').doc(uid).get();
final ok = PasswordHasher.instance.verify(
password: passwordController.text,
combined: doc['passwordHash'] as String,
);
if (!ok) throw Exception('Wrong password');
Validate a stored hash string:
PasswordHasher.instance.isValidHash(storedValue); // bool
๐ Egyptian ID Parser #
Parse and extract full information from a 14-digit Egyptian National ID.
final parser = BaiomyEgyptianIdParser('29901011234567');
print(parser.birthDate); // e.g. "1999-01-01"
print(parser.governorate); // e.g. "Cairo"
print(parser.gender); // e.g. "Male"
print(parser.age); // Age object
๐งฉ Extensions #
BuildContextExtension #
// Navigation
context.pop();
context.popWithValue('result');
await context.mayBePop(); // Future<bool>
// Screen dimensions
final width = context.screenWidth; // double
final height = context.screenHeight; // double
final dpr = context.devicePixelRatio; // double
FormAutoScroll #
Automatically scrolls to the first invalid field on form submission.
Called as an extension on GlobalKey<FormState>:
final _formKey = GlobalKey<FormState>();
// Instead of _formKey.currentState!.validate()
final isValid = _formKey.validateAndScroll(); // bool
// Scrolls to the first field with an error if invalid
EmailValidator #
'user@gmail.com'.isValidEmail(); // true
'not-an-email'.isValidEmail(); // false
'user@uni.edu.eg'.isAcademicEmail(); // true
'user@company.com'.isCorporateEmail(); // true
'test@test.com'.hasSuspiciousEmailPattern(); // true
'user@gmail.com'.capitalize(); // 'User@gmail.com'
PasswordValidator #
'MyPass1!'.hasUppercase(); // true
'MyPass1!'.hasLowercase(); // true
'MyPass1!'.hasDigit(); // true
'MyPass1!'.hasSpecialCharacter(); // true
'MyPass1!'.hasWhitespace(); // false
'MyPass1!'.hasMixedCase(); // true
'MyPass1!'.hasMultipleDigits(); // false
'MyPass1!'.hasMultipleSpecialChars(); // false
'password123'.isCommonPassword(); // true
'abc123'.hasSequentialCharacters(); // true
'aaabbb'.hasExcessiveRepeatedCharacters(); // true
NotesValidator #
'spam content'.hasInappropriateContent(); // true
'Hello!!!!!!'.hasExcessiveSpecialCharacters(); // true
'aaaaaaa note'.hasExcessiveRepeatedText(); // true
'Study near the library'.hasMeaningfulContent(); // true
'Valid Note.'.hasProperStructure(); // true
'Room 101 level 2'.hasSpecificDetails(); // true
'Near the faculty building'.hasLocationDetails(); // true
'Near university campus'.hasEducationalContext(); // true
'Hello world'.getWordCount(); // 2
'Hello world'.getCharacterCountWithoutSpaces(); // 10
DomainValidator #
'flutter.dev'.isDomainValid(); // true
'mail.uni.edu.eg'.isDomainValid(); // true
'invalid'.isDomainValid(); // false
'ู
ุซุงู.com'.isInternationalDomain(); // true
๐ ๏ธ Utils #
BaiomyInputFormatters #
Apply as inputFormatters on any TextFormField:
// โโ Ready-made formatters โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
TextFormField(inputFormatters: BaiomyInputFormatters.nameField);
TextFormField(inputFormatters: BaiomyInputFormatters.phoneField);
TextFormField(inputFormatters: BaiomyInputFormatters.emailField);
TextFormField(inputFormatters: BaiomyInputFormatters.passwordField);
TextFormField(inputFormatters: BaiomyInputFormatters.notesField);
TextFormField(inputFormatters: BaiomyInputFormatters.cleanText);
TextFormField(inputFormatters: BaiomyInputFormatters.username);
TextFormField(inputFormatters: BaiomyInputFormatters.creditCard);
TextFormField(inputFormatters: BaiomyInputFormatters.currency);
// โโ Basic formatters โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
BaiomyInputFormatters.denyEmojis
BaiomyInputFormatters.numbersOnly
BaiomyInputFormatters.lettersOnly
BaiomyInputFormatters.alphanumericOnly
BaiomyInputFormatters.phoneNumberSafe
BaiomyInputFormatters.emailSafe
BaiomyInputFormatters.urlSafe
BaiomyInputFormatters.passwordSafe
BaiomyInputFormatters.denyProfanity
// โโ With length limits โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
BaiomyInputFormatters.lengthLimit(10)
BaiomyInputFormatters.nameWithLength(35) // default 35
BaiomyInputFormatters.phoneWithLength(11) // default 11
BaiomyInputFormatters.notesWithLength(500) // default 500
// โโ Custom โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
BaiomyInputFormatters.customDeny([RegExp(r'[xyz]')], allowEmojis: false)
BaiomyInputFormatters.customAllow([RegExp(r'[0-9]')])
BaiomyInputFormatters.caseFormatter(uppercase: true)
// โโ Validation helpers (no TextFormField needed) โโโโโโโโโโโโโโโโโโโโโโโ
BaiomyInputFormatters.containsEmojis('hello ๐'); // true
BaiomyInputFormatters.isNumericOnly('12345'); // true
BaiomyInputFormatters.containsProfanity('some text'); // false
BaiomyInputFormatters.getCleanCharacterCount('hi ๐'); // 3
inputDecoration() #
A global function that returns a styled InputDecoration:
// Underline style (default)
TextFormField(
decoration: inputDecoration(
'Enter your email',
Theme.of(context),
suffixIcon: const Icon(Icons.email),
helperText: 'We will never share your email',
),
)
// Outlined style
TextFormField(
decoration: inputDecoration(
'Enter your password',
Theme.of(context),
isOutlined: true,
suffixIcon: const Icon(Icons.lock),
),
)
๐จ Widgets #
Widget files are in
lib/widgets/. Refer to each file for full constructor details as the APIs depend on your local implementation.
BaiomyToast #
Quick snackbar-style notifications.
BaiomyAvatarGlow #
Avatar widget with an animated glow effect.
BaiomyConditionalBuilder #
Renders different widgets based on a condition.
CustomSizedBox #
Convenient spacing widget using extension.
BaiomyValueListenableBuilder2 #
Reactive widget that rebuilds when a ValueListenable changes.
BaiomyLoadingItem #
Loading skeleton / overlay widget (from widgets/loading/loading_item.dart).
๐ก๏ธ Error Handling #
Every module throws its own typed exception โ never a raw platform error.
// Storage errors
try {
await BaiomySecureStorage.instance.updateString('missing_key', 'value');
} on StorageException catch (e) {
print(e.message); // 'Cannot update a key that does not exist.'
print(e.key); // 'missing_key'
print(e.cause); // original platform error
print(e.stackTrace); // original stack trace
}
// Crypto errors
try {
BaiomyPasswordEncryption.instance.decrypt('bad_format');
} on CryptoException catch (e) {
print(e.message); // 'Decryption failed. The key may be wrong...'
print(e.cause); // original error
}
๐ Package Structure #
lib/
โโโ egyptian_id_parser/
โ โโโ impl/
โ โโโ models/
โ โโโ repo/
โ โโโ country_id_parser_base.dart โ BaiomyEgyptianIdParser
โโโ extensions/
โ โโโ validator/
โ โ โโโ domain_validator.dart โ DomainValidator (extension)
โ โ โโโ email_validator.dart โ EmailValidator (extension)
โ โ โโโ notes_validator.dart โ NotesValidator (extension)
โ โ โโโ password_validator.dart โ PasswordValidator (extension)
โ โโโ build_context_extensions.dart โ BuildContextExtension (extension)
โ โโโ form_auto_scroll.dart โ FormAutoScroll (extension on GlobalKey)
โโโ local_storage/
โ โโโ shared_preferences.dart โ BaiomySharedPrefs
โ โโโ secure_storage.dart โ BaiomySecureStorage
โ โโโ storage_exception.dart โ StorageException
โโโ password_encryption/
โ โโโ password_encryption.dart โ BaiomyPasswordEncryption
โ โโโ password_hasher.dart โ PasswordHasher
โ โโโ encrypted_payload.dart โ EncryptedPayload
โ โโโ hashed_password.dart โ HashedPassword
โ โโโ crypto_exception.dart โ CryptoException
โโโ utils/
โ โโโ app_input_formatters.dart โ BaiomyInputFormatters
โ โโโ logger_class.dart
โ โโโ text_form_field_decoration.dart โ inputDecoration()
โโโ widgets/
โ โโโ loading/
โ โ โโโ loading_item.dart
โ โโโ app_toasts.dart
โ โโโ avatar_glow.dart
โ โโโ conditional_builder.dart
โ โโโ custom_sized_box.dart
โ โโโ custom_value_listenable.dart
โโโ baiomy.dart
โ๏ธ License #
Copyright (c) 2026 Mohamed Elbaiomy. All Rights Reserved.
This software is proprietary. Unauthorized copying, modification,
distribution, or use of this package, via any medium, is strictly
prohibited without prior written permission from the author.
See the LICENSE file for full details.
Built with โค๏ธ by Baiomy