chore: bump line length to 120 (#20191)

This commit is contained in:
shenlong
2025-07-25 08:07:22 +05:30
committed by GitHub
parent 977c9b96ba
commit ad65e9011a
517 changed files with 4520 additions and 9514 deletions

View File

@@ -53,10 +53,8 @@ sealed class BaseAsset {
return const Duration();
}
bool get hasRemote =>
storage == AssetState.remote || storage == AssetState.merged;
bool get hasLocal =>
storage == AssetState.local || storage == AssetState.merged;
bool get hasRemote => storage == AssetState.remote || storage == AssetState.merged;
bool get hasLocal => storage == AssetState.local || storage == AssetState.merged;
bool get isLocalOnly => storage == AssetState.local;
bool get isRemoteOnly => storage == AssetState.remote;

View File

@@ -22,8 +22,7 @@ class LocalAsset extends BaseAsset {
});
@override
AssetState get storage =>
remoteId == null ? AssetState.local : AssetState.merged;
AssetState get storage => remoteId == null ? AssetState.local : AssetState.merged;
@override
String get heroTag => '${id}_${remoteId ?? checksum}';
@@ -54,8 +53,7 @@ class LocalAsset extends BaseAsset {
}
@override
int get hashCode =>
super.hashCode ^ id.hashCode ^ remoteId.hashCode ^ orientation.hashCode;
int get hashCode => super.hashCode ^ id.hashCode ^ remoteId.hashCode ^ orientation.hashCode;
LocalAsset copyWith({
String? id,

View File

@@ -36,8 +36,7 @@ class RemoteAsset extends BaseAsset {
});
@override
AssetState get storage =>
localId == null ? AssetState.remote : AssetState.merged;
AssetState get storage => localId == null ? AssetState.remote : AssetState.merged;
@override
String get heroTag => '${localId ?? checksum}_$id';

View File

@@ -15,9 +15,7 @@ class DeviceAsset {
bool operator ==(covariant DeviceAsset other) {
if (identical(this, other)) return true;
return other.assetId == assetId &&
other.hash == hash &&
other.modifiedTime == modifiedTime;
return other.assetId == assetId && other.hash == hash && other.modifiedTime == modifiedTime;
}
@override

View File

@@ -25,8 +25,7 @@ class ExifInfo {
final int? iso;
final double? exposureSeconds;
bool get hasCoordinates =>
latitude != null && longitude != null && latitude != 0 && longitude != 0;
bool get hasCoordinates => latitude != null && longitude != null && latitude != 0 && longitude != 0;
String get exposureTime {
if (exposureSeconds == null) {

View File

@@ -43,12 +43,7 @@ class LogMessage {
@override
int get hashCode {
return message.hashCode ^
level.hashCode ^
createdAt.hashCode ^
logger.hashCode ^
error.hashCode ^
stack.hashCode;
return message.hashCode ^ level.hashCode ^ createdAt.hashCode ^ logger.hashCode ^ error.hashCode ^ stack.hashCode;
}
@override

View File

@@ -39,8 +39,7 @@ class MemoryData {
String toJson() => json.encode(toMap());
factory MemoryData.fromJson(String source) =>
MemoryData.fromMap(json.decode(source) as Map<String, dynamic>);
factory MemoryData.fromJson(String source) => MemoryData.fromMap(json.decode(source) as Map<String, dynamic>);
@override
String toString() => 'MemoryData(year: $year)';

View File

@@ -55,22 +55,17 @@ class PersonDto {
factory PersonDto.fromMap(Map<String, dynamic> map) {
return PersonDto(
id: map['id'] as String,
birthDate: map['birthDate'] != null
? DateTime.fromMillisecondsSinceEpoch(map['birthDate'] as int)
: null,
birthDate: map['birthDate'] != null ? DateTime.fromMillisecondsSinceEpoch(map['birthDate'] as int) : null,
isHidden: map['isHidden'] as bool,
name: map['name'] as String,
thumbnailPath: map['thumbnailPath'] as String,
updatedAt: map['updatedAt'] != null
? DateTime.fromMillisecondsSinceEpoch(map['updatedAt'] as int)
: null,
updatedAt: map['updatedAt'] != null ? DateTime.fromMillisecondsSinceEpoch(map['updatedAt'] as int) : null,
);
}
String toJson() => json.encode(toMap());
factory PersonDto.fromJson(String source) =>
PersonDto.fromMap(json.decode(source) as Map<String, dynamic>);
factory PersonDto.fromJson(String source) => PersonDto.fromMap(json.decode(source) as Map<String, dynamic>);
@override
bool operator ==(covariant PersonDto other) {

View File

@@ -54,11 +54,7 @@ class Stack {
@override
int get hashCode {
return id.hashCode ^
createdAt.hashCode ^
updatedAt.hashCode ^
ownerId.hashCode ^
primaryAssetId.hashCode;
return id.hashCode ^ createdAt.hashCode ^ updatedAt.hashCode ^ ownerId.hashCode ^ primaryAssetId.hashCode;
}
}
@@ -77,9 +73,7 @@ class StackResponse {
bool operator ==(covariant StackResponse other) {
if (identical(this, other)) return true;
return other.id == id &&
other.primaryAssetId == primaryAssetId &&
other.assetIds == assetIds;
return other.id == id && other.primaryAssetId == primaryAssetId && other.assetIds == assetIds;
}
@override

View File

@@ -175,16 +175,13 @@ class PartnerUserDto {
email: map['email'] as String,
name: map['name'] as String,
inTimeline: map['inTimeline'] as bool,
profileImagePath: map['profileImagePath'] != null
? map['profileImagePath'] as String
: null,
profileImagePath: map['profileImagePath'] != null ? map['profileImagePath'] as String : null,
);
}
String toJson() => json.encode(toMap());
factory PartnerUserDto.fromJson(String source) =>
PartnerUserDto.fromMap(json.decode(source) as Map<String, dynamic>);
factory PartnerUserDto.fromJson(String source) => PartnerUserDto.fromMap(json.decode(source) as Map<String, dynamic>);
@override
String toString() {
@@ -204,10 +201,6 @@ class PartnerUserDto {
@override
int get hashCode {
return id.hashCode ^
email.hashCode ^
name.hashCode ^
inTimeline.hashCode ^
profileImagePath.hashCode;
return id.hashCode ^ email.hashCode ^ name.hashCode ^ inTimeline.hashCode ^ profileImagePath.hashCode;
}
}

View File

@@ -24,8 +24,7 @@ enum AvatarColor {
const AvatarColor(this.value);
Color toColor({bool isDarkTheme = false}) => switch (this) {
AvatarColor.primary =>
isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
AvatarColor.primary => isDarkTheme ? const Color(0xFFABCBFA) : const Color(0xFF4250AF),
AvatarColor.pink => const Color.fromARGB(255, 244, 114, 182),
AvatarColor.red => const Color.fromARGB(255, 239, 68, 68),
AvatarColor.yellow => const Color.fromARGB(255, 234, 179, 8),
@@ -241,14 +240,11 @@ licenseKey: $licenseKey,
bool operator ==(covariant License other) {
if (identical(this, other)) return true;
return activatedAt == other.activatedAt &&
activationKey == other.activationKey &&
licenseKey == other.licenseKey;
return activatedAt == other.activatedAt && activationKey == other.activationKey && licenseKey == other.licenseKey;
}
@override
int get hashCode =>
activatedAt.hashCode ^ activationKey.hashCode ^ licenseKey.hashCode;
int get hashCode => activatedAt.hashCode ^ activationKey.hashCode ^ licenseKey.hashCode;
}
// Model for a user metadata stored in the server
@@ -310,10 +306,6 @@ license: ${license ?? "<NA>"},
@override
int get hashCode {
return userId.hashCode ^
key.hashCode ^
onboarding.hashCode ^
preferences.hashCode ^
license.hashCode;
return userId.hashCode ^ key.hashCode ^ onboarding.hashCode ^ preferences.hashCode ^ license.hashCode;
}
}

View File

@@ -19,9 +19,7 @@ class AssetService {
Stream<BaseAsset?> watchAsset(BaseAsset asset) {
final id = asset is LocalAsset ? asset.id : (asset as RemoteAsset).id;
return asset is LocalAsset
? _localAssetRepository.watchAsset(id)
: _remoteAssetRepository.watchAsset(id);
return asset is LocalAsset ? _localAssetRepository.watchAsset(id) : _remoteAssetRepository.watchAsset(id);
}
Future<List<RemoteAsset>> getStack(RemoteAsset asset) async {
@@ -40,8 +38,7 @@ class AssetService {
return null;
}
final id =
asset is LocalAsset ? asset.remoteId! : (asset as RemoteAsset).id;
final id = asset is LocalAsset ? asset.remoteId! : (asset as RemoteAsset).id;
return _remoteAssetRepository.getExif(id);
}
@@ -56,8 +53,7 @@ class AssetService {
width = exif?.width ?? asset.width?.toDouble();
height = exif?.height ?? asset.height?.toDouble();
} else if (asset is LocalAsset) {
isFlipped = _platform.isAndroid &&
(asset.orientation == 90 || asset.orientation == 270);
isFlipped = _platform.isAndroid && (asset.orientation == 90 || asset.orientation == 270);
width = asset.width?.toDouble();
height = asset.height?.toDouble();
} else {
@@ -78,10 +74,7 @@ class AssetService {
}
Future<(int local, int remote)> getAssetCounts() async {
return (
await _localAssetRepository.getCount(),
await _remoteAssetRepository.getCount()
);
return (await _localAssetRepository.getCount(), await _remoteAssetRepository.getCount());
}
Future<int> getLocalHashedCount() {

View File

@@ -41,8 +41,7 @@ class HashService {
);
for (final album in localAlbums) {
final assetsToHash =
await _localAlbumRepository.getAssetsToHash(album.id);
final assetsToHash = await _localAlbumRepository.getAssetsToHash(album.id);
if (assetsToHash.isNotEmpty) {
await _hashAssets(assetsToHash);
}
@@ -88,8 +87,7 @@ class HashService {
_log.fine("Hashing ${toHash.length} files");
final hashed = <LocalAsset>[];
final hashes =
await _nativeSyncApi.hashPaths(toHash.map((e) => e.path).toList());
final hashes = await _nativeSyncApi.hashPaths(toHash.map((e) => e.path).toList());
assert(
hashes.length == toHash.length,
"Hashes length does not match toHash length: ${hashes.length} != ${toHash.length}",

View File

@@ -66,8 +66,7 @@ class LocalSyncService {
// On iOS, we need to full sync albums that are marked as cloud as the delta sync
// does not include changes for cloud albums. If ignoreIcloudAssets is enabled,
// remove the albums from the local database from the previous sync
final cloudAlbums =
deviceAlbums.where((a) => a.isCloud).toLocalAlbums();
final cloudAlbums = deviceAlbums.where((a) => a.isCloud).toLocalAlbums();
for (final album in cloudAlbums) {
final dbAlbum = dbAlbums.firstWhereOrNull((a) => a.id == album.id);
if (dbAlbum == null) {
@@ -95,8 +94,7 @@ class LocalSyncService {
final Stopwatch stopwatch = Stopwatch()..start();
final deviceAlbums = await _nativeSyncApi.getAlbums();
final dbAlbums =
await _localAlbumRepository.getAll(sortBy: {SortLocalAlbumsBy.id});
final dbAlbums = await _localAlbumRepository.getAll(sortBy: {SortLocalAlbumsBy.id});
await diffSortedLists(
dbAlbums,
@@ -120,9 +118,7 @@ class LocalSyncService {
try {
_log.fine("Adding device album ${album.name}");
final assets = album.assetCount > 0
? await _nativeSyncApi.getAssetsForAlbum(album.id)
: <PlatformAsset>[];
final assets = album.assetCount > 0 ? await _nativeSyncApi.getAssetsForAlbum(album.id) : <PlatformAsset>[];
await _localAlbumRepository.upsert(
album,
@@ -188,10 +184,8 @@ class LocalSyncService {
return false;
}
final updatedTime =
(dbAlbum.updatedAt.millisecondsSinceEpoch ~/ 1000) + 1;
final newAssetsCount =
await _nativeSyncApi.getAssetsCountSince(deviceAlbum.id, updatedTime);
final updatedTime = (dbAlbum.updatedAt.millisecondsSinceEpoch ~/ 1000) + 1;
final newAssetsCount = await _nativeSyncApi.getAssetsCountSince(deviceAlbum.id, updatedTime);
// Early return if no new assets were found
if (newAssetsCount == 0) {
@@ -230,13 +224,9 @@ class LocalSyncService {
Future<bool> fullDiff(LocalAlbum dbAlbum, LocalAlbum deviceAlbum) async {
try {
final assetsInDevice = deviceAlbum.assetCount > 0
? await _nativeSyncApi
.getAssetsForAlbum(deviceAlbum.id)
.then((a) => a.toLocalAssets())
: <LocalAsset>[];
final assetsInDb = dbAlbum.assetCount > 0
? await _localAlbumRepository.getAssets(dbAlbum.id)
? await _nativeSyncApi.getAssetsForAlbum(deviceAlbum.id).then((a) => a.toLocalAssets())
: <LocalAsset>[];
final assetsInDb = dbAlbum.assetCount > 0 ? await _localAlbumRepository.getAssets(dbAlbum.id) : <LocalAsset>[];
if (deviceAlbum.assetCount == 0) {
_log.fine(
@@ -321,9 +311,7 @@ class LocalSyncService {
}
bool _albumsEqual(LocalAlbum a, LocalAlbum b) {
return a.name == b.name &&
a.assetCount == b.assetCount &&
a.updatedAt.isAtSameMomentAs(b.updatedAt);
return a.name == b.name && a.assetCount == b.assetCount && a.updatedAt.isAtSameMomentAs(b.updatedAt);
}
}
@@ -333,9 +321,7 @@ extension on Iterable<PlatformAlbum> {
(e) => LocalAlbum(
id: e.id,
name: e.name,
updatedAt: e.updatedAt == null
? DateTime.now()
: DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
updatedAt: e.updatedAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
assetCount: e.assetCount,
),
).toList();
@@ -350,12 +336,8 @@ extension on Iterable<PlatformAsset> {
name: e.name,
checksum: null,
type: AssetType.values.elementAtOrNull(e.type) ?? AssetType.other,
createdAt: e.createdAt == null
? DateTime.now()
: DateTime.fromMillisecondsSinceEpoch(e.createdAt! * 1000),
updatedAt: e.updatedAt == null
? DateTime.now()
: DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
createdAt: e.createdAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.createdAt! * 1000),
updatedAt: e.updatedAt == null ? DateTime.now() : DateTime.fromMillisecondsSinceEpoch(e.updatedAt! * 1000),
width: e.width,
height: e.height,
durationInSeconds: e.durationInSeconds,

View File

@@ -56,8 +56,7 @@ class LogService {
}) async {
final instance = LogService._(logRepository, storeRepository, shouldBuffer);
await logRepository.truncate(limit: kLogTruncateLimit);
final level = await instance._storeRepository.tryGet(StoreKey.logLevel) ??
LogLevel.info.index;
final level = await instance._storeRepository.tryGet(StoreKey.logLevel) ?? LogLevel.info.index;
Logger.root.level = Level.LEVELS.elementAtOrNull(level) ?? Level.INFO;
return instance;
}
@@ -146,9 +145,7 @@ class LoggerUnInitializedException implements Exception {
/// Log levels according to dart logging [Level]
extension LevelDomainToInfraExtension on Level {
LogLevel toLogLevel() =>
LogLevel.values.elementAtOrNull(Level.LEVELS.indexOf(this)) ??
LogLevel.info;
LogLevel toLogLevel() => LogLevel.values.elementAtOrNull(Level.LEVELS.indexOf(this)) ?? LogLevel.info;
}
extension on LogLevel {

View File

@@ -23,10 +23,8 @@ class DriftPartnerService {
Future<List<PartnerUserDto>> getAvailablePartners(
String currentUserId,
) async {
final otherUsers =
await _driftPartnerRepository.getAvailablePartners(currentUserId);
final currentPartners =
await _driftPartnerRepository.getSharedBy(currentUserId);
final otherUsers = await _driftPartnerRepository.getAvailablePartners(currentUserId);
final currentPartners = await _driftPartnerRepository.getSharedBy(currentUserId);
final available = otherUsers.where((user) {
return !currentPartners.any((partner) => partner.id == user.id);
}).toList();

View File

@@ -44,8 +44,7 @@ class RemoteAlbumService {
filtered = filtered
.where(
(album) =>
album.name.toLowerCase().contains(lowerQuery) ||
album.description.toLowerCase().contains(lowerQuery),
album.name.toLowerCase().contains(lowerQuery) || album.description.toLowerCase().contains(lowerQuery),
)
.toList();
}
@@ -53,12 +52,10 @@ class RemoteAlbumService {
if (userId != null) {
switch (filterMode) {
case QuickFilterMode.myAlbums:
filtered =
filtered.where((album) => album.ownerId == userId).toList();
filtered = filtered.where((album) => album.ownerId == userId).toList();
break;
case QuickFilterMode.sharedWithMe:
filtered =
filtered.where((album) => album.ownerId != userId).toList();
filtered = filtered.where((album) => album.ownerId != userId).toList();
break;
case QuickFilterMode.all:
break;

View File

@@ -9,16 +9,11 @@ final AppSetting = SettingsService(storeService: StoreService.I);
class SettingsService {
final StoreService _storeService;
const SettingsService({required StoreService storeService})
: _storeService = storeService;
const SettingsService({required StoreService storeService}) : _storeService = storeService;
T get<T>(Setting<T> setting) =>
_storeService.get(setting.storeKey, setting.defaultValue);
T get<T>(Setting<T> setting) => _storeService.get(setting.storeKey, setting.defaultValue);
Future<void> set<T>(Setting<T> setting, T value) =>
_storeService.put(setting.storeKey, value);
Future<void> set<T>(Setting<T> setting, T value) => _storeService.put(setting.storeKey, value);
Stream<T> watch<T>(Setting<T> setting) => _storeService
.watch(setting.storeKey)
.map((v) => v ?? setting.defaultValue);
Stream<T> watch<T>(Setting<T> setting) => _storeService.watch(setting.storeKey).map((v) => v ?? setting.defaultValue);
}

View File

@@ -12,8 +12,7 @@ class StoreService {
final Map<int, Object?> _cache = {};
late final StreamSubscription<StoreDto> _storeUpdateSubscription;
StoreService._({required IsarStoreRepository storeRepository})
: _storeRepository = storeRepository;
StoreService._({required IsarStoreRepository storeRepository}) : _storeRepository = storeRepository;
// TODO: Temporary typedef to make minimal changes. Remove this and make the presentation layer access store through a provider
static StoreService? _instance;
@@ -48,8 +47,7 @@ class StoreService {
}
}
StreamSubscription<StoreDto> _listenForChange() =>
_storeRepository.watchAll().listen((event) {
StreamSubscription<StoreDto> _listenForChange() => _storeRepository.watchAll().listen((event) {
_cache[event.key.id] = event.value;
});

View File

@@ -34,14 +34,12 @@ class TimelineFactory {
_settingsService = settingsService;
GroupAssetsBy get groupBy {
final group =
GroupAssetsBy.values[_settingsService.get(Setting.groupAssetsBy)];
final group = GroupAssetsBy.values[_settingsService.get(Setting.groupAssetsBy)];
// We do not support auto grouping in the new timeline yet, fallback to day grouping
return group == GroupAssetsBy.auto ? GroupAssetsBy.day : group;
}
TimelineService main(List<String> timelineUsers) =>
TimelineService(_timelineRepository.main(timelineUsers, groupBy));
TimelineService main(List<String> timelineUsers) => TimelineService(_timelineRepository.main(timelineUsers, groupBy));
TimelineService localAlbum({required String albumId}) =>
TimelineService(_timelineRepository.localAlbum(albumId, groupBy));
@@ -49,29 +47,21 @@ class TimelineFactory {
TimelineService remoteAlbum({required String albumId}) =>
TimelineService(_timelineRepository.remoteAlbum(albumId, groupBy));
TimelineService remoteAssets(String userId) =>
TimelineService(_timelineRepository.remote(userId, groupBy));
TimelineService remoteAssets(String userId) => TimelineService(_timelineRepository.remote(userId, groupBy));
TimelineService favorite(String userId) =>
TimelineService(_timelineRepository.favorite(userId, groupBy));
TimelineService favorite(String userId) => TimelineService(_timelineRepository.favorite(userId, groupBy));
TimelineService trash(String userId) =>
TimelineService(_timelineRepository.trash(userId, groupBy));
TimelineService trash(String userId) => TimelineService(_timelineRepository.trash(userId, groupBy));
TimelineService archive(String userId) =>
TimelineService(_timelineRepository.archived(userId, groupBy));
TimelineService archive(String userId) => TimelineService(_timelineRepository.archived(userId, groupBy));
TimelineService lockedFolder(String userId) =>
TimelineService(_timelineRepository.locked(userId, groupBy));
TimelineService lockedFolder(String userId) => TimelineService(_timelineRepository.locked(userId, groupBy));
TimelineService video(String userId) =>
TimelineService(_timelineRepository.video(userId, groupBy));
TimelineService video(String userId) => TimelineService(_timelineRepository.video(userId, groupBy));
TimelineService place(String place) =>
TimelineService(_timelineRepository.place(place, groupBy));
TimelineService place(String place) => TimelineService(_timelineRepository.place(place, groupBy));
TimelineService fromAssets(List<BaseAsset> assets) =>
TimelineService(_timelineRepository.fromAssets(assets));
TimelineService fromAssets(List<BaseAsset> assets) => TimelineService(_timelineRepository.fromAssets(assets));
}
class TimelineService {
@@ -98,8 +88,7 @@ class TimelineService {
_bucketSource = bucketSource {
_bucketSubscription = _bucketSource().listen((buckets) {
_mutex.run(() async {
final totalAssets =
buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
final totalAssets = buckets.fold<int>(0, (acc, bucket) => acc + bucket.assetCount);
if (totalAssets == 0) {
_bufferOffset = 0;
@@ -132,8 +121,7 @@ class TimelineService {
Stream<List<Bucket>> Function() get watchBuckets => _bucketSource;
Future<List<BaseAsset>> loadAssets(int index, int count) =>
_mutex.run(() => _loadAssets(index, count));
Future<List<BaseAsset>> loadAssets(int index, int count) => _mutex.run(() => _loadAssets(index, count));
Future<List<BaseAsset>> _loadAssets(int index, int count) async {
if (hasRange(index, count)) {
@@ -182,11 +170,9 @@ class TimelineService {
}
// Pre-cache assets around the given index for asset viewer
Future<void> preCacheAssets(int index) =>
_mutex.run(() => _loadAssets(index, math.min(5, _totalAssets - index)));
Future<void> preCacheAssets(int index) => _mutex.run(() => _loadAssets(index, math.min(5, _totalAssets - index)));
BaseAsset getRandomAsset() =>
_buffer.elementAt(math.Random().nextInt(_buffer.length));
BaseAsset getRandomAsset() => _buffer.elementAt(math.Random().nextInt(_buffer.length));
BaseAsset getAsset(int index) {
if (!hasRange(index, 1)) {

View File

@@ -67,12 +67,10 @@ class BackgroundSyncManager {
// captured by the closure passed to [runInIsolateGentle].
_deviceAlbumSyncTask = full
? runInIsolateGentle(
computation: (ref) =>
ref.read(localSyncServiceProvider).sync(full: true),
computation: (ref) => ref.read(localSyncServiceProvider).sync(full: true),
)
: runInIsolateGentle(
computation: (ref) =>
ref.read(localSyncServiceProvider).sync(full: false),
computation: (ref) => ref.read(localSyncServiceProvider).sync(full: false),
);
return _deviceAlbumSyncTask!.whenComplete(() {
@@ -139,7 +137,5 @@ Cancelable<void> _handleWsAssetUploadReadyV1Batch(
List<dynamic> batchData,
) =>
runInIsolateGentle(
computation: (ref) => ref
.read(syncStreamServiceProvider)
.handleWsAssetUploadReadyV1Batch(batchData),
computation: (ref) => ref.read(syncStreamServiceProvider).handleWsAssetUploadReadyV1Batch(batchData),
);

View File

@@ -9,8 +9,7 @@ class EventStream {
static final EventStream shared = EventStream._();
final StreamController<Event> _controller =
StreamController<Event>.broadcast();
final StreamController<Event> _controller = StreamController<Event>.broadcast();
void emit(Event event) {
_controller.add(event);