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
updaterand add a document ofid = 1with and fieldsversion,androidLinkandwindowsLink. - 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.yamlfile 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.dartwith 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.arbwith 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.dartwith 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.dartwith 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
Libraries
- auth
- auth/change_password/change_password_view
- auth/change_password/change_password_view_model
- auth/core_config
- auth/exception_error_message
- auth/forgot/forgot_view
- auth/forgot/forgot_view_model
- auth/login/login_view
- auth/login/login_view_model
- auth/profile/profile_view
- auth/profile/profile_view_model
- auth/repository/auth_exception
- auth/repository/auth_repository
- auth/repository/repository
- auth/repository/user
- auth/router
- auth/routes
- auth/splash/splash_view
- auth/splash/splash_view_model
- auth/splash/version_info
- l10n/gen/app_localizations
- l10n/gen/app_localizations_en
- l10n/l10n
- l10n/l10n_extension
- ui
- A Very Good Project created by Very Good CLI.
- ui/command_error_widget
- ui/confirm_password
- ui/confirm_password_text_field
- ui/email
- ui/email_text_field
- ui/password
- ui/password_text_field
- ui/placeholder_view
- ui/ui
- updater
- Updater page
- updater/api_update_info
- updater/update_info
- updater/updater
- updater/updater_api
- updater/updater_repository
- utility
- A Very Good Project created by Very Good CLI.
- utility/base_firestore_api
- utility/base_firestore_dto
- utility/command
- utility/package_info_provider
- utility/paginated_result
- utility/theme
- utility/timestamp_converter
- utility/url_launcher
- utility/utility