blob: cf87914f1e2b333f0afa4a3533b69dcc7ff455fe [file] [log] [blame]
// Copyright 2019 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.
import 'dart:async';
import 'package:collection/collection.dart';
import 'package:flutter_web/foundation.dart';
import 'package:flutter_web/material.dart';
import '../services/build_status_service.dart';
import 'providers.dart';
class BuildStatus {
const BuildStatus(
{this.anticipatedBuildStatus,
this.failingAgents = const <String>[],
this.commitTestResults = const <CommitTestResult>[]});
final String anticipatedBuildStatus;
final List<String> failingAgents;
final List<CommitTestResult> commitTestResults;
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final BuildStatus otherStatus = other;
return otherStatus.anticipatedBuildStatus == anticipatedBuildStatus &&
const ListEquality().equals(otherStatus.failingAgents, failingAgents) &&
const DeepCollectionEquality()
.equals(otherStatus.commitTestResults, commitTestResults);
}
@override
int get hashCode => hashValues(anticipatedBuildStatus, failingAgents);
}
class CommitTestResult {
const CommitTestResult(
{this.sha,
this.authorName,
this.avatarImageURL,
this.createDateTime,
this.inProgressTestCount,
this.succeededTestCount,
this.failedFlakyTestCount,
this.failedTestCount,
this.failingTests = const <String>[]});
final String sha;
final String authorName;
final String avatarImageURL;
final DateTime createDateTime;
final int inProgressTestCount;
final int succeededTestCount;
final int failedFlakyTestCount;
final int failedTestCount;
final List<String> failingTests;
@override
bool operator ==(Object other) {
if (identical(this, other)) {
return true;
}
if (other.runtimeType != runtimeType) {
return false;
}
final CommitTestResult otherResult = other;
return (otherResult.sha == sha) &&
(otherResult.authorName == authorName) &&
(otherResult.avatarImageURL == avatarImageURL) &&
(otherResult.createDateTime == createDateTime) &&
(otherResult.inProgressTestCount == inProgressTestCount) &&
(otherResult.succeededTestCount == succeededTestCount) &&
(otherResult.failedFlakyTestCount == failedFlakyTestCount) &&
(otherResult.failedTestCount == failedTestCount) &&
const ListEquality().equals(otherResult.failingTests, failingTests);
}
@override
int get hashCode => hashValues(
sha,
authorName,
avatarImageURL,
createDateTime,
inProgressTestCount,
succeededTestCount,
failedFlakyTestCount,
failedTestCount,
failingTests);
}
class RefreshBuildStatus extends StatefulWidget {
const RefreshBuildStatus({@required this.child});
final Widget child;
@override
State<StatefulWidget> createState() {
return _RefreshRefreshBuildStatusState();
}
}
class _RefreshRefreshBuildStatusState extends State<RefreshBuildStatus>
with AutomaticKeepAliveClientMixin<RefreshBuildStatus> {
Timer _refreshTimer;
@override
void initState() {
_refreshTimer = Timer.periodic(const Duration(minutes: 5), _refresh);
super.initState();
Timer.run(() => _refresh(null));
}
@override
void dispose() {
_refreshTimer?.cancel();
super.dispose();
}
@override
bool get wantKeepAlive => true;
Future<void> _refresh(Timer timer) async {
try {
final BuildStatus status = await fetchBuildStatus();
if (status != null) {
ModelBinding.update<BuildStatus>(context, status);
}
} catch (error) {
print('Error refreshing build status $error');
}
}
@override
Widget build(BuildContext context) {
super.build(context);
return widget.child;
}
}