Skip to content

Instantly share code, notes, and snippets.

@maheshj01
Last active March 24, 2025 23:16
Show Gist options
  • Save maheshj01/acfaeef67cec467684ef34230d9c3acc to your computer and use it in GitHub Desktop.
Save maheshj01/acfaeef67cec467684ef34230d9c3acc to your computer and use it in GitHub Desktop.
OTA update flutter Shorebird
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_riverpod/flutter_riverpod.dart';
import 'package:shorebird_code_push/shorebird_code_push.dart';
class Home extends ConsumerStatefulWidget {
const Home({super.key});
@override
ConsumerState<ConsumerStatefulWidget> createState() => _HomeState();
}
class _HomeState extends ConsumerState<Home> {
final updater = ShorebirdUpdater();
@override
void initState() {
_checkForUpdates();
super.initState();
}
Widget _downloadProgress() {
return TweenAnimationBuilder<double>(
duration: _updateDuration,
tween: Tween(begin: 0.0, end: 1.0),
onEnd: () {
if (patchFailed) {
return;
}
ScaffoldMessenger.of(context).hideCurrentSnackBar();
_showRestartSnackBar();
},
builder: (BuildContext context, double value, Widget? child) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 5),
child: Row(
children: [
CircularProgressIndicator(value: value),
SizedBox(width: 20),
Text('Downloading update...'),
],
),
);
},
);
}
final Duration _updateDuration = const Duration(seconds: 25);
Future<void> restartApp() async {
SystemChannels.platform.invokeMethod('SystemNavigator.pop');
}
Future<void> _checkForUpdates() async {
await Future.delayed(const Duration(seconds: 2));
final status = await updater.checkForUpdate();
if (status == UpdateStatus.outdated) {
_showUpdateAvailable();
} else if (status == UpdateStatus.restartRequired) {
_showRestartSnackBar();
}
}
Future<void> _showRestartSnackBar() async {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
margin: const EdgeInsets.all(10),
content: Text('An update is available! Please restart the app.'),
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 500),
action: SnackBarAction(label: 'Restart', onPressed: restartApp),
),
);
}
bool patchFailed = false;
Future<void> _showUpdateAvailable() async {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
margin: const EdgeInsets.all(10),
content: Text('An update is available!'),
behavior: SnackBarBehavior.floating,
duration: const Duration(seconds: 500),
action: SnackBarAction(
label: 'Update',
onPressed: () async {
try {
// Hide the initial snackbar
ScaffoldMessenger.of(context).hideCurrentSnackBar();
await updater.update();
// Show the downloading progress snackbar
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
margin: const EdgeInsets.all(10),
content: _downloadProgress(),
behavior: SnackBarBehavior.floating,
duration: _updateDuration,
),
);
} on UpdateException catch (error) {
patchFailed = true;
ScaffoldMessenger.of(context).hideCurrentSnackBar();
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text('${error.message}'),
duration: const Duration(seconds: 500),
behavior: SnackBarBehavior.floating,
action: SnackBarAction(
label: 'Close',
onPressed: () {
ScaffoldMessenger.of(context).hideCurrentSnackBar();
},
),
),
);
}
},
),
),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(body: Container());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment