mirror of
https://github.com/hanskokx/arcane_framework.git
synced 2026-05-14 10:29:06 +02:00
Update example documentation
Signed-off-by: Hans Kokx <hans.d.kokx@gmail.com>
This commit is contained in:
+90
-42
@@ -4,51 +4,54 @@ import "package:arcane_framework/arcane_framework.dart";
|
|||||||
import "package:example/config.dart";
|
import "package:example/config.dart";
|
||||||
import "package:example/interfaces/debug_auth_interface.dart";
|
import "package:example/interfaces/debug_auth_interface.dart";
|
||||||
import "package:example/interfaces/debug_print_interface.dart";
|
import "package:example/interfaces/debug_print_interface.dart";
|
||||||
import "package:example/services/demo_service.dart";
|
|
||||||
import "package:example/services/favorite_color_service.dart";
|
import "package:example/services/favorite_color_service.dart";
|
||||||
import "package:example/theme/theme.dart";
|
import "package:example/theme/theme.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
|
|
||||||
Future<void> main() async {
|
Future<void> main() async {
|
||||||
WidgetsFlutterBinding.ensureInitialized();
|
// If any Feature enum items are `enabledAtStartup`, enable them within Arcane.
|
||||||
|
|
||||||
for (final Feature feature in Feature.values) {
|
for (final Feature feature in Feature.values) {
|
||||||
if (feature.enabledAtStartup) Arcane.features.enableFeature(feature);
|
if (feature.enabledAtStartup) Arcane.features.enableFeature(feature);
|
||||||
}
|
}
|
||||||
|
|
||||||
await Future.wait([
|
// Register the logging interface
|
||||||
Arcane.logger.registerInterfaces([
|
await Arcane.logger.registerInterface(DebugPrint.I);
|
||||||
DebugPrint.I,
|
|
||||||
]),
|
|
||||||
IdService.I.init(),
|
|
||||||
]);
|
|
||||||
|
|
||||||
|
// Add some persistent metadata to be used in every future log message
|
||||||
Arcane.logger.addPersistentMetadata({
|
Arcane.logger.addPersistentMetadata({
|
||||||
"session_id": IdService.I.sessionId.value,
|
"demo": "This message will be included in all log messages.",
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Register the authentication interface
|
||||||
await Arcane.auth.registerInterface(DebugAuthInterface.I);
|
await Arcane.auth.registerInterface(DebugAuthInterface.I);
|
||||||
|
|
||||||
|
// Set the light and dark mode themes using our pre-defined ThemeData classes
|
||||||
Arcane.theme
|
Arcane.theme
|
||||||
..setDarkTheme(darkTheme)
|
..setLightTheme(lightTheme)
|
||||||
..setLightTheme(lightTheme);
|
..setDarkTheme(darkTheme);
|
||||||
|
|
||||||
|
// Log a message that the app has been initialized
|
||||||
Arcane.log(
|
Arcane.log(
|
||||||
"Initialization complete.",
|
"Initialization complete.",
|
||||||
|
// Set an appropriate log level
|
||||||
level: Level.info,
|
level: Level.info,
|
||||||
|
// The `module` and `method` are _often_ automatically determined, but they can be overridden.
|
||||||
module: "main",
|
module: "main",
|
||||||
method: "main",
|
method: "main",
|
||||||
|
// Skip autodetction of the `module`, `method`, and file/line number where logs originated from.
|
||||||
|
skipAutodetection: true,
|
||||||
|
// Add some optional metadata to be included in this single log message. This is added to the
|
||||||
|
// persistent metadata, if any has been set.
|
||||||
metadata: {
|
metadata: {
|
||||||
"ready": "true",
|
"ready": "true",
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ArcaneApp(
|
// The `ArcaneApp` widget is optional but provides the `ArcaneEnvironmentProvider`,
|
||||||
services: [
|
// `ArcaneServiceProvider`, and `ArcaneThemeSwitcher` widgets.
|
||||||
IdService.I,
|
const ArcaneApp(
|
||||||
],
|
child: MainApp(),
|
||||||
child: const MainApp(),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -59,9 +62,13 @@ class MainApp extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return MaterialApp(
|
return MaterialApp(
|
||||||
debugShowCheckedModeBanner: false,
|
// Use the light and dark theme objects registered in Arcane. If either style is
|
||||||
|
// updated in Arcane, the changes will reflect here. This allows for on-the-fly
|
||||||
|
// customizations without requiring compile-time themes to be pre-defined.
|
||||||
theme: Arcane.theme.light,
|
theme: Arcane.theme.light,
|
||||||
darkTheme: Arcane.theme.dark,
|
darkTheme: Arcane.theme.dark,
|
||||||
|
// By fetching the current ThemeMode from Arcane, the app will automatically rebuild
|
||||||
|
// when the theme is switched, either manually or automatically.
|
||||||
themeMode: Arcane.theme.currentModeOf(context),
|
themeMode: Arcane.theme.currentModeOf(context),
|
||||||
home: Scaffold(
|
home: Scaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -81,9 +88,37 @@ class HomeScreen extends StatefulWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class _HomeScreenState extends State<HomeScreen> {
|
class _HomeScreenState extends State<HomeScreen> {
|
||||||
late final StreamSubscription<String> _subscription;
|
// Set up a subscriber that we can use to listen to logs in realtime.
|
||||||
|
// Note: this is completely optional and does _not_ impact whether logs are
|
||||||
|
// sent to any registered logging interfaces.
|
||||||
|
late final StreamSubscription<String> _logStreamSubscriber;
|
||||||
|
|
||||||
|
// Used to collect the logs from the stream.
|
||||||
final List<String> latestLogs = [];
|
final List<String> latestLogs = [];
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
// Listens to the Arcane logger stream of logs and adds them to the latestLogs list.
|
||||||
|
_logStreamSubscriber = Arcane.logger.logStream.listen((message) {
|
||||||
|
// If [Feature.logging] is disabled, we won't add the logs to the list or trigger
|
||||||
|
// a rebuild.
|
||||||
|
if (Feature.logging.enabled) {
|
||||||
|
setState(() {
|
||||||
|
latestLogs.insert(0, message);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
void dispose() {
|
||||||
|
// Don't forget to properly dispose of the subscriber
|
||||||
|
_logStreamSubscriber.cancel();
|
||||||
|
super.dispose();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Some colors we'll use for our example
|
||||||
static const List<MaterialColor> colors = [
|
static const List<MaterialColor> colors = [
|
||||||
Colors.red,
|
Colors.red,
|
||||||
Colors.orange,
|
Colors.orange,
|
||||||
@@ -103,7 +138,11 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
maxCrossAxisExtent: 300,
|
maxCrossAxisExtent: 300,
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
children: [
|
children: [
|
||||||
// Theme
|
// * Theme
|
||||||
|
// Arcane enables easy, dynamic theme switching. Themes can be switched
|
||||||
|
// at any time between light mode and dark mode, or set to follow the
|
||||||
|
// system theme. In addition, themes can be swapped out on-the-fly,
|
||||||
|
// enabling dynamic customizations and remote theme fetching.
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -220,7 +259,7 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Arcane.log(
|
Arcane.log(
|
||||||
"Setting ${Arcane.theme.currentThemeMode.name} theme color to ${colors[index]}",
|
"Setting ${Arcane.theme.currentThemeMode.name} theme color to ${colors[index].name}",
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -245,7 +284,12 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Authentication
|
// * Authentication
|
||||||
|
// Arcane's authentication system provides a simple, standard interface
|
||||||
|
// for common authentication tasks - including registration and account
|
||||||
|
// management, logging in and out, etc. Authentication status is reflected
|
||||||
|
// in realtime within the application as changes happen, so you can focus
|
||||||
|
// on what's most important.
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -291,7 +335,13 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Feature flags
|
// * Feature flags
|
||||||
|
// Arcane's feature flag system is extremely simple and flexible to use.
|
||||||
|
// By registering _any_ enum (or even multiple enums!), features can be
|
||||||
|
// toggled on and off at any point. The feature flag system even offers
|
||||||
|
// a notifier, so you can listen to changes as they happen. Fetch your
|
||||||
|
// remote config and use it to dynamically enable and disable features
|
||||||
|
// with ease!
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -330,7 +380,11 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Environment
|
// * Environment
|
||||||
|
// Quickly and easily toggle between a "normal" and "debug" environment
|
||||||
|
// within your application. This is particularly useful during development
|
||||||
|
// when you may want to change the behavior of the application under
|
||||||
|
// certain conditions.
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -381,7 +435,10 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Services
|
// * Services
|
||||||
|
// Arcane's services system is flexible and minimal, leaving the power
|
||||||
|
// and control in developers' hands. This system powers much of Arcane
|
||||||
|
// internally, so you know it's reliable.
|
||||||
Card(
|
Card(
|
||||||
child: Padding(
|
child: Padding(
|
||||||
padding: const EdgeInsets.all(8.0),
|
padding: const EdgeInsets.all(8.0),
|
||||||
@@ -486,7 +543,14 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
||||||
// Logging
|
// * Logging
|
||||||
|
// Arcane's logging system gives developers the power to dynamically add and
|
||||||
|
// remove logging interfaces on-the-fly: try enabling a debug logging interface
|
||||||
|
// when the app is running in debug mode, adding a third-party logging interface
|
||||||
|
// when in production, and waiting until after the user has gone through the
|
||||||
|
// login process to ask them for permission to track. Include useful metadata,
|
||||||
|
// including persistent metadata, in your log messages. All of these things, and
|
||||||
|
// more, are possible when using Arcane's logging system.
|
||||||
Padding(
|
Padding(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
@@ -527,20 +591,4 @@ class _HomeScreenState extends State<HomeScreen> {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
void initState() {
|
|
||||||
super.initState();
|
|
||||||
_subscription = Arcane.logger.logStream.listen((message) {
|
|
||||||
setState(() {
|
|
||||||
if (Feature.logging.enabled) latestLogs.insert(0, message);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
void dispose() {
|
|
||||||
_subscription.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,33 +0,0 @@
|
|||||||
import "package:arcane_framework/arcane_framework.dart";
|
|
||||||
import "package:flutter/foundation.dart";
|
|
||||||
import "package:uuid/uuid.dart";
|
|
||||||
|
|
||||||
class IdService extends ArcaneService {
|
|
||||||
static final IdService _instance = IdService._internal();
|
|
||||||
static IdService get I => _instance;
|
|
||||||
|
|
||||||
IdService._internal();
|
|
||||||
|
|
||||||
bool _initialized = false;
|
|
||||||
bool get initialized => I._initialized;
|
|
||||||
|
|
||||||
String? _sessionId;
|
|
||||||
ValueListenable<String?> get sessionId =>
|
|
||||||
ValueNotifier<String?>(I._sessionId);
|
|
||||||
|
|
||||||
String get newId => uuid.v7();
|
|
||||||
|
|
||||||
/// The `Uuid` instance used for generating unique IDs.
|
|
||||||
static const Uuid uuid = Uuid();
|
|
||||||
|
|
||||||
Future<void> init() async {
|
|
||||||
Arcane.log(
|
|
||||||
"Initializing ID Service",
|
|
||||||
level: Level.debug,
|
|
||||||
);
|
|
||||||
|
|
||||||
I._sessionId = uuid.v7();
|
|
||||||
I._initialized = true;
|
|
||||||
notifyListeners();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -58,6 +58,8 @@ abstract class Arcane {
|
|||||||
/// - [stackTrace]: Optional stack trace information.
|
/// - [stackTrace]: Optional stack trace information.
|
||||||
/// - [metadata]: Optional additional metadata in key-value pairs.
|
/// - [metadata]: Optional additional metadata in key-value pairs.
|
||||||
/// - [extra]: Optional data passed to the logger.
|
/// - [extra]: Optional data passed to the logger.
|
||||||
|
/// - [skipAutodetection]: Bypass automatically determining the module, method,
|
||||||
|
/// and file/line number of log messages.
|
||||||
static void log(
|
static void log(
|
||||||
String message, {
|
String message, {
|
||||||
String? module,
|
String? module,
|
||||||
@@ -66,6 +68,7 @@ abstract class Arcane {
|
|||||||
StackTrace? stackTrace,
|
StackTrace? stackTrace,
|
||||||
Map<String, String>? metadata,
|
Map<String, String>? metadata,
|
||||||
Object? extra,
|
Object? extra,
|
||||||
|
bool skipAutodetection = false,
|
||||||
}) {
|
}) {
|
||||||
ArcaneLogger.I.log(
|
ArcaneLogger.I.log(
|
||||||
message,
|
message,
|
||||||
@@ -75,6 +78,7 @@ abstract class Arcane {
|
|||||||
stackTrace: stackTrace,
|
stackTrace: stackTrace,
|
||||||
metadata: metadata,
|
metadata: metadata,
|
||||||
extra: extra,
|
extra: extra,
|
||||||
|
skipAutodetection: skipAutodetection,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user