blob: f1d5fbeb59bbaa48ee795704fa79f306f3d4758c [file] [log] [blame]
// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// This file is hand-formatted.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:rfw/rfw.dart';
const String urlPrefix = 'https://raw.githubusercontent.com/flutter/packages/main/packages/rfw/example/remote/remote_widget_libraries';
void main() {
runApp(const MaterialApp(home: Example()));
}
class Example extends StatefulWidget {
const Example({Key? key}) : super(key: key);
@override
State<Example> createState() => _ExampleState();
}
class _ExampleState extends State<Example> {
final Runtime _runtime = Runtime();
final DynamicContent _data = DynamicContent();
bool _ready = false;
int _counter = 0;
@override
void initState() {
super.initState();
_runtime.update(const LibraryName(<String>['core', 'widgets']), createCoreWidgets());
_runtime.update(const LibraryName(<String>['core', 'material']), createMaterialWidgets());
_updateData();
_updateWidgets();
}
void _updateData() {
_data.update('counter', _counter.toString());
}
Future<void> _updateWidgets() async {
final Directory home = await getApplicationSupportDirectory();
final File settingsFile = File(path.join(home.path, 'settings.txt'));
String nextFile = 'counter_app1.rfw';
if (settingsFile.existsSync()) {
final String settings = await settingsFile.readAsString();
if (settings == nextFile) {
nextFile = 'counter_app2.rfw';
}
}
final File currentFile = File(path.join(home.path, 'current.rfw'));
if (currentFile.existsSync()) {
try {
_runtime.update(const LibraryName(<String>['main']), decodeLibraryBlob(await currentFile.readAsBytes()));
setState(() {
_ready = true;
});
} catch (e, stack) {
FlutterError.reportError(FlutterErrorDetails(exception: e, stack: stack));
}
}
print('Fetching: $urlPrefix/$nextFile');
final HttpClientResponse client = await (await HttpClient().getUrl(Uri.parse('$urlPrefix/$nextFile'))).close();
await currentFile.writeAsBytes(await client.expand((List<int> chunk) => chunk).toList());
await settingsFile.writeAsString(nextFile);
}
@override
Widget build(BuildContext context) {
final Widget result;
if (_ready) {
result = RemoteWidget(
runtime: _runtime,
data: _data,
widget: const FullyQualifiedWidgetName(LibraryName(<String>['main']), 'Counter'),
onEvent: (String name, DynamicMap arguments) {
if (name == 'increment') {
_counter += 1;
_updateData();
}
},
);
} else {
result = Material(
child: SafeArea(
child: Padding(
padding: const EdgeInsets.all(20.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: const <Widget>[
Padding(padding: EdgeInsets.only(right: 100.0), child: Text('REMOTE', textAlign: TextAlign.center, style: TextStyle(letterSpacing: 12.0))),
Expanded(child: DecoratedBox(decoration: FlutterLogoDecoration(style: FlutterLogoStyle.horizontal))),
Padding(padding: EdgeInsets.only(left: 100.0), child: Text('WIDGETS', textAlign: TextAlign.center, style: TextStyle(letterSpacing: 12.0))),
Spacer(),
Expanded(child: Text('Every time this program is run, it fetches a new remote widgets library.', textAlign: TextAlign.center)),
Expanded(child: Text('The interface that it shows is whatever library was last fetched.', textAlign: TextAlign.center)),
Expanded(child: Text('Restart this application to see the new interface!', textAlign: TextAlign.center)),
],
),
),
),
);
}
return AnimatedSwitcher(duration: const Duration(milliseconds: 1250), switchOutCurve: Curves.easeOut, switchInCurve: Curves.easeOut, child: result);
}
}