esmaulhusna_muslimbg 1.0.6 copy "esmaulhusna_muslimbg: ^1.0.6" to clipboard
esmaulhusna_muslimbg: ^1.0.6 copied to clipboard

Flutter package for Esmaul Husna / Asma ul Husna with Arabic text, meanings, offline JSON data, and Balkan locale support for Islamic apps.

example/lib/main.dart

import 'package:esmaulhusna_muslimbg/esmaulhusna_muslimbg.dart';
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Esmaul Husna Example',
      debugShowCheckedModeBanner: false,
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.teal),
        useMaterial3: true,
      ),
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  int _selectedIndex = 0;

  final List<Widget> _pages = const [
    _NamesListPage(),
    _RandomNamePage(),
    _LocaleSupportPage(),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: _pages[_selectedIndex],
      bottomNavigationBar: NavigationBar(
        selectedIndex: _selectedIndex,
        onDestinationSelected: (index) =>
            setState(() => _selectedIndex = index),
        destinations: const [
          NavigationDestination(icon: Icon(Icons.list), label: 'Names'),
          NavigationDestination(icon: Icon(Icons.shuffle), label: 'Random'),
          NavigationDestination(icon: Icon(Icons.language), label: 'Locales'),
        ],
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Tab 1 — Full list with language selector
// ---------------------------------------------------------------------------

class _NamesListPage extends StatefulWidget {
  const _NamesListPage();

  @override
  State<_NamesListPage> createState() => _NamesListPageState();
}

class _NamesListPageState extends State<_NamesListPage> {
  String _language = 'en';

  static const _localeOptions = [
    ('en', 'English'),
    ('ar', 'Arabic'),
    ('tr', 'Turkish'),
    ('bg', 'Bulgarian'),
    ('bs_BA', 'Bosnian'),
    ('mk_MK', 'Macedonian'),
    ('sq_AL', 'Albanian (AL)'),
    ('sq_XK', 'Albanian (XK)'),
  ];

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: const Text('99 Names of Allah'),
        actions: [
          Padding(
            padding: const EdgeInsets.only(right: 12),
            child: DropdownButton<String>(
              value: _language,
              underline: const SizedBox.shrink(),
              items: _localeOptions
                  .map((e) => DropdownMenuItem(
                        value: e.$1,
                        child: Text(e.$2),
                      ))
                  .toList(),
              onChanged: (value) {
                if (value != null) setState(() => _language = value);
              },
            ),
          ),
        ],
      ),
      body: FutureBuilder<List<Map<String, String>>>(
        future: EsmaulHusna.getNames(_language),
        builder: (context, snapshot) {
          if (snapshot.hasError) {
            return Center(child: Text('Error: ${snapshot.error}'));
          }
          if (!snapshot.hasData) {
            return const Center(child: CircularProgressIndicator());
          }

          final names = snapshot.data!;

          return ListView.separated(
            itemCount: names.length,
            separatorBuilder: (_, __) => const Divider(height: 0),
            itemBuilder: (context, index) {
              final entry = names[index];
              return ListTile(
                leading: CircleAvatar(
                  backgroundColor:
                      Theme.of(context).colorScheme.primaryContainer,
                  child: Text(
                    '${index + 1}',
                    style: TextStyle(
                      color: Theme.of(context).colorScheme.onPrimaryContainer,
                      fontSize: 12,
                    ),
                  ),
                ),
                title: Text(entry['name'] ?? ''),
                subtitle: Text(
                  entry['translation'] ?? '',
                  maxLines: 2,
                  overflow: TextOverflow.ellipsis,
                ),
                trailing: Text(
                  entry['arabic'] ?? '',
                  style: const TextStyle(fontSize: 22),
                  textDirection: TextDirection.rtl,
                ),
                onTap: () => _showDetail(context, index + 1, entry),
              );
            },
          );
        },
      ),
    );
  }

  void _showDetail(
    BuildContext context,
    int number,
    Map<String, String> entry,
  ) {
    showModalBottomSheet<void>(
      context: context,
      shape: const RoundedRectangleBorder(
        borderRadius: BorderRadius.vertical(top: Radius.circular(16)),
      ),
      builder: (_) => Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          mainAxisSize: MainAxisSize.min,
          children: [
            Text(
              entry['arabic'] ?? '',
              style: const TextStyle(fontSize: 48),
              textDirection: TextDirection.rtl,
            ),
            const SizedBox(height: 12),
            Text(
              '${entry['name']} (#$number)',
              style: Theme.of(context).textTheme.titleLarge,
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 8),
            Text(
              entry['translation'] ?? '',
              style: Theme.of(context).textTheme.bodyMedium,
              textAlign: TextAlign.center,
            ),
            const SizedBox(height: 24),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Tab 2 — Random name
// ---------------------------------------------------------------------------

class _RandomNamePage extends StatefulWidget {
  const _RandomNamePage();

  @override
  State<_RandomNamePage> createState() => _RandomNamePageState();
}

class _RandomNamePageState extends State<_RandomNamePage> {
  String _language = 'en';
  Future<Map<String, String>>? _future;

  static const _localeOptions = [
    ('en', 'English'),
    ('ar', 'Arabic'),
    ('tr', 'Turkish'),
    ('bg', 'Bulgarian'),
    ('bs_BA', 'Bosnian'),
    ('mk_MK', 'Macedonian'),
    ('sq_AL', 'Albanian'),
  ];

  void _refresh() => setState(
        () => _future = EsmaulHusna.getRandomName(_language),
      );

  @override
  void initState() {
    super.initState();
    _future = EsmaulHusna.getRandomName(_language);
  }

  @override
  Widget build(BuildContext context) {
    final scheme = Theme.of(context).colorScheme;

    return Scaffold(
      appBar: AppBar(title: const Text('Random Name')),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            FutureBuilder<Map<String, String>>(
              future: _future,
              builder: (context, snapshot) {
                if (snapshot.hasError) {
                  return Text('Error: ${snapshot.error}');
                }
                if (!snapshot.hasData) {
                  return const CircularProgressIndicator();
                }

                final name = snapshot.data!;

                return Card(
                  margin: const EdgeInsets.symmetric(horizontal: 32),
                  elevation: 4,
                  child: Padding(
                    padding: const EdgeInsets.all(32),
                    child: Column(
                      children: [
                        Text(
                          name['arabic'] ?? '',
                          style: const TextStyle(fontSize: 52),
                          textDirection: TextDirection.rtl,
                        ),
                        const SizedBox(height: 16),
                        Text(
                          name['name'] ?? '',
                          style: Theme.of(context).textTheme.headlineSmall,
                          textAlign: TextAlign.center,
                        ),
                        const SizedBox(height: 8),
                        Text(
                          name['translation'] ?? '',
                          style: Theme.of(context)
                              .textTheme
                              .bodyMedium
                              ?.copyWith(color: scheme.onSurfaceVariant),
                          textAlign: TextAlign.center,
                        ),
                      ],
                    ),
                  ),
                );
              },
            ),
            const SizedBox(height: 32),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                DropdownButton<String>(
                  value: _language,
                  underline: const SizedBox.shrink(),
                  items: _localeOptions
                      .map((e) => DropdownMenuItem(
                            value: e.$1,
                            child: Text(e.$2),
                          ))
                      .toList(),
                  onChanged: (value) {
                    if (value != null) {
                      setState(() => _language = value);
                      _refresh();
                    }
                  },
                ),
                const SizedBox(width: 16),
                FilledButton.icon(
                  onPressed: _refresh,
                  icon: const Icon(Icons.shuffle),
                  label: const Text('New name'),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

// ---------------------------------------------------------------------------
// Tab 3 — Supported locales & alias reference
// ---------------------------------------------------------------------------

class _LocaleSupportPage extends StatelessWidget {
  const _LocaleSupportPage();

  @override
  Widget build(BuildContext context) {
    final locales = EsmaulHusna.getSupportedLanguages();

    return Scaffold(
      appBar: AppBar(title: const Text('Supported Locales')),
      body: ListView(
        padding: const EdgeInsets.all(16),
        children: [
          Text(
            '${locales.length} canonical locale codes',
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 8),
          ...locales.map(
            (locale) => ListTile(
              leading: const Icon(Icons.translate),
              title: Text(locale),
              trailing: FutureBuilder<List<Map<String, String>>>(
                future: EsmaulHusna.getNames(locale),
                builder: (_, snap) {
                  if (!snap.hasData) return const SizedBox.shrink();
                  return Text('${snap.data!.length} names');
                },
              ),
            ),
          ),
          const Divider(height: 32),
          Text(
            'Alias examples',
            style: Theme.of(context).textTheme.titleMedium,
          ),
          const SizedBox(height: 8),
          const _AliasRow(input: 'english', resolves: 'en'),
          const _AliasRow(input: 'en_US', resolves: 'en'),
          const _AliasRow(input: 'turkish', resolves: 'tr'),
          const _AliasRow(input: 'bs', resolves: 'bs_BA'),
          const _AliasRow(input: 'bs-BA', resolves: 'bs_BA'),
          const _AliasRow(input: 'mk', resolves: 'mk_MK'),
          const _AliasRow(input: 'sq', resolves: 'sq_AL'),
          const _AliasRow(input: 'unknown', resolves: 'en (fallback)'),
        ],
      ),
    );
  }
}

class _AliasRow extends StatelessWidget {
  const _AliasRow({required this.input, required this.resolves});

  final String input;
  final String resolves;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          Expanded(
            child: Text(
              input,
              style: const TextStyle(fontFamily: 'monospace'),
            ),
          ),
          const Icon(Icons.arrow_forward, size: 16),
          const SizedBox(width: 8),
          Text(
            resolves,
            style: TextStyle(
              fontFamily: 'monospace',
              color: Theme.of(context).colorScheme.primary,
            ),
          ),
        ],
      ),
    );
  }
}
4
likes
0
points
75
downloads

Documentation

Documentation

Publisher

verified publishercemalkarabulakli.com

Weekly Downloads

Flutter package for Esmaul Husna / Asma ul Husna with Arabic text, meanings, offline JSON data, and Balkan locale support for Islamic apps.

Repository (GitHub)
View/report issues

Topics

#islam #quran #flutter #localization #dua

License

unknown (license)

Dependencies

flutter, plugin_platform_interface

More

Packages that depend on esmaulhusna_muslimbg