Wise Ultra Update
A Flutter package for managing app update notifications with customizable UI and behavior.
Features
- ๐ Automatic Update Checking: Checks for app updates on app launch and resume
- ๐จ Customizable UI: Fully customizable update dialog with theming support
- ๐ง Flexible Configuration: Support for required and optional updates
- ๐ฑ Platform Agnostic: Works on iOS and Android
- ๐งช Well Tested: 87.4% test coverage with 106 passing tests
- ๐๏ธ Clean Architecture: Built with Riverpod for state management
Installation
Add this to your package's pubspec.yaml file:
dependencies:
wise_ultra_update: ^1.0.0
Then run:
flutter pub get
Quick Start
1. Initialize the Update Feature
First, initialize the update feature in your app's main function:
import 'package:wise_ultra_update/wise_ultra_update.dart';
void main() {
// Initialize the update feature
UpdateFeature.init(
updateLocalizations: MyUpdateLocalizations(),
updateAssets: MyUpdateAssets(),
updateNavigationManager: Provider((ref) => MyUpdateNavigationManager()),
);
runApp(MyApp());
}
2. Implement Required Interfaces
Update Localizations
class MyUpdateLocalizations implements UpdateLocalizations {
@override
String get newUpdateAvailableTitle => 'Update Available';
@override
String get newUpdateAvailableSubtitle => 'A new version of the app is available';
@override
String get installUpdate => 'Update Now';
@override
String get illDoThisLater => 'Later';
}
Update Assets
class MyUpdateAssets implements UpdateAssets {
@override
String? get avatar => 'assets/images/app_icon.png'; // Optional
}
Update Navigation Manager
class MyUpdateNavigationManager implements UpdateNavigationManager {
@override
void installUpdate() {
// Navigate to app store or trigger update process
// Example: launch app store URL
}
@override
void installLater() {
// Handle "later" action (usually just dismiss)
}
}
3. Wrap Your App with UpdateWrapper
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ProviderScope(
child: MaterialApp(
home: UpdateWrapper(
child: MyHomePage(),
),
),
);
}
}
Advanced Usage
Manual Update Check
You can manually trigger an update check:
class MyWidget extends ConsumerWidget {
@override
Widget build(BuildContext context, WidgetRef ref) {
return ElevatedButton(
onPressed: () async {
await UpdateController.showUpdateDialogIfNeeded(context, ref);
},
child: Text('Check for Updates'),
);
}
}
Custom Update Repository
You can provide your own update repository implementation:
class MyUpdateRepository implements UpdateRepository {
@override
Future<(bool, bool)> checkNeedsUpdate() async {
// Your custom update checking logic
// Returns (needsUpdate, isRequired)
return (true, false);
}
}
// Initialize with custom repository
UpdateFeature.init(
updateLocalizations: MyUpdateLocalizations(),
updateAssets: MyUpdateAssets(),
updateNavigationManager: Provider((ref) => MyUpdateNavigationManager()),
updateRepository: Provider((ref) => MyUpdateRepository()),
);
Direct Widget Usage
You can also use the update widget directly:
UpdateWidget(
isRequired: true, // or false for optional updates
)
API Reference
Core Classes
UpdateFeature
Main entry point for initializing the update feature.
static void init({
required UpdateLocalizations updateLocalizations,
required UpdateAssets updateAssets,
required Provider<UpdateNavigationManager> updateNavigationManager,
Provider<UpdateRepository>? updateRepository,
})
UpdateWrapper
Widget that automatically checks for updates and shows dialogs.
UpdateWrapper({
required Widget child,
Key? key,
})
UpdateController
Controller for manually triggering update checks.
static Future<void> showUpdateDialogIfNeeded(
BuildContext context,
WidgetRef ref,
)
Interfaces
UpdateLocalizations
Interface for providing localized strings.
abstract class UpdateLocalizations {
String get newUpdateAvailableTitle;
String get newUpdateAvailableSubtitle;
String get installUpdate;
String get illDoThisLater;
}
UpdateAssets
Interface for providing assets like icons.
abstract class UpdateAssets {
String? get avatar;
}
UpdateNavigationManager
Interface for handling navigation actions.
abstract class UpdateNavigationManager {
void installUpdate();
void installLater();
}
UpdateRepository
Interface for custom update checking logic.
abstract class UpdateRepository {
Future<(bool, bool)> checkNeedsUpdate();
}
Version Comparison
The package includes a robust version comparison function:
bool isVersionLower(String current, String latest)
This function:
- Handles semantic versioning (e.g., "1.2.3")
- Supports different version lengths
- Handles non-numeric parts gracefully
- Properly compares multi-digit version numbers
Behavior
Update Check Triggers
- App launch (when
UpdateWrapperis first built) - App resume (when app comes back from background)
Update Dialog Logic
- Required Updates: Always shown, no "Later" button
- Optional Updates: Shown once per session, includes "Later" button
- No Updates: No dialog shown
State Management
The package uses Riverpod for state management and includes:
hasShownUpdateProvider: Tracks whether an optional update dialog has been shown
Testing
The package is thoroughly tested with 87.4% coverage. Run tests with:
flutter test --coverage
Dependencies
flutter: SDKhooks_riverpod: State managementpackage_info_plus: Getting app versionwisecore: Network requestswise_theming: UI theming
Contributing
Contributions are welcome! Please read the contributing guidelines before submitting PRs.
License
This project is licensed under the MIT License - see the LICENSE file for details.