blob: 73034002b8a799098ff66c0564b185c72df2f934 [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 'package:flutter/foundation.dart';
typedef BrookCallback<T> = void Function(T event);
/// A source of events of type T.
///
/// This is a light-weight stream, hence the name of the class.
///
/// Listeners cannot be registered multiple times simultaneously.
class Brook<T> {
Brook();
final Set<BrookCallback<T>> _listeners = <BrookCallback<T>>{};
void addListener(BrookCallback<T> listener) {
assert(!_listeners.contains(listener));
_listeners.add(listener);
}
void removeListener(BrookCallback<T> listener) {
assert(_listeners.contains(listener));
_listeners.remove(listener);
}
}
/// A place to send events of type T.
///
/// Instances of this class can be given to consumers, as the type [Brook].
/// This allows consumers to register for events without being able to send
/// events.
class BrookSink<T> extends Brook<T> {
BrookSink();
void send(T event) {
final List<BrookCallback<T>> frozenListeners = _listeners.toList();
for (final BrookCallback<T> listener in frozenListeners) {
try {
if (_listeners.contains(listener)) {
listener(event);
}
} catch (exception, stack) {
FlutterError.reportError(
FlutterErrorDetails(
exception: exception,
stack: stack,
library: 'Flutter Dashboard',
context: ErrorDescription('while sending event'),
informationCollector: () sync* {
yield DiagnosticsProperty<BrookSink<T>>(
'The $runtimeType sending the event was',
this,
style: DiagnosticsTreeStyle.errorProperty,
);
yield DiagnosticsProperty<T>(
'The $T event was',
event,
style: DiagnosticsTreeStyle.errorProperty,
);
},
),
);
}
}
}
}
class ErrorSink extends BrookSink<String> {
ErrorSink();
@override
void send(String event) {
// TODO(ianh): log errors to a service as well, https://github.com/flutter/flutter/issues/52697
debugPrint(event); // to allow for copy/paste
super.send(event);
}
}