blob: 0bfe074667b6a6c855d1749023b9b5a4a999a809 [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:async';
import 'dart:io';
import 'package:flutter/rendering.dart';
import 'package:flutter/widgets.dart';
import 'package:path/path.dart' as path;
import 'package:path_provider/path_provider.dart';
import 'package:rfw/rfw.dart';
import 'package:wasm/wasm.dart';
const String urlPrefix = 'https://raw.githubusercontent.com/flutter/packages/main/packages/rfw/example/wasm/logic';
const String interfaceUrl = '$urlPrefix/calculator.rfw';
const String logicUrl = '$urlPrefix/calculator.wasm';
void main() {
runApp(WidgetsApp(color: const Color(0xFF000000), builder: (BuildContext context, Widget? navigator) => const 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();
late final WasmInstance _logic;
@override
void initState() {
super.initState();
RendererBinding.instance.deferFirstFrame();
_runtime.update(const LibraryName(<String>['core', 'widgets']), createCoreWidgets());
_loadLogic();
}
late final WasmFunction _dataFetcher;
Future<void> _loadLogic() async {
final DateTime expiryDate = DateTime.now().subtract(const Duration(hours: 6));
final Directory home = await getApplicationSupportDirectory();
final File interfaceFile = File(path.join(home.path, 'cache.rfw'));
if (!interfaceFile.existsSync() || interfaceFile.lastModifiedSync().isBefore(expiryDate)) {
final HttpClientResponse client = await (await HttpClient().getUrl(Uri.parse(interfaceUrl))).close();
await interfaceFile.writeAsBytes(await client.expand((List<int> chunk) => chunk).toList());
}
final File logicFile = File(path.join(home.path, 'cache.wasm'));
if (!logicFile.existsSync() || logicFile.lastModifiedSync().isBefore(expiryDate)) {
final HttpClientResponse client = await (await HttpClient().getUrl(Uri.parse(logicUrl))).close();
await logicFile.writeAsBytes(await client.expand((List<int> chunk) => chunk).toList());
}
_runtime.update(const LibraryName(<String>['main']), decodeLibraryBlob(await interfaceFile.readAsBytes()));
_logic = WasmModule(await logicFile.readAsBytes()).builder().build();
_dataFetcher = _logic.lookupFunction('value') as WasmFunction;
_updateData();
setState(() { RendererBinding.instance.allowFirstFrame(); });
}
void _updateData() {
final dynamic value = _dataFetcher.apply(const <Object?>[]);
_data.update('value', <String, Object?>{ 'numeric': value, 'string': value.toString() });
}
List<Object?> _asList(Object? value) {
if (value is List<Object?>) {
return value;
}
return const <Object?>[];
}
@override
Widget build(BuildContext context) {
if (!RendererBinding.instance.sendFramesToEngine) {
return const SizedBox.shrink();
}
return RemoteWidget(
runtime: _runtime,
data: _data,
widget: const FullyQualifiedWidgetName(LibraryName(<String>['main']), 'root'),
onEvent: (String name, DynamicMap arguments) {
final WasmFunction function = _logic.lookupFunction(name) as WasmFunction;
function.apply(_asList(arguments['arguments']));
_updateData();
},
);
}
}