Skip to content
Merged
Show file tree
Hide file tree
Changes from 52 commits
Commits
Show all changes
58 commits
Select commit Hold shift + click to select a range
87eabf0
Made ArcaneTheme private (_ArcaneTheme)
hanskokx Apr 29, 2025
3e62ffc
Updated changelog
hanskokx Apr 29, 2025
8711eae
Fix updateShouldNotify on ArcaneServiceProvider
hanskokx Apr 29, 2025
87f86d8
Update service provider
hanskokx Apr 29, 2025
a04038a
Put service locators in an extension
hanskokx Apr 29, 2025
c3eb677
Try using a mixin instead
hanskokx Apr 29, 2025
d069eb0
Remove 'of' and 'requiredOf' locators
hanskokx Apr 29, 2025
304c6c8
Re-add service locators. They should be called as:
hanskokx Apr 29, 2025
d1daf0e
Renamed getters on ArcaneService
hanskokx Apr 29, 2025
3ef93bb
Renamed serviceInstances => registeredServices and added a removeServ…
hanskokx Apr 29, 2025
25b456a
Broke up arcane service into separate files
hanskokx Apr 29, 2025
88210ce
Added requiredServiceOfType getter on ArcaneServiceProvider
hanskokx Apr 29, 2025
2e26f90
Updated services section of the readme
hanskokx Apr 29, 2025
0caea70
Updated example to add a services example
hanskokx Apr 30, 2025
ad63b15
Removed unused variable
hanskokx Apr 30, 2025
1eab50b
Update example documentation
hanskokx Apr 30, 2025
2f18c42
Update example
hanskokx Apr 30, 2025
68ce73a
Breaking up example into smaller widgets
hanskokx Apr 30, 2025
e6646d3
Remove bloc dependency
hanskokx May 2, 2025
515c7fb
Fixes the notifier for feature flags and updates the example
hanskokx May 13, 2025
0c5568a
Fixed a bug in the example
hanskokx May 13, 2025
7bf5a6d
Update ServiceProvider to make service instances optional
hanskokx May 13, 2025
55ff65b
Remove unnecessary notifyListeners calls
hanskokx May 14, 2025
077956b
Organize theme service
hanskokx May 14, 2025
c2cfb46
Fix authentication interface and service methods for logout and login.
hanskokx May 19, 2025
93f90a3
Fix DebugAuthInterface logout method
hanskokx May 19, 2025
1e84e8f
Enhance theme management with StreamBuilder for dynamic updates
hanskokx Jul 1, 2025
f5056c3
Add configuration files and update authentication service error handling
hanskokx May 7, 2026
bcd66f8
Update dependency versions to use 'any' for arcane_helper_utils and a…
hanskokx May 7, 2026
30b5787
Remove unnecessary 'const' keyword from Result.ok calls in DebugAuthI…
hanskokx May 13, 2026
3ffaacc
Add 'const' keyword to Result.ok calls in DebugAuthInterface methods
hanskokx May 13, 2026
d3fdf7f
Enhance logging service with new lifecycle capabilities and intercept…
hanskokx May 21, 2026
d7fd642
Add stream-based updates for authentication, feature flags, logging, …
hanskokx May 21, 2026
83cd75c
Refactor ArcaneEnvironment and AuthenticationService for improved env…
hanskokx May 21, 2026
510b18a
Add application environment management and tests for authentication s…
hanskokx May 21, 2026
15f76d1
feat: Enhance service management with ArcaneApp provider composition
hanskokx May 25, 2026
5dd9c76
chore(example): Add ignore rules for example builds
hanskokx May 25, 2026
eca94fc
feat(logging): Introduce log interceptors and origin control
hanskokx May 25, 2026
3a6fd44
fix(theme): Update theme mode check to use currentModeOf method
hanskokx May 25, 2026
a91c5d7
fix(theme): Improve theme mode detection and toggling
hanskokx May 25, 2026
1dd92b6
feat(example): Improve theme and service integration demo
hanskokx May 25, 2026
c7767e5
feat(example): Add interactive persistent metadata toggle
hanskokx May 25, 2026
50c07d4
feat(theme): Add assignment-style theme setters
hanskokx May 25, 2026
bbef7be
docs(README): Add Application Environments section to features list
hanskokx May 25, 2026
101f21e
Adds `ArcaneApp.builder` to provide a provider-aware `BuildContext`
hanskokx May 25, 2026
0482918
docs(arcane_app): Clarify ArcaneApp API and provider access documenta…
hanskokx May 25, 2026
ef4c281
feat: Overhaul Arcane framework for 2.0.0 release notes
hanskokx May 25, 2026
8bd4bfe
refactor(environment): Rename environment access getter to current
hanskokx May 25, 2026
c777b14
chore: Relax result_monad dependency constraint
hanskokx May 25, 2026
0aba1f5
refactor(logging): Replace LoggingInitializationMixin with LoggingIni…
hanskokx May 25, 2026
ce15557
docs(changelog): Add migration steps for ArcaneThemeService and updat…
hanskokx May 25, 2026
49e4c4a
refactor(workflow): Simplify analyze-and-test workflow by removing un…
hanskokx May 25, 2026
1650c9e
docs(changelog): Update Arcane.log metadata type and add migration st…
hanskokx May 25, 2026
26abff3
test: Add unit tests for authentication and feature flags functionality
hanskokx May 25, 2026
b3e256e
feat(theme): track user-defined theme overrides in ArcaneThemeService
hanskokx May 25, 2026
66a95f1
refactor(service): update service access methods in ArcaneServiceProv…
hanskokx May 25, 2026
0e758c4
refactor(tests): format login and logout method signatures in MockAut…
hanskokx May 25, 2026
6c2f01d
feat(tests): add unit tests for ArcaneThemeService functionality
hanskokx May 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 1 addition & 15 deletions .github/workflows/analyze-and-unit-test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -2,34 +2,20 @@ name: Tests
on:
workflow_dispatch:
pull_request:
env:
PURO_FLUTTER_VERSION: ""
FLUTTER_VERSION: ""
jobs:
test:
name: Analyze and test
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Get Flutter version from .puro.json
id: puro_version
run: |
if [[ -f ".puro.json" ]]; then
flutter_version=$(jq -r '.env' .puro.json)
echo "PURO_FLUTTER_VERSION=$flutter_version" >> $GITHUB_ENV
else
echo "Warning: .puro.json not found, using default Flutter stable channel."
echo "PURO_FLUTTER_VERSION=stable" >> $GITHUB_ENV
fi
- name: Setup Flutter
uses: subosito/flutter-action@v2
with:
channel: "stable"
flutter-version: ${{ env.PURO_FLUTTER_VERSION == 'stable' && '' || env.FLUTTER_VERSION }}
- name: Install dependencies
run: flutter pub get
- name: Analyze
run: flutter analyze
- name: Test
run: flutter test
run: flutter test
7 changes: 4 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ migrate_working_dir/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
.vscode/

# Flutter/Dart/Pub related
# Libraries should not include pubspec.lock, per https://dart.dev/guides/libraries/private-files#pubspeclock.
Expand Down Expand Up @@ -51,5 +51,6 @@ app.*.map.json
**/android/app/profile
**/android/app/release

# Puro
!/.puro.json
# Example builds
**/example/.metadata
**/example/web/
3 changes: 0 additions & 3 deletions .puro.json

This file was deleted.

Empty file added .vscode/settings.json
Empty file.
286 changes: 236 additions & 50 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,72 +1,258 @@
## 2.0.0-dev
## Unreleased

### Arcane Framework

- [NEW] `ArcaneApp` now owns and publishes a live service registry for
provider-aware static lookups.
- [CHANGE] `Arcane.features`, `Arcane.auth`, `Arcane.theme`, and
`Arcane.environment` now prefer the live `ArcaneApp` registry instance when
available, then fall back to built-in singletons.
- [BREAKING] `Arcane` is now a static utility surface (no instantiable
singleton constructor).
- [BREAKING] Several `package:arcane_framework/src/...` import paths changed
(for example, `src/providers/...` -> `src/service/...` and
`src/services/reactive_theme/...` -> `src/services/theme/...`). Consumers
importing from `src` directly must update import paths.
- [NEW] Added optional `ArcaneApp.builder` callback (TransitionBuilder style)
for capturing provider-aware build contexts from within `ArcaneApp`.
- [DEPRECATED] `ArcaneApp.child` is now deprecated in favor of
`ArcaneApp.builder` (legacy child usage remains supported during migration).
- [DEPRECATED] `BuildContext.serviceOfType<T>()` is now deprecated in favor of
`BuildContext.service<T>()`.

### Environment Service

- [NEW] Added `ArcaneEnvironmentService` as a singleton `ArcaneService` instance.
- [CHANGE] Changed `ArcaneEnvironment` is no longer a `Cubit` and is now an
`InheritedWidget`.
- [NEW] Added `Arcane.environment` shortcut for direct environment access.
- [NEW] Added environment service to `Arcane.services` built-in list.
- [CHANGE] `ArcaneEnvironmentProvider` is now a `StatefulWidget` instead of a
`StatelessWidget` with a `BlocProvider`.
- [NEW] `ArcaneEnvironmentProvider` now provides methods for
`enableDebugMode()`, `disableDebugMode()` and `setEnvironment()`.
- [NEW] Added `environmentChanges` stream for realtime environment updates.

#### Migration Steps (ArcaneEnvironment)

1. The `state` getter has been removed from `ArcaneEnvironment`. If you previously accessed environment state via `Arcane.environment.state`, update your code to use the new API:

- **Before:**

```dart
final env = Arcane.environment.state;
```

- **After:**

```dart
final env = Arcane.environment.current;
```

2. If you were using `Cubit`-style APIs, migrate to the new `InheritedWidget`/`ValueNotifier`-based approach. See the README for updated usage examples.

### Authentication Service

- [BREAKING] `ArcaneAuthInterface.logout` now accepts optional
`onLoggedOut` callback parameters. `ArcaneAuthInterface` implementers must
update logout signature to accept optional `onLoggedOut`. See the migration
steps for further details.
- [NEW] Added `statusChanges` stream to observe `AuthenticationStatus` updates.
- [NEW] Added `signedInChanges` stream to observe sign-in state changes.
- [FIX] Added stream lifecycle cleanup in `dispose` with safe lazy recreation.

#### Migration Steps (ArcaneAuthInterface)

1. Update `ArcaneAuthInterface` implementations to accept the new optional
`onLoggedOut` callback parameter in `logout(...)`.
2. If your implementation performs cleanup side effects on logout, invoke
`onLoggedOut` when provided.
3. Run tests to confirm your authentication adapter still satisfies your
login/logout flows.

Before:

### Arcane

- [FIX] The `Arcane` class is now `abstract`

### ArcaneEnvironment

- [CHANGE] The dependency on `flutter_bloc` has been removed.
- [CHANGE] The feature has been completely rewritten as an inherited widget, rather than using a `Cubit`.
- [NEW] The `ArcaneEnvironment` widget now includes the `maybeOf(context)` and `of(context)` service locators.
- [NEW] An `ArcaneEnvironmentProvider` widget has been added. This is used by `ArcaneApp` but can also be used independently when not using the `ArcaneApp` widget.
- [NEW] The `ArcaneEnvironment`
```dart
@override
Future<Result<void, String>> logout() async {
// ...
return Result.ok(null);
}
```

### ArcaneServiceProvider
After:

- [BREAKING] `ArcaneServiceProvider.of(context)` now returns a nullable instance, rather than throwing an exception.
```dart
@override
Future<Result<void, String>> logout({
Future<void> Function()? onLoggedOut,
}) async {
// ...
if (onLoggedOut != null) await onLoggedOut();
return Result.ok(null);
}
```

### Authentication Service (ArcaneAuth)
### Feature Flag Service

- [CHANGE] Renamed service class `ArcaneFeatureFlags` to
`ArcaneFeatureFlagService`.
- [NEW] Added backward compatibility typedef:
`typedef ArcaneFeatureFlags = ArcaneFeatureFlagService`.
- [NEW] Added `enabledFeaturesChanges` stream to observe enabled feature
updates in realtime.
- [FIX] Added stream lifecycle cleanup in `dispose` with safe lazy recreation.
- [NEW] Added `ArcaneFeatureFlagProvider` (`InheritedWidget`) and
`ArcaneFeatureFlagsProvider` (`StatefulWidget`) for first-class feature-flag
integration in the widget tree.
- [DEPRECATED] `ArcaneFeatureFlagsScope` has been renamed to
`ArcaneFeatureFlagProvider`.
- [NEW] Added `BuildContext` convenience accessors for feature flags, including
`context.featureFlags`, `context.maybeFeatureFlags`,
`context.isFeatureEnabled(...)`, and `context.isFeatureDisabled(...)`.
- [NEW] `ArcaneApp` now includes `ArcaneFeatureFlagsProvider` by default,
enabling rebuilds for widgets that depend on
`ArcaneFeatureFlagProvider.of(context)`.
- [UPDATE] README now documents `ArcaneFeatureFlagProvider` and `ArcaneApp`
provider composition.

### Theme Service

- [CHANGE] Renamed `ArcaneReactiveTheme` to `ArcaneThemeService` for clearer
naming.
- [NEW] Added backward compatibility typedef:
`typedef ArcaneReactiveTheme = ArcaneThemeService`.
- [FIX] Theme initialization now respects `ThemeMode.system` and initializes
`ThemeData` using the effective brightness.
- [FIX] `ArcaneThemeSwitcher` now initializes system-follow behavior once on
first dependency resolution.
- [FIX] `ArcaneThemeSwitcher` now defaults to `followSystemTheme(context)` when
mounted under `ArcaneApp`, so system-follow is enabled by default and system
brightness changes are handled framework-side (no app-level observer needed).
- [FIX] `switchTheme()` now toggles from the effective theme when current mode
is `ThemeMode.system` (system dark -> light, system light -> dark).
- [CHANGE] `context.isDarkMode` now reflects effective app theme brightness
(`Theme.of(context).brightness`) instead of raw platform brightness.
- [FIX] `followSystemTheme()` now reads platform brightness directly to avoid
coupling system-follow behavior to app theme overrides.
- [NEW] Added assignment-style theme setters: `Arcane.theme.dark = ...` and
`Arcane.theme.light = ...` (in addition to `setDarkTheme` /
`setLightTheme`).
- [FIX] Reactive theme stream controllers now close only during service dispose,
preventing stream shutdown when a single subscriber cancels.
- [FIX] Setting a theme (e.g., dark) while in the opposite mode (e.g., light) no
longer changes the current brightness or rendered theme. Only the active
mode's theme updates the rendered appearance.
- [NEW] Added `themeModeChanges` and `themeDataChanges` streams for realtime
theme updates.

#### Migration Steps (ArcaneThemeService)

1. Replace legacy `ThemeMode` reads from `Arcane.theme.systemTheme.value` with
`Arcane.theme.currentModeOf(context)` when configuring app `themeMode`.

Before:

- [FIX] Switching between `Environment.normal` and `Environment.debug` now correctly notifies subscribers
- [BREAKING] Switching between environments now remembers the previous authentication status (e.g., switching to debug mode and then back to normal mode will now remember whether you were authenticated or unauthenticated in normal mode when you switched to debug mode.)
```dart
MaterialApp(
theme: Arcane.theme.light,
darkTheme: Arcane.theme.dark,
themeMode: Arcane.theme.systemTheme.value,
)
```

### Feature Flags Service (ArcaneFeatureFlags)
After:

- [NEW] A `reset` method has been added, which will remove all enabled features and de-initialize the service.
```dart
MaterialApp(
theme: Arcane.theme.light,
darkTheme: Arcane.theme.dark,
themeMode: Arcane.theme.currentModeOf(context),
)
```

### Logging Service (ArcaneLogger)
### Arcane Logger

- [NEW] Added `logStream` for realtime log subscriptions.
- [NEW] Added explicit `dispose` cleanup for logger stream resources.
- [BREAKING] `LoggingInterface` no longer includes built-in singleton-style
initialization state.
- [NEW] Added optional lifecycle capability via `LoggingInitializable` and
`LoggingInitialization`.
- [NEW] Added optional `feature` tag support via `@LoggingFeature(...)`
annotation.
- [CHANGE] `initializeInterfaces()` now initializes only interfaces that
implement `LoggingInitializable`; other interfaces are skipped.
- [NEW] Added a `skipAutodetection` parameter to `Arcane.log` (defaults to
`false`) that, when enabled, skips detection of the `module`, `method`, and
file/line number where logs originated from.
- [NEW] Added the `LogInterceptor` class which can (optionally) be added to
`ArcaneLogger` to pre-process log messages before they are sent to the
registered `ArcaneLoggingInterface`(s).

#### Migration Steps (LoggingInterface)

1. Remove `initialized` and `init` from interfaces that do not require startup
work.
2. If an interface requires startup/lifecycle management, add
`LoggingInitialization` (or implement `LoggingInitializable`) and move
setup logic into `init()`.
3. Update `log(...)` implementations to guard behavior with `initialized` only
for interfaces that opted into initialization.
4. Run tests to verify interface registration and logging behavior still match
expectations.

Before:

- [NEW] A `logStream` has been added. This will stream all log messages that are sent to `ArcaneLogger`. These messages are not processed by any registered `LoggingInterface`.
- [BREAKING] Invoking the `log` method no longer throws an exception if `ArcaneLogger` has not been initialized. Log messages will always be sent to the `logStream` and will only be sent to the registered `LoggingInterface`s if the `init` method has ben invoked.
- [FIX] Automatic file and line number detection has been improved, both in terms of performance and in reliability.
- [NEW] In addition to the existing `registerInterfaces` method, a new `registerInterface` method has been added.
- [NEW] The following methods have been added: `unregisterInterface`, `unregisterInterfaces`, and `unregisterAllInterfaces`.
- [NEW] Added a `reset` method that clears all registered interfaces, clears all persistent metadata, and de-initializes `ArcaneLogger`
```dart
class DebugConsole implements LoggingInterface {
@override
bool get initialized => true;

### Theme (ArcaneTheme)
@override
Future<LoggingInterface?> init() async => this;

- [NEW] Added the `ArcaneTheme` inherited widget
- [NEW] Added `themeMode` extension to `BuildContext` to get the current `ThemeMode` (e.g., light/dark)
- [BREAKING] Completely rewrote `ArcaneReactiveTheme`
- [NEW] Added the `ArcaneThemeSwitcher` widget.
@override
void log(String message, {Map<String, Object?>? metadata, Level? level}) {}
}
```

#### ArcaneReactiveTheme
After:

- [NEW] The `isFollowingSystemTheme` getter has been added.
- [NEW] The `themeModeChanges` getter will stream events when the `ThemeMode` changes (e.g., light/dark)
- [NEW] The `themeDataChanges` getter will stream events when the current `ThemeData` changes
- [NEW] The `systemThemeMode` getter will return the OS-level brightness (e.g., light/dark)
- [BREAKING] The `currentMode` getter was renamed to `currentThemeMode`
- [NEW] The `currentTheme` getter was added to retrieve the current `ThemeData`.
- [BREAKING] The `systemTheme` getter was replaced by the `systemThemeMode` getter
- [NEW] A `currentModeOf(context)` getter was added. Using this value will trigger a rebuild when the mode changes.
- [CHANGE] The `switchTheme` method now (optionally) takes in a `ThemeMode` parameter. If it is omitted, the new mode will be automatically determined.
- [FIX] The `followSystemTheme` method will now correctly trigger widget rebuilds under the correct circumstances.
- [FIX] Invoking the `setDarkTheme` and `setLightTheme` methods will trigger widget rebuilds under the correct circumstances.
```dart
class DebugConsole extends LoggingInterface {
@override
void log(String message, {Map<String, Object?>? metadata, Level? level}) {}
}
```

#### ArcaneThemeSwitcher
- For SDK-backed loggers, opt into initialization with the mixin.

- [NEW] This new widget will, when added to the widget tree, trigger rebuilds when the theme mode or theme style is updated via `ArcaneTheme`/`ArcaneReactiveTheme`.
- [NEW] This widget has been added to `ArcaneApp`.
```dart
class ExternalLogger extends LoggingInterface with LoggingInitialization {
@override
Future<void> init() async {
if (initialized) return;
// Start SDK.
await super.init();
}

### Testing
@override
void log(String message, {Map<String, Object?>? metadata, Level? level}) {
if (!initialized) return;
// Send to SDK.
}
}
```

- [NEW] Tests have been written for much of the framework.
- If desired, adopt `feature` for destination-aware filtering in interceptors.

### Example
### Dependencies

- [FIX] The example has been completely reworked. It now includes examples of all features that Arcane has to offer
- [CHANGE] Relaxed `result_monad` constraint from `^2.3.2` to `any`.
- [CHANGE] Removed direct `flutter_bloc` dependency.
- [CHANGE] Updated `collection` from `^1.18.0` to `^1.19.0`.
- [CHANGE] Relaxed `arcane_helper_utils` constraint from `^1.4.7` to `any`.

## 1.2.5

Expand Down
Loading
Loading