baiomy 0.0.6 copy "baiomy: ^0.0.6" to clipboard
baiomy: ^0.0.6 copied to clipboard

A Flutter toolkit for local storage, secure storage, password encryption, Egyptian ID parsing, input validation, formatters, and reusable widgets

๐Ÿš€ 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
๐Ÿšง Routes BaiomyNavKit
๐Ÿงฉ 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

BaiomyNavKit #

Features #

Feature Detail
Named route validation Typos are caught at debug-time via assert
5 transition styles bottomToUpWithFade ยท fade ยท slideWithFade ยท slideOnly ยท cupertino
Platform-aware defaults Cupertino on iOS, fade/slide on Android
Semantic push methods pushWithSlideUp, pushWithFade, pushWithSlideAndFade, pushWithSlide
Replace / clear-stack pushReplacement, pushAndRemoveAll, replaceStack
Direct widget push No route name required โ€” great for modal sheets
BuildContext extensions context.navPush(...) ยท context.navPop() ยท context.navCanPop
Zero dependencies Only Flutter itself

Usage #

1 โ€” Declare your routes #

Create one file that owns every route string in your app. Extending NavRoutes and listing them in get all is what enables debug-time typo detection.

// lib/routes/routes.dart
import 'package:flutter_nav_kit/flutter_nav_kit.dart';
 
class Routes extends NavRoutes {
  static const String home    = '/home';
  static const String login   = '/login';
  static const String detail  = '/detail';
  static const String profile = '/profile';
 
  @override
  List<String> get all => [home, login, detail, profile];
}

2 โ€” Initialise and wire up #

Call BaiomyNavKit.init once before runApp, then pass NavRouteGenerator to MaterialApp.onGenerateRoute. The builders map is the only place you ever write the mapping between a route name and a screen widget.

// lib/main.dart
import 'package:flutter_nav_kit/flutter_nav_kit.dart';
import 'routes/routes.dart';
 
void main() {
  BaiomyNavKit.init(routes: Routes()); // turns on assert-based route validation
  runApp(const MyApp());
}
 
class MyApp extends StatelessWidget {
  const MyApp({super.key});
 
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      initialRoute: Routes.home,
      onGenerateRoute: NavRouteGenerator(
        routes: Routes(),
        noRouteScreen: const NotFoundScreen(), // shown for unknown routes
        firstRoute: Routes.home,
        builders: {
          // args is the value you passed via the `arguments:` parameter,
          // with all transition metadata already stripped out for you.
          Routes.home:    (_)    => const HomeScreen(),
          Routes.login:   (_)    => const LoginScreen(),
          Routes.detail:  (args) => DetailScreen(item: args as MyItem),
          Routes.profile: (args) => ProfileScreen(userId: args as String),
        },
      ).generateRoute,
    );
  }
}

3 โ€” Push screens #

Simple push โ€” platform-default transition

On iOS this uses the native Cupertino swipe; on Android it uses a fade. No configuration required.

BaiomyNavKit.push(context, Routes.home);
BaiomyNavKit.push(context, Routes.detail, arguments: myItem);

Push with a specific animation

BaiomyNavKit.pushWithSlideUp(context, Routes.detail, arguments: myItem);
BaiomyNavKit.pushWithFade(context, Routes.settings);
BaiomyNavKit.pushWithSlide(context, Routes.profile, arguments: userId);
BaiomyNavKit.pushWithSlideAndFade(context, Routes.detail);

Replace the current screen (no back button left behind)

BaiomyNavKit.pushReplacement(context, Routes.home);
BaiomyNavKit.pushReplacementWithFade(context, Routes.login);
BaiomyNavKit.pushReplacementWithSlideUp(context, Routes.onboarding);

Clear the entire stack (logout, post-login redirect, splash โ†’ home)

BaiomyNavKit.pushAndRemoveAll(context, Routes.login);
BaiomyNavKit.pushAndRemoveAllWithFade(context, Routes.home);
BaiomyNavKit.pushAndRemoveAllWithSlideUp(context, Routes.dashboard);

Replace the whole stack with multiple screens

Useful for deep-link handling โ€” clears the stack, pushes the first route, then pushes the rest on top so the back-stack is exactly as you specify.

BaiomyNavKit.replaceStack(context, [Routes.home, Routes.detail]);

Avoid pushing the same screen twice

// No-op if the user is already on Routes.home
BaiomyNavKit.pushIfNotCurrent(context, Routes.home);

4 โ€” Pop / go back #

BaiomyNavKit.pop(context);                     // simple back
BaiomyNavKit.pop(context, myResult);           // back with a return value
BaiomyNavKit.popUntil(context, Routes.home);   // unwind to a specific screen
BaiomyNavKit.canPop(context);                  // โ†’ bool

5 โ€” Push a widget directly (no route name needed) #

Good for modals, confirmation sheets, or one-off screens you don't want registered in the route table.

// Lazy builder โ€” widget isn't constructed until the transition begins
BaiomyNavKit.pushWidget(context, () => const ConfirmationSheet());
 
// Or pass an already-constructed widget
BaiomyNavKit.pushWidgetWithSlideUp(context, const ConfirmationSheet());
BaiomyNavKit.pushWidgetWithFade(context, const ConfirmationSheet());

6 โ€” Custom transition durations #

Every method accepts optional transitionDuration and reverseTransitionDuration. Omit them to use the built-in defaults.

BaiomyNavKit.pushWithSlideUp(
  context,
  Routes.detail,
  arguments: myItem,
  transitionDuration: const Duration(milliseconds: 500),
  reverseTransitionDuration: const Duration(milliseconds: 350),
);

7 โ€” Context extensions (optional shorthand) #

Every BaiomyNavKit method has a matching extension on BuildContext prefixed with nav. Use whichever style fits your codebase โ€” they are identical under the hood.

// These two lines do exactly the same thing:
BaiomyNavKit.pushWithSlideUp(context, Routes.detail, arguments: item);
context.navPushWithSlideUp(Routes.detail, arguments: item);
 
// Other examples
context.navPush(Routes.home);
context.navPushWithFade(Routes.settings);
context.navPushReplacement(Routes.login);
context.navPushAndRemoveAll(Routes.home);
context.navPop();
context.navPopUntil(Routes.home);
bool can = context.navCanPop;
context.navPushWidgetWithSlideUp(const MyModal());

๐Ÿ› ๏ธ 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).

BaiomyKeepAlivePage #

utility wrapper widget designed to preserve the state of its child widget, preventing it from being disposed of when it moves out of view


๐Ÿ›ก๏ธ 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
โ”œโ”€โ”€ routes/
โ”‚   โ”œโ”€โ”€ src/
โ”‚   โ”‚   โ”œโ”€โ”€ nav_extensions.dart      โ†’ NavKitContext (extension)
โ”‚   โ”‚   โ”œโ”€โ”€ nav_kit.dart             โ†’ BaiomyNavKit
โ”‚   โ”‚   โ”œโ”€โ”€ nav_route_generator.dart โ†’ NavRouteGenerator
โ”‚   โ”‚   โ”œโ”€โ”€ nav_routes.dart          โ†’ NavRoutes
โ”‚   โ”‚   โ””โ”€โ”€ nav_transition_type.dart โ†’ NavTransitionType (enum)
โ”‚   โ””โ”€โ”€ flutter_nav_kit.dart
โ”œโ”€โ”€ 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 #

BAIOMY PROPRIETARY SOFTWARE LICENSE

================================================================================
Copyright (c) 2026 Mohamed Elbaiomy. All Rights Reserved.
================================================================================

IMPORTANT โ€” READ CAREFULLY BEFORE USING THIS SOFTWARE.

This license agreement ("Agreement") is a legal agreement between you
("Licensee") and the author of this software package ("Licensor", "Mohamed Elbaiomy").
By accessing, downloading, copying, installing, or using any part of this
software, its source code, documentation, or any associated files
(collectively, the "Software"), you agree to be bound by the terms of this
Agreement. If you do not agree, you must immediately delete all copies of the
Software and cease all use.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
1. GRANT OF LICENSE
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

No license is granted under this Agreement unless explicitly authorized in
writing by Mohamed Elbaiomy. Mohamed reserves ALL rights to this Software,
including but not limited to the right to use, copy, modify, merge, publish,
distribute, sublicense, and sell copies of the Software.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
2. RESTRICTIONS
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Unless you have received prior WRITTEN PERMISSION from the Licensor, you are
STRICTLY PROHIBITED from:

  a) Using this Software, in whole or in part, for any personal, academic,
     commercial, or non-commercial project.

  b) Copying, reproducing, or duplicating the Software or any portion thereof.

  c) Modifying, adapting, translating, reverse engineering, decompiling,
     disassembling, or creating derivative works based on the Software.

  d) Distributing, publishing, sublicensing, selling, renting, leasing, or
     transferring the Software or any rights therein to any third party.

  e) Incorporating the Software or any part of it into another software
     package, library, product, or service.

  f) Removing, altering, or obscuring any copyright notice, license text,
     attribution, or proprietary marking included in the Software.

  g) Using the name "Baiomy", the package name, or any associated branding
     to endorse or promote products derived from this Software without prior
     written consent.

  h) Uploading, mirroring, or re-hosting this Software on any public or
     private repository, platform, or registry (including but not limited to
     pub.dev, GitHub, GitLab, Bitbucket, or npm) without explicit written
     authorization from the Licensor.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
3. OWNERSHIP
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

The Software is proprietary to Mohamed Elbaiomy and is protected by copyright law
and international treaty provisions. The Licensor retains exclusive ownership
of all intellectual property rights in and to the Software, including all
copies, modifications, and derivative works, regardless of who created them.

This Agreement does not transfer any ownership, title, or intellectual property
rights in the Software to the Licensee. Any use of the Software not expressly
permitted by this Agreement is strictly prohibited and constitutes a violation
of the Licensor's intellectual property rights.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
4. NO WARRANTIES
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE, ACCURACY, OR NON-INFRINGEMENT. THE LICENSOR
DOES NOT WARRANT THAT THE SOFTWARE WILL MEET YOUR REQUIREMENTS, OPERATE WITHOUT
INTERRUPTION, OR BE ERROR-FREE.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
5. LIMITATION OF LIABILITY
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

IN NO EVENT SHALL THE LICENSOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
SPECIAL, EXEMPLARY, CONSEQUENTIAL, OR PUNITIVE DAMAGES (INCLUDING BUT NOT
LIMITED TO LOSS OF DATA, LOSS OF PROFITS, BUSINESS INTERRUPTION, OR LOSS OF
GOODWILL) ARISING OUT OF OR IN CONNECTION WITH THE USE OR INABILITY TO USE
THE SOFTWARE, EVEN IF THE LICENSOR HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
6. ENFORCEMENT
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Any unauthorized use, reproduction, distribution, or modification of this
Software constitutes copyright infringement and will be subject to civil and
criminal penalties under applicable law, including international copyright
treaties. The Licensor reserves the right to seek all available legal and
equitable remedies, including injunctive relief and monetary damages.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
7. TERMINATION
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

Any rights conditionally granted by Mohamed Elbaiomy (if any) terminate
immediately and automatically upon any breach of this Agreement by the
Licensee. Upon termination, the Licensee must destroy all copies of the
Software in their possession or control.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
8. GOVERNING LAW
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

This Agreement shall be governed by and construed in accordance with the laws
of the Arab Republic of Egypt, without regard to its conflict of law provisions.
Any dispute arising under or relating to this Agreement shall be subject to the
exclusive jurisdiction of the competent courts of Egypt.

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
9. CONTACT
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€

For licensing inquiries, permission requests, or any questions regarding this
Agreement, contact the Licensor at:

  Author  : Mohamed Elbaiomy
  Project : https://github.com/mohamedelbaiomy/baiomy

โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€
ALL RIGHTS RESERVED. UNAUTHORIZED USE IS STRICTLY PROHIBITED.
โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€


Built with โค๏ธ by Baiomy

1
likes
0
points
75
downloads

Publisher

unverified uploader

Weekly Downloads

A Flutter toolkit for local storage, secure storage, password encryption, Egyptian ID parsing, input validation, formatters, and reusable widgets

Repository (GitHub)
View/report issues

License

unknown (license)

Dependencies

encrypt, flutter, flutter_secure_storage, pointycastle, shared_preferences, skeletonizer

More

Packages that depend on baiomy