blob: f27efd641bfbf5151168006a8ed658bdce4b68b6 [file] [log] [blame]
// Copyright 2017 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:fidl_fuchsia_modular/fidl.dart';
import 'package:flutter/material.dart';
import 'package:flutter/scheduler.dart';
import 'package:lib.app.dart/app.dart';
import 'package:lib.app.dart/logging.dart';
import 'package:lib.module_resolver.dart/intent_builder.dart';
import 'package:lib.widgets.dart/model.dart';
import 'package:lib.module.dart/module.dart';
import 'package:meta/meta.dart';
import 'build_status_model.dart';
/// Manages the framework FIDL services for this module.
class DashboardModel extends Model implements TickerProvider {
final Future<ModuleControllerClient> Function(Intent intent) launchWebview;
final DeviceMapProxy _deviceMapProxy = new DeviceMapProxy();
/// The models that get the various build statuses.
final List<List<BuildStatusModel>> buildStatusModels;
final DateTime _startTime = new DateTime.now();
DateTime _lastRefreshed;
List<String> _devices;
ModuleControllerClient _webviewModuleControllerClient;
Timer _deviceMapTimer;
/// Constructor.
DashboardModel({
@required this.launchWebview,
this.buildStatusModels,
}) : assert(launchWebview != null) {
// ignore: avoid_function_literals_in_foreach_calls
buildStatusModels.expand((List<BuildStatusModel> models) => models).forEach(
(BuildStatusModel buildStatusModel) =>
buildStatusModel.addListener(_updatePassFailTime),
);
}
void onStop() {
closeWebView();
_deviceMapProxy.ctrl.close();
_deviceMapTimer?.cancel();
_deviceMapTimer = null;
}
@override
Ticker createTicker(TickerCallback onTick) => new Ticker(onTick);
/// The time the dashboard started.
DateTime get startTime => _startTime;
/// The time the dashboard was last refreshed.
DateTime get lastRefreshed => _lastRefreshed;
/// The devices for the current user.
List<String> get devices => _devices;
/// Starts loading the device map from the environment.
void loadDeviceMap(StartupContext startupContext) {
connectToService(
startupContext.environmentServices,
_deviceMapProxy.ctrl,
);
_deviceMapTimer?.cancel();
_deviceMapTimer = new Timer.periodic(
const Duration(seconds: 30), (_) => _queryDeviceMap());
}
void _queryDeviceMap() {
_deviceMapProxy.query((List<DeviceMapEntry> devices) {
List<String> newDeviceList =
devices.map((DeviceMapEntry entry) => entry.deviceId).toList();
if (!const ListEquality<String>().equals(_devices, newDeviceList)) {
_devices = new List<String>.unmodifiable(newDeviceList);
notifyListeners();
}
});
}
/// Starts a web view module pointing to the given [buildName].
void launchWebView(String buildName) {
final String url =
'https://luci-scheduler.appspot.com/jobs/fuchsia/$buildName';
final intentBuilder = new IntentBuilder.handler(url);
_webviewModuleControllerClient?.proxy?.ctrl?.close();
launchWebview(intentBuilder.intent).then((ModuleControllerClient client) {
_webviewModuleControllerClient = client;
client.proxy.onStateChange = onStateChange;
}).catchError((err) => log.warning('Error launching webview: $err'));
}
void onStateChange(ModuleState newState) {
/// If our module was stopped by the framework, notify this.
if (newState == ModuleState.stopped) {
onStop();
}
}
/// Closes a previously launched web view.
void closeWebView() {
_webviewModuleControllerClient?.proxy?.ctrl?.close();
_webviewModuleControllerClient = null;
}
void _updatePassFailTime() {
_lastRefreshed = new DateTime.now();
notifyListeners();
}
/// Wraps [ModelFinder.of] for this [Model]. See [ModelFinder.of] for more
/// details.
static DashboardModel of(BuildContext context) =>
new ModelFinder<DashboardModel>().of(context);
}