To Use utility:

import 'package/aptof_core/utility.dart'

Click here for details doc

To use 'ui'

import 'package/aptof_core/ui.dart'

Authentication

import 'package/aptof_core/auth.dart'

And follow the below steps

Setup firebase to your project

  • Create a firebase project with Authentication and Firestore
  • Read official documentation and setup firebase to flutter app.
  • Then use product firebase auth and cloud firestore
  • Authentication: Use Email/Password provider only and add an user. Disable signup.
  • Firestore: Add collection updater and add a document of id = 1 with and fields version, androidLink and windowsLink.
  • In cloud firestore rules use the following
rules_version = '2';

service cloud.firestore {
  match /databases/{database}/documents {
  	match /updater/{document} {
      // Only signed-in users can read
      allow read: if request.auth != null;

      // No one can write (create, update, delete)
      allow write: if false;
    }
  
    match /{document=**} {
      allow read, write: if false;
    }
  }
}

Use l10n in your project

  • Create an l10n.yaml file in root of your project with the following content.
arb-dir: lib/l10n/arb
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
output-dir: lib/l10n/gen
nullable-getter: false

# Needed to ensure the formatter does not run on the generated files.
# See https://github.com/dart-lang/dart_style/issues/864 for more information
header: "// dart format off\n// coverage:ignore-file"
  • Create a lib/l10n/l10n.dart with following content
import 'package:flutter/widgets.dart';
import 'package:<your_app_name>/l10n/gen/app_localizations.dart';

export 'package:<your_app_name>/l10n/gen/app_localizations.dart';

extension AppLocalizationsX on BuildContext {
  AppLocalizations get l10n => AppLocalizations.of(this);
}
  • Create lib/l10n/arb/app_en.arb with following content
{
  "@@locale": "en"
}
  • Add following to pubspec.yaml
...
dependencies:
  flutter_localizations:
    sdk: flutter
...

flutter:
  use-material-design: true
  generate: true
  • Run flutter gen-l10n

Create lib/router.dart with following content

There are two version of router, Shell and Non-shell. The shell router uses a bottom navigation bar and shell branch of go_router.

ShellRouter should be used like this

import 'package:aptof_core/auth/router.dart';
import 'package:aptof_core/auth/routes.dart';
import 'package:aptof_core/ui.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:<your_app_name>/home/home.dart';

class AppRouter extends AptofShellRouter {
  AppRouter(super.authRepository);

  @override
  List<StatefulShellBranch> branches() {
    return [
      StatefulShellBranch(
        routes: [
          GoRoute(
            path: AptofRoutes.home,
            builder: (context, state) => const HomeView(),
          ),
        ],
      ),
      StatefulShellBranch(
        routes: [
          GoRoute(
            path: '/home2',
            builder: (context, state) => const PlaceholderView(title: 'Home 2'),
          ),
        ],
      ),
      StatefulShellBranch(
        routes: [
          GoRoute(
            path: '/home3',
            builder: (context, state) => const PlaceholderView(title: 'Home 3'),
          ),
        ],
      ),
    ];
  }

  @override
  List<NavigationDestination> destinations(BuildContext context) {
    return [
      const NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
      const NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
      const NavigationDestination(icon: Icon(Icons.home), label: 'Home'),
    ];
  }
}

NonShellRouter should be used like this

Non shell router no bottom barred is used. Home view is the root and all other routes or child to the Home. You should add a button to the home view which will navigate to the profile route.

import 'package:aptof_core/auth/router.dart';
import 'package:flutter/material.dart';
import 'package:go_router/go_router.dart';
import 'package:<your_app_name>/home/home.dart';
import 'package:<your_app_name>/routes.dart';

class AppRouter extends AptofRouter {
  AppRouter(super.authRepository);

  @override
  List<GoRoute> get routes => [
    GoRoute(
      path: Routes.chaptersRelative,
      builder: (context, state) =>
          ChaptersView(subjectId: state.pathParameters['subjectId']!),
      routes: [
        GoRoute(
          path: Routes.addChapterRelative,
          builder: (context, state) =>
              ChapterAddView(subjectId: state.pathParameters['subjectId']!),
        ),
      ],
    ),
  ];

  @override
  Widget homeBuilder(BuildContext context, GoRouterState state) {
    return const HomeView();
  }
}

Create a HomeView

  • Create lib/home/home_view.dart with following content
import 'package:flutter/material.dart';


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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: const Text('Home')),

      // Use this body while you are not using shell router
      body: Center(
        child: FilledButton(
          onPressed: () => context.go(AptofRoutes.profile),
          child: const Text('Profile'),
        ),
      ),
    );
  }
}
  • Create lib/home/home.dart with following content
export 'home_view.dart';

Replace content of lib/main.dart with following

import 'package:aptof_core/auth.dart';
import 'package:aptof_core/l10n/l10n.dart';
import 'package:aptof_core/updater.dart';
import 'package:aptof_core/utility.dart';
import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';
import 'package:firebase_core/firebase_core.dart';
import 'package:flutter/material.dart';
import 'package:<your_package_name>/firebase_options.dart';
import 'package:<your_package_name>/l10n/gen/app_localizations.dart';
import 'package:<your_package_name>/router.dart';
import 'package:provider/provider.dart';

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();
  await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);

  runApp(const MainApp());
}

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

  List<SingleChildWidget> get providers => [
    Provider.value(value: FirebaseAuth.instance),
    Provider.value(value: FirebaseFirestore.instance),
    Provider(create: (_) => UrlLauncher()),
    Provider(create: (_) => PackageInfoProvider()),
    Provider(
      create: (context) => AuthRepository(firebaseAuth: context.read()),
        dispose: (_, provider) => provider.dispose(),
      ),
    Provider(create: (context) => UpdaterApi(context.read())),
    Provider(
      create: (context) =>
        UpdaterRepository(context.read(), context.read()),
    ),
  ]

  @override
  Widget build(BuildContext context) {
    return MultiProvider(
      providers: providers,
      child: _AppView(),
    );
  }
}

class _AppView extends StatelessWidget {
  const _AppView();

  @override
  Widget build(BuildContext context) {
    final theme = AptofTheme(seedColor: Colors.green);
    final router = AppRouter(context.read());

    return MaterialApp.router(
      theme: theme.light,
      darkTheme: theme.dark,
      localizationsDelegates: const [
        ...AppLocalizations.localizationsDelegates,
        ...AptofLocalizations.localizationsDelegates,
      ],
      supportedLocales: {
        ...AppLocalizations.supportedLocales,
        ...AptofLocalizations.supportedLocales,
      }.toList(),
      routerConfig: router.createRouter(),
    );
  }
}

Finally run app