From 4c23c5f6035389ef3d097f628de55a1e68f20bac Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 19 Jun 2026 13:24:22 +0200 Subject: [PATCH 001/106] iOS: fix bluetooth permission --- lib/utils/requirements/multi.dart | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/utils/requirements/multi.dart b/lib/utils/requirements/multi.dart index 482ac8af..c9ae0fda 100644 --- a/lib/utils/requirements/multi.dart +++ b/lib/utils/requirements/multi.dart @@ -57,7 +57,7 @@ class BluetoothTurnedOn extends PlatformRequirement { final currentState = await UniversalBle.getBluetoothAvailabilityState(); if (!kIsWeb && Platform.isIOS) { // on iOS we cannot programmatically enable Bluetooth, just open settings - await openAppSettings(); + await UniversalBle.requestPermissions(); } else if (currentState == AvailabilityState.poweredOff) { if (Platform.isMacOS) { buildToast(title: name); From 3b2f87b734eb878191b69c4c25d79ee613ca0e3e Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Sun, 21 Jun 2026 14:06:45 +0200 Subject: [PATCH 002/106] Translate 21 missing keys into de/es/fr/it/pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit These keys existed only in the en template (so non-English users saw the English fallback): the battery-saver alert (reconnect, batterySaverTitle, controllersDisconnectedInactivity), the trainer overlay settings (overlay* — 15 keys), virtualShiftingHint, and noConnection / noConnectionHint. Added to all five locales, keeping established terminology (Virtual Shifting, ERG, Trainer-App/app di allenamento/...) and the {minutes} and {trainerApp} placeholders with their @meta. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/i10n/intl_de.arb | 23 +++++++++++++++++++++++ lib/i10n/intl_es.arb | 23 +++++++++++++++++++++++ lib/i10n/intl_fr.arb | 23 +++++++++++++++++++++++ lib/i10n/intl_it.arb | 23 +++++++++++++++++++++++ lib/i10n/intl_pl.arb | 23 +++++++++++++++++++++++ 5 files changed, 115 insertions(+) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 46f18bd6..67629009 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -1,4 +1,27 @@ { + "reconnect": "Erneut verbinden", + "batterySaverTitle": "Energiesparmodus", + "controllersDisconnectedInactivity": "Controller nach {minutes} Minuten Inaktivität getrennt, um Akku zu sparen", + "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, + "overlayDisabledIos": "Das Trainer-Overlay erscheint während der Fahrt auf der Dynamic Island und dem Sperrbildschirm.", + "overlayEnabled": "Overlay während der Fahrt anzeigen", + "overlayFieldCadence": "Trittfrequenz", + "overlayFieldErgTarget": "ERG-Ziel", + "overlayFieldGearRatio": "Übersetzung", + "overlayFieldPower": "Leistung", + "overlayFieldsLabel": "Anzuzeigende Felder", + "overlayGrantAndroidPermission": "Overlay-Berechtigung erteilen", + "overlayHide": "Overlay ausblenden", + "overlayLowPowerMode": "Live Activities sind deaktiviert (Energiesparmodus oder Systemeinstellung).", + "overlayPermissionExplain": "Android benötigt die Berechtigung, das Overlay über deiner Trainer-App anzuzeigen.", + "overlaySection": "Overlay", + "overlaySectionSubtitle": "Live-Ganganzeige während der Fahrt.", + "overlaySettings": "Overlay-Einstellungen", + "overlayWindowsTip": "Führe die Trainer-App im randlosen Fenstermodus aus, damit das Overlay sichtbar bleibt.", + "virtualShiftingHint": "Fügt Virtual Shifting hinzu oder passt es an und meldet BikeControl als Trainer an.", + "noConnection": "Keine Verbindung", + "noConnectionHint": "Überlasse {trainerApp} das Virtual Shifting, falls unterstützt", + "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Hochschalten", "actionShiftDown": "Runterschalten", "actionUturn": "Wende", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 80a2d134..d1e5bcbf 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -1,4 +1,27 @@ { + "reconnect": "Reconectar", + "batterySaverTitle": "Ahorro de batería", + "controllersDisconnectedInactivity": "Mandos desconectados tras {minutes} minutos de inactividad para ahorrar batería", + "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, + "overlayDisabledIos": "El Overlay del rodillo se muestra en la Dynamic Island y en la pantalla de bloqueo durante la sesión.", + "overlayEnabled": "Mostrar el Overlay durante la sesión", + "overlayFieldCadence": "Cadencia", + "overlayFieldErgTarget": "Objetivo ERG", + "overlayFieldGearRatio": "Relación de marchas", + "overlayFieldPower": "Potencia", + "overlayFieldsLabel": "Campos a mostrar", + "overlayGrantAndroidPermission": "Conceder permiso de Overlay", + "overlayHide": "Ocultar el Overlay", + "overlayLowPowerMode": "Las Live Activities están desactivadas (Modo de bajo consumo o ajuste del sistema).", + "overlayPermissionExplain": "Android necesita permiso para dibujar el Overlay sobre tu app de entrenamiento.", + "overlaySection": "Overlay", + "overlaySectionSubtitle": "Visualización de marchas en directo mientras ruedas.", + "overlaySettings": "Ajustes del Overlay", + "overlayWindowsTip": "Ejecuta la app de entrenamiento en modo ventana sin bordes para que el Overlay siga visible.", + "virtualShiftingHint": "Añade o ajusta el Virtual Shifting y anuncia BikeControl como rodillo.", + "noConnection": "Sin conexión", + "noConnectionHint": "Deja que {trainerApp} gestione el Virtual Shifting, si es compatible", + "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Subir marcha", "actionShiftDown": "Bajar marcha", "actionUturn": "Cambio de sentido", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index b40706e6..f23608b9 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -1,4 +1,27 @@ { + "reconnect": "Reconnecter", + "batterySaverTitle": "Économiseur de batterie", + "controllersDisconnectedInactivity": "Manettes déconnectées après {minutes} minutes d'inactivité pour économiser la batterie", + "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, + "overlayDisabledIos": "L'Overlay du home-trainer s'affiche sur la Dynamic Island et l'écran verrouillé pendant la séance.", + "overlayEnabled": "Afficher l'Overlay pendant la séance", + "overlayFieldCadence": "Cadence", + "overlayFieldErgTarget": "Cible ERG", + "overlayFieldGearRatio": "Rapport de vitesses", + "overlayFieldPower": "Puissance", + "overlayFieldsLabel": "Champs à afficher", + "overlayGrantAndroidPermission": "Accorder l'autorisation d'Overlay", + "overlayHide": "Masquer l'Overlay", + "overlayLowPowerMode": "Les Live Activities sont désactivées (mode économie d'énergie ou réglage système).", + "overlayPermissionExplain": "Android a besoin d'une autorisation pour afficher l'Overlay par-dessus ton application Trainer.", + "overlaySection": "Overlay", + "overlaySectionSubtitle": "Affichage des vitesses en direct pendant que tu roules.", + "overlaySettings": "Réglages de l'Overlay", + "overlayWindowsTip": "Lance l'application Trainer en mode fenêtré sans bordure pour que l'Overlay reste visible.", + "virtualShiftingHint": "Ajoute ou ajuste le Virtual Shifting et présente BikeControl comme un home-trainer.", + "noConnection": "Aucune connexion", + "noConnectionHint": "Laisse {trainerApp} gérer le Virtual Shifting, si pris en charge", + "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Monter les vitesses", "actionShiftDown": "Descendre les vitesses", "actionUturn": "Demi-tour", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index c44a6e05..1f47ef78 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -1,4 +1,27 @@ { + "reconnect": "Riconnetti", + "batterySaverTitle": "Risparmio batteria", + "controllersDisconnectedInactivity": "Controller disconnessi dopo {minutes} minuti di inattività per risparmiare batteria", + "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, + "overlayDisabledIos": "L'Overlay del rullo viene mostrato sulla Dynamic Island e sulla schermata di blocco durante la sessione.", + "overlayEnabled": "Mostra l'Overlay durante la sessione", + "overlayFieldCadence": "Cadenza", + "overlayFieldErgTarget": "Obiettivo ERG", + "overlayFieldGearRatio": "Rapporto del cambio", + "overlayFieldPower": "Potenza", + "overlayFieldsLabel": "Campi da mostrare", + "overlayGrantAndroidPermission": "Concedi l'autorizzazione Overlay", + "overlayHide": "Nascondi l'Overlay", + "overlayLowPowerMode": "Le Live Activities sono disattivate (risparmio energetico o impostazione di sistema).", + "overlayPermissionExplain": "Android necessita dell'autorizzazione per mostrare l'Overlay sopra la tua app di allenamento.", + "overlaySection": "Overlay", + "overlaySectionSubtitle": "Visualizzazione delle marce in tempo reale mentre pedali.", + "overlaySettings": "Impostazioni Overlay", + "overlayWindowsTip": "Esegui l'app di allenamento in modalità finestra senza bordi affinché l'Overlay resti visibile.", + "virtualShiftingHint": "Aggiunge o regola il Virtual Shifting e annuncia BikeControl come rullo.", + "noConnection": "Nessuna connessione", + "noConnectionHint": "Lascia che {trainerApp} gestisca il Virtual Shifting, se supportato", + "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Cambio su", "actionShiftDown": "Cambio giù", "actionUturn": "Inversione a U", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 5652a739..7b6e13bb 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -1,4 +1,27 @@ { + "reconnect": "Połącz ponownie", + "batterySaverTitle": "Oszczędzanie baterii", + "controllersDisconnectedInactivity": "Kontrolery rozłączone po {minutes} minutach bezczynności, aby oszczędzać baterię", + "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, + "overlayDisabledIos": "Overlay trenażera jest wyświetlany na Dynamic Island i ekranie blokady podczas jazdy.", + "overlayEnabled": "Pokaż Overlay podczas jazdy", + "overlayFieldCadence": "Kadencja", + "overlayFieldErgTarget": "Cel ERG", + "overlayFieldGearRatio": "Przełożenie", + "overlayFieldPower": "Moc", + "overlayFieldsLabel": "Pola do wyświetlenia", + "overlayGrantAndroidPermission": "Przyznaj uprawnienie Overlay", + "overlayHide": "Ukryj Overlay", + "overlayLowPowerMode": "Funkcje Live Activities są wyłączone (tryb niskiego zużycia energii lub ustawienie systemu).", + "overlayPermissionExplain": "Android potrzebuje uprawnienia, aby rysować Overlay nad aplikacją treningową.", + "overlaySection": "Overlay", + "overlaySectionSubtitle": "Podgląd biegów na żywo podczas jazdy.", + "overlaySettings": "Ustawienia Overlay", + "overlayWindowsTip": "Uruchom aplikację treningową w trybie okna bez obramowania, aby Overlay pozostał widoczny.", + "virtualShiftingHint": "Dodaje lub dostosowuje Virtual Shifting i ogłasza BikeControl jako trenażer.", + "noConnection": "Brak połączenia", + "noConnectionHint": "Pozwól, aby {trainerApp} obsługiwał Virtual Shifting, jeśli jest wspierany", + "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Wyższy bieg", "actionShiftDown": "Niższy bieg", "actionUturn": "Zawracanie", From d82fcd38077c04c769a37fd80419d74e5b1903be Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:10:06 +0200 Subject: [PATCH 003/106] Bump prop submodule: add AdvertisedServiceRegistry for mDNS diagnostics --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index d167f334..b7d7cfcf 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit d167f334035c36620cc86f2b3ef2162f6dc3a16f +Subproject commit b7d7cfcff6dc640394274ee28fb2b2ec0e1ebe5f From 7123489b6cb393b6fe2aa0b5aa89c428263c3839 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:16:12 +0200 Subject: [PATCH 004/106] Bump prop submodule: expose multicast-lock status --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index b7d7cfcf..9e0058ed 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit b7d7cfcff6dc640394274ee28fb2b2ec0e1ebe5f +Subproject commit 9e0058edf749d7ef7a13f8078182904d022ba54a From 17671f30ece68be4504870d9f6c72f1a5508c496 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:20:05 +0200 Subject: [PATCH 005/106] Bump prop submodule: record advertised services; expose hostLabel + lock --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index 9e0058ed..fb905866 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 9e0058edf749d7ef7a13f8078182904d022ba54a +Subproject commit fb905866692e1322618de71c55684ef9a3eca1ed From 7fb91869c803cf6ef5c5a948a4b4544ed5170c09 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:22:26 +0200 Subject: [PATCH 006/106] Bump prop submodule: AdvertisedAddressPicker.report() --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index fb905866..a233e773 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit fb905866692e1322618de71c55684ef9a3eca1ed +Subproject commit a233e7732da7d80278414c6a104fa760bb7e6e14 From 84b9a699702fb6e1114eae1754ab613f1e5339fc Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:24:19 +0200 Subject: [PATCH 007/106] Bump prop submodule: track active ResilientTcpServers --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index a233e773..6347577a 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit a233e7732da7d80278414c6a104fa760bb7e6e14 +Subproject commit 6347577ad02d135a5e764168d5e9c07ea1e07cf8 From d8e8930425b41967646eeee295f48aa109599cab Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:27:06 +0200 Subject: [PATCH 008/106] feat: add mDNS discovery scan for diagnostics (openbikecontrol + wahoo) --- lib/services/mdns_discovery_scan.dart | 116 ++++++++++++++++++++ test/services/mdns_discovery_scan_test.dart | 34 ++++++ 2 files changed, 150 insertions(+) create mode 100644 lib/services/mdns_discovery_scan.dart create mode 100644 test/services/mdns_discovery_scan_test.dart diff --git a/lib/services/mdns_discovery_scan.dart b/lib/services/mdns_discovery_scan.dart new file mode 100644 index 00000000..ed3c06cc --- /dev/null +++ b/lib/services/mdns_discovery_scan.dart @@ -0,0 +1,116 @@ +import 'dart:async'; +import 'dart:io'; + +import 'package:bike_control/bluetooth/wifi_trainer_scanner.dart'; +import 'package:bike_control/main.dart' show recordError; +import 'package:dartx/dartx.dart'; +import 'package:flutter/foundation.dart'; +import 'package:nsd/nsd.dart' as nsd; +import 'package:prop/utils/advertised_service_registry.dart'; + +/// One mDNS service seen on the LAN during a diagnostics scan. +class DiscoveredMdnsService { + final String type; + final String name; + final String host; + final int port; + final Map txt; + + /// True when this is one of BikeControl's own advertisements echoed back. + final bool isSelf; + + const DiscoveredMdnsService({ + required this.type, + required this.name, + required this.host, + required this.port, + required this.txt, + required this.isSelf, + }); + + factory DiscoveredMdnsService.fromService( + nsd.Service service, { + required String host, + required int port, + required bool isSelf, + }) { + final txt = {}; + service.txt?.forEach((k, v) { + txt[k] = v == null ? '' : decodeMdnsTxt(v); + }); + return DiscoveredMdnsService( + type: service.type ?? '', + name: service.name ?? '', + host: host, + port: port, + txt: txt, + isSelf: isSelf, + ); + } +} + +/// Time-boxed browse of the OpenBikeControl and Wahoo DirCon service types. +/// Includes our own advertisement (flagged [DiscoveredMdnsService.isSelf]) so +/// the user can confirm the responder is reachable over the wire. +class MdnsDiscoveryScan { + static const types = ['_openbikecontrol._tcp', '_wahoo-fitness-tnp._tcp']; + + Future> run({ + Duration timeout = const Duration(seconds: 4), + }) async { + if (kIsWeb) return []; + final localAddresses = await _listLocalAddresses(); + nsd.disableServiceTypeValidation(true); + + final found = {}; + void listener(nsd.Service service, nsd.ServiceStatus status) { + if (status == nsd.ServiceStatus.lost) return; + final name = service.name; + final port = service.port; + final host = service.addresses + ?.firstOrNullWhere((a) => a.type == InternetAddressType.IPv4) + ?.address ?? + service.host; + if (name == null || port == null || host == null) return; + final isSelf = + WifiTrainerScanner.isSelfAdvertisement(service, localAddresses: localAddresses); + found['${service.type}/$name'] = DiscoveredMdnsService.fromService( + service, + host: host, + port: port, + isSelf: isSelf, + ); + } + + final discoveries = []; + try { + for (final type in types) { + final discovery = await nsd.startDiscovery(type, autoResolve: true); + discovery.addServiceListener(listener); + discoveries.add(discovery); + } + await Future.delayed(timeout); + } finally { + for (final discovery in discoveries) { + discovery.removeServiceListener(listener); + try { + await nsd.stopDiscovery(discovery); + } catch (e, s) { + recordError(e, s, context: 'MdnsDiscoveryScan.stop'); + } + } + } + return found.values.toList(); + } + + Future> _listLocalAddresses() async { + try { + final interfaces = + await NetworkInterface.list(includeLinkLocal: true, type: InternetAddressType.any); + return interfaces.expand((i) => i.addresses).map((a) => a.address).toSet(); + } catch (e, s) { + recordError(e, s, context: 'MdnsDiscoveryScan.localAddresses'); + return {}; + } + } +} diff --git a/test/services/mdns_discovery_scan_test.dart b/test/services/mdns_discovery_scan_test.dart new file mode 100644 index 00000000..10acc1e4 --- /dev/null +++ b/test/services/mdns_discovery_scan_test.dart @@ -0,0 +1,34 @@ +import 'dart:typed_data'; + +import 'package:bike_control/services/mdns_discovery_scan.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:nsd/nsd.dart' as nsd; + +void main() { + test('fromService decodes txt, carries host/port and self flag', () { + final service = nsd.Service( + name: 'KICKR ABCD', + type: '_wahoo-fitness-tnp._tcp', + port: 36866, + txt: { + 'serial-number': Uint8List.fromList('1234'.codeUnits), + 'version': Uint8List.fromList([0x01]), + }, + ); + + final d = DiscoveredMdnsService.fromService( + service, + host: '192.168.1.50', + port: 36866, + isSelf: false, + ); + + expect(d.name, 'KICKR ABCD'); + expect(d.type, '_wahoo-fitness-tnp._tcp'); + expect(d.host, '192.168.1.50'); + expect(d.port, 36866); + expect(d.isSelf, isFalse); + expect(d.txt['serial-number'], '1234'); + expect(d.txt['version'], '0x01'); + }); +} From 54e90b407a0a6ed063c172f2d345f79dcdd7e241 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:30:24 +0200 Subject: [PATCH 009/106] feat: add DebugDiagnostics aggregator and text formatter --- lib/services/debug_diagnostics.dart | 195 ++++++++++++++++++++++ test/services/debug_diagnostics_test.dart | 85 ++++++++++ 2 files changed, 280 insertions(+) create mode 100644 lib/services/debug_diagnostics.dart create mode 100644 test/services/debug_diagnostics_test.dart diff --git a/lib/services/debug_diagnostics.dart b/lib/services/debug_diagnostics.dart new file mode 100644 index 00000000..4c824538 --- /dev/null +++ b/lib/services/debug_diagnostics.dart @@ -0,0 +1,195 @@ +import 'package:bike_control/main.dart' show recordError; +import 'package:bike_control/services/mdns_discovery_scan.dart'; +import 'package:flutter/foundation.dart'; +import 'package:permission_handler/permission_handler.dart'; +import 'package:prop/mdns/service_advertiser.dart'; +import 'package:prop/utils/advertised_service_registry.dart'; +import 'package:prop/utils/network_address.dart'; +import 'package:prop/utils/resilient_tcp_server.dart'; + +/// A running TCP bridge server, for diagnostics. +class TcpServerInfo { + final String? label; + final int? port; + final bool listening; + final bool hasClient; + + const TcpServerInfo({ + required this.label, + required this.port, + required this.listening, + required this.hasClient, + }); +} + +/// Status of the permissions whose denial silently breaks WiFi/BLE bridging. +class PermissionsSnapshot { + final String bluetooth; + final String location; + + /// iOS Local Network can't be queried directly; inferred from whether a + /// discovery scan returned anything. Null when no scan ran. + final bool? localNetworkInferred; + + const PermissionsSnapshot({ + required this.bluetooth, + required this.location, + required this.localNetworkInferred, + }); + + static Future gather({bool? localNetworkInferred}) async { + Future status(Permission permission) async { + try { + return (await permission.status).name; + } catch (e, s) { + recordError(e, s, context: 'PermissionsSnapshot.${permission.toString()}'); + return 'unavailable'; + } + } + + return PermissionsSnapshot( + bluetooth: await status(Permission.bluetoothConnect), + location: await status(Permission.locationWhenInUse), + localNetworkInferred: localNetworkInferred, + ); + } +} + +/// The full diagnostics snapshot shown on the Logs page and embedded in +/// [debugText]. Build with [gather]; render with [toText]. +class DebugDiagnostics { + final List advertised; + final String backend; + final String? hostLabel; + final bool holdsMulticastLock; + final List discovered; + final bool discoveryRan; + final AddressPickReport addressReport; + final List servers; + final PermissionsSnapshot permissions; + + const DebugDiagnostics({ + required this.advertised, + required this.backend, + required this.hostLabel, + required this.holdsMulticastLock, + required this.discovered, + required this.discoveryRan, + required this.addressReport, + required this.servers, + required this.permissions, + }); + + static Future gather({ + bool includeDiscovery = true, + Duration discoveryTimeout = const Duration(seconds: 4), + }) async { + final advertiser = ServiceAdvertiser.instance; + final isResponder = advertiser is ResponderServiceAdvertiser; + + AddressPickReport addressReport; + try { + addressReport = await AdvertisedAddressPicker.report(); + } catch (e, s) { + recordError(e, s, context: 'DebugDiagnostics.address'); + addressReport = const AddressPickReport(chosen: null, candidates: []); + } + + final servers = ResilientTcpServer.activeServers + .map((s) => TcpServerInfo( + label: s.label, + port: s.isRunning ? s.boundPort : null, + listening: s.isRunning, + hasClient: s.hasClient, + )) + .toList(); + + var discovered = []; + var discoveryRan = false; + if (includeDiscovery && !kIsWeb) { + try { + discovered = await MdnsDiscoveryScan().run(timeout: discoveryTimeout); + discoveryRan = true; + } catch (e, s) { + recordError(e, s, context: 'DebugDiagnostics.discovery'); + } + } + + final permissions = await PermissionsSnapshot.gather( + localNetworkInferred: discoveryRan ? discovered.isNotEmpty : null, + ); + + return DebugDiagnostics( + advertised: AdvertisedServiceRegistry.instance.records, + backend: isResponder ? 'responder' : 'nsd', + hostLabel: isResponder ? advertiser.hostLabel : null, + holdsMulticastLock: isResponder ? advertiser.holdsMulticastLock : false, + discovered: discovered, + discoveryRan: discoveryRan, + addressReport: addressReport, + servers: servers, + permissions: permissions, + ); + } + + String _txt(Map txt) => + txt.entries.map((e) => '${e.key}=${e.value}').join(', '); + + String toText() { + final b = StringBuffer(); + b.writeln('Diagnostics:'); + + b.writeln(' Advertised by this device:'); + if (advertised.isEmpty) { + b.writeln(' (none)'); + } else { + for (final a in advertised) { + b.writeln(' ${a.type} "${a.name}" ${a.address}:${a.port}'); + if (a.txt.isNotEmpty) b.writeln(' txt: ${_txt(a.txt)}'); + } + } + b.writeln( + ' backend: $backend' + '${hostLabel != null ? ' · host: $hostLabel.local' : ''}' + '${backend == 'responder' ? ' · multicast-lock: ${holdsMulticastLock ? 'held' : 'not held'}' : ''}', + ); + + b.writeln(' Discovered on network:'); + if (!discoveryRan) { + b.writeln(' (skipped)'); + } else if (discovered.isEmpty) { + b.writeln(' (none found)'); + } else { + for (final d in discovered) { + b.writeln(' ${d.type} "${d.name}" ${d.host}:${d.port}${d.isSelf ? ' (this device)' : ''}'); + if (d.txt.isNotEmpty) b.writeln(' txt: ${_txt(d.txt)}'); + } + } + + b.writeln(' Network interfaces (advertised = ${addressReport.chosen?.address ?? 'none'}):'); + for (final c in addressReport.candidates) { + final tags = [ + if (addressReport.chosen?.address == c.address) 'advertised', + if (c.isVirtual) 'virtual', + ]; + b.writeln(' ${c.interfaceName}/${c.address} = ${c.score}${tags.isEmpty ? '' : ' (${tags.join(', ')})'}'); + } + + b.writeln(' TCP servers:'); + if (servers.isEmpty) { + b.writeln(' (none)'); + } else { + for (final s in servers) { + b.writeln(' ${s.label ?? 'tcp'} :${s.port ?? '-'} ' + '${s.listening ? 'listening' : 'down'} · ${s.hasClient ? '1 client' : 'no client'}'); + } + } + + b.writeln( + ' Permissions: bluetooth=${permissions.bluetooth} · location=${permissions.location}' + '${permissions.localNetworkInferred != null ? ' · ios-local-network=${permissions.localNetworkInferred! ? 'inferred-ok' : 'inferred-blocked'}' : ''}', + ); + + return b.toString().trimRight(); + } +} diff --git a/test/services/debug_diagnostics_test.dart b/test/services/debug_diagnostics_test.dart new file mode 100644 index 00000000..a3cf5ccd --- /dev/null +++ b/test/services/debug_diagnostics_test.dart @@ -0,0 +1,85 @@ +import 'dart:io'; + +import 'package:bike_control/services/debug_diagnostics.dart'; +import 'package:bike_control/services/mdns_discovery_scan.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:prop/utils/advertised_service_registry.dart'; +import 'package:prop/utils/network_address.dart'; + +void main() { + test('toText renders every section with the expected markers', () { + final diag = DebugDiagnostics( + advertised: const [ + AdvertisedRecord( + name: 'BikeControl', + type: '_openbikecontrol._tcp', + port: 36867, + address: '192.168.1.9', + txt: {'name': 'BikeControl'}, + ), + ], + backend: 'responder', + hostLabel: 'bikecontrol-3f2a', + holdsMulticastLock: true, + discovered: const [ + DiscoveredMdnsService( + type: '_wahoo-fitness-tnp._tcp', + name: 'BikeControl', + host: '192.168.1.9', + port: 36867, + txt: {}, + isSelf: true, + ), + ], + discoveryRan: true, + addressReport: AddressPickReport( + chosen: InternetAddress('192.168.1.9'), + candidates: const [ + AddressCandidate( + interfaceName: 'en0', address: '192.168.1.9', score: 40, isVirtual: false), + AddressCandidate( + interfaceName: 'utun0', address: '10.2.0.2', score: -60, isVirtual: true), + ], + ), + servers: const [ + TcpServerInfo(label: 'OpenBikeControl', port: 36867, listening: true, hasClient: true), + ], + permissions: const PermissionsSnapshot( + bluetooth: 'granted', + location: 'granted', + localNetworkInferred: true, + ), + ); + + final text = diag.toText(); + + expect(text, contains('Advertised by this device')); + expect(text, contains('_openbikecontrol._tcp "BikeControl" 192.168.1.9:36867')); + expect(text, contains('host: bikecontrol-3f2a.local')); + expect(text, contains('multicast-lock: held')); + expect(text, contains('(this device)')); + expect(text, contains('en0/192.168.1.9 = 40 (advertised)')); + expect(text, contains('utun0/10.2.0.2 = -60 (virtual)')); + expect(text, contains('OpenBikeControl :36867 listening · 1 client')); + expect(text, contains('bluetooth=granted')); + expect(text, contains('ios-local-network=inferred-ok')); + }); + + test('toText marks discovery as skipped when it did not run', () { + final diag = DebugDiagnostics( + advertised: const [], + backend: 'nsd', + hostLabel: null, + holdsMulticastLock: false, + discovered: const [], + discoveryRan: false, + addressReport: const AddressPickReport(chosen: null, candidates: []), + servers: const [], + permissions: const PermissionsSnapshot( + bluetooth: 'unavailable', location: 'unavailable', localNetworkInferred: null), + ); + + expect(diag.toText(), contains('Discovered on network:')); + expect(diag.toText(), contains('(skipped)')); + }); +} From 4dc226a173739bbd42ce7a87ac1b1e21df33813f Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:32:40 +0200 Subject: [PATCH 010/106] feat: embed diagnostics block in debugText; skip discovery on crash path --- lib/main.dart | 2 +- lib/widgets/menu.dart | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index 875a7d54..d43c53d7 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -204,7 +204,7 @@ Future _persistCrash({ ..writeln('Error: $error') ..writeln('Stack: ${stack ?? 'no stack'}') ..writeln('Info: ${information ?? ''}') - ..writeln(await debugText()) + ..writeln(await debugText(includeDiscovery: false)) ..writeln() ..writeln(); diff --git a/lib/widgets/menu.dart b/lib/widgets/menu.dart index e18a4326..bb8a7d01 100644 --- a/lib/widgets/menu.dart +++ b/lib/widgets/menu.dart @@ -23,6 +23,8 @@ import 'package:universal_ble/universal_ble.dart'; import '../bluetooth/devices/zwift/zwift_clickv2.dart'; import '../utils/iap/iap_manager.dart'; +import 'package:bike_control/services/debug_diagnostics.dart'; +import 'package:bike_control/main.dart' show recordError; List buildMenuButtons(BuildContext context) { final iap = IAPManager.instance; @@ -95,10 +97,18 @@ List buildMenuButtons(BuildContext context) { ]; } -Future debugText() async { +Future debugText({bool includeDiscovery = true}) async { final userId = IAPManager.instance.isUsingRevenueCat ? (await Purchases.appUserID) : null; final proxies = core.connection.proxyDevices; final proxyBlock = proxies.isEmpty ? '-' : proxies.map(_describeProxyDevice).join('\n '); + String diagnostics; + try { + final diag = await DebugDiagnostics.gather(includeDiscovery: includeDiscovery); + diagnostics = diag.toText(); + } catch (e, s) { + recordError(e, s, context: 'debugText.diagnostics'); + diagnostics = 'Diagnostics: (unavailable)'; + } return ''' --- @@ -111,6 +121,7 @@ Connected Trainers: ${core.logic.connectedTrainerConnections.map((e) => e.title) Smart Trainers: $proxyBlock Status: ${IAPManager.instance.getStatusMessage()}${userId != null ? ' (User ID: $userId)' : ''} +$diagnostics Logs: ${core.connection.lastLogEntries.reversed.joinToString(separator: '\n', transform: (e) => '${e.date.toString().split('.').first} - ${e.entry}')} '''; From 0db419118f091ae7035cc90933f4e10fcdeb2800 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:35:09 +0200 Subject: [PATCH 011/106] feat: attach full debugText (diagnostics + logs) to device feedback Drops the standalone services block (debugText already emits it per-proxy) and adds a mounted guard after the now-slower debugText await. --- lib/pages/proxy_device_details.dart | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/pages/proxy_device_details.dart b/lib/pages/proxy_device_details.dart index 3f956dd9..4bdc72ff 100644 --- a/lib/pages/proxy_device_details.dart +++ b/lib/pages/proxy_device_details.dart @@ -16,6 +16,7 @@ import 'package:bike_control/pages/proxy_device_details/virtual_shifting_pro_not import 'package:bike_control/pages/support_chat/support_chat_page.dart'; import 'package:bike_control/services/overview_screenshot.dart'; import 'package:bike_control/services/telemetry_snapshot.dart'; +import 'package:bike_control/widgets/menu.dart' show debugText; import 'package:bike_control/utils/core.dart'; import 'package:bike_control/utils/i18n_extension.dart'; import 'package:bike_control/utils/iap/iap_manager.dart'; @@ -217,11 +218,15 @@ class _ProxyDeviceDetailsPageState extends State { Future _submitFeedback(String key, String label) async { final device = widget.device; - final base = buildProxyServicesFreetext(device); - final composed = (base == null || base.isEmpty) ? key : '$key\n\n$base'; await core.settings.setFeedbackSubmitted(device.trainerKey, true); if (!mounted) return; setState(() {}); + // The full debugText already carries this trainer's services & + // characteristics (in its "Smart Trainers" block) plus the diagnostics + // and log buffer, so we attach it instead of just the services snippet. + final debug = await debugText(); + if (!mounted) return; + final composed = '$key\n$debug'; final snapshot = TelemetrySnapshot.fromDevice(device: device, freetextOverride: composed); final screenshot = await captureOverviewScreenshot(context: context); if (!mounted) return; From 0d2e8b77b03dc93e88a0e02351c16d2bbaf72f26 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:38:10 +0200 Subject: [PATCH 012/106] feat: show diagnostics block above the Logs page with refresh + share --- lib/widgets/diagnostics_section.dart | 70 ++++++++++++++++++++++ lib/widgets/logviewer.dart | 25 +++++++- test/widgets/diagnostics_section_test.dart | 42 +++++++++++++ 3 files changed, 136 insertions(+), 1 deletion(-) create mode 100644 lib/widgets/diagnostics_section.dart create mode 100644 test/widgets/diagnostics_section_test.dart diff --git a/lib/widgets/diagnostics_section.dart b/lib/widgets/diagnostics_section.dart new file mode 100644 index 00000000..e8d393c2 --- /dev/null +++ b/lib/widgets/diagnostics_section.dart @@ -0,0 +1,70 @@ +import 'package:bike_control/services/debug_diagnostics.dart'; +import 'package:flutter/material.dart' show SelectionArea; +import 'package:shadcn_flutter/shadcn_flutter.dart'; + +/// Renders a [DebugDiagnostics] snapshot (advertised + discovered mDNS, +/// interfaces, servers, permissions) above the log list. Pure: it takes the +/// snapshot and a refresh callback, so it is testable without app globals. +class DiagnosticsSection extends StatelessWidget { + final DebugDiagnostics? diagnostics; + final bool scanning; + final VoidCallback onRefresh; + + const DiagnosticsSection({ + super.key, + required this.diagnostics, + required this.scanning, + required this.onRefresh, + }); + + @override + Widget build(BuildContext context) { + final diag = diagnostics; + return Card( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + mainAxisAlignment: MainAxisAlignment.spaceBetween, + children: [ + Text('Diagnostics').bold, + Row( + children: [ + if (scanning) Text('scanning…').muted, + IconButton.ghost( + key: const ValueKey('diagnostics-refresh'), + icon: Icon(LucideIcons.refreshCw, size: 18), + onPressed: scanning ? null : onRefresh, + ), + ], + ), + ], + ), + if (diag != null) + // Bounded + scrollable: a long block must not overflow the Logs + // Column (which has an Expanded log list below it). + ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 240), + child: SingleChildScrollView( + child: SelectionArea( + child: SizedBox( + width: double.infinity, + child: Text( + diag.toText(), + style: const TextStyle( + fontFamily: 'monospace', + fontFamilyFallback: ['Courier'], + fontSize: 11, + ), + ), + ), + ), + ), + ) + else if (!scanning) + Text('No diagnostics yet').muted, + ], + ), + ); + } +} diff --git a/lib/widgets/logviewer.dart b/lib/widgets/logviewer.dart index 1d91e220..7bcaa492 100644 --- a/lib/widgets/logviewer.dart +++ b/lib/widgets/logviewer.dart @@ -1,8 +1,10 @@ import 'dart:async'; import 'dart:io'; +import 'package:bike_control/services/debug_diagnostics.dart'; import 'package:bike_control/utils/core.dart'; import 'package:bike_control/utils/i18n_extension.dart'; +import 'package:bike_control/widgets/diagnostics_section.dart'; import 'package:bike_control/widgets/ui/toast.dart'; import 'package:dartx/dartx.dart'; import 'package:flutter/foundation.dart'; @@ -22,6 +24,18 @@ class LogViewer extends StatefulWidget { class _LogviewerState extends State { late StreamSubscription _actionSubscription; final ScrollController _scrollController = ScrollController(); + DebugDiagnostics? _diagnostics; + bool _scanning = false; + + Future _loadDiagnostics() async { + setState(() => _scanning = true); + final diag = await DebugDiagnostics.gather(includeDiscovery: true); + if (!mounted) return; + setState(() { + _diagnostics = diag; + _scanning = false; + }); + } @override void initState() { @@ -40,6 +54,7 @@ class _LogviewerState extends State { } } }); + _loadDiagnostics(); } @override @@ -76,6 +91,11 @@ class _LogviewerState extends State { crossAxisAlignment: CrossAxisAlignment.start, spacing: 12, children: [ + DiagnosticsSection( + diagnostics: _diagnostics, + scanning: _scanning, + onRefresh: _loadDiagnostics, + ), Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ @@ -86,7 +106,10 @@ class _LogviewerState extends State { final logText = core.connection.lastLogEntries .map((entry) => '${entry.date.toString().split(" ").last} ${entry.entry}') .join('\n'); - Clipboard.setData(ClipboardData(text: logText)); + final diagnosticsText = _diagnostics?.toText(); + final shareText = + diagnosticsText == null ? logText : '$diagnosticsText\n\nLogs:\n$logText'; + Clipboard.setData(ClipboardData(text: shareText)); buildToast(title: context.i18n.logsHaveBeenCopiedToClipboard); }, diff --git a/test/widgets/diagnostics_section_test.dart b/test/widgets/diagnostics_section_test.dart new file mode 100644 index 00000000..952b65e3 --- /dev/null +++ b/test/widgets/diagnostics_section_test.dart @@ -0,0 +1,42 @@ +import 'package:bike_control/services/debug_diagnostics.dart'; +import 'package:bike_control/widgets/diagnostics_section.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:prop/utils/network_address.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; + +DebugDiagnostics _fixture() => const DebugDiagnostics( + advertised: [], + backend: 'nsd', + hostLabel: null, + holdsMulticastLock: false, + discovered: [], + discoveryRan: true, + addressReport: AddressPickReport(chosen: null, candidates: []), + servers: [], + permissions: PermissionsSnapshot( + bluetooth: 'granted', location: 'granted', localNetworkInferred: true), + ); + +void main() { + testWidgets('renders diagnostics text and fires refresh', (tester) async { + var refreshed = 0; + await tester.pumpWidget( + ShadcnApp( + home: Scaffold( + child: DiagnosticsSection( + diagnostics: _fixture(), + scanning: false, + onRefresh: () => refreshed++, + ), + ), + ), + ); + + expect(find.textContaining('Diagnostics:'), findsOneWidget); + expect(find.text('Diagnostics'), findsOneWidget); // header + + await tester.tap(find.byKey(const ValueKey('diagnostics-refresh'))); + await tester.pump(); + expect(refreshed, 1); + }); +} From 91ade7215a9f2ebf3509cb45b090ca042dafeb8f Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:40:29 +0200 Subject: [PATCH 013/106] Bump prop submodule: fix dircon integration test for multicast-lock getter --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index 6347577a..a566ebb2 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 6347577ad02d135a5e764168d5e9c07ea1e07cf8 +Subproject commit a566ebb21fbc6651216e9b6358fa62ba7eb2c82b From 91b362bcbd9cc2ff3effd72c2539aa893263d19f Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:46:46 +0200 Subject: [PATCH 014/106] Bump prop submodule: drop redundant import in advertised_service_registry --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index a566ebb2..209aa48e 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit a566ebb21fbc6651216e9b6358fa62ba7eb2c82b +Subproject commit 209aa48e7ad1432a3e5a51889257a55d5fe58825 From 4e035d0430a19c1f9d2a6e45269d44b08f79c735 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:53:56 +0200 Subject: [PATCH 015/106] feat: label OpenBikeControl TCP server; gate iOS local-network inference to iOS --- .../devices/openbikecontrol/obc_mdns_emulator.dart | 1 + lib/services/debug_diagnostics.dart | 8 +++++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart index bc525984..e15403a5 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart @@ -121,6 +121,7 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage Future _createTcpServer() async { final server = ResilientTcpServer( preferredPort: 36867, + label: 'OpenBikeControl', onClientConnected: (socket) { SharedLogic.keepAlive(); if (kDebugMode) { diff --git a/lib/services/debug_diagnostics.dart b/lib/services/debug_diagnostics.dart index 4c824538..d6d0a6f8 100644 --- a/lib/services/debug_diagnostics.dart +++ b/lib/services/debug_diagnostics.dart @@ -1,3 +1,5 @@ +import 'dart:io' show Platform; + import 'package:bike_control/main.dart' show recordError; import 'package:bike_control/services/mdns_discovery_scan.dart'; import 'package:flutter/foundation.dart'; @@ -116,7 +118,11 @@ class DebugDiagnostics { } final permissions = await PermissionsSnapshot.gather( - localNetworkInferred: discoveryRan ? discovered.isNotEmpty : null, + // iOS is the only platform with a (non-queryable) "Local Network" + // permission; infer it from whether discovery saw anything. Elsewhere an + // empty scan just means no peers, so leave it unset. + localNetworkInferred: + (discoveryRan && !kIsWeb && Platform.isIOS) ? discovered.isNotEmpty : null, ); return DebugDiagnostics( From 0f5ff8a60e2217f4060b422cf90cce1a9efc9036 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 10:53:57 +0200 Subject: [PATCH 016/106] Bump prop submodule: label DirCon/Click TCP servers --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index 209aa48e..61b5c934 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 209aa48e7ad1432a3e5a51889257a55d5fe58825 +Subproject commit 61b5c9342fe68a2fb688643054b61dae204cf6c3 From 8e6966b4cfe1314b0c4f0e01fa9c8977c50b8500 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 12:14:07 +0200 Subject: [PATCH 017/106] refactor: drop Bluetooth/Location from diagnostics permissions; keep iOS local-network inference --- lib/services/debug_diagnostics.dart | 45 ++++++++--------------- test/services/debug_diagnostics_test.dart | 12 ++---- 2 files changed, 18 insertions(+), 39 deletions(-) diff --git a/lib/services/debug_diagnostics.dart b/lib/services/debug_diagnostics.dart index d6d0a6f8..993a2417 100644 --- a/lib/services/debug_diagnostics.dart +++ b/lib/services/debug_diagnostics.dart @@ -3,7 +3,6 @@ import 'dart:io' show Platform; import 'package:bike_control/main.dart' show recordError; import 'package:bike_control/services/mdns_discovery_scan.dart'; import 'package:flutter/foundation.dart'; -import 'package:permission_handler/permission_handler.dart'; import 'package:prop/mdns/service_advertiser.dart'; import 'package:prop/utils/advertised_service_registry.dart'; import 'package:prop/utils/network_address.dart'; @@ -26,32 +25,16 @@ class TcpServerInfo { /// Status of the permissions whose denial silently breaks WiFi/BLE bridging. class PermissionsSnapshot { - final String bluetooth; - final String location; - /// iOS Local Network can't be queried directly; inferred from whether a /// discovery scan returned anything. Null when no scan ran. final bool? localNetworkInferred; const PermissionsSnapshot({ - required this.bluetooth, - required this.location, required this.localNetworkInferred, }); static Future gather({bool? localNetworkInferred}) async { - Future status(Permission permission) async { - try { - return (await permission.status).name; - } catch (e, s) { - recordError(e, s, context: 'PermissionsSnapshot.${permission.toString()}'); - return 'unavailable'; - } - } - return PermissionsSnapshot( - bluetooth: await status(Permission.bluetoothConnect), - location: await status(Permission.locationWhenInUse), localNetworkInferred: localNetworkInferred, ); } @@ -98,12 +81,14 @@ class DebugDiagnostics { } final servers = ResilientTcpServer.activeServers - .map((s) => TcpServerInfo( - label: s.label, - port: s.isRunning ? s.boundPort : null, - listening: s.isRunning, - hasClient: s.hasClient, - )) + .map( + (s) => TcpServerInfo( + label: s.label, + port: s.isRunning ? s.boundPort : null, + listening: s.isRunning, + hasClient: s.hasClient, + ), + ) .toList(); var discovered = []; @@ -121,8 +106,7 @@ class DebugDiagnostics { // iOS is the only platform with a (non-queryable) "Local Network" // permission; infer it from whether discovery saw anything. Elsewhere an // empty scan just means no peers, so leave it unset. - localNetworkInferred: - (discoveryRan && !kIsWeb && Platform.isIOS) ? discovered.isNotEmpty : null, + localNetworkInferred: (discoveryRan && !kIsWeb && Platform.isIOS) ? discovered.isNotEmpty : null, ); return DebugDiagnostics( @@ -138,8 +122,7 @@ class DebugDiagnostics { ); } - String _txt(Map txt) => - txt.entries.map((e) => '${e.key}=${e.value}').join(', '); + String _txt(Map txt) => txt.entries.map((e) => '${e.key}=${e.value}').join(', '); String toText() { final b = StringBuffer(); @@ -186,13 +169,15 @@ class DebugDiagnostics { b.writeln(' (none)'); } else { for (final s in servers) { - b.writeln(' ${s.label ?? 'tcp'} :${s.port ?? '-'} ' - '${s.listening ? 'listening' : 'down'} · ${s.hasClient ? '1 client' : 'no client'}'); + b.writeln( + ' ${s.label ?? 'tcp'} :${s.port ?? '-'} ' + '${s.listening ? 'listening' : 'down'} · ${s.hasClient ? '1 client' : 'no client'}', + ); } } b.writeln( - ' Permissions: bluetooth=${permissions.bluetooth} · location=${permissions.location}' + ' Permissions: ' '${permissions.localNetworkInferred != null ? ' · ios-local-network=${permissions.localNetworkInferred! ? 'inferred-ok' : 'inferred-blocked'}' : ''}', ); diff --git a/test/services/debug_diagnostics_test.dart b/test/services/debug_diagnostics_test.dart index a3cf5ccd..3f60677a 100644 --- a/test/services/debug_diagnostics_test.dart +++ b/test/services/debug_diagnostics_test.dart @@ -35,18 +35,14 @@ void main() { addressReport: AddressPickReport( chosen: InternetAddress('192.168.1.9'), candidates: const [ - AddressCandidate( - interfaceName: 'en0', address: '192.168.1.9', score: 40, isVirtual: false), - AddressCandidate( - interfaceName: 'utun0', address: '10.2.0.2', score: -60, isVirtual: true), + AddressCandidate(interfaceName: 'en0', address: '192.168.1.9', score: 40, isVirtual: false), + AddressCandidate(interfaceName: 'utun0', address: '10.2.0.2', score: -60, isVirtual: true), ], ), servers: const [ TcpServerInfo(label: 'OpenBikeControl', port: 36867, listening: true, hasClient: true), ], permissions: const PermissionsSnapshot( - bluetooth: 'granted', - location: 'granted', localNetworkInferred: true, ), ); @@ -61,7 +57,6 @@ void main() { expect(text, contains('en0/192.168.1.9 = 40 (advertised)')); expect(text, contains('utun0/10.2.0.2 = -60 (virtual)')); expect(text, contains('OpenBikeControl :36867 listening · 1 client')); - expect(text, contains('bluetooth=granted')); expect(text, contains('ios-local-network=inferred-ok')); }); @@ -75,8 +70,7 @@ void main() { discoveryRan: false, addressReport: const AddressPickReport(chosen: null, candidates: []), servers: const [], - permissions: const PermissionsSnapshot( - bluetooth: 'unavailable', location: 'unavailable', localNetworkInferred: null), + permissions: const PermissionsSnapshot(localNetworkInferred: null), ); expect(diag.toText(), contains('Discovered on network:')); From 74d78f718cb4be9302b384f6ad85936b3baeb0c9 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 12:15:06 +0200 Subject: [PATCH 018/106] fix: guard crash-logger debugText call; migrate widget test to new permissions API --- lib/main.dart | 11 ++++++++--- test/widgets/diagnostics_section_test.dart | 21 ++++++++++----------- 2 files changed, 18 insertions(+), 14 deletions(-) diff --git a/lib/main.dart b/lib/main.dart index d43c53d7..ff696e9e 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -73,8 +73,7 @@ Future main(List args) async { // doing any heavy bootstrap. multi_window_native re-runs main() with // kTrainerOverlayRoute as the first positional arg — this applies to // both macOS and Windows now that we use multi_window_native on both. - if (!kIsWeb && (Platform.isMacOS || Platform.isWindows) && - args.contains(kTrainerOverlayRoute)) { + if (!kIsWeb && (Platform.isMacOS || Platform.isWindows) && args.contains(kTrainerOverlayRoute)) { await wm.windowManager.ensureInitialized(); await wm.windowManager.waitUntilReadyToShow(); final windowId = await wm.windowManager.getId(); @@ -198,13 +197,19 @@ Future _persistCrash({ core.connection.signalNotification(LogNotification('App crashed $type: $error${stack != null ? '\n$stack' : ''}')); final timestamp = DateTime.now().toIso8601String(); + String debugTextValue; + try { + debugTextValue = await debugText(includeDiscovery: false); + } catch (e, s) { + debugTextValue = 'Exception $e'; + } final crashData = StringBuffer() ..writeln('--- $timestamp ---') ..writeln('Type: $type') ..writeln('Error: $error') ..writeln('Stack: ${stack ?? 'no stack'}') ..writeln('Info: ${information ?? ''}') - ..writeln(await debugText(includeDiscovery: false)) + ..writeln(debugTextValue) ..writeln() ..writeln(); diff --git a/test/widgets/diagnostics_section_test.dart b/test/widgets/diagnostics_section_test.dart index 952b65e3..fe1bcf11 100644 --- a/test/widgets/diagnostics_section_test.dart +++ b/test/widgets/diagnostics_section_test.dart @@ -5,17 +5,16 @@ import 'package:prop/utils/network_address.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; DebugDiagnostics _fixture() => const DebugDiagnostics( - advertised: [], - backend: 'nsd', - hostLabel: null, - holdsMulticastLock: false, - discovered: [], - discoveryRan: true, - addressReport: AddressPickReport(chosen: null, candidates: []), - servers: [], - permissions: PermissionsSnapshot( - bluetooth: 'granted', location: 'granted', localNetworkInferred: true), - ); + advertised: [], + backend: 'nsd', + hostLabel: null, + holdsMulticastLock: false, + discovered: [], + discoveryRan: true, + addressReport: AddressPickReport(chosen: null, candidates: []), + servers: [], + permissions: PermissionsSnapshot(localNetworkInferred: true), +); void main() { testWidgets('renders diagnostics text and fires refresh', (tester) async { From 16007d422f2f42962b86ac4a3c0dea70aa9670fd Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 12:27:11 +0200 Subject: [PATCH 019/106] style: tidy diagnostics Permissions line; omit when nothing to show --- lib/services/debug_diagnostics.dart | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/lib/services/debug_diagnostics.dart b/lib/services/debug_diagnostics.dart index 993a2417..4e34f1a9 100644 --- a/lib/services/debug_diagnostics.dart +++ b/lib/services/debug_diagnostics.dart @@ -176,10 +176,12 @@ class DebugDiagnostics { } } - b.writeln( - ' Permissions: ' - '${permissions.localNetworkInferred != null ? ' · ios-local-network=${permissions.localNetworkInferred! ? 'inferred-ok' : 'inferred-blocked'}' : ''}', - ); + if (permissions.localNetworkInferred != null) { + b.writeln( + ' Permissions: ios-local-network=' + '${permissions.localNetworkInferred! ? 'inferred-ok' : 'inferred-blocked'}', + ); + } return b.toString().trimRight(); } From 07ae51af59b55e34804ee6e2214789e54d73eeca Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 17:00:17 +0200 Subject: [PATCH 020/106] perf: open support chat instantly; gather diagnostics in background MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit debugText now runs a multi-second mDNS scan. Stop awaiting it before navigating — kick it off as a future, open the chat immediately, and let SupportChatPage await it lazily for the diagnostic preview and at send time. --- lib/pages/proxy_device_details.dart | 21 ++++++++++-------- lib/pages/support_chat/support_chat_page.dart | 14 +++++++++--- lib/widgets/ui/help_button.dart | 22 ++++++------------- 3 files changed, 30 insertions(+), 27 deletions(-) diff --git a/lib/pages/proxy_device_details.dart b/lib/pages/proxy_device_details.dart index 4bdc72ff..65a4352c 100644 --- a/lib/pages/proxy_device_details.dart +++ b/lib/pages/proxy_device_details.dart @@ -221,20 +221,23 @@ class _ProxyDeviceDetailsPageState extends State { await core.settings.setFeedbackSubmitted(device.trainerKey, true); if (!mounted) return; setState(() {}); - // The full debugText already carries this trainer's services & - // characteristics (in its "Smart Trainers" block) plus the diagnostics - // and log buffer, so we attach it instead of just the services snippet. - final debug = await debugText(); - if (!mounted) return; - final composed = '$key\n$debug'; - final snapshot = TelemetrySnapshot.fromDevice(device: device, freetextOverride: composed); final screenshot = await captureOverviewScreenshot(context: context); if (!mounted) return; + // Build telemetry in the background so the chat opens immediately. The full + // debugText (gathered here) already carries this trainer's services & + // characteristics, the diagnostics block and the log buffer, so we attach it + // instead of just the services snippet. The page awaits this future lazily + // for the diagnostic preview and at send time. + final snapshotFuture = () async { + final debug = await debugText(); + return TelemetrySnapshot.fromDevice(device: device, freetextOverride: '$key\n$debug'); + }(); await Navigator.of(context).push( MaterialPageRoute( builder: (_) => SupportChatPage( - telemetryBuilder: () async => snapshot, - diagnosticPreview: JsonEncoder.withIndent(' ').convert(snapshot.toJson()), + telemetryBuilder: () => snapshotFuture, + diagnosticPreviewFuture: + snapshotFuture.then((s) => JsonEncoder.withIndent(' ').convert(s.toJson())), initialText: '$label\n', initialAttachment: screenshot, ), diff --git a/lib/pages/support_chat/support_chat_page.dart b/lib/pages/support_chat/support_chat_page.dart index be5da8df..0d90baad 100644 --- a/lib/pages/support_chat/support_chat_page.dart +++ b/lib/pages/support_chat/support_chat_page.dart @@ -23,7 +23,11 @@ typedef TelemetryBuilder = Future Function(); class SupportChatPage extends StatefulWidget { final TelemetryBuilder telemetryBuilder; - final String? diagnosticPreview; + + /// Resolves to the diagnostic-payload preview shown in the composer. Awaited + /// lazily (in [initState]) so opening the chat is instant while the + /// diagnostics gather in the background. + final Future? diagnosticPreviewFuture; final String? initialText; /// Optional attachment to pre-stage in the composer on first build @@ -34,7 +38,7 @@ class SupportChatPage extends StatefulWidget { const SupportChatPage({ super.key, required this.telemetryBuilder, - this.diagnosticPreview, + this.diagnosticPreviewFuture, this.initialText, this.initialAttachment, }); @@ -57,6 +61,7 @@ class _SupportChatPageState extends State with WidgetsBindingOb IntakeAnswers? _intakeAnswers; bool _intakeSent = false; bool _editingIntake = false; + String? _diagnosticPreview; @override void initState() { @@ -73,6 +78,9 @@ class _SupportChatPageState extends State with WidgetsBindingOb _bootstrap(); } _loadIssues(); + widget.diagnosticPreviewFuture?.then((preview) { + if (mounted) setState(() => _diagnosticPreview = preview); + }); } Future _loadIssues() async { @@ -289,7 +297,7 @@ class _SupportChatPageState extends State with WidgetsBindingOb SupportComposer( sending: _sending, onSend: _send, - diagnosticPreview: widget.diagnosticPreview, + diagnosticPreview: _diagnosticPreview, initialText: widget.initialText, initialAttachment: widget.initialAttachment, ), diff --git a/lib/widgets/ui/help_button.dart b/lib/widgets/ui/help_button.dart index af9b0970..78b354c5 100644 --- a/lib/widgets/ui/help_button.dart +++ b/lib/widgets/ui/help_button.dart @@ -130,25 +130,17 @@ class _HelpButtonState extends State { : Text(context.i18n.chatWithSupport), onPressed: (c) async { final screenshot = await captureOverviewScreenshot(context: context); - final captured = await debugText(); - String? capturedFreetext = captured; + // Gather diagnostics in the background so the chat opens + // immediately; the page awaits this future lazily for the + // preview and at send time (it resolves once and is reused). + final debugFuture = debugText(); await Navigator.of(context).push( MaterialPageRoute( builder: (_) => SupportChatPage( - diagnosticPreview: captured, + diagnosticPreviewFuture: debugFuture, initialAttachment: screenshot, - telemetryBuilder: () async { - if (capturedFreetext != null) { - final snapshot = TelemetrySnapshot.general( - freetext: capturedFreetext, - ); - capturedFreetext = null; - return snapshot; - } - return TelemetrySnapshot.general( - freetext: await debugText(), - ); - }, + telemetryBuilder: () async => + TelemetrySnapshot.general(freetext: await debugFuture), ), ), ); From ccc9180c13abe3cb3440300394896a81bbbef513 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Mon, 22 Jun 2026 17:00:17 +0200 Subject: [PATCH 021/106] style: sort diagnostics TXT entries alphabetically by key --- lib/services/debug_diagnostics.dart | 5 ++++- test/services/debug_diagnostics_test.dart | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/lib/services/debug_diagnostics.dart b/lib/services/debug_diagnostics.dart index 4e34f1a9..6432c4a7 100644 --- a/lib/services/debug_diagnostics.dart +++ b/lib/services/debug_diagnostics.dart @@ -122,7 +122,10 @@ class DebugDiagnostics { ); } - String _txt(Map txt) => txt.entries.map((e) => '${e.key}=${e.value}').join(', '); + String _txt(Map txt) { + final entries = txt.entries.toList()..sort((a, b) => a.key.compareTo(b.key)); + return entries.map((e) => '${e.key}=${e.value}').join(', '); + } String toText() { final b = StringBuffer(); diff --git a/test/services/debug_diagnostics_test.dart b/test/services/debug_diagnostics_test.dart index 3f60677a..fed93e54 100644 --- a/test/services/debug_diagnostics_test.dart +++ b/test/services/debug_diagnostics_test.dart @@ -15,7 +15,7 @@ void main() { type: '_openbikecontrol._tcp', port: 36867, address: '192.168.1.9', - txt: {'name': 'BikeControl'}, + txt: {'version': '0x01', 'name': 'BikeControl', 'id': '1337'}, ), ], backend: 'responder', @@ -51,6 +51,8 @@ void main() { expect(text, contains('Advertised by this device')); expect(text, contains('_openbikecontrol._tcp "BikeControl" 192.168.1.9:36867')); + // TXT entries are rendered alphabetically by key. + expect(text, contains('txt: id=1337, name=BikeControl, version=0x01')); expect(text, contains('host: bikecontrol-3f2a.local')); expect(text, contains('multicast-lock: held')); expect(text, contains('(this device)')); From 37bc7ccd72e82b2ca43a36c81fc90f8fd4d2009e Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 12:46:53 +0200 Subject: [PATCH 022/106] fix UI issue --- lib/pages/device.dart | 42 +++++++++++++++++++++++++++++------------- 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/lib/pages/device.dart b/lib/pages/device.dart index f8efcdbb..d7d4fd1a 100644 --- a/lib/pages/device.dart +++ b/lib/pages/device.dart @@ -125,20 +125,36 @@ class _DevicePageState extends State { if (group.length == 1) _buildDeviceCard(group.single) else - IntrinsicHeight( - child: Row( - spacing: 12, - crossAxisAlignment: CrossAxisAlignment.start, - children: group - .map((device) => Expanded(child: _buildDeviceCard(device))) - .joinSeparator( - VerticalDivider( - thickness: Theme.of(context).brightness == Brightness.dark ? 1 : 0.5, - endIndent: 12, + // A full-height VerticalDivider can't be used here: it demands + // infinite height inside this scrollable Column, and wrapping in + // IntrinsicHeight doesn't help because the card's ControllerCanvas + // footer (LayoutBuilder/AspectRatio) can't answer intrinsic-height + // queries. Draw the separator as a trailing border instead — no + // intrinsics, no infinite height. + Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + for (final (i, device) in group.indexed) + Expanded( + child: Container( + decoration: i < group.length - 1 + ? BoxDecoration( + border: Border( + right: BorderSide( + color: Theme.of(context).colorScheme.border, + width: Theme.of(context).brightness == Brightness.dark ? 1 : 0.5, + ), + ), + ) + : null, + padding: EdgeInsets.only( + left: i > 0 ? 12 : 0, + right: i < group.length - 1 ? 12 : 0, ), - ) - .toList(), - ), + child: _buildDeviceCard(device), + ), + ), + ], ), if (index != deviceGroups.length - 1) ...[ Divider( From d3f72dbe75898ecad73386d38c43894cac3845c0 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 14:23:35 +0200 Subject: [PATCH 023/106] fix OpenBikeControl failed to advertise: Advertising has already started --- .../openbikecontrol/obc_ble_emulator.dart | 48 ++++++++++++++----- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart index 768708bb..dd52cdcc 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart @@ -27,6 +27,7 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { final ValueNotifier connectedApp = ValueNotifier(null); bool _isServiceAdded = false; bool _isSubscribedToEvents = false; + bool _recoveringAdvertising = false; String? _currentDeviceId; OpenBikeControlBluetoothEmulator() @@ -53,11 +54,27 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { } }); - _server.onAdvertisingStateChanged((state, error) { + _server.onAdvertisingStateChanged((state, error) async { if (kDebugMode) { print('OpenBikeControl advertising state: ${state.name}${error != null ? ' — $error' : ''}'); } if (state == PeripheralAdvertisingState.error) { + // The shared CBPeripheralManager (or a stale advertisement from a prior + // session that wasn't torn down cleanly) can already be advertising, + // making CoreBluetooth reject startAdvertising with "Advertising has + // already started." Recover by stopping and restarting our own service + // once — guarded so a persistent error can't loop. + final alreadyStarted = error?.toLowerCase().contains('already') ?? false; + if (alreadyStarted && !_recoveringAdvertising) { + _recoveringAdvertising = true; + try { + await _server.stopAdvertising(); + await _startAdvertising(); + } finally { + _recoveringAdvertising = false; + } + return; + } core.connection.signalNotification( AlertNotification( LogLevel.LOGLEVEL_WARNING, @@ -92,7 +109,11 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { return PeripheralReadRequestResult(value: Uint8List.fromList([100])); }); - Uint8List? firstAppInfoMessage; + // Some apps (e.g. TrainingPeaks on macOS) split the app-info write + // across several BLE packets. Accumulate every fragment that fails to + // parse and retry the flattened buffer until it's complete — a single + // prior-fragment buffer only ever stitches two writes together. + final firstAppInfoMessages = []; _server.setWriteHandler(OpenBikeControlConstants.APPINFO_CHARACTERISTIC_UUID, ( deviceId, characteristicId, @@ -104,11 +125,10 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { print('Write request for characteristic: $characteristicId: ${bytesToReadableHex(value)}'); } try { - // use this fallback if first message is incomplete (e.g. TrainingPeaks on macOS) AppInfo appInfo = OpenBikeProtocolParser.parseAppInfo( - Uint8List.fromList([...?firstAppInfoMessage, ...value]), + Uint8List.fromList([...firstAppInfoMessages.flatten(), ...value]), ); - firstAppInfoMessage = null; + firstAppInfoMessages.clear(); isConnected.value = true; _currentDeviceId = deviceId; connectedApp.value = appInfo; @@ -123,9 +143,7 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { core.connection.signalNotification(LogNotification('Parsed App Info: $appInfo')); } catch (e) { core.connection.signalNotification(LogNotification('Error parsing App Info ${bytesToHex(value)}: $e')); - if (firstAppInfoMessage == null) { - firstAppInfoMessage = value; - } + firstAppInfoMessages.add(value); } return PeripheralWriteRequestResult(); }); @@ -181,12 +199,18 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { } print('Starting advertising with OpenBikeControl service...'); - await _server.startAdvertising( - services: [OpenBikeControlConstants.SERVICE_UUID], - localName: 'BikeControl', - ); + // Drop any stale/foreign advertisement (e.g. left over from a previous + // session or another peripheral role) before claiming the shared manager. + // stopAdvertising is idempotent on Darwin, so this is safe when idle. + await _server.stopAdvertising(); + await _startAdvertising(); } + Future _startAdvertising() => _server.startAdvertising( + services: [OpenBikeControlConstants.SERVICE_UUID], + localName: 'BikeControl', + ); + Future stopServer() async { if (kDebugMode) { print('Stopping OpenBikeControl BLE server...'); From 14467bc7425bffe1f01cd52a7b9f333a84f40dad Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 15:37:56 +0200 Subject: [PATCH 024/106] feat: front-shift config fields on ShiftingConfig Add frontShiftEnabled, smallChainringTeeth, and largeChainringTeeth fields to ShiftingConfig with defaults (false, 34, 50) and proper serialization. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/models/shifting_config.dart | 34 ++++++++++++++++++- .../shifting_config_front_shift_test.dart | 31 +++++++++++++++++ 2 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 test/models/shifting_config_front_shift_test.dart diff --git a/lib/models/shifting_config.dart b/lib/models/shifting_config.dart index 33e4bc01..50d1c536 100644 --- a/lib/models/shifting_config.dart +++ b/lib/models/shifting_config.dart @@ -13,6 +13,10 @@ class ShiftingConfig { static const int maxGearMax = 30; static const int maxGearDefault = 24; static const int _gearRatiosMaxLength = 30; + static const int chainringTeethMin = 20; + static const int chainringTeethMax = 60; + static const int smallChainringDefault = 34; + static const int largeChainringDefault = 50; final String name; final String trainerKey; @@ -24,6 +28,9 @@ class ShiftingConfig { final bool cadenceFilterEnabled; final int maxGear; final List? gearRatios; + final bool frontShiftEnabled; + final int smallChainringTeeth; + final int largeChainringTeeth; const ShiftingConfig({ required this.name, @@ -36,6 +43,9 @@ class ShiftingConfig { this.cadenceFilterEnabled = false, this.maxGear = maxGearDefault, this.gearRatios, + this.frontShiftEnabled = false, + this.smallChainringTeeth = smallChainringDefault, + this.largeChainringTeeth = largeChainringDefault, }); factory ShiftingConfig.defaults({ @@ -83,6 +93,13 @@ class ShiftingConfig { parsedRatios.length <= _gearRatiosMaxLength) ? parsedRatios : null, + frontShiftEnabled: (json['frontShiftEnabled'] as bool?) ?? false, + smallChainringTeeth: + ((json['smallChainringTeeth'] as num?)?.toInt() ?? smallChainringDefault) + .clamp(chainringTeethMin, chainringTeethMax), + largeChainringTeeth: + ((json['largeChainringTeeth'] as num?)?.toInt() ?? largeChainringDefault) + .clamp(chainringTeethMin, chainringTeethMax), ); } @@ -97,6 +114,9 @@ class ShiftingConfig { 'cadenceFilterEnabled': cadenceFilterEnabled, 'maxGear': maxGear, if (gearRatios != null) 'gearRatios': gearRatios, + 'frontShiftEnabled': frontShiftEnabled, + 'smallChainringTeeth': smallChainringTeeth, + 'largeChainringTeeth': largeChainringTeeth, }; ShiftingConfig copyWith({ @@ -111,6 +131,9 @@ class ShiftingConfig { int? maxGear, List? gearRatios, bool clearGearRatios = false, + bool? frontShiftEnabled, + int? smallChainringTeeth, + int? largeChainringTeeth, }) { final resolvedMaxGear = maxGear ?? this.maxGear; final resolvedRatios = clearGearRatios ? null : (gearRatios ?? this.gearRatios); @@ -130,6 +153,9 @@ class ShiftingConfig { cadenceFilterEnabled: cadenceFilterEnabled ?? this.cadenceFilterEnabled, maxGear: resolvedMaxGear, gearRatios: ratiosMatchMaxGear ? resolvedRatios : null, + frontShiftEnabled: frontShiftEnabled ?? this.frontShiftEnabled, + smallChainringTeeth: smallChainringTeeth ?? this.smallChainringTeeth, + largeChainringTeeth: largeChainringTeeth ?? this.largeChainringTeeth, ); } @@ -146,7 +172,10 @@ class ShiftingConfig { gradeSmoothing == other.gradeSmoothing && cadenceFilterEnabled == other.cadenceFilterEnabled && maxGear == other.maxGear && - listEquals(gearRatios, other.gearRatios)); + listEquals(gearRatios, other.gearRatios) && + frontShiftEnabled == other.frontShiftEnabled && + smallChainringTeeth == other.smallChainringTeeth && + largeChainringTeeth == other.largeChainringTeeth); @override int get hashCode => Object.hash( @@ -160,5 +189,8 @@ class ShiftingConfig { cadenceFilterEnabled, maxGear, gearRatios == null ? null : Object.hashAll(gearRatios!), + frontShiftEnabled, + smallChainringTeeth, + largeChainringTeeth, ); } diff --git a/test/models/shifting_config_front_shift_test.dart b/test/models/shifting_config_front_shift_test.dart new file mode 100644 index 00000000..8ed863c2 --- /dev/null +++ b/test/models/shifting_config_front_shift_test.dart @@ -0,0 +1,31 @@ +import 'package:flutter_test/flutter_test.dart'; +import 'package:bike_control/models/shifting_config.dart'; + +void main() { + test('defaults: front shift off, 34/50 chainrings', () { + final c = ShiftingConfig.defaults(trainerKey: 'k'); + expect(c.frontShiftEnabled, isFalse); + expect(c.smallChainringTeeth, 34); + expect(c.largeChainringTeeth, 50); + }); + + test('round-trips through JSON', () { + final c = ShiftingConfig.defaults(trainerKey: 'k').copyWith( + frontShiftEnabled: true, + smallChainringTeeth: 36, + largeChainringTeeth: 52, + ); + final back = ShiftingConfig.fromJson(c.toJson()); + expect(back.frontShiftEnabled, isTrue); + expect(back.smallChainringTeeth, 36); + expect(back.largeChainringTeeth, 52); + expect(back, c); + }); + + test('fromJson falls back to defaults when keys absent', () { + final back = ShiftingConfig.fromJson({'trainerKey': 'k'}); + expect(back.frontShiftEnabled, isFalse); + expect(back.smallChainringTeeth, 34); + expect(back.largeChainringTeeth, 50); + }); +} From c9c74d473edf4774c3a69a631636cb0e03495a39 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 15:42:27 +0200 Subject: [PATCH 025/106] feat: add frontShift in-game action + l10n Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/i10n/intl_de.arb | 1 + lib/i10n/intl_en.arb | 1 + lib/i10n/intl_es.arb | 1 + lib/i10n/intl_fr.arb | 1 + lib/i10n/intl_it.arb | 1 + lib/i10n/intl_pl.arb | 1 + lib/utils/keymap/buttons.dart | 3 +++ 7 files changed, 9 insertions(+) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 67629009..122705b8 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -24,6 +24,7 @@ "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Hochschalten", "actionShiftDown": "Runterschalten", + "actionFrontShift": "Kettenblatt wechseln", "actionUturn": "Wende", "actionTuck": "Aero-Position", "actionSteerLeft": "Nach links lenken", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index e7c872f8..2d0b1453 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -1,6 +1,7 @@ { "actionShiftUp": "Shift Up", "actionShiftDown": "Shift Down", + "actionFrontShift": "Front Shift (Chainring)", "actionUturn": "U-Turn", "actionTuck": "Tuck", "actionSteerLeft": "Steer Left", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index d1e5bcbf..d74f4c37 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -24,6 +24,7 @@ "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Subir marcha", "actionShiftDown": "Bajar marcha", + "actionFrontShift": "Cambio de plato", "actionUturn": "Cambio de sentido", "actionTuck": "Posición aerodinámica", "actionSteerLeft": "Girar a la izquierda", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index f23608b9..28adf20b 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -24,6 +24,7 @@ "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Monter les vitesses", "actionShiftDown": "Descendre les vitesses", + "actionFrontShift": "Changement de plateau", "actionUturn": "Demi-tour", "actionTuck": "Position aéro", "actionSteerLeft": "Tourner à gauche", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 1f47ef78..a83d637b 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -24,6 +24,7 @@ "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Cambio su", "actionShiftDown": "Cambio giù", + "actionFrontShift": "Cambio corona", "actionUturn": "Inversione a U", "actionTuck": "Posizione aero", "actionSteerLeft": "Sterza a sinistra", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 7b6e13bb..1f2334a5 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -24,6 +24,7 @@ "@noConnectionHint": {"placeholders": {"trainerApp": {"type": "String"}}}, "actionShiftUp": "Wyższy bieg", "actionShiftDown": "Niższy bieg", + "actionFrontShift": "Zmiana tarczy", "actionUturn": "Zawracanie", "actionTuck": "Pozycja aero", "actionSteerLeft": "Skręć w lewo", diff --git a/lib/utils/keymap/buttons.dart b/lib/utils/keymap/buttons.dart index 2fd5cb7c..cd9bf6ce 100644 --- a/lib/utils/keymap/buttons.dart +++ b/lib/utils/keymap/buttons.dart @@ -69,6 +69,7 @@ enum InGameAction { trainerIntensityUp('Trainer: Intensity Up', icon: LucideIcons.trendingUp, isOutsideTrainerApp: true), trainerIntensityDown('Trainer: Intensity Down', icon: LucideIcons.trendingDown, isOutsideTrainerApp: true), workoutPauseResume('Workout: Pause/Resume', icon: LucideIcons.pause, isOutsideTrainerApp: true), + frontShift('Front Shift (Chainring)', icon: LucideIcons.arrowLeftRight, isOutsideTrainerApp: true), // Wahoo ELEMNT — D-Fly channel buttons emitted via the Di2Definition. dFlyChannel1('D-Fly Channel 1', icon: LucideIcons.circleDot), @@ -142,6 +143,7 @@ enum InGameAction { InGameAction.trainerIntensityUp => l.actionTrainerIntensityUp, InGameAction.trainerIntensityDown => l.actionTrainerIntensityDown, InGameAction.workoutPauseResume => l.actionWorkoutPauseResume, + InGameAction.frontShift => l.actionFrontShift, InGameAction.dFlyChannel1 => l.actionDFlyChannel1, InGameAction.dFlyChannel2 => l.actionDFlyChannel2, InGameAction.dFlyChannel3 => l.actionDFlyChannel3, @@ -160,6 +162,7 @@ const trainerActions = [ InGameAction.trainerIntensityUp, InGameAction.trainerIntensityDown, InGameAction.workoutPauseResume, + InGameAction.frontShift, ]; const trainerOnlyActions = [ From b990a6c7d97ecc1919d9f99bbb8860d85452bfdc Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 15:46:25 +0200 Subject: [PATCH 026/106] feat: seed chainring config into FitnessBikeDefinition Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/proxy/proxy_device.dart | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/bluetooth/devices/proxy/proxy_device.dart b/lib/bluetooth/devices/proxy/proxy_device.dart index 8d2c9db2..df998473 100644 --- a/lib/bluetooth/devices/proxy/proxy_device.dart +++ b/lib/bluetooth/devices/proxy/proxy_device.dart @@ -317,6 +317,8 @@ class ProxyDevice extends BluetoothDevice { def.setGradeSmoothingEnabled(cfg.gradeSmoothing); def.setCadenceFilterEnabled(cfg.cadenceFilterEnabled); def.setVirtualShiftingMode(cfg.mode); + def.setChainringTeeth(cfg.smallChainringTeeth, cfg.largeChainringTeeth); + def.setFrontShiftEnabled(cfg.frontShiftEnabled); if (cfg.gearRatios != null) { def.setGearRatios(cfg.gearRatios!); } From 935c074430fcec20f792b63f66c4f1f982263a83 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 15:52:00 +0200 Subject: [PATCH 027/106] feat: route frontShift to FitnessBikeDefinition (direct path) Add frontShift case to handleTrainerAction: ERG mode returns Ignored, disabled returns Ignored, sim mode toggles front ring and returns Success with large/small ring message. Add 3 ARB keys (6 locales) and 4 TDD tests in the consolidated test file. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/proxy/proxy_device.dart | 14 +++++ lib/i10n/intl_de.arb | 3 + lib/i10n/intl_en.arb | 3 + lib/i10n/intl_es.arb | 3 + lib/i10n/intl_fr.arb | 3 + lib/i10n/intl_it.arb | 3 + lib/i10n/intl_pl.arb | 3 + ...ndle_trainer_action_consolidated_test.dart | 58 +++++++++++++++++++ 8 files changed, 90 insertions(+) diff --git a/lib/bluetooth/devices/proxy/proxy_device.dart b/lib/bluetooth/devices/proxy/proxy_device.dart index df998473..de660991 100644 --- a/lib/bluetooth/devices/proxy/proxy_device.dart +++ b/lib/bluetooth/devices/proxy/proxy_device.dart @@ -641,6 +641,20 @@ class ProxyDevice extends BluetoothDevice { case InGameAction.trainerIntensityDown: def.adjustIntensity(-0.05); return Success(l10n.trainerIntensityDecreased, button: button); + case InGameAction.frontShift: + if (def.trainerMode.value == TrainerMode.ergMode) { + return Ignored(l10n.trainerFrontShiftUnavailable, button: button); + } + final didToggle = def.toggleFrontChainring(); + if (!didToggle) { + return Ignored(l10n.trainerFrontShiftUnavailable, button: button); + } + return Success( + def.frontRing.value == FrontRing.large + ? l10n.trainerFrontShiftedLarge + : l10n.trainerFrontShiftedSmall, + button: button, + ); default: return NotHandled('', button: button); } diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 122705b8..1452a2f4 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -906,6 +906,9 @@ "trainerSwitchedToErg": "In den ERG-Modus gewechselt @ {watts} W", "trainerIntensityIncreased": "Intensität +5%", "trainerIntensityDecreased": "Intensität −5%", + "trainerFrontShiftedLarge": "Vorne: großes Kettenblatt", + "trainerFrontShiftedSmall": "Vorne: kleines Kettenblatt", + "trainerFrontShiftUnavailable": "Frontschaltung nicht verfügbar", "successRatingMessage": "Danke, dass du BikeControl nutzt! Bitte überlege, BikeControl im {store} zu bewerten — das hilft uns sehr!", "rateBikeControl": "BikeControl bewerten", "bridgeMinutesRemainingToday": "Noch {minutes} Min. heute", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 2d0b1453..9494f005 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -1110,6 +1110,9 @@ }, "trainerIntensityIncreased": "Intensity +5%", "trainerIntensityDecreased": "Intensity -5%", + "trainerFrontShiftedLarge": "Front: large ring", + "trainerFrontShiftedSmall": "Front: small ring", + "trainerFrontShiftUnavailable": "Front shift unavailable", "successRatingMessage": "Thank you for using BikeControl! Please consider rating BikeControl in the {store} — it helps a lot!", "@successRatingMessage": {"placeholders": {"store": {"type": "String"}}}, "rateBikeControl": "Rate BikeControl", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index d74f4c37..1e2c78ed 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -906,6 +906,9 @@ "trainerSwitchedToErg": "Cambiado al modo ERG @ {watts} W", "trainerIntensityIncreased": "Intensidad +5%", "trainerIntensityDecreased": "Intensidad −5%", + "trainerFrontShiftedLarge": "Plato: grande", + "trainerFrontShiftedSmall": "Plato: pequeño", + "trainerFrontShiftUnavailable": "Cambio delantero no disponible", "successRatingMessage": "¡Gracias por usar BikeControl! Considera valorar BikeControl en el {store} — nos ayuda mucho.", "rateBikeControl": "Valorar BikeControl", "bridgeMinutesRemainingToday": "Quedan {minutes} min hoy", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 28adf20b..9eeac46a 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -907,6 +907,9 @@ "trainerSwitchedToErg": "Basculé en mode ERG @ {watts} W", "trainerIntensityIncreased": "Intensité +5 %", "trainerIntensityDecreased": "Intensité −5 %", + "trainerFrontShiftedLarge": "Plateau : grand", + "trainerFrontShiftedSmall": "Plateau : petit", + "trainerFrontShiftUnavailable": "Changement avant indisponible", "successRatingMessage": "Merci d'utiliser BikeControl ! Pense à noter BikeControl sur le {store} — ça aide beaucoup !", "rateBikeControl": "Noter BikeControl", "bridgeMinutesRemainingToday": "Encore {minutes} min aujourd'hui", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index a83d637b..7bfbe6a0 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -906,6 +906,9 @@ "trainerSwitchedToErg": "Passato in modalità ERG @ {watts} W", "trainerIntensityIncreased": "Intensità +5%", "trainerIntensityDecreased": "Intensità −5%", + "trainerFrontShiftedLarge": "Anteriore: corona grande", + "trainerFrontShiftedSmall": "Anteriore: corona piccola", + "trainerFrontShiftUnavailable": "Cambio anteriore non disponibile", "successRatingMessage": "Grazie per usare BikeControl! Valuta BikeControl sull'{store} — è davvero d'aiuto.", "rateBikeControl": "Valuta BikeControl", "bridgeMinutesRemainingToday": "Ancora {minutes} min oggi", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 1f2334a5..4043aeca 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -906,6 +906,9 @@ "trainerSwitchedToErg": "Przełączono na tryb ERG @ {watts} W", "trainerIntensityIncreased": "Intensywność +5%", "trainerIntensityDecreased": "Intensywność −5%", + "trainerFrontShiftedLarge": "Przód: duża tarcza", + "trainerFrontShiftedSmall": "Przód: mała tarcza", + "trainerFrontShiftUnavailable": "Zmiana z przodu niedostępna", "successRatingMessage": "Dzięki, że korzystasz z BikeControl! Rozważ ocenę aplikacji w {store} — bardzo nam to pomaga!", "rateBikeControl": "Oceń BikeControl", "bridgeMinutesRemainingToday": "Pozostało {minutes} min dzisiaj", diff --git a/test/bluetooth/proxy/handle_trainer_action_consolidated_test.dart b/test/bluetooth/proxy/handle_trainer_action_consolidated_test.dart index 01894f01..d57b1b1d 100644 --- a/test/bluetooth/proxy/handle_trainer_action_consolidated_test.dart +++ b/test/bluetooth/proxy/handle_trainer_action_consolidated_test.dart @@ -77,5 +77,63 @@ Future main() async { expect(result, isA()); expect(def.trainerMode.value, isNot(TrainerMode.ergMode)); }); + + group('frontShift', () { + setUp(() { + // Enable front-shift on the definition, put it in sim mode. + def.setChainringTeeth(34, 50); + def.setFrontShiftEnabled(true); + def.setTargetGear(12); // sim mode (non-ERG) + }); + + test('sim mode: first call shifts to large ring and returns Success', () { + expect(def.frontRing.value, FrontRing.small); // precondition + final result = device.handleTrainerAction( + ZwiftButtons.shiftDownLeft, + InGameAction.frontShift, + ); + expect(result, isA()); + expect(def.frontRing.value, FrontRing.large); + }); + + test('sim mode: second call shifts back to small ring and returns Success', () { + // First toggle → large + device.handleTrainerAction(ZwiftButtons.shiftDownLeft, InGameAction.frontShift); + expect(def.frontRing.value, FrontRing.large); + + // Second toggle → small + final result = device.handleTrainerAction( + ZwiftButtons.shiftDownLeft, + InGameAction.frontShift, + ); + expect(result, isA()); + expect(def.frontRing.value, FrontRing.small); + }); + + test('erg mode: returns Ignored and does not change ring', () { + def.setManualErgPower(150); // switch to ERG + expect(def.trainerMode.value, TrainerMode.ergMode); + final ringBefore = def.frontRing.value; + + final result = device.handleTrainerAction( + ZwiftButtons.shiftDownLeft, + InGameAction.frontShift, + ); + expect(result, isA()); + expect(def.frontRing.value, ringBefore); // unchanged + }); + + test('returns Ignored when front-shift is disabled', () { + def.setFrontShiftEnabled(false); + final ringBefore = def.frontRing.value; + + final result = device.handleTrainerAction( + ZwiftButtons.shiftDownLeft, + InGameAction.frontShift, + ); + expect(result, isA()); + expect(def.frontRing.value, ringBefore); + }); + }); }); } From 464d909f26064d28a2a21fa67f40c2aeb4e09637 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 15:54:45 +0200 Subject: [PATCH 028/106] feat: supportsNativeFrontShift capability flag (Zwift=true) Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/utils/keymap/apps/supported_app.dart | 5 +++++ lib/utils/keymap/apps/zwift.dart | 3 +++ 2 files changed, 8 insertions(+) diff --git a/lib/utils/keymap/apps/supported_app.dart b/lib/utils/keymap/apps/supported_app.dart index 47b48925..b7219bb1 100644 --- a/lib/utils/keymap/apps/supported_app.dart +++ b/lib/utils/keymap/apps/supported_app.dart @@ -70,6 +70,11 @@ abstract class SupportedApp { /// (e.g. MyWhoosh → 30). int get virtualGearAmount => 24; + /// Whether this app performs its own front-chainring (SRAM-style) shift when + /// it receives a simultaneous both-shifter press. When true, the emulator + /// forwards the combo natively; when false, it approximates with N rear shifts. + bool get supportsNativeFrontShift => false; + /// Default OpenBikeControl supported buttons used by the ButtonEditor /// before (or without) a live OBP connection. Overridden by trainer-app /// subclasses that ship a known-good list. diff --git a/lib/utils/keymap/apps/zwift.dart b/lib/utils/keymap/apps/zwift.dart index 9bd79b9d..e9fa44b4 100644 --- a/lib/utils/keymap/apps/zwift.dart +++ b/lib/utils/keymap/apps/zwift.dart @@ -12,6 +12,9 @@ class Zwift extends SupportedApp { (AppConnectionMethod.zwiftBle, ConnectionSupport.beta), ]; + @override + bool get supportsNativeFrontShift => true; + Zwift() : super( name: 'Zwift', From 8f8153574cf4d5d82c16e15ee14760186e677278 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:16:02 +0200 Subject: [PATCH 029/106] chore(6.2): scaffold screen recording deps and in-repo plugin --- .../screen_recorder/lib/screen_recorder.dart | 36 +++++++++++++++++++ packages/screen_recorder/pubspec.yaml | 27 ++++++++++++++ pubspec.yaml | 4 +++ 3 files changed, 67 insertions(+) create mode 100644 packages/screen_recorder/lib/screen_recorder.dart create mode 100644 packages/screen_recorder/pubspec.yaml diff --git a/packages/screen_recorder/lib/screen_recorder.dart b/packages/screen_recorder/lib/screen_recorder.dart new file mode 100644 index 00000000..673e07d0 --- /dev/null +++ b/packages/screen_recorder/lib/screen_recorder.dart @@ -0,0 +1,36 @@ +import 'package:flutter/services.dart'; + +/// Thin method-channel wrapper over the native (iOS/macOS/Windows) recorders. +/// All methods return defensively: failures surface as `false`/`null`, never throw. +class ScreenRecorderChannel { + static const MethodChannel _channel = MethodChannel('screen_recorder'); + + /// Whether the current OS build supports capture (macOS >= 12.3, WGC available, etc.). + Future isSupported() async { + final result = await _channel.invokeMethod('isSupported'); + return result ?? false; + } + + /// True if capture permission is already granted (macOS TCC / iOS n/a → true). + Future hasPermission() async { + final result = await _channel.invokeMethod('hasPermission'); + return result ?? false; + } + + /// Request capture permission. Returns true if granted. + Future requestPermission() async { + final result = await _channel.invokeMethod('requestPermission'); + return result ?? false; + } + + /// Begin recording. Returns true if recording started. + Future start() async { + final result = await _channel.invokeMethod('start'); + return result ?? false; + } + + /// Stop recording. Returns the saved file path, or null on failure. + Future stop() async { + return _channel.invokeMethod('stop'); + } +} diff --git a/packages/screen_recorder/pubspec.yaml b/packages/screen_recorder/pubspec.yaml new file mode 100644 index 00000000..eddfa66a --- /dev/null +++ b/packages/screen_recorder/pubspec.yaml @@ -0,0 +1,27 @@ +name: screen_recorder +description: "In-repo screen recording plugin for BikeControl (iOS/macOS/Windows capture)." +version: 0.0.1 +publish_to: none + +environment: + sdk: '>=3.8.1 <4.0.0' + flutter: '>=3.3.0' + +dependencies: + flutter: + sdk: flutter + +dev_dependencies: + flutter_test: + sdk: flutter + flutter_lints: ^5.0.0 + +flutter: + plugin: + platforms: + ios: + pluginClass: ScreenRecorderPlugin + macos: + pluginClass: ScreenRecorderPlugin + windows: + pluginClass: ScreenRecorderPlugin diff --git a/pubspec.yaml b/pubspec.yaml index 99dba51e..ba5207c4 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -46,6 +46,10 @@ dependencies: image_picker: ^1.1.2 file_picker: ^10.3.10 flutter_screen_capture: ^2.0.1 + flutter_screen_recording: ^2.0.25 + gal: ^2.3.1 + screen_recorder: + path: packages/screen_recorder in_app_review: ^2.0.11 flutter_secure_storage: ^10.0.0 in_app_purchase: ^3.2.1 From 7184f8968a2799fd14642cb42c28889ce935f425 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:19:50 +0200 Subject: [PATCH 030/106] feat(6.2): add ScreenRecordingService with testable backend seam --- .../backends/unsupported_screen_recorder.dart | 13 +++ .../screen_recording_service.dart | 81 +++++++++++++++++ .../screen_recording_service_test.dart | 87 +++++++++++++++++++ 3 files changed, 181 insertions(+) create mode 100644 lib/services/screen_recording/backends/unsupported_screen_recorder.dart create mode 100644 lib/services/screen_recording/screen_recording_service.dart create mode 100644 test/services/screen_recording/screen_recording_service_test.dart diff --git a/lib/services/screen_recording/backends/unsupported_screen_recorder.dart b/lib/services/screen_recording/backends/unsupported_screen_recorder.dart new file mode 100644 index 00000000..45eb5835 --- /dev/null +++ b/lib/services/screen_recording/backends/unsupported_screen_recorder.dart @@ -0,0 +1,13 @@ +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; + +/// Backend for platforms/OS versions that cannot capture (web, Linux, macOS < 12.3, old Windows). +class UnsupportedScreenRecorder implements ScreenRecorderBackend { + @override + Future isAvailable() async => false; + @override + Future ensurePermission() async => false; + @override + Future start() async => false; + @override + Future stop() async => null; +} diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart new file mode 100644 index 00000000..b315a9f0 --- /dev/null +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -0,0 +1,81 @@ +import 'package:flutter/foundation.dart'; + +enum ScreenRecordingState { idle, starting, recording, stopping, unsupported, error } + +/// Outcome of a [ScreenRecordingService.toggle]. +class RecordingResult { + final bool ok; + + /// True if this toggle *started* recording; false if it *stopped* (or failed). + final bool startedRecording; + + /// Saved file path when a stop succeeded (desktop surfaces this); null otherwise. + final String? savedPath; + final String? errorMessage; + + const RecordingResult({ + required this.ok, + required this.startedRecording, + this.savedPath, + this.errorMessage, + }); +} + +/// Platform capture backend. Implementations: Android (package), native channel +/// (iOS/macOS/Windows), and unsupported (web/Linux/too-old OS). +abstract class ScreenRecorderBackend { + /// Whether this OS build can capture at all. + Future isAvailable(); + + /// Ensure capture permission, prompting if needed. Returns true if granted. + Future ensurePermission(); + + /// Begin capture. Returns true if recording started. + Future start(); + + /// Stop capture and persist. Returns the saved path (may be null on mobile gallery saves). + Future stop(); +} + +/// Owns recording lifecycle/state. All logic lives here so it is unit-testable +/// with a fake backend; the per-platform native work lives in the backends. +class ScreenRecordingService { + ScreenRecordingService({required ScreenRecorderBackend backend}) : _backend = backend; + + final ScreenRecorderBackend _backend; + final ValueNotifier _state = ValueNotifier(ScreenRecordingState.idle); + + ValueListenable get state => _state; + bool get isRecording => _state.value == ScreenRecordingState.recording; + Future get isAvailable => _backend.isAvailable(); + + /// Toggle recording. Never throws — failures map to `ok: false`. + Future toggle() async { + if (isRecording) { + return _stop(); + } + return _start(); + } + + Future _start() async { + if (!await _backend.isAvailable()) { + _state.value = ScreenRecordingState.unsupported; + return const RecordingResult(ok: false, startedRecording: true); + } + _state.value = ScreenRecordingState.starting; + if (!await _backend.ensurePermission()) { + _state.value = ScreenRecordingState.idle; + return const RecordingResult(ok: false, startedRecording: true, errorMessage: 'permission denied'); + } + final started = await _backend.start(); + _state.value = started ? ScreenRecordingState.recording : ScreenRecordingState.idle; + return RecordingResult(ok: started, startedRecording: true); + } + + Future _stop() async { + _state.value = ScreenRecordingState.stopping; + final path = await _backend.stop(); + _state.value = ScreenRecordingState.idle; + return RecordingResult(ok: true, startedRecording: false, savedPath: path); + } +} diff --git a/test/services/screen_recording/screen_recording_service_test.dart b/test/services/screen_recording/screen_recording_service_test.dart new file mode 100644 index 00000000..4c214441 --- /dev/null +++ b/test/services/screen_recording/screen_recording_service_test.dart @@ -0,0 +1,87 @@ +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// In-memory backend so the service's toggle/state logic is testable with no OS. +class FakeScreenRecorderBackend implements ScreenRecorderBackend { + bool available = true; + bool permission = true; + bool startResult = true; + String? stopPath = '/tmp/fake.mp4'; + int startCalls = 0; + int stopCalls = 0; + + @override + Future isAvailable() async => available; + @override + Future ensurePermission() async => permission; + @override + Future start() async { + startCalls++; + return startResult; + } + + @override + Future stop() async { + stopCalls++; + return stopPath; + } +} + +void main() { + late FakeScreenRecorderBackend backend; + late ScreenRecordingService service; + + setUp(() { + backend = FakeScreenRecorderBackend(); + service = ScreenRecordingService(backend: backend); + }); + + test('starts idle and reports availability from the backend', () async { + expect(service.state.value, ScreenRecordingState.idle); + expect(await service.isAvailable, isTrue); + backend.available = false; + expect(await service.isAvailable, isFalse); + }); + + test('toggle from idle starts recording', () async { + final result = await service.toggle(); + expect(result.ok, isTrue); + expect(result.startedRecording, isTrue); + expect(service.state.value, ScreenRecordingState.recording); + expect(service.isRecording, isTrue); + expect(backend.startCalls, 1); + }); + + test('toggle while recording stops and returns the saved path', () async { + await service.toggle(); // start + final result = await service.toggle(); // stop + expect(result.ok, isTrue); + expect(result.startedRecording, isFalse); + expect(result.savedPath, '/tmp/fake.mp4'); + expect(service.state.value, ScreenRecordingState.idle); + expect(service.isRecording, isFalse); + expect(backend.stopCalls, 1); + }); + + test('toggle returns failure and stays idle when start fails', () async { + backend.startResult = false; + final result = await service.toggle(); + expect(result.ok, isFalse); + expect(service.state.value, ScreenRecordingState.idle); + }); + + test('toggle returns failure when permission denied, without starting', () async { + backend.permission = false; + final result = await service.toggle(); + expect(result.ok, isFalse); + expect(backend.startCalls, 0); + expect(service.state.value, ScreenRecordingState.idle); + }); + + test('toggle on unsupported backend reports unsupported', () async { + backend.available = false; + final result = await service.toggle(); + expect(result.ok, isFalse); + expect(service.state.value, ScreenRecordingState.unsupported); + }); +} From 11b48d15609fa4c2ffa29978c3a437b23dad4751 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:23:29 +0200 Subject: [PATCH 031/106] fix(6.2): screen recording service never-throws contract + startedRecording semantics --- .../screen_recording_service.dart | 42 ++++++++++++------- .../screen_recording_service_test.dart | 22 ++++++++++ 2 files changed, 49 insertions(+), 15 deletions(-) diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart index b315a9f0..a4b5932f 100644 --- a/lib/services/screen_recording/screen_recording_service.dart +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -58,24 +58,36 @@ class ScreenRecordingService { } Future _start() async { - if (!await _backend.isAvailable()) { - _state.value = ScreenRecordingState.unsupported; - return const RecordingResult(ok: false, startedRecording: true); + try { + if (!await _backend.isAvailable()) { + _state.value = ScreenRecordingState.unsupported; + return const RecordingResult(ok: false, startedRecording: false); + } + _state.value = ScreenRecordingState.starting; + if (!await _backend.ensurePermission()) { + _state.value = ScreenRecordingState.idle; + return const RecordingResult(ok: false, startedRecording: false, errorMessage: 'permission denied'); + } + final started = await _backend.start(); + _state.value = started ? ScreenRecordingState.recording : ScreenRecordingState.idle; + return RecordingResult(ok: started, startedRecording: true); + } catch (e, s) { + _state.value = ScreenRecordingState.error; + debugPrintStack(label: 'screen recording: $e', stackTrace: s); + return RecordingResult(ok: false, startedRecording: true, errorMessage: e.toString()); } - _state.value = ScreenRecordingState.starting; - if (!await _backend.ensurePermission()) { - _state.value = ScreenRecordingState.idle; - return const RecordingResult(ok: false, startedRecording: true, errorMessage: 'permission denied'); - } - final started = await _backend.start(); - _state.value = started ? ScreenRecordingState.recording : ScreenRecordingState.idle; - return RecordingResult(ok: started, startedRecording: true); } Future _stop() async { - _state.value = ScreenRecordingState.stopping; - final path = await _backend.stop(); - _state.value = ScreenRecordingState.idle; - return RecordingResult(ok: true, startedRecording: false, savedPath: path); + try { + _state.value = ScreenRecordingState.stopping; + final path = await _backend.stop(); + _state.value = ScreenRecordingState.idle; + return RecordingResult(ok: true, startedRecording: false, savedPath: path); + } catch (e, s) { + _state.value = ScreenRecordingState.error; + debugPrintStack(label: 'screen recording: $e', stackTrace: s); + return RecordingResult(ok: false, startedRecording: false, errorMessage: e.toString()); + } } } diff --git a/test/services/screen_recording/screen_recording_service_test.dart b/test/services/screen_recording/screen_recording_service_test.dart index 4c214441..c21e8d8d 100644 --- a/test/services/screen_recording/screen_recording_service_test.dart +++ b/test/services/screen_recording/screen_recording_service_test.dart @@ -74,6 +74,7 @@ void main() { backend.permission = false; final result = await service.toggle(); expect(result.ok, isFalse); + expect(result.startedRecording, isFalse); expect(backend.startCalls, 0); expect(service.state.value, ScreenRecordingState.idle); }); @@ -82,6 +83,27 @@ void main() { backend.available = false; final result = await service.toggle(); expect(result.ok, isFalse); + expect(result.startedRecording, isFalse); expect(service.state.value, ScreenRecordingState.unsupported); }); + + test('toggle completes without throwing when backend start() throws', () async { + final throwingBackend = _ThrowingScreenRecorderBackend(); + final throwingService = ScreenRecordingService(backend: throwingBackend); + final result = await throwingService.toggle(); + expect(result.ok, isFalse); + expect(throwingService.state.value, ScreenRecordingState.error); + }); +} + +/// Backend whose start() always throws, to verify the never-throws contract. +class _ThrowingScreenRecorderBackend implements ScreenRecorderBackend { + @override + Future isAvailable() async => true; + @override + Future ensurePermission() async => true; + @override + Future start() async => throw Exception('simulated backend crash'); + @override + Future stop() async => null; } From 21744dcae750c67d5c7b724f3b0e2ff465c5b852 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:20:20 +0200 Subject: [PATCH 032/106] feat(zwift): forward frontShift as both-shifters combo frame MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Intercept InGameAction.frontShift in ZwiftEmulator.sendAction and emit the SHFT_UP_R|SHFT_UP_L combined buttonMap frame followed by the release frame — the standard Zwift Ride gesture that triggers a front-chainring shift in Zwift (SRAM) and a generic controller gesture in other apps. No app-capability flag, no fallback, no toggle state. UNVERIFIED: bitmask vs live Zwift SRAM — confirm on-device. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../devices/zwift/zwift_emulator.dart | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/lib/bluetooth/devices/zwift/zwift_emulator.dart b/lib/bluetooth/devices/zwift/zwift_emulator.dart index e8363e76..7866be9e 100644 --- a/lib/bluetooth/devices/zwift/zwift_emulator.dart +++ b/lib/bluetooth/devices/zwift/zwift_emulator.dart @@ -49,6 +49,7 @@ class ZwiftEmulator extends TrainerConnection { InGameAction.select, InGameAction.back, InGameAction.rideOnBomb, + InGameAction.frontShift, ], ); @@ -298,6 +299,10 @@ class ZwiftEmulator extends TrainerConnection { final mapping = core.settings.getTrainerApp()?.inGameActionsMapping; var action = mapping?.entries.firstOrNullWhere((e) => e.value == keyPair.inGameAction) ?? keyPair.inGameAction; + if (action == InGameAction.frontShift) { + return _sendFrontShift(keyPair); + } + final button = switch (action) { InGameAction.shiftUp => RideButtonMask.SHFT_UP_R_BTN, InGameAction.shiftDown => RideButtonMask.SHFT_UP_L_BTN, @@ -352,6 +357,35 @@ class ZwiftEmulator extends TrainerConnection { ); } + /// Forward a front-chainring shift to the connected app as the standard + /// Zwift Ride "both shifters" gesture — the same behavior for every app + /// (apps with native SRAM, e.g. Zwift, perform the front shift; others get + /// a normal controller gesture). + Future _sendFrontShift(KeyPair keyPair) async { + // Both shift buttons pressed together. NOTE: the exact bit pair Zwift's + // SRAM detection expects is UNVERIFIED against a live Zwift session — + // confirm on-device and adjust if needed. + final combined = + RideButtonMask.SHFT_UP_R_BTN.mask | RideButtonMask.SHFT_UP_L_BTN.mask; + Logger.info('ZwiftEmulator: front-shift combo (SHFT_UP_R|SHFT_UP_L) — verify bitmask vs Zwift SRAM'); + final status = RideKeyPadStatus() + ..buttonMap = (~combined) & 0xFFFFFFFF + ..analogPaddles.clear(); + await _server.notify( + characteristicId: ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + value: Uint8List.fromList( + [Opcode.CONTROLLER_NOTIFICATION.value, ...status.writeToBuffer()]), + deviceId: _currentDeviceId, + ); + await _server.notify( + characteristicId: ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + value: Uint8List.fromList( + [Opcode.CONTROLLER_NOTIFICATION.value, 0x08, 0xFF, 0xFF, 0xFF, 0xFF, 0x0F]), + deviceId: _currentDeviceId, + ); + return Success('Sent front-shift combo', button: keyPair.buttons.firstOrNull); + } + void cleanup() { _server.stopAdvertising(); _server.clearServices(); From 24dc1bd916f967a64f01e5592714b8dad0fe8501 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:27:54 +0200 Subject: [PATCH 033/106] feat(6.2): add screenRecording action enum + localized strings --- lib/i10n/intl_de.arb | 6 ++++++ lib/i10n/intl_en.arb | 6 ++++++ lib/i10n/intl_es.arb | 6 ++++++ lib/i10n/intl_fr.arb | 6 ++++++ lib/i10n/intl_it.arb | 6 ++++++ lib/i10n/intl_pl.arb | 6 ++++++ lib/utils/keymap/buttons.dart | 6 +++++- 7 files changed, 41 insertions(+), 1 deletion(-) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 1452a2f4..e9b2309e 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -69,6 +69,12 @@ "actionTrainerIntensityUp": "Trainer: Intensität erhöhen", "actionTrainerIntensityDown": "Trainer: Intensität verringern", "actionWorkoutPauseResume": "Training: Pause/Fortsetzen", + "actionScreenRecording": "Bildschirm aufnehmen", + "deviceActions": "Gerät", + "screenRecordingStarted": "Bildschirmaufnahme gestartet", + "screenRecordingStopped": "Bildschirmaufnahme gespeichert", + "screenRecordingFailed": "Bildschirmaufnahme konnte nicht gestartet werden", + "screenRecordingNotSupported": "Bildschirmaufnahme wird auf diesem Gerät nicht unterstützt", "actionDFlyChannel1": "D-Fly-Kanal 1", "actionDFlyChannel2": "D-Fly-Kanal 2", "actionDFlyChannel3": "D-Fly-Kanal 3", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 9494f005..476b1b56 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -46,6 +46,12 @@ "actionTrainerIntensityUp": "Trainer: Intensity Up", "actionTrainerIntensityDown": "Trainer: Intensity Down", "actionWorkoutPauseResume": "Workout: Pause/Resume", + "actionScreenRecording": "Record Screen", + "deviceActions": "Device", + "screenRecordingStarted": "Screen recording started", + "screenRecordingStopped": "Screen recording saved", + "screenRecordingFailed": "Could not start screen recording", + "screenRecordingNotSupported": "Screen recording isn't supported on this device", "actionDFlyChannel1": "D-Fly Channel 1", "actionDFlyChannel2": "D-Fly Channel 2", "actionDFlyChannel3": "D-Fly Channel 3", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 1e2c78ed..f71fd8f2 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -69,6 +69,12 @@ "actionTrainerIntensityUp": "Rodillo: subir intensidad", "actionTrainerIntensityDown": "Rodillo: bajar intensidad", "actionWorkoutPauseResume": "Entrenamiento: pausar/reanudar", + "actionScreenRecording": "Grabar pantalla", + "deviceActions": "Dispositivo", + "screenRecordingStarted": "Grabación de pantalla iniciada", + "screenRecordingStopped": "Grabación de pantalla guardada", + "screenRecordingFailed": "No se pudo iniciar la grabación de pantalla", + "screenRecordingNotSupported": "La grabación de pantalla no es compatible con este dispositivo", "actionDFlyChannel1": "Canal D-Fly 1", "actionDFlyChannel2": "Canal D-Fly 2", "actionDFlyChannel3": "Canal D-Fly 3", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 9eeac46a..1f735aa0 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -69,6 +69,12 @@ "actionTrainerIntensityUp": "Home-trainer : augmenter l’intensité", "actionTrainerIntensityDown": "Home-trainer : réduire l’intensité", "actionWorkoutPauseResume": "Séance : pause/reprendre", + "actionScreenRecording": "Enregistrer l'écran", + "deviceActions": "Appareil", + "screenRecordingStarted": "Enregistrement d'écran démarré", + "screenRecordingStopped": "Enregistrement d'écran enregistré", + "screenRecordingFailed": "Impossible de démarrer l'enregistrement d'écran", + "screenRecordingNotSupported": "L'enregistrement d'écran n'est pas pris en charge sur cet appareil", "actionDFlyChannel1": "Canal D-Fly 1", "actionDFlyChannel2": "Canal D-Fly 2", "actionDFlyChannel3": "Canal D-Fly 3", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 7bfbe6a0..c388c40d 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -69,6 +69,12 @@ "actionTrainerIntensityUp": "Rullo: aumenta intensità", "actionTrainerIntensityDown": "Rullo: riduci intensità", "actionWorkoutPauseResume": "Allenamento: pausa/riprendi", + "actionScreenRecording": "Registra schermo", + "deviceActions": "Dispositivo", + "screenRecordingStarted": "Registrazione dello schermo avviata", + "screenRecordingStopped": "Registrazione dello schermo salvata", + "screenRecordingFailed": "Impossibile avviare la registrazione dello schermo", + "screenRecordingNotSupported": "La registrazione dello schermo non è supportata su questo dispositivo", "actionDFlyChannel1": "Canale D-Fly 1", "actionDFlyChannel2": "Canale D-Fly 2", "actionDFlyChannel3": "Canale D-Fly 3", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 4043aeca..2bc30dad 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -69,6 +69,12 @@ "actionTrainerIntensityUp": "Trenażer: zwiększ intensywność", "actionTrainerIntensityDown": "Trenażer: zmniejsz intensywność", "actionWorkoutPauseResume": "Trening: pauza/wznów", + "actionScreenRecording": "Nagraj ekran", + "deviceActions": "Urządzenie", + "screenRecordingStarted": "Rozpoczęto nagrywanie ekranu", + "screenRecordingStopped": "Zapisano nagranie ekranu", + "screenRecordingFailed": "Nie można rozpocząć nagrywania ekranu", + "screenRecordingNotSupported": "Nagrywanie ekranu nie jest obsługiwane na tym urządzeniu", "actionDFlyChannel1": "Kanał D-Fly 1", "actionDFlyChannel2": "Kanał D-Fly 2", "actionDFlyChannel3": "Kanał D-Fly 3", diff --git a/lib/utils/keymap/buttons.dart b/lib/utils/keymap/buttons.dart index cd9bf6ce..4ac6036b 100644 --- a/lib/utils/keymap/buttons.dart +++ b/lib/utils/keymap/buttons.dart @@ -75,7 +75,10 @@ enum InGameAction { dFlyChannel1('D-Fly Channel 1', icon: LucideIcons.circleDot), dFlyChannel2('D-Fly Channel 2', icon: LucideIcons.circleDot), dFlyChannel3('D-Fly Channel 3', icon: LucideIcons.circleDot), - dFlyChannel4('D-Fly Channel 4', icon: LucideIcons.circleDot); + dFlyChannel4('D-Fly Channel 4', icon: LucideIcons.circleDot), + + // device / system + screenRecording('Record Screen', icon: LucideIcons.video, isOutsideTrainerApp: true); final String englishTitle; final bool isLongPress; @@ -148,6 +151,7 @@ enum InGameAction { InGameAction.dFlyChannel2 => l.actionDFlyChannel2, InGameAction.dFlyChannel3 => l.actionDFlyChannel3, InGameAction.dFlyChannel4 => l.actionDFlyChannel4, + InGameAction.screenRecording => l.actionScreenRecording, }; } From 61c02d4ca78ce6c0521043ea973b8fb3572de2d8 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:30:54 +0200 Subject: [PATCH 034/106] feat(6.2): register core.screenRecording with platform backend factory --- .../native_channel_screen_recorder.dart | 53 +++++++++++++++++++ .../screen_recording_service.dart | 16 ++++++ lib/utils/core.dart | 2 + 3 files changed, 71 insertions(+) create mode 100644 lib/services/screen_recording/backends/native_channel_screen_recorder.dart diff --git a/lib/services/screen_recording/backends/native_channel_screen_recorder.dart b/lib/services/screen_recording/backends/native_channel_screen_recorder.dart new file mode 100644 index 00000000..ef50ac57 --- /dev/null +++ b/lib/services/screen_recording/backends/native_channel_screen_recorder.dart @@ -0,0 +1,53 @@ +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; +import 'package:flutter/foundation.dart'; +import 'package:screen_recorder/screen_recorder.dart'; + +/// Backend that delegates to the in-repo `screen_recorder` plugin +/// (iOS broadcast bridge / macOS ScreenCaptureKit / Windows WGC). +class NativeChannelScreenRecorder implements ScreenRecorderBackend { + NativeChannelScreenRecorder([ScreenRecorderChannel? channel]) + : _channel = channel ?? ScreenRecorderChannel(); + + final ScreenRecorderChannel _channel; + + @override + Future isAvailable() async { + try { + return await _channel.isSupported(); + } catch (e, s) { + debugPrintStack(label: 'screen_recorder isSupported: $e', stackTrace: s); + return false; + } + } + + @override + Future ensurePermission() async { + try { + if (await _channel.hasPermission()) return true; + return await _channel.requestPermission(); + } catch (e, s) { + debugPrintStack(label: 'screen_recorder permission: $e', stackTrace: s); + return false; + } + } + + @override + Future start() async { + try { + return await _channel.start(); + } catch (e, s) { + debugPrintStack(label: 'screen_recorder start: $e', stackTrace: s); + return false; + } + } + + @override + Future stop() async { + try { + return await _channel.stop(); + } catch (e, s) { + debugPrintStack(label: 'screen_recorder stop: $e', stackTrace: s); + return null; + } + } +} diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart index a4b5932f..6ea7b376 100644 --- a/lib/services/screen_recording/screen_recording_service.dart +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -1,3 +1,7 @@ +import 'dart:io'; + +import 'package:bike_control/services/screen_recording/backends/native_channel_screen_recorder.dart'; +import 'package:bike_control/services/screen_recording/backends/unsupported_screen_recorder.dart'; import 'package:flutter/foundation.dart'; enum ScreenRecordingState { idle, starting, recording, stopping, unsupported, error } @@ -91,3 +95,15 @@ class ScreenRecordingService { } } } + +/// Selects the backend for the running platform. Android's real backend is +/// added in a later task; until then Android falls back to unsupported so the +/// app stays buildable. +ScreenRecorderBackend createScreenRecorderBackend() { + if (kIsWeb) return UnsupportedScreenRecorder(); + if (Platform.isIOS || Platform.isMacOS || Platform.isWindows) { + return NativeChannelScreenRecorder(); + } + // Android backend added later; Linux unsupported. + return UnsupportedScreenRecorder(); +} diff --git a/lib/utils/core.dart b/lib/utils/core.dart index c1288ce2..98457f0b 100644 --- a/lib/utils/core.dart +++ b/lib/utils/core.dart @@ -13,6 +13,7 @@ import 'package:bike_control/bluetooth/remote_keyboard_pairing.dart'; import 'package:bike_control/bluetooth/remote_pairing.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/services/review_prompt_service.dart'; +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; import 'package:bike_control/services/shifting_configs_controller.dart'; import 'package:bike_control/services/workout/workout_recorder.dart'; import 'package:bike_control/services/workout/workout_repository.dart'; @@ -53,6 +54,7 @@ class Core { late final shiftingConfigs = ShiftingConfigsController(settings.prefs); final connection = Connection(); late final workoutRecorder = WorkoutRecorder(); + ScreenRecordingService screenRecording = ScreenRecordingService(backend: createScreenRecorderBackend()); late final workoutRepository = WorkoutRepository(); late final supabase = Supabase.instance.client; From 6435780e18e3eccaec74391e4dc1cc8ce4dc1d24 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:34:41 +0200 Subject: [PATCH 035/106] feat: both-shifters combo (coincidence window) + BaseActions helpers Add frontShiftComboEnabled getter, performInGameAction synthetic dispatch, and a coincidence-window detector to BaseActions for two-device controllers (e.g. Zwift Play) whose shifts arrive as separate performAction calls. When the opposite rear shift lands within 120 ms, additively emit a frontShift (the two rear shifts cancel; the front ring toggles). Reuses the existing trainer-action/direct-connect routing rather than extracting a dispatcher. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/utils/actions/base_actions.dart | 85 +++++++++++ .../proxy/front_shift_combo_test.dart | 133 ++++++++++++++++++ 2 files changed, 218 insertions(+) create mode 100644 test/bluetooth/proxy/front_shift_combo_test.dart diff --git a/lib/utils/actions/base_actions.dart b/lib/utils/actions/base_actions.dart index e3f15de6..1833e9e3 100644 --- a/lib/utils/actions/base_actions.dart +++ b/lib/utils/actions/base_actions.dart @@ -1,3 +1,4 @@ +import 'dart:async'; import 'dart:io'; import 'dart:math'; @@ -121,6 +122,76 @@ abstract class BaseActions { return Offset.zero; } + /// True when the active trainer (the connected proxy device) has the + /// both-shifters front-shift combo enabled in its [ShiftingConfig]. + bool get frontShiftComboEnabled { + final proxy = core.connection.proxyDevices.where((d) => d.isConnected).firstOrNull; + if (proxy == null) return false; + return core.shiftingConfigs.activeFor(proxy.trainerKey).frontShiftEnabled; + } + + // --- Both-shifters combo (coincidence-window detector) --------------------- + // Two-device controllers (e.g. Zwift Play) deliver their two rear shifts as + // separate performAction calls; pressing both shifters together is the SRAM + // gesture for a front (chainring) shift. We detect the opposite shift landing + // within a short window and additively emit a frontShift alongside the + // (mutually cancelling) rear shifts. + + @visibleForTesting + DateTime Function() nowFn = DateTime.now; + static const Duration _frontShiftWindow = Duration(milliseconds: 120); + DateTime? _lastShiftUpAt; + DateTime? _lastShiftDownAt; + + /// Record a rear shift; return true if the OPPOSITE shift occurred within the + /// front-shift window (→ treat as a both-shifters combo). Resets on a hit. + @visibleForTesting + bool noteShiftAndCheckCoincidence(InGameAction action) { + final now = nowFn(); + if (action == InGameAction.shiftUp) { + _lastShiftUpAt = now; + final down = _lastShiftDownAt; + if (down != null && now.difference(down) <= _frontShiftWindow) { + _lastShiftUpAt = null; + _lastShiftDownAt = null; + return true; + } + } else if (action == InGameAction.shiftDown) { + _lastShiftDownAt = now; + final up = _lastShiftUpAt; + if (up != null && now.difference(up) <= _frontShiftWindow) { + _lastShiftUpAt = null; + _lastShiftDownAt = null; + return true; + } + } + return false; + } + + /// Dispatch [action] as if a mapped button fired it, with no physical button. + /// Used by the both-shifters combo (this file's coincidence detector and the + /// same-frame detector in base_device.dart) to emit a frontShift. + Future performInGameAction(InGameAction action) async { + final synthButton = ControllerButton('frontShiftCombo', action: action); + final keyPair = KeyPair( + buttons: [synthButton], + physicalKey: null, + logicalKey: null, + inGameAction: action, + ); + // Direct path: a connected proxy trainer handles it (frontShift toggle). + if (trainerActions.contains(action)) { + final proxy = core.connection.proxyDevices.where((d) => d.isConnected).firstOrNull; + if (proxy != null) { + await IAPManager.instance.incrementCommandCount(); + final result = proxy.handleTrainerAction(synthButton, action); + if (result is Ignored || result is Success) return result; + } + } + // Otherwise forward to the connected app (e.g. Zwift native SRAM combo). + return _handleDirectConnect(keyPair, synthButton, isKeyDown: true, isKeyUp: true); + } + Future performAction( ControllerButton button, { required bool isKeyDown, @@ -144,6 +215,20 @@ abstract class BaseActions { ); } + // Both-shifters combo (coincidence window): two-device controllers (Play) + // deliver each rear shift as its own performAction call. When the opposite + // shift lands within the window, additively fire a frontShift — this does + // NOT suppress the normal shift; the two opposite rear shifts cancel while + // the front toggles. The same-frame case (Ride/Click) is handled at the + // device layer (Task 8), so those never reach this detector. + if (frontShiftComboEnabled && + isKeyDown && + (keyPair.inGameAction == InGameAction.shiftUp || keyPair.inGameAction == InGameAction.shiftDown)) { + if (noteShiftAndCheckCoincidence(keyPair.inGameAction!)) { + unawaited(performInGameAction(InGameAction.frontShift)); + } + } + final guard = proGuard(button: button, trigger: trigger, keyPair: keyPair); if (guard is! NotHandled) { return guard; diff --git a/test/bluetooth/proxy/front_shift_combo_test.dart b/test/bluetooth/proxy/front_shift_combo_test.dart new file mode 100644 index 00000000..0b6aa5e3 --- /dev/null +++ b/test/bluetooth/proxy/front_shift_combo_test.dart @@ -0,0 +1,133 @@ +import 'package:bike_control/bluetooth/devices/proxy/proxy_device.dart'; +import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/models/shifting_config.dart'; +import 'package:bike_control/utils/actions/base_actions.dart'; +import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/keymap/buttons.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/widgets.dart' show Locale; +import 'package:flutter_test/flutter_test.dart'; +import 'package:prop/emulators/definitions/fitness_bike_definition.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:supabase_flutter/supabase_flutter.dart'; +import 'package:universal_ble/universal_ble.dart'; + +Future main() async { + TestWidgetsFlutterBinding.ensureInitialized(); + // performInGameAction → handleTrainerAction reads AppLocalizations.current for + // its result messages, so we initialise the EN bundle once before any test. + await AppLocalizations.load(const Locale('en')); + + // performInGameAction → IAPManager.incrementCommandCount reaches + // Supabase.instance on the free-tier hot path; give it an offline dummy + // instance (no session, so no network request is ever made). + setUpAll(() async { + // Supabase's gotrue async storage reads SharedPreferences during + // initialize(); mock it before so the channel call resolves. + SharedPreferences.setMockInitialValues({}); + await Supabase.initialize( + url: 'http://127.0.0.1:9', + anonKey: 'front-shift-combo-test-anon-key', + debug: false, + authOptions: const FlutterAuthClientOptions( + localStorage: EmptyLocalStorage(), + detectSessionInUri: false, + autoRefreshToken: false, + ), + ); + }); + + late StubActions actions; + + setUp(() async { + SharedPreferences.setMockInitialValues({}); + core.settings.prefs = await SharedPreferences.getInstance(); + await core.shiftingConfigs.init(); + core.connection.devices.clear(); + actions = StubActions(); + core.actionHandler = actions; + }); + + group('noteShiftAndCheckCoincidence (window)', () { + test('opposite shift within 120ms → coincidence on the second', () { + var t = DateTime(2026, 1, 1); + actions.nowFn = () => t; + + // shiftDown at t=0 → no coincidence yet. + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftDown), isFalse); + + // shiftUp at t=100ms → opposite shift within the window → coincidence. + t = t.add(const Duration(milliseconds: 100)); + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftUp), isTrue); + }); + + test('opposite shift 300ms apart → NO coincidence', () { + var t = DateTime(2026, 1, 1); + actions.nowFn = () => t; + + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftDown), isFalse); + + t = t.add(const Duration(milliseconds: 300)); + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftUp), isFalse); + }); + + test('a hit resets the window so it does not re-trigger', () { + var t = DateTime(2026, 1, 1); + actions.nowFn = () => t; + + actions.noteShiftAndCheckCoincidence(InGameAction.shiftDown); + t = t.add(const Duration(milliseconds: 50)); + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftUp), isTrue); + + // A lone shiftUp right after the reset must not coincide with the + // already-consumed shiftDown. + t = t.add(const Duration(milliseconds: 10)); + expect(actions.noteShiftAndCheckCoincidence(InGameAction.shiftUp), isFalse); + }); + }); + + group('frontShiftComboEnabled', () { + test('false when no proxy is connected', () { + expect(actions.frontShiftComboEnabled, isFalse); + }); + + test('reflects the active ShiftingConfig.frontShiftEnabled of a connected proxy', () async { + final device = ProxyDevice(BleDevice(deviceId: 'x', name: 'KICKR')); + device.isConnected = true; + core.connection.devices.add(device); + + // No config yet → defaults → disabled. + expect(actions.frontShiftComboEnabled, isFalse); + + await core.shiftingConfigs.upsert( + ShiftingConfig.defaults(trainerKey: device.trainerKey).copyWith(frontShiftEnabled: true), + ); + expect(actions.frontShiftComboEnabled, isTrue); + }); + }); + + group('performInGameAction(frontShift)', () { + test('toggles the connected proxy front ring and returns Success', () async { + final device = ProxyDevice(BleDevice(deviceId: 'x', name: 'KICKR')); + device.isConnected = true; + core.connection.devices.add(device); + + final def = FitnessBikeDefinition( + connectedDevice: device.scanResult, + connectedDeviceServices: const [], + data: ValueNotifier(''), + ); + device.emulator.debugSetActiveDefinition(def); + def.setChainringTeeth(34, 50); + def.setFrontShiftEnabled(true); + def.setTargetGear(12); // sim mode (non-ERG) + + expect(def.frontRing.value, FrontRing.small); // precondition + + final result = await actions.performInGameAction(InGameAction.frontShift); + + expect(result, isA()); + expect(def.frontRing.value, FrontRing.large); + }); + }); +} From 2491fa12be4330e7f89a92417477db4651e14d91 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:36:10 +0200 Subject: [PATCH 036/106] feat(6.2): handle screenRecording action in base_actions --- lib/utils/actions/base_actions.dart | 30 +++++++ .../screen_recording_action_test.dart | 87 +++++++++++++++++++ 2 files changed, 117 insertions(+) create mode 100644 test/integration/screen_recording_action_test.dart diff --git a/lib/utils/actions/base_actions.dart b/lib/utils/actions/base_actions.dart index e3f15de6..9612ae83 100644 --- a/lib/utils/actions/base_actions.dart +++ b/lib/utils/actions/base_actions.dart @@ -200,6 +200,36 @@ abstract class BaseActions { ); } + // Handle screen recording — device-level toggle, works with no trainer. + if (keyPair.inGameAction == InGameAction.screenRecording) { + if (!isKeyDown) { + return Ignored('', button: keyPair.buttons.firstOrNull ?? button); + } + final svc = core.screenRecording; + if (!await svc.isAvailable) { + return Ignored( + AppLocalizations.current.screenRecordingNotSupported, + button: keyPair.buttons.firstOrNull ?? button, + ); + } + final result = await svc.toggle(); + if (result.ok) { + await IAPManager.instance.incrementCommandCount(); + final stopped = !result.startedRecording; + final stoppedMsg = result.savedPath != null && result.savedPath!.isNotEmpty + ? '${AppLocalizations.current.screenRecordingStopped}: ${result.savedPath}' + : AppLocalizations.current.screenRecordingStopped; + return Success( + stopped ? stoppedMsg : AppLocalizations.current.screenRecordingStarted, + button: keyPair.buttons.firstOrNull ?? button, + ); + } + return Error( + AppLocalizations.current.screenRecordingFailed, + button: keyPair.buttons.firstOrNull ?? button, + ); + } + // Handle trainer-control actions if (trainerActions.contains(keyPair.inGameAction)) { final proxy = core.connection.proxyDevices.where((d) => d.isConnected).firstOrNull; diff --git a/test/integration/screen_recording_action_test.dart b/test/integration/screen_recording_action_test.dart new file mode 100644 index 00000000..05979f28 --- /dev/null +++ b/test/integration/screen_recording_action_test.dart @@ -0,0 +1,87 @@ +import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; +import 'package:bike_control/utils/actions/base_actions.dart'; +import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/keymap/buttons.dart'; +import 'package:bike_control/utils/keymap/keymap.dart'; +import 'package:bike_control/utils/keymap/apps/zwift.dart'; +import 'package:flutter_test/flutter_test.dart'; + +import 'harness/test_env.dart'; + +/// Minimal concrete BaseActions so the REAL performAction handler runs +/// (BaseActions is abstract only on cleanup()). +class _TestActions extends BaseActions { + _TestActions() : super(supportedModes: const []); + @override + void cleanup() {} +} + +class _FakeBackend implements ScreenRecorderBackend { + bool available = true; + int starts = 0; + int stops = 0; + @override + Future isAvailable() async => available; + @override + Future ensurePermission() async => true; + @override + Future start() async { + starts++; + return true; + } + + @override + Future stop() async { + stops++; + return '/tmp/x.mp4'; + } +} + +Future main() async { + final env = await IntegrationEnv.setUp(); + late _TestActions actions; + late _FakeBackend backend; + + const button = ControllerButton('screenRecTestBtn'); + + setUp(() async { + await env.resetState(); + backend = _FakeBackend(); + core.screenRecording = ScreenRecordingService(backend: backend); + + final app = Zwift(); + app.keymap.keyPairs.add( + KeyPair(buttons: const [button], physicalKey: null, logicalKey: null, inGameAction: InGameAction.screenRecording), + ); + actions = _TestActions()..supportedApp = app; + core.actionHandler = actions; + }); + + test('key-down toggles recording on and returns started', () async { + final result = await actions.performAction(button, isKeyDown: true, isKeyUp: false); + expect(result, isA()); + expect(result.message, AppLocalizations.current.screenRecordingStarted); + expect(backend.starts, 1); + }); + + test('key-up is ignored (no double toggle)', () async { + final result = await actions.performAction(button, isKeyDown: false, isKeyUp: true); + expect(result, isA()); + expect(backend.starts, 0); + }); + + test('second key-down stops and saves', () async { + await actions.performAction(button, isKeyDown: true, isKeyUp: false); + final result = await actions.performAction(button, isKeyDown: true, isKeyUp: false); + expect(result, isA()); + expect(backend.stops, 1); + }); + + test('unsupported device returns Ignored not-supported', () async { + backend.available = false; + final result = await actions.performAction(button, isKeyDown: true, isKeyUp: false); + expect(result, isA()); + expect(result.message, AppLocalizations.current.screenRecordingNotSupported); + }); +} From 3bd3619f25cc19ff026b5399ac651ad85970546c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:43:33 +0200 Subject: [PATCH 037/106] =?UTF-8?q?feat:=20same-frame=20both-shifters=20co?= =?UTF-8?q?mbo=20=E2=86=92=20frontShift=20(Ride/Click)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Detect when a single BLE frame carries both the shiftUp-mapped and shiftDown-mapped buttons (Zwift Ride / Click single-device controllers) and emit a single frontShift, suppressing the two rear shifts. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/base_device.dart | 19 +++ test/bluetooth/front_shift_combo_test.dart | 132 +++++++++++++++++++++ 2 files changed, 151 insertions(+) create mode 100644 test/bluetooth/front_shift_combo_test.dart diff --git a/lib/bluetooth/devices/base_device.dart b/lib/bluetooth/devices/base_device.dart index fdab05e9..95933473 100644 --- a/lib/bluetooth/devices/base_device.dart +++ b/lib/bluetooth/devices/base_device.dart @@ -123,6 +123,7 @@ abstract class BaseDevice { _activeLongPressButtons.clear(); } _previouslyPressedButtons = buttonsClicked.toSet(); + if (await _maybeHandleFrontShiftCombo(buttonsClicked)) return; await performClick(buttonsClicked, trigger: ButtonTrigger.singleClick); return; } @@ -574,6 +575,24 @@ abstract class BaseDevice { return button; } + /// If [buttons] resolve to exactly {shiftUp, shiftDown} and the front-shift + /// combo is enabled, emit a single frontShift and suppress the rear shifts. + Future _maybeHandleFrontShiftCombo(List buttons) async { + if (!core.actionHandler.frontShiftComboEnabled) return false; + if (buttons.length < 2) return false; + final actions = buttons + .map((b) => core.actionHandler.supportedApp?.keymap + .getKeyPair(b, trigger: ButtonTrigger.singleClick) + ?.inGameAction) + .toSet(); + if (actions.contains(InGameAction.shiftUp) && actions.contains(InGameAction.shiftDown)) { + final result = await core.actionHandler.performInGameAction(InGameAction.frontShift); + actionStreamInternal.add(ActionNotification(result)); + return true; + } + return false; + } + void _showCommandLimitAlert() { actionStreamInternal.add( AlertNotification( diff --git a/test/bluetooth/front_shift_combo_test.dart b/test/bluetooth/front_shift_combo_test.dart new file mode 100644 index 00000000..03b7f288 --- /dev/null +++ b/test/bluetooth/front_shift_combo_test.dart @@ -0,0 +1,132 @@ +import 'package:bike_control/bluetooth/devices/zwift/constants.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_ride.dart'; +import 'package:bike_control/bluetooth/messages/notification.dart'; +import 'package:bike_control/utils/actions/base_actions.dart'; +import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/keymap/apps/zwift.dart'; +import 'package:bike_control/utils/keymap/buttons.dart'; +import 'package:bike_control/utils/keymap/keymap.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:prop/prop.dart' hide RideButtonMask; + +import '../integration/harness/fake_ble_platform.dart'; +import '../integration/harness/fake_peripherals.dart'; +import '../integration/harness/test_env.dart'; + +/// Test-local StubActions subclass that exposes the combo hooks with full +/// control over [frontShiftComboEnabled], without touching the shared +/// [StubActions] (so other tests are unaffected). +class _ComboStubActions extends StubActions { + bool comboEnabled = true; + final List inGameActionsPerformed = []; + + @override + bool get frontShiftComboEnabled => comboEnabled; + + @override + Future performInGameAction(InGameAction action) async { + inGameActionsPerformed.add(action); + return Success('stub', button: null); + } +} + +Future main() async { + final env = await IntegrationEnv.setUp(); + late _ComboStubActions comboActions; + + core.connection.initialize(); + + setUp(() async { + await env.resetState(); + comboActions = _ComboStubActions(); + comboActions.supportedApp = Zwift(); + core.actionHandler = comboActions; + }); + + tearDown(() async { + await env.resetConnection(); + }); + + Future<(FakePeripheral, ZwiftRide)> connectRide() async { + final ride = buildZwiftRide(); + autoRespondToZwiftHandshake(env.ble, ride, startResponse: ZwiftConstants.RESPONSE_START_PLAY); + env.ble.addPeripheral(ride); + await core.connection.performScanning(); + await IntegrationEnv.waitFor( + () => core.connection.devices.whereType().isNotEmpty, + description: 'Zwift Ride in device list', + ); + final device = core.connection.devices.whereType().first; + await IntegrationEnv.waitFor(() => ride.writes.isNotEmpty, description: 'Zwift Ride handshake'); + return (ride, device); + } + + group('same-frame both-shifters combo', () { + test('combo enabled: single Ride frame with both shift buttons emits frontShift and suppresses rear shifts', + () async { + final (ride, _) = await connectRide(); + + // shiftUpRight → InGameAction.shiftUp; shiftUpLeft → InGameAction.shiftDown + // One frame containing both = same-frame combo → should fire frontShift only. + env.ble.notify( + ride.deviceId, + ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + zwiftRideNotification(pressed: [RideButtonMask.SHFT_UP_R_BTN, RideButtonMask.SHFT_UP_L_BTN]), + ); + // Release frame + env.ble.notify( + ride.deviceId, + ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + zwiftRideNotification(), + ); + + await IntegrationEnv.waitFor( + () => comboActions.inGameActionsPerformed.isNotEmpty, + description: 'frontShift in-game action', + ); + + expect(comboActions.inGameActionsPerformed, [InGameAction.frontShift]); + + // The rear shifts must be suppressed — performedActions should be empty + // (the combo returns early before performClick is reached). + await Future.delayed(const Duration(milliseconds: 100)); + expect( + comboActions.performedActions.where( + (a) => a.button == ZwiftButtons.shiftUpRight || a.button == ZwiftButtons.shiftUpLeft, + ), + isEmpty, + reason: 'rear shifts must be suppressed when combo fires', + ); + }); + + test('combo disabled: same frame fires both rear shifts normally and no frontShift', () async { + comboActions.comboEnabled = false; + + final (ride, _) = await connectRide(); + + env.ble.notify( + ride.deviceId, + ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + zwiftRideNotification(pressed: [RideButtonMask.SHFT_UP_R_BTN, RideButtonMask.SHFT_UP_L_BTN]), + ); + env.ble.notify( + ride.deviceId, + ZwiftConstants.ZWIFT_ASYNC_CHARACTERISTIC_UUID, + zwiftRideNotification(), + ); + + await IntegrationEnv.waitFor( + () => comboActions.performedActions.length >= 2, + description: 'both shift buttons performed', + ); + await Future.delayed(const Duration(milliseconds: 100)); + + expect( + comboActions.performedActions.map((a) => a.button).toSet(), + containsAll([ZwiftButtons.shiftUpRight, ZwiftButtons.shiftUpLeft]), + reason: 'both rear shifts should fire when combo is disabled', + ); + expect(comboActions.inGameActionsPerformed, isEmpty, reason: 'no frontShift when combo is disabled'); + }); + }); +} From cda77d1fd38e631d7658a85bae228ad0cd99c192 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:43:47 +0200 Subject: [PATCH 038/106] feat(6.2): add Record Screen editor card and recording indicator Co-Authored-By: Claude Sonnet 4.6 --- lib/pages/button_edit.dart | 24 ++++++++++++++++++++++++ lib/pages/overview.dart | 15 +++++++++++++++ 2 files changed, 39 insertions(+) diff --git a/lib/pages/button_edit.dart b/lib/pages/button_edit.dart index 3fa124ab..e7c4b96e 100644 --- a/lib/pages/button_edit.dart +++ b/lib/pages/button_edit.dart @@ -614,6 +614,30 @@ class _ButtonEditPageState extends State { ), ], + if (!kIsWeb) ...[ + SizedBox(height: 8), + ColoredTitle(text: context.i18n.deviceActions), + SelectableCard( + icon: LucideIcons.video, + title: Text(context.i18n.actionScreenRecording), + isActive: _keyPair.inGameAction == InGameAction.screenRecording, + onPressed: () { + _keyPair.inGameAction = InGameAction.screenRecording; + _keyPair.inGameActionValue = null; + _keyPair.physicalKey = null; + _keyPair.logicalKey = null; + _keyPair.modifiers = []; + _keyPair.touchPosition = Offset.zero; + _keyPair.androidAction = null; + _keyPair.androidIntentAction = null; + _keyPair.command = null; + _keyPair.screenshotPath = null; + setState(() {}); + widget.onUpdate(); + }, + ), + ], + if (core.connection.accessories.isNotEmpty) ...[ SizedBox(height: 8), ColoredTitle(text: context.i18n.accessoryActions), diff --git a/lib/pages/overview.dart b/lib/pages/overview.dart index 11346e26..d331e42c 100644 --- a/lib/pages/overview.dart +++ b/lib/pages/overview.dart @@ -10,6 +10,7 @@ import 'package:bike_control/pages/proxy.dart'; import 'package:bike_control/pages/subscription.dart'; import 'package:bike_control/pages/trainer_connection_settings.dart'; import 'package:bike_control/services/blog_service.dart'; +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/utils/core.dart'; import 'package:bike_control/utils/i18n_extension.dart'; @@ -350,6 +351,20 @@ class _OverviewPageState extends State with TickerProviderStateMix Expanded( child: _buildSectionHeader(icon: Icons.gamepad, title: AppLocalizations.of(context).controllers), ), + ValueListenableBuilder( + valueListenable: core.screenRecording.state, + builder: (context, state, _) { + if (state != ScreenRecordingState.recording) return const SizedBox.shrink(); + return Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.fiber_manual_record, color: Colors.red, size: 12), + const SizedBox(width: 4), + Text(context.i18n.screenRecordingStarted).xSmall.muted, + ], + ); + }, + ), if (core.settings.getIgnoredDevices().isNotEmpty) Button.text( style: ButtonStyle.menu(), From 825d70b07e1483a8b8b6ba0d8b57ce2a48cdd401 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:49:19 +0200 Subject: [PATCH 039/106] feat: front-shift config UI (enable + chainring teeth) Add SRAM-style front-shift card to gear-ratios editor: enable toggle bound to frontShiftEnabled, small/large chainring StepperControls clamped to ShiftingConfig constants, derived ratio helper text. Persists via _updateActive copyWith. Localized in all six ARBs (en/de/es/fr/it/pl). Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/i10n/intl_de.arb | 6 +- lib/i10n/intl_en.arb | 6 +- lib/i10n/intl_es.arb | 6 +- lib/i10n/intl_fr.arb | 6 +- lib/i10n/intl_it.arb | 6 +- lib/i10n/intl_pl.arb | 6 +- .../gear_ratios_editor_page.dart | 76 +++++++++++++++++++ 7 files changed, 106 insertions(+), 6 deletions(-) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 1452a2f4..0bce81a0 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -993,5 +993,9 @@ "vsIntroFeedbackTitle": "Wir helfen dir gerne", "vsIntroFeedbackBody": "Wir freuen uns über dein Feedback und helfen dir jederzeit, deine Einrichtung perfekt abzustimmen.", "vsIntroSupportedTrainersCta": "Unterstützte Trainer ansehen", - "vsIntroGotIt": "Verstanden" + "vsIntroGotIt": "Verstanden", + "frontShiftEnableLabel": "SRAM-Frontschalter", + "frontShiftEnableDesc": "Simuliert das vordere Kettenblatt eines 2×-Antriebs", + "frontShiftSmallRingLabel": "Kleines Kettenblatt (Zähne)", + "frontShiftLargeRingLabel": "Großes Kettenblatt (Zähne)" } diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 9494f005..d5550a4a 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -1160,5 +1160,9 @@ "vsIntroFeedbackTitle": "We've got your back", "vsIntroFeedbackBody": "We love your feedback and are always happy to help get your setup dialed in just right.", "vsIntroSupportedTrainersCta": "See supported trainers", - "vsIntroGotIt": "Got it" + "vsIntroGotIt": "Got it", + "frontShiftEnableLabel": "SRAM-style front shift", + "frontShiftEnableDesc": "Simulates 2× drivetrain front chainring switching", + "frontShiftSmallRingLabel": "Small chainring (teeth)", + "frontShiftLargeRingLabel": "Large chainring (teeth)" } diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 1e2c78ed..27451ecd 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -993,5 +993,9 @@ "vsIntroFeedbackTitle": "Estamos aquí para ayudarte", "vsIntroFeedbackBody": "Nos encantan tus comentarios y siempre estaremos encantados de ayudarte a dejar tu configuración perfecta.", "vsIntroSupportedTrainersCta": "Ver Smart Trainers compatibles", - "vsIntroGotIt": "Entendido" + "vsIntroGotIt": "Entendido", + "frontShiftEnableLabel": "Cambio frontal estilo SRAM", + "frontShiftEnableDesc": "Simula el cambio de plato delantero en una transmisión 2×", + "frontShiftSmallRingLabel": "Plato pequeño (dientes)", + "frontShiftLargeRingLabel": "Plato grande (dientes)" } diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 9eeac46a..44c519e9 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -994,5 +994,9 @@ "vsIntroFeedbackTitle": "Nous sommes là pour vous", "vsIntroFeedbackBody": "Vos retours nous tiennent à cœur et nous sommes toujours ravis de vous aider à régler votre configuration aux petits oignons.", "vsIntroSupportedTrainersCta": "Voir les Smart Trainers compatibles", - "vsIntroGotIt": "J'ai compris" + "vsIntroGotIt": "J'ai compris", + "frontShiftEnableLabel": "Changement frontal style SRAM", + "frontShiftEnableDesc": "Simule le changement de plateau avant sur un groupe 2×", + "frontShiftSmallRingLabel": "Petit plateau (dents)", + "frontShiftLargeRingLabel": "Grand plateau (dents)" } diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 7bfbe6a0..1101b140 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -993,5 +993,9 @@ "vsIntroFeedbackTitle": "Siamo al tuo fianco", "vsIntroFeedbackBody": "Adoriamo i tuoi feedback e siamo sempre felici di aiutarti a configurare tutto al meglio.", "vsIntroSupportedTrainersCta": "Vedi gli Smart Trainer supportati", - "vsIntroGotIt": "Ho capito" + "vsIntroGotIt": "Ho capito", + "frontShiftEnableLabel": "Cambio frontale stile SRAM", + "frontShiftEnableDesc": "Simula il cambio della corona anteriore su un gruppo 2×", + "frontShiftSmallRingLabel": "Corona piccola (denti)", + "frontShiftLargeRingLabel": "Corona grande (denti)" } diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 4043aeca..bfd2e431 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -993,5 +993,9 @@ "vsIntroFeedbackTitle": "Jesteśmy do Twojej dyspozycji", "vsIntroFeedbackBody": "Uwielbiamy Twoją opinię i zawsze chętnie pomożemy idealnie skonfigurować Twój sprzęt.", "vsIntroSupportedTrainersCta": "Zobacz obsługiwane trenażery", - "vsIntroGotIt": "Rozumiem" + "vsIntroGotIt": "Rozumiem", + "frontShiftEnableLabel": "Przedni przerzutnik w stylu SRAM", + "frontShiftEnableDesc": "Symuluje zmianę tarczy przedniej w napędzie 2×", + "frontShiftSmallRingLabel": "Mała tarcza (zęby)", + "frontShiftLargeRingLabel": "Duża tarcza (zęby)" } diff --git a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart index 49b1e105..b5e41e08 100644 --- a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart +++ b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart @@ -113,6 +113,7 @@ class _GearRatiosEditorPageState extends State { _vsModeCard(), _gradeSmoothingCard(context), _cadenceFilterCard(context), + _frontShiftCard(context), ], _gearCountCard(context), _heroCurve(context), @@ -271,6 +272,81 @@ class _GearRatiosEditorPageState extends State { ); } + Widget _frontShiftCard(BuildContext context) { + final config = core.shiftingConfigs.activeFor(widget.device.trainerKey); + final enabled = config.frontShiftEnabled; + final small = config.smallChainringTeeth; + final large = config.largeChainringTeeth; + final factor = large / small; + final cs = Theme.of(context).colorScheme; + return SettingTile( + icon: LucideIcons.bike, + title: AppLocalizations.of(context).frontShiftEnableLabel, + subtitle: AppLocalizations.of(context).frontShiftEnableDesc, + trailing: Switch( + value: enabled, + onChanged: (v) async { + await _updateActive((c) => c.copyWith(frontShiftEnabled: v)); + }, + ), + child: enabled + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 12, + children: [ + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of(context).frontShiftSmallRingLabel, + style: const TextStyle(fontSize: 13), + ), + ), + StepperControl( + value: small.toDouble(), + step: 1.0, + min: ShiftingConfig.chainringTeethMin.toDouble(), + max: ShiftingConfig.chainringTeethMax.toDouble(), + format: (v) => v.toStringAsFixed(0), + onChanged: (v) async { + final next = v.toInt(); + await _updateActive((c) => c.copyWith(smallChainringTeeth: next)); + }, + ), + ], + ), + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of(context).frontShiftLargeRingLabel, + style: const TextStyle(fontSize: 13), + ), + ), + StepperControl( + value: large.toDouble(), + step: 1.0, + min: small.toDouble(), + max: ShiftingConfig.chainringTeethMax.toDouble(), + format: (v) => v.toStringAsFixed(0), + onChanged: (v) async { + final next = v.toInt(); + await _updateActive((c) => c.copyWith(largeChainringTeeth: next)); + }, + ), + ], + ), + Text( + '${factor.toStringAsFixed(2)}×', + style: TextStyle(fontSize: 12, color: cs.mutedForeground), + textAlign: TextAlign.end, + ), + ], + ) + : null, + ); + } + // ---------- Presets ---------- static List _evenSteps(double lo, double hi, int count) => From 48fbb4726388539d7a919f8ebfa039d7c9c3feae Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:51:58 +0200 Subject: [PATCH 040/106] feat(6.2): Android screen recording backend (MediaProjection + gallery save) --- android/app/src/main/AndroidManifest.xml | 2 + .../backends/android_screen_recorder.dart | 51 +++++++++++++++++++ .../screen_recording_service.dart | 3 +- 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 lib/services/screen_recording/backends/android_screen_recorder.dart diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 1e740d6d..c117eda3 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -28,6 +28,8 @@ + + diff --git a/lib/services/screen_recording/backends/android_screen_recorder.dart b/lib/services/screen_recording/backends/android_screen_recorder.dart new file mode 100644 index 00000000..bc7a67e9 --- /dev/null +++ b/lib/services/screen_recording/backends/android_screen_recorder.dart @@ -0,0 +1,51 @@ +import 'dart:io'; + +import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; +import 'package:flutter/foundation.dart'; +import 'package:flutter_screen_recording/flutter_screen_recording.dart'; +import 'package:gal/gal.dart'; + +/// Android backend: system-wide MediaProjection capture via flutter_screen_recording, +/// then the resulting mp4 is copied into the device gallery via `gal`. +class AndroidScreenRecorder implements ScreenRecorderBackend { + @override + Future isAvailable() async => true; + + @override + Future ensurePermission() async { + // MediaProjection consent is requested by startRecordScreen itself. + // Gallery save needs gallery access on older Androids; request up front. + try { + if (await Gal.hasAccess(toAlbum: true)) return true; + return await Gal.requestAccess(toAlbum: true); + } catch (e, s) { + debugPrintStack(label: 'gal access: $e', stackTrace: s); + return true; // don't block recording if the gallery check itself failed + } + } + + @override + Future start() async { + try { + // Video only — use startRecordScreen (no audio variant). + final name = 'BikeControl_${DateTime.now().millisecondsSinceEpoch}'; + return await FlutterScreenRecording.startRecordScreen(name); + } catch (e, s) { + debugPrintStack(label: 'android startRecordScreen: $e', stackTrace: s); + return false; + } + } + + @override + Future stop() async { + try { + final path = await FlutterScreenRecording.stopRecordScreen; + if (path.isEmpty || !File(path).existsSync()) return null; + await Gal.putVideo(path, album: 'BikeControl'); + return path; + } catch (e, s) { + debugPrintStack(label: 'android stopRecordScreen/gal: $e', stackTrace: s); + return null; + } + } +} diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart index 6ea7b376..ba178e8b 100644 --- a/lib/services/screen_recording/screen_recording_service.dart +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -1,5 +1,6 @@ import 'dart:io'; +import 'package:bike_control/services/screen_recording/backends/android_screen_recorder.dart'; import 'package:bike_control/services/screen_recording/backends/native_channel_screen_recorder.dart'; import 'package:bike_control/services/screen_recording/backends/unsupported_screen_recorder.dart'; import 'package:flutter/foundation.dart'; @@ -104,6 +105,6 @@ ScreenRecorderBackend createScreenRecorderBackend() { if (Platform.isIOS || Platform.isMacOS || Platform.isWindows) { return NativeChannelScreenRecorder(); } - // Android backend added later; Linux unsupported. + if (Platform.isAndroid) return AndroidScreenRecorder(); return UnsupportedScreenRecorder(); } From 4a657ac89f1185896a3eb12c0758003dfbd11cea Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:52:56 +0200 Subject: [PATCH 041/106] feat: show active front chainring on gear hero card Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/pages/proxy_device_details/gear_hero_card.dart | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/pages/proxy_device_details/gear_hero_card.dart b/lib/pages/proxy_device_details/gear_hero_card.dart index 9c21dff2..87d705bc 100644 --- a/lib/pages/proxy_device_details/gear_hero_card.dart +++ b/lib/pages/proxy_device_details/gear_hero_card.dart @@ -47,6 +47,7 @@ class _GearHeroCardState extends State { widget.definition.targetPowerW, widget.definition.currentGear, widget.definition.gearRatio, + widget.definition.frontRing, ]), builder: (context, _) { final isErg = widget.definition.trainerMode.value == TrainerMode.ergMode; @@ -172,6 +173,13 @@ class _GearHeroCardState extends State { color: cs.mutedForeground, ), ), + if (widget.definition.frontShiftEnabled) + Text( + widget.definition.frontRing.value == FrontRing.large + ? '${widget.definition.largeChainringTeeth}T' + : '${widget.definition.smallChainringTeeth}T', + style: TextStyle(fontSize: 13, color: cs.mutedForeground), + ), ], ); } From 985dc7c53ba09c278499f4d3db43479f463dc180 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:55:37 +0200 Subject: [PATCH 042/106] docs: changelog for SRAM-style front shifting Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cca557dd..8b23f0c8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,7 @@ +### 6.2.0 (24-06-2026) +**Features**: +- SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Pressing both shift buttons at once also triggers it (Zwift Ride and Click; Zwift Play via a short simultaneous-press window). Set your chainring sizes per trainer in the gear settings. + ### 6.1.0 (19-06-2026) **Features**: - WiFi enabled Smart Trainers are now supported From 53faca8ebd39842238a358bd7581b8c68499804c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:55:38 +0200 Subject: [PATCH 043/106] Bump prop submodule: front chainring toggle Co-Authored-By: Claude Opus 4.8 (1M context) --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index 61b5c934..45ed0b97 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 61b5c9342fe68a2fb688643054b61dae204cf6c3 +Subproject commit 45ed0b97e4a85dd86e2fb04292bc8298e92dde5b From 08f084824edd502af975178508521e52ce985538 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:05:18 +0200 Subject: [PATCH 044/106] fix(6.2): screen_recorder plugin declares no native platforms yet (unblock macOS/Windows builds) + comment/semantics tidy Co-Authored-By: Claude Sonnet 4.6 --- .../screen_recording/screen_recording_service.dart | 8 ++++---- packages/screen_recorder/pubspec.yaml | 13 ++++++------- 2 files changed, 10 insertions(+), 11 deletions(-) diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart index ba178e8b..f8ab26ea 100644 --- a/lib/services/screen_recording/screen_recording_service.dart +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -79,7 +79,7 @@ class ScreenRecordingService { } catch (e, s) { _state.value = ScreenRecordingState.error; debugPrintStack(label: 'screen recording: $e', stackTrace: s); - return RecordingResult(ok: false, startedRecording: true, errorMessage: e.toString()); + return RecordingResult(ok: false, startedRecording: false, errorMessage: e.toString()); } } @@ -97,9 +97,9 @@ class ScreenRecordingService { } } -/// Selects the backend for the running platform. Android's real backend is -/// added in a later task; until then Android falls back to unsupported so the -/// app stays buildable. +/// Selects the screen-recording backend for the running platform: Android +/// (package-based), iOS/macOS/Windows (native channel — currently unsupported +/// until native code lands), web/Linux unsupported. ScreenRecorderBackend createScreenRecorderBackend() { if (kIsWeb) return UnsupportedScreenRecorder(); if (Platform.isIOS || Platform.isMacOS || Platform.isWindows) { diff --git a/packages/screen_recorder/pubspec.yaml b/packages/screen_recorder/pubspec.yaml index eddfa66a..02c1f2bb 100644 --- a/packages/screen_recorder/pubspec.yaml +++ b/packages/screen_recorder/pubspec.yaml @@ -17,11 +17,10 @@ dev_dependencies: flutter_lints: ^5.0.0 flutter: + # Native platform implementations (macos/windows/ios) are added in the + # follow-up native tasks; until then this is a Dart-only MethodChannel + # wrapper and `screen_recorder` calls throw MissingPluginException (caught + # by NativeChannelScreenRecorder → reported as "not supported"). Declaring + # platforms here without native code breaks macOS/Windows plugin registrants. plugin: - platforms: - ios: - pluginClass: ScreenRecorderPlugin - macos: - pluginClass: ScreenRecorderPlugin - windows: - pluginClass: ScreenRecorderPlugin + platforms: {} From f051c4c359d0514614b2ea28500c3b037a014463 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:12:27 +0200 Subject: [PATCH 045/106] chore(6.2): lock new deps + regenerate plugin registrants (gal; no screen_recorder native yet) --- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + pubspec.lock | 63 +++++++++++++++---- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 4 files changed, 57 insertions(+), 12 deletions(-) diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 3b3ce37c..68c2d6e0 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -15,6 +15,7 @@ import flutter_local_notifications import flutter_screen_capture import flutter_secure_storage_darwin import flutter_volume_controller +import gal import gamepads_darwin import google_sign_in_ios import in_app_purchase_storekit @@ -47,6 +48,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FlutterScreenCapturePlugin.register(with: registry.registrar(forPlugin: "FlutterScreenCapturePlugin")) FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) FlutterVolumeControllerPlugin.register(with: registry.registrar(forPlugin: "FlutterVolumeControllerPlugin")) + GalPlugin.register(with: registry.registrar(forPlugin: "GalPlugin")) GamepadsDarwinPlugin.register(with: registry.registrar(forPlugin: "GamepadsDarwinPlugin")) FLTGoogleSignInPlugin.register(with: registry.registrar(forPlugin: "FLTGoogleSignInPlugin")) InAppPurchasePlugin.register(with: registry.registrar(forPlugin: "InAppPurchasePlugin")) diff --git a/pubspec.lock b/pubspec.lock index 7d0680a9..c1e3831e 100755 --- a/pubspec.lock +++ b/pubspec.lock @@ -427,6 +427,14 @@ packages: description: flutter source: sdk version: "0.0.0" + flutter_foreground_task: + dependency: transitive + description: + name: flutter_foreground_task + sha256: fc5c01a5e1b8f7bb51d0c737714f0c50440dbdf1aeddc5f8cbba313aa6fd4856 + url: "https://pub.dev" + source: hosted + version: "9.2.2" flutter_lints: dependency: "direct dev" description: @@ -520,6 +528,30 @@ packages: url: "https://pub.dev" source: hosted version: "2.0.1" + flutter_screen_recording: + dependency: "direct main" + description: + name: flutter_screen_recording + sha256: "0fb52011aa11ac4dc3e89bea3aaee4a709321af374b3b318e74fa8ed8338412e" + url: "https://pub.dev" + source: hosted + version: "2.0.25" + flutter_screen_recording_platform_interface: + dependency: transitive + description: + name: flutter_screen_recording_platform_interface + sha256: "9e07f78a2529bc5b6c77d045b392ed4062445543613fcad431c4cc1da57558d7" + url: "https://pub.dev" + source: hosted + version: "1.0.3" + flutter_screen_recording_web: + dependency: transitive + description: + name: flutter_screen_recording_web + sha256: bb19b3875e0d8ddfe009ed42086339f8016df05e685c37ff06cb56e165f2f7fa + url: "https://pub.dev" + source: hosted + version: "1.0.8" flutter_secure_storage: dependency: "direct main" description: @@ -623,6 +655,14 @@ packages: url: "https://pub.dev" source: hosted version: "2.5.0" + gal: + dependency: "direct main" + description: + name: gal + sha256: "969598f986789127fd407a750413249e1352116d4c2be66e81837ffeeaafdfee" + url: "https://pub.dev" + source: hosted + version: "2.3.2" gamepads: dependency: "direct main" description: @@ -675,10 +715,10 @@ packages: dependency: transitive description: name: gamepads_web - sha256: bf198f958727cd2d96f19be8b8d49057c9eb6b3095728d794181362b740d69ac + sha256: "860eb4f11fdb6dfcf18f793a491282747007909075d161373df7f067dfddb9a4" url: "https://pub.dev" source: hosted - version: "0.1.1" + version: "0.1.1+1" gamepads_windows: dependency: transitive description: @@ -968,18 +1008,10 @@ packages: dependency: transitive description: name: js - sha256: f2c445dce49627136094980615a031419f7f3eb393237e4ecd97ac15dea343f3 - url: "https://pub.dev" - source: hosted - version: "0.6.7" - js_interop: - dependency: transitive - description: - name: js_interop - sha256: "7ec859c296958ccea34dc770504bd3ff4ae52fdd9e7eeb2bacc7081ad476a1f5" + sha256: "53385261521cc4a0c4658fd0ad07a7d14591cf8fc33abbceae306ddb974888dc" url: "https://pub.dev" source: hosted - version: "0.0.1" + version: "0.7.2" json_annotation: dependency: transitive description: @@ -1553,6 +1585,13 @@ packages: url: "https://pub.dev" source: hosted version: "0.28.0" + screen_recorder: + dependency: "direct main" + description: + path: "packages/screen_recorder" + relative: true + source: path + version: "0.0.1" screen_retriever: dependency: transitive description: diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index 3bd74bd9..c8e005eb 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -11,6 +11,7 @@ #include #include #include +#include #include #include #include @@ -35,6 +36,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("FlutterSecureStorageWindowsPlugin")); FlutterVolumeControllerPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("FlutterVolumeControllerPluginCApi")); + GalPluginCApiRegisterWithRegistrar( + registry->GetRegistrarForPlugin("GalPluginCApi")); GamepadsWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("GamepadsWindowsPluginCApi")); KeypressSimulatorWindowsPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index 8cff4d1a..f87a1ee4 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -8,6 +8,7 @@ list(APPEND FLUTTER_PLUGIN_LIST flutter_screen_capture flutter_secure_storage_windows flutter_volume_controller + gal gamepads_windows keypress_simulator_windows media_key_detector_windows From 91b63b8f627f36e053c5d3e9f2449498164df11f Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:28:09 +0200 Subject: [PATCH 046/106] feat(6.2): macOS screen recording backend (ScreenCaptureKit) Co-Authored-By: Claude Opus 4.8 (1M context) --- macos/Flutter/GeneratedPluginRegistrant.swift | 2 + macos/Podfile.lock | 6 ++ macos/Runner/DebugProfile.entitlements | 2 + macos/Runner/Release.entitlements | 2 + .../macos/Classes/ScreenCaptureRecorder.swift | 83 +++++++++++++++++++ .../macos/Classes/ScreenRecorderPlugin.swift | 38 +++++++++ .../macos/screen_recorder.podspec | 15 ++++ packages/screen_recorder/pubspec.yaml | 9 +- 8 files changed, 151 insertions(+), 6 deletions(-) create mode 100644 packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift create mode 100644 packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift create mode 100644 packages/screen_recorder/macos/screen_recorder.podspec diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 68c2d6e0..97b17c95 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -28,6 +28,7 @@ import nsd_macos import package_info_plus import path_provider_foundation import purchases_flutter +import screen_recorder import screen_retriever_macos import share_plus import shared_preferences_foundation @@ -61,6 +62,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) PathProviderPlugin.register(with: registry.registrar(forPlugin: "PathProviderPlugin")) PurchasesFlutterPlugin.register(with: registry.registrar(forPlugin: "PurchasesFlutterPlugin")) + ScreenRecorderPlugin.register(with: registry.registrar(forPlugin: "ScreenRecorderPlugin")) ScreenRetrieverMacosPlugin.register(with: registry.registrar(forPlugin: "ScreenRetrieverMacosPlugin")) SharePlusMacosPlugin.register(with: registry.registrar(forPlugin: "SharePlusMacosPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) diff --git a/macos/Podfile.lock b/macos/Podfile.lock index eb366a26..49f6c7d0 100644 --- a/macos/Podfile.lock +++ b/macos/Podfile.lock @@ -14,6 +14,8 @@ PODS: - FlutterMacOS - nsd_macos (0.0.1): - FlutterMacOS + - screen_recorder (0.0.1): + - FlutterMacOS - screen_retriever_macos (0.0.1): - FlutterMacOS - sign_in_with_apple (0.0.1): @@ -28,6 +30,7 @@ DEPENDENCIES: - media_key_detector_macos (from `Flutter/ephemeral/.symlinks/plugins/media_key_detector_macos/macos`) - multi_window_native (from `Flutter/ephemeral/.symlinks/plugins/multi_window_native/macos`) - nsd_macos (from `Flutter/ephemeral/.symlinks/plugins/nsd_macos/macos`) + - screen_recorder (from `Flutter/ephemeral/.symlinks/plugins/screen_recorder/macos`) - screen_retriever_macos (from `Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos`) - sign_in_with_apple (from `Flutter/ephemeral/.symlinks/plugins/sign_in_with_apple/macos`) @@ -48,6 +51,8 @@ EXTERNAL SOURCES: :path: Flutter/ephemeral/.symlinks/plugins/multi_window_native/macos nsd_macos: :path: Flutter/ephemeral/.symlinks/plugins/nsd_macos/macos + screen_recorder: + :path: Flutter/ephemeral/.symlinks/plugins/screen_recorder/macos screen_retriever_macos: :path: Flutter/ephemeral/.symlinks/plugins/screen_retriever_macos/macos sign_in_with_apple: @@ -62,6 +67,7 @@ SPEC CHECKSUMS: media_key_detector_macos: f2fecf51b0cc30d6e2e4605410ae5602ff067ed8 multi_window_native: 090b0376429681c0ea21fee77f0a33c437d36fed nsd_macos: a472240e770b92f6c6df1022403aa29c90d012e3 + screen_recorder: b1a6a675694fd381a2aa66c56360a08416d70224 screen_retriever_macos: 452e51764a9e1cdb74b3c541238795849f21557f sign_in_with_apple: 6673c03c9e3643f6c8d33601943fbfa9ae99f94e diff --git a/macos/Runner/DebugProfile.entitlements b/macos/Runner/DebugProfile.entitlements index 68caaa7c..3afc7c2e 100644 --- a/macos/Runner/DebugProfile.entitlements +++ b/macos/Runner/DebugProfile.entitlements @@ -18,6 +18,8 @@ com.apple.security.network.server + com.apple.security.assets.movies.read-write + keychain-access-groups $(AppIdentifierPrefix)com.google.GIDSignIn diff --git a/macos/Runner/Release.entitlements b/macos/Runner/Release.entitlements index c5ff71ce..991dbbc0 100755 --- a/macos/Runner/Release.entitlements +++ b/macos/Runner/Release.entitlements @@ -18,6 +18,8 @@ com.apple.security.network.server + com.apple.security.assets.movies.read-write + keychain-access-groups $(AppIdentifierPrefix)com.google.GIDSignIn diff --git a/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift new file mode 100644 index 00000000..4f4065c4 --- /dev/null +++ b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift @@ -0,0 +1,83 @@ +import Foundation +import AVFoundation +import CoreGraphics +@preconcurrency import ScreenCaptureKit + +/// Records the main display to an mp4 using ScreenCaptureKit + AVAssetWriter. +@available(macOS 12.3, *) +final class ScreenCaptureRecorder: NSObject, SCStreamOutput { + private var stream: SCStream? + private var writer: AVAssetWriter? + private var videoInput: AVAssetWriterInput? + private var sessionStarted = false + private var outputURL: URL? + + func start() async throws { + let content = try await SCShareableContent.excludingDesktopWindows(false, onScreenWindowsOnly: false) + guard let display = content.displays.first else { + throw NSError(domain: "screen_recorder", code: 1, userInfo: [NSLocalizedDescriptionKey: "No display"]) + } + + let dir = FileManager.default.homeDirectoryForCurrentUser + .appendingPathComponent("Movies/BikeControl", isDirectory: true) + try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) + let url = dir.appendingPathComponent("BikeControl_\(Int(Date().timeIntervalSince1970)).mp4") + self.outputURL = url + + let writer = try AVAssetWriter(outputURL: url, fileType: .mp4) + let settings: [String: Any] = [ + AVVideoCodecKey: AVVideoCodecType.h264, + AVVideoWidthKey: display.width, + AVVideoHeightKey: display.height, + ] + let input = AVAssetWriterInput(mediaType: .video, outputSettings: settings) + input.expectsMediaDataInRealTime = true + writer.add(input) + self.writer = writer + self.videoInput = input + + let filter = SCContentFilter(display: display, excludingWindows: []) + let config = SCStreamConfiguration() + config.width = display.width + config.height = display.height + config.minimumFrameInterval = CMTime(value: 1, timescale: 30) + config.queueDepth = 5 + config.pixelFormat = kCVPixelFormatType_32BGRA + + let stream = SCStream(filter: filter, configuration: config, delegate: nil) + try stream.addStreamOutput(self, type: .screen, sampleHandlerQueue: DispatchQueue(label: "screen_recorder.capture")) + self.stream = stream + writer.startWriting() + try await stream.startCapture() + } + + func stop() async -> String? { + guard let stream = stream else { return nil } + try? await stream.stopCapture() + self.stream = nil + videoInput?.markAsFinished() + await writer?.finishWriting() + let path = outputURL?.path + writer = nil + videoInput = nil + sessionStarted = false + return path + } + + // SCStreamOutput + func stream(_ stream: SCStream, didOutputSampleBuffer sampleBuffer: CMSampleBuffer, of type: SCStreamOutputType) { + guard type == .screen, sampleBuffer.isValid, + let writer = writer, let input = videoInput else { return } + guard let attachments = CMSampleBufferGetSampleAttachmentsArray(sampleBuffer, createIfNecessary: false) as? [[SCStreamFrameInfo: Any]], + let statusRaw = attachments.first?[.status] as? Int, + let status = SCFrameStatus(rawValue: statusRaw), status == .complete else { return } + + if !sessionStarted { + writer.startSession(atSourceTime: CMSampleBufferGetPresentationTimeStamp(sampleBuffer)) + sessionStarted = true + } + if input.isReadyForMoreMediaData { + input.append(sampleBuffer) + } + } +} diff --git a/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift new file mode 100644 index 00000000..2a91cc2b --- /dev/null +++ b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift @@ -0,0 +1,38 @@ +import Cocoa +import FlutterMacOS +import CoreGraphics + +public class ScreenRecorderPlugin: NSObject, FlutterPlugin { + private var recorder: AnyObject? + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "screen_recorder", binaryMessenger: registrar.messenger) + registrar.addMethodCallDelegate(ScreenRecorderPlugin(), channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "isSupported": + if #available(macOS 12.3, *) { result(true) } else { result(false) } + case "hasPermission": + result(CGPreflightScreenCaptureAccess()) + case "requestPermission": + result(CGRequestScreenCaptureAccess()) + case "start": + if #available(macOS 12.3, *) { + let rec = ScreenCaptureRecorder() + self.recorder = rec + Task { + do { try await rec.start(); result(true) } + catch { NSLog("screen_recorder start error: \(error)"); result(false) } + } + } else { result(false) } + case "stop": + if #available(macOS 12.3, *), let rec = self.recorder as? ScreenCaptureRecorder { + Task { let path = await rec.stop(); self.recorder = nil; result(path) } + } else { result(nil) } + default: + result(FlutterMethodNotImplemented) + } + } +} diff --git a/packages/screen_recorder/macos/screen_recorder.podspec b/packages/screen_recorder/macos/screen_recorder.podspec new file mode 100644 index 00000000..fc847ab8 --- /dev/null +++ b/packages/screen_recorder/macos/screen_recorder.podspec @@ -0,0 +1,15 @@ +Pod::Spec.new do |s| + s.name = 'screen_recorder' + s.version = '0.0.1' + s.summary = 'In-repo screen recorder.' + s.description = 'macOS ScreenCaptureKit screen recording.' + s.homepage = 'https://bikecontrol.app' + s.license = { :type => 'Proprietary' } + s.author = { 'BikeControl' => 'jonas@bikecontrol.app' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'FlutterMacOS' + s.platform = :osx, '12.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/packages/screen_recorder/pubspec.yaml b/packages/screen_recorder/pubspec.yaml index 02c1f2bb..8c321138 100644 --- a/packages/screen_recorder/pubspec.yaml +++ b/packages/screen_recorder/pubspec.yaml @@ -17,10 +17,7 @@ dev_dependencies: flutter_lints: ^5.0.0 flutter: - # Native platform implementations (macos/windows/ios) are added in the - # follow-up native tasks; until then this is a Dart-only MethodChannel - # wrapper and `screen_recorder` calls throw MissingPluginException (caught - # by NativeChannelScreenRecorder → reported as "not supported"). Declaring - # platforms here without native code breaks macOS/Windows plugin registrants. plugin: - platforms: {} + platforms: + macos: + pluginClass: ScreenRecorderPlugin From 5f8fdf860f877a198bf7157fed2b7d15365d3e9b Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:33:11 +0200 Subject: [PATCH 047/106] fix(6.2): macOS capture robustness (native-res, finalize check, main-thread result, double-start guard, stream errors) Co-Authored-By: Claude Opus 4.8 (1M context) --- .../macos/Classes/ScreenCaptureRecorder.swift | 65 ++++++++++++++++--- .../macos/Classes/ScreenRecorderPlugin.swift | 19 +++++- 2 files changed, 73 insertions(+), 11 deletions(-) diff --git a/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift index 4f4065c4..9c992ab0 100644 --- a/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift +++ b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift @@ -5,7 +5,7 @@ import CoreGraphics /// Records the main display to an mp4 using ScreenCaptureKit + AVAssetWriter. @available(macOS 12.3, *) -final class ScreenCaptureRecorder: NSObject, SCStreamOutput { +final class ScreenCaptureRecorder: NSObject, SCStreamOutput, SCStreamDelegate { private var stream: SCStream? private var writer: AVAssetWriter? private var videoInput: AVAssetWriterInput? @@ -18,6 +18,13 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput { throw NSError(domain: "screen_recorder", code: 1, userInfo: [NSLocalizedDescriptionKey: "No display"]) } + // Fix 1 (Retina): capture at native pixels using scaleFactor. + // TODO: scaleFactor — SCDisplay does not expose scaleFactor in this SDK version; + // use display.width/height (points) for now. On Retina displays this may capture + // at logical resolution rather than native pixel resolution. + let pixelWidth = display.width + let pixelHeight = display.height + let dir = FileManager.default.homeDirectoryForCurrentUser .appendingPathComponent("Movies/BikeControl", isDirectory: true) try FileManager.default.createDirectory(at: dir, withIntermediateDirectories: true) @@ -27,8 +34,8 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput { let writer = try AVAssetWriter(outputURL: url, fileType: .mp4) let settings: [String: Any] = [ AVVideoCodecKey: AVVideoCodecType.h264, - AVVideoWidthKey: display.width, - AVVideoHeightKey: display.height, + AVVideoWidthKey: pixelWidth, + AVVideoHeightKey: pixelHeight, ] let input = AVAssetWriterInput(mediaType: .video, outputSettings: settings) input.expectsMediaDataInRealTime = true @@ -38,26 +45,63 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput { let filter = SCContentFilter(display: display, excludingWindows: []) let config = SCStreamConfiguration() - config.width = display.width - config.height = display.height + // Fix 1 (Retina): set stream dimensions to native pixel dimensions + config.width = pixelWidth + config.height = pixelHeight config.minimumFrameInterval = CMTime(value: 1, timescale: 30) config.queueDepth = 5 config.pixelFormat = kCVPixelFormatType_32BGRA - let stream = SCStream(filter: filter, configuration: config, delegate: nil) + // Fix 5 (stream errors): pass self as delegate to observe mid-session failures + let stream = SCStream(filter: filter, configuration: config, delegate: self) try stream.addStreamOutput(self, type: .screen, sampleHandlerQueue: DispatchQueue(label: "screen_recorder.capture")) self.stream = stream - writer.startWriting() + + // Fix 3 (cleanup on throw): cancel writer if start() throws after writer creation + var started = false + defer { + if !started { + writer.cancelWriting() + self.writer = nil + self.videoInput = nil + self.stream = nil + } + } + + // Fix 2 (startWriting): guard the Bool return value + guard writer.startWriting() else { + throw writer.error ?? NSError(domain: "screen_recorder", code: 2, userInfo: [NSLocalizedDescriptionKey: "AVAssetWriter failed to start"]) + } + try await stream.startCapture() + started = true } func stop() async -> String? { guard let stream = stream else { return nil } + + // Fix 4 (stop-before-first-frame): cancel instead of finalize if no frames were written + if !sessionStarted { + try? await stream.stopCapture() + self.stream = nil + writer?.cancelWriting() + writer = nil + videoInput = nil + return nil + } + try? await stream.stopCapture() self.stream = nil videoInput?.markAsFinished() await writer?.finishWriting() - let path = outputURL?.path + + // Fix 4 (stop finalize): only return path if finalization succeeded + let status = writer?.status + let path = status == .completed ? outputURL?.path : nil + if status != .completed { + NSLog("screen_recorder: finishWriting status=\(String(describing: status)) err=\(String(describing: writer?.error))") + } + writer = nil videoInput = nil sessionStarted = false @@ -80,4 +124,9 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput { input.append(sampleBuffer) } } + + // Fix 5 (stream errors): SCStreamDelegate — log mid-session stream errors + func stream(_ stream: SCStream, didStopWithError error: Error) { + NSLog("screen_recorder: SCStream stopped with error: \(error)") + } } diff --git a/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift index 2a91cc2b..b3c3965e 100644 --- a/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift +++ b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift @@ -20,16 +20,29 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { result(CGRequestScreenCaptureAccess()) case "start": if #available(macOS 12.3, *) { + // Fix 6 (double-start leak): guard against starting a second recorder + guard self.recorder == nil else { result(false); return } let rec = ScreenCaptureRecorder() self.recorder = rec Task { - do { try await rec.start(); result(true) } - catch { NSLog("screen_recorder start error: \(error)"); result(false) } + do { + try await rec.start() + // Fix 7 (main thread): call FlutterResult on the main thread + DispatchQueue.main.async { result(true) } + } catch { + NSLog("screen_recorder start error: \(error)") + DispatchQueue.main.async { result(false) } + } } } else { result(false) } case "stop": if #available(macOS 12.3, *), let rec = self.recorder as? ScreenCaptureRecorder { - Task { let path = await rec.stop(); self.recorder = nil; result(path) } + Task { + let path = await rec.stop() + self.recorder = nil + // Fix 7 (main thread): call FlutterResult on the main thread + DispatchQueue.main.async { result(path) } + } } else { result(nil) } default: result(FlutterMethodNotImplemented) From c17be4c9628d1790f1fa3ec6b0ea6cb56816d318 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:35:38 +0200 Subject: [PATCH 048/106] fix(6.2): macOS capture at native (Retina) pixel resolution via CGDisplayMode --- .../macos/Classes/ScreenCaptureRecorder.swift | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift index 9c992ab0..faa8771c 100644 --- a/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift +++ b/packages/screen_recorder/macos/Classes/ScreenCaptureRecorder.swift @@ -18,12 +18,10 @@ final class ScreenCaptureRecorder: NSObject, SCStreamOutput, SCStreamDelegate { throw NSError(domain: "screen_recorder", code: 1, userInfo: [NSLocalizedDescriptionKey: "No display"]) } - // Fix 1 (Retina): capture at native pixels using scaleFactor. - // TODO: scaleFactor — SCDisplay does not expose scaleFactor in this SDK version; - // use display.width/height (points) for now. On Retina displays this may capture - // at logical resolution rather than native pixel resolution. - let pixelWidth = display.width - let pixelHeight = display.height + // Fix 1 (Retina): capture at native pixels via CGDisplayMode. + let mode = CGDisplayCopyDisplayMode(display.displayID) + let pixelWidth = mode?.pixelWidth ?? display.width + let pixelHeight = mode?.pixelHeight ?? display.height let dir = FileManager.default.homeDirectoryForCurrentUser .appendingPathComponent("Movies/BikeControl", isDirectory: true) From 43723f86ab040b1cac895777e3765c18f0e993a6 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:42:15 +0200 Subject: [PATCH 049/106] =?UTF-8?q?feat(6.2):=20Windows=20screen=20recordi?= =?UTF-8?q?ng=20backend=20(WGC=20+=20Media=20Foundation)=20[UNVERIFIED=20?= =?UTF-8?q?=E2=80=94=20needs=20Windows=20build]?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-Authored-By: Claude Sonnet 4.6 --- packages/screen_recorder/pubspec.yaml | 2 + .../screen_recorder/windows/CMakeLists.txt | 20 ++ .../windows/capture_recorder.cpp | 308 ++++++++++++++++++ .../windows/capture_recorder.h | 19 ++ .../screen_recorder/screen_recorder_plugin.h | 23 ++ .../screen_recorder_plugin_c_api.h | 17 + .../windows/screen_recorder_plugin.cpp | 48 +++ .../windows/screen_recorder_plugin.h | 20 ++ .../windows/screen_recorder_plugin_c_api.cpp | 19 ++ pubspec.yaml | 2 +- .../flutter/generated_plugin_registrant.cc | 3 + windows/flutter/generated_plugins.cmake | 1 + 12 files changed, 481 insertions(+), 1 deletion(-) create mode 100644 packages/screen_recorder/windows/CMakeLists.txt create mode 100644 packages/screen_recorder/windows/capture_recorder.cpp create mode 100644 packages/screen_recorder/windows/capture_recorder.h create mode 100644 packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin.h create mode 100644 packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin_c_api.h create mode 100644 packages/screen_recorder/windows/screen_recorder_plugin.cpp create mode 100644 packages/screen_recorder/windows/screen_recorder_plugin.h create mode 100644 packages/screen_recorder/windows/screen_recorder_plugin_c_api.cpp diff --git a/packages/screen_recorder/pubspec.yaml b/packages/screen_recorder/pubspec.yaml index 8c321138..09c37f99 100644 --- a/packages/screen_recorder/pubspec.yaml +++ b/packages/screen_recorder/pubspec.yaml @@ -21,3 +21,5 @@ flutter: platforms: macos: pluginClass: ScreenRecorderPlugin + windows: + pluginClass: ScreenRecorderPlugin diff --git a/packages/screen_recorder/windows/CMakeLists.txt b/packages/screen_recorder/windows/CMakeLists.txt new file mode 100644 index 00000000..23e1e4aa --- /dev/null +++ b/packages/screen_recorder/windows/CMakeLists.txt @@ -0,0 +1,20 @@ +cmake_minimum_required(VERSION 3.14) +set(PROJECT_NAME "screen_recorder") +project(${PROJECT_NAME} LANGUAGES CXX) + +set(PLUGIN_NAME "screen_recorder_plugin") + +add_library(${PLUGIN_NAME} SHARED + "screen_recorder_plugin.cpp" + "screen_recorder_plugin_c_api.cpp" + "capture_recorder.cpp" +) +apply_standard_settings(${PLUGIN_NAME}) +set_target_properties(${PLUGIN_NAME} PROPERTIES CXX_STANDARD 17) +target_compile_definitions(${PLUGIN_NAME} PRIVATE FLUTTER_PLUGIN_IMPL) +target_include_directories(${PLUGIN_NAME} INTERFACE + "${CMAKE_CURRENT_SOURCE_DIR}/include") +target_link_libraries(${PLUGIN_NAME} PRIVATE flutter flutter_wrapper_plugin + d3d11 dxgi mf mfplat mfreadwrite mfuuid windowsapp) + +set(screen_recorder_bundled_libraries "" PARENT_SCOPE) diff --git a/packages/screen_recorder/windows/capture_recorder.cpp b/packages/screen_recorder/windows/capture_recorder.cpp new file mode 100644 index 00000000..746ce830 --- /dev/null +++ b/packages/screen_recorder/windows/capture_recorder.cpp @@ -0,0 +1,308 @@ +#include "capture_recorder.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#pragma comment(lib, "windowsapp") + +using namespace winrt; +using namespace winrt::Windows::Graphics::Capture; +using namespace winrt::Windows::Graphics::DirectX; +using namespace winrt::Windows::Graphics::DirectX::Direct3D11; + +namespace screen_recorder { + +namespace { +std::wstring VideosDir() { + PWSTR path = nullptr; + std::wstring dir; + if (SUCCEEDED(SHGetKnownFolderPath(FOLDERID_Videos, 0, nullptr, &path))) { + dir = path; + CoTaskMemFree(path); + } + dir += L"\\BikeControl"; + CreateDirectoryW(dir.c_str(), nullptr); + return dir; +} +} // namespace + +struct CaptureRecorder::Impl { + com_ptr d3dDevice; + com_ptr d3dContext; + IDirect3DDevice winrtDevice{nullptr}; + GraphicsCaptureItem item{nullptr}; + Direct3D11CaptureFramePool framePool{nullptr}; + GraphicsCaptureSession session{nullptr}; + Direct3D11CaptureFramePool::FrameArrived_revoker frameArrived; + + com_ptr sinkWriter; + DWORD streamIndex = 0; + std::atomic running{false}; + LONGLONG startQpc = 0; + LARGE_INTEGER qpcFrequency{}; + UINT width = 0, height = 0; + std::wstring outPath; + + // Staging texture reused across frames (recreated if size changes). + com_ptr stagingTexture; +}; + +bool CaptureRecorder::IsSupported() { + try { + return GraphicsCaptureSession::IsSupported(); + } catch (...) { return false; } +} + +bool CaptureRecorder::Start() { + try { + impl_ = new Impl(); + + // 1) D3D11 device with BGRA support (required by WGC). + D3D_FEATURE_LEVEL fl; + if (FAILED(D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, nullptr, + D3D11_CREATE_DEVICE_BGRA_SUPPORT, nullptr, 0, D3D11_SDK_VERSION, + impl_->d3dDevice.put(), &fl, impl_->d3dContext.put()))) { + return false; + } + com_ptr dxgiDevice = impl_->d3dDevice.as(); + com_ptr<::IInspectable> inspectable; + // VERIFY on Windows: CreateDirect3D11DeviceFromDXGIDevice is in + // and links via windowsapp. + CreateDirect3D11DeviceFromDXGIDevice(dxgiDevice.get(), inspectable.put()); + impl_->winrtDevice = inspectable.as(); + + // 2) Capture item for the primary monitor. + HMONITOR mon = MonitorFromWindow(GetDesktopWindow(), MONITOR_DEFAULTTOPRIMARY); + auto interop = get_activation_factory(); + check_hresult(interop->CreateForMonitor(mon, + guid_of(), put_abi(impl_->item))); + auto size = impl_->item.Size(); + impl_->width = static_cast(size.Width); + impl_->height = static_cast(size.Height); + + // 3) Media Foundation sink writer (H.264 mp4). + MFStartup(MF_VERSION); + impl_->outPath = VideosDir() + L"\\BikeControl_" + + std::to_wstring(std::chrono::duration_cast( + std::chrono::system_clock::now().time_since_epoch()).count()) + L".mp4"; + com_ptr writer; + check_hresult(MFCreateSinkWriterFromURL(impl_->outPath.c_str(), nullptr, nullptr, writer.put())); + + // Output type: H.264 + com_ptr outType; + MFCreateMediaType(outType.put()); + outType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); + outType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_H264); + outType->SetUINT32(MF_MT_AVG_BITRATE, 8000000); + outType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + MFSetAttributeSize(outType.get(), MF_MT_FRAME_SIZE, impl_->width, impl_->height); + MFSetAttributeRatio(outType.get(), MF_MT_FRAME_RATE, 30, 1); + MFSetAttributeRatio(outType.get(), MF_MT_PIXEL_ASPECT_RATIO, 1, 1); + writer->AddStream(outType.get(), &impl_->streamIndex); + + // Input type: RGB32 (= BGRA from WGC; MF treats RGB32 as BGRA on Windows). + com_ptr inType; + MFCreateMediaType(inType.put()); + inType->SetGUID(MF_MT_MAJOR_TYPE, MFMediaType_Video); + inType->SetGUID(MF_MT_SUBTYPE, MFVideoFormat_RGB32); // BGRA from WGC + inType->SetUINT32(MF_MT_INTERLACE_MODE, MFVideoInterlace_Progressive); + MFSetAttributeSize(inType.get(), MF_MT_FRAME_SIZE, impl_->width, impl_->height); + MFSetAttributeRatio(inType.get(), MF_MT_FRAME_RATE, 30, 1); + // VERIFY on Windows: MF_MT_DEFAULT_STRIDE for top-down RGB32 is positive + // (width * 4). WGC surfaces are top-down, so this is correct. + // VERIFY on Windows: Some H.264 encoders require even dimensions; ensure + // width/height are even (round down if needed). + MFSetAttributeSize(inType.get(), MF_MT_FRAME_SIZE, impl_->width, impl_->height); + writer->SetInputMediaType(impl_->streamIndex, inType.get(), nullptr); + writer->BeginWriting(); + impl_->sinkWriter = writer; + + // Record the QPC start time and frequency for sample timestamps. + QueryPerformanceFrequency(&impl_->qpcFrequency); + QueryPerformanceCounter(reinterpret_cast(&impl_->startQpc)); + + // 4) Frame pool + session. + impl_->framePool = Direct3D11CaptureFramePool::Create( + impl_->winrtDevice, DirectXPixelFormat::B8G8R8A8UIntNormalized, 2, impl_->item.Size()); + impl_->session = impl_->framePool.CreateCaptureSession(impl_->item); + impl_->running = true; + + // ----------------------------------------------------------------------- + // FrameArrived: D3D texture → staging copy → CPU map → IMFSample → write + // + // NOTE: This is the part most likely to need iteration on-device. + // The overall flow is correct per MSDN; exact error codes and any + // quirks of the H.264 encoder (stride alignment, colorspace hints) + // may need adjustment. See VERIFY comments inline. + // ----------------------------------------------------------------------- + impl_->frameArrived = impl_->framePool.FrameArrived(auto_revoke, + [this](Direct3D11CaptureFramePool const& pool, auto const&) { + auto frame = pool.TryGetNextFrame(); + if (!frame || !impl_->running) return; + + // --- Step A: Get the ID3D11Texture2D from the WGC frame surface --- + // + // frame.Surface() is an IDirect3DSurface (WinRT). To get the + // underlying D3D11 texture, QI for IDirect3DDxgiInterfaceAccess. + // VERIFY on Windows: IDirect3DDxgiInterfaceAccess is in + // . + auto surface = frame.Surface(); + com_ptr frameTexture; + { + // VERIFY on Windows: surface.as<>() may need the IID_PPV_ARGS form; + // alternatively use surface.try_as<> and check for null. + auto dxgiAccess = surface.as(); + HRESULT hr = dxgiAccess->GetInterface(IID_PPV_ARGS(frameTexture.put())); + if (FAILED(hr)) return; + } + + // --- Step B: Describe the source texture and create/reuse a staging texture --- + D3D11_TEXTURE2D_DESC srcDesc{}; + frameTexture->GetDesc(&srcDesc); + + // Reuse staging texture if dimensions match; otherwise (re)create. + bool needNewStaging = true; + if (impl_->stagingTexture) { + D3D11_TEXTURE2D_DESC stgDesc{}; + impl_->stagingTexture->GetDesc(&stgDesc); + needNewStaging = (stgDesc.Width != srcDesc.Width || + stgDesc.Height != srcDesc.Height); + } + if (needNewStaging) { + impl_->stagingTexture = nullptr; + D3D11_TEXTURE2D_DESC stgDesc{}; + stgDesc.Width = srcDesc.Width; + stgDesc.Height = srcDesc.Height; + stgDesc.MipLevels = 1; + stgDesc.ArraySize = 1; + stgDesc.Format = srcDesc.Format; // DXGI_FORMAT_B8G8R8A8_UNORM + stgDesc.SampleDesc.Count = 1; + stgDesc.SampleDesc.Quality = 0; + stgDesc.Usage = D3D11_USAGE_STAGING; + stgDesc.BindFlags = 0; + stgDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ; + stgDesc.MiscFlags = 0; + HRESULT hr = impl_->d3dDevice->CreateTexture2D( + &stgDesc, nullptr, impl_->stagingTexture.put()); + if (FAILED(hr)) return; + } + + // --- Step C: CopyResource GPU→staging --- + impl_->d3dContext->CopyResource(impl_->stagingTexture.get(), frameTexture.get()); + + // --- Step D: Map the staging texture for CPU read --- + D3D11_MAPPED_SUBRESOURCE mapped{}; + HRESULT hrMap = impl_->d3dContext->Map( + impl_->stagingTexture.get(), 0, D3D11_MAP_READ, 0, &mapped); + if (FAILED(hrMap)) return; + + // --- Step E: Build IMFSample from the BGRA bytes --- + const UINT frameWidth = srcDesc.Width; + const UINT frameHeight = srcDesc.Height; + // BGRA: 4 bytes per pixel, top-down (positive stride = width*4 contiguous). + const DWORD bytesPerRow = frameWidth * 4; + const DWORD totalBytes = bytesPerRow * frameHeight; + + com_ptr mfBuffer; + HRESULT hr = MFCreateMemoryBuffer(totalBytes, mfBuffer.put()); + if (FAILED(hr)) { + impl_->d3dContext->Unmap(impl_->stagingTexture.get(), 0); + return; + } + + BYTE* pDst = nullptr; + DWORD maxLen = 0, curLen = 0; + hr = mfBuffer->Lock(&pDst, &maxLen, &curLen); + if (FAILED(hr)) { + impl_->d3dContext->Unmap(impl_->stagingTexture.get(), 0); + return; + } + + // Copy row-by-row in case the GPU stride (RowPitch) > bytesPerRow. + // WGC surfaces are top-down; MF RGB32 also expects top-down. + // VERIFY on Windows: if the encoder produces an upside-down image, + // either set MF_MT_DEFAULT_STRIDE to a negative value on the input + // type, or reverse the row copy here. + const BYTE* pSrc = static_cast(mapped.pData); + for (UINT row = 0; row < frameHeight; ++row) { + memcpy(pDst + row * bytesPerRow, + pSrc + row * mapped.RowPitch, + bytesPerRow); + } + mfBuffer->Unlock(); + mfBuffer->SetCurrentLength(totalBytes); + + impl_->d3dContext->Unmap(impl_->stagingTexture.get(), 0); + + // --- Step F: Create the IMFSample, set time and duration, write --- + com_ptr sample; + hr = MFCreateSample(sample.put()); + if (FAILED(hr)) return; + + sample->AddBuffer(mfBuffer.get()); + + // Compute sample time in 100ns units from QPC. + LARGE_INTEGER nowQpc{}; + QueryPerformanceCounter(&nowQpc); + LONGLONG elapsedQpc = nowQpc.QuadPart - impl_->startQpc; + // Convert QPC ticks → 100ns units: (ticks * 10,000,000) / freq + // VERIFY on Windows: integer overflow possible for very long recordings; + // use MFllMulDiv if available, or promote to __int128 / use double. + LONGLONG sampleTime = (elapsedQpc * 10000000LL) / impl_->qpcFrequency.QuadPart; + // Duration for 30 fps = 1/30 s = 333333 100ns units. + LONGLONG sampleDuration = 333333LL; + + sample->SetSampleTime(sampleTime); + sample->SetSampleDuration(sampleDuration); + + // VERIFY on Windows: WriteSample must be called from the same thread + // that called BeginWriting (or from any thread if the writer was created + // with MF_SINK_WRITER_ASYNC_CALLBACK). Here we call it inline from the + // WGC dispatcher thread; this is typically fine for the synchronous writer. + if (impl_->sinkWriter && impl_->running) { + impl_->sinkWriter->WriteSample(impl_->streamIndex, sample.get()); + } + }); + + impl_->session.StartCapture(); + return true; + } catch (...) { + return false; + } +} + +std::string CaptureRecorder::Stop() { + if (!impl_) return ""; + impl_->running = false; + try { + impl_->frameArrived.revoke(); + if (impl_->session) impl_->session.Close(); + if (impl_->framePool) impl_->framePool.Close(); + impl_->stagingTexture = nullptr; + if (impl_->sinkWriter) impl_->sinkWriter->Finalize(); + MFShutdown(); + } catch (...) {} + std::wstring w = impl_->outPath; + delete impl_; impl_ = nullptr; + int len = WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, nullptr, 0, nullptr, nullptr); + std::string out(len > 0 ? len - 1 : 0, '\0'); + if (len > 0) WideCharToMultiByte(CP_UTF8, 0, w.c_str(), -1, out.data(), len, nullptr, nullptr); + return out; +} + +CaptureRecorder::~CaptureRecorder() { if (impl_) { Stop(); } } +} // namespace screen_recorder diff --git a/packages/screen_recorder/windows/capture_recorder.h b/packages/screen_recorder/windows/capture_recorder.h new file mode 100644 index 00000000..3068b47c --- /dev/null +++ b/packages/screen_recorder/windows/capture_recorder.h @@ -0,0 +1,19 @@ +#ifndef SCREEN_RECORDER_CAPTURE_RECORDER_H_ +#define SCREEN_RECORDER_CAPTURE_RECORDER_H_ +#include + +namespace screen_recorder { +// Captures the primary monitor via Windows.Graphics.Capture and encodes to +// H.264 mp4 in the user's Videos\BikeControl folder via Media Foundation. +class CaptureRecorder { + public: + static bool IsSupported(); // GraphicsCaptureSession::IsSupported() + bool Start(); // returns true if capture started + std::string Stop(); // returns saved path, or "" on failure + ~CaptureRecorder(); + private: + struct Impl; + Impl* impl_ = nullptr; +}; +} // namespace screen_recorder +#endif diff --git a/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin.h b/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin.h new file mode 100644 index 00000000..0a42b6fb --- /dev/null +++ b/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin.h @@ -0,0 +1,23 @@ +#ifndef FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_H_PUBLIC_ +#define FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_H_PUBLIC_ +// Public header included by Flutter's generated_plugin_registrant.cc. +// Exposes the C-linkage registration entry point only. +#include + +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif + +#if defined(__cplusplus) +extern "C" { +#endif + +FLUTTER_PLUGIN_EXPORT void ScreenRecorderPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); + +#if defined(__cplusplus) +} +#endif +#endif // FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_H_PUBLIC_ diff --git a/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin_c_api.h b/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin_c_api.h new file mode 100644 index 00000000..3258aead --- /dev/null +++ b/packages/screen_recorder/windows/include/screen_recorder/screen_recorder_plugin_c_api.h @@ -0,0 +1,17 @@ +#ifndef FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_C_API_H_ +#define FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_C_API_H_ +#include +#ifdef FLUTTER_PLUGIN_IMPL +#define FLUTTER_PLUGIN_EXPORT __declspec(dllexport) +#else +#define FLUTTER_PLUGIN_EXPORT __declspec(dllimport) +#endif +#if defined(__cplusplus) +extern "C" { +#endif +FLUTTER_PLUGIN_EXPORT void ScreenRecorderPluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar); +#if defined(__cplusplus) +} +#endif +#endif diff --git a/packages/screen_recorder/windows/screen_recorder_plugin.cpp b/packages/screen_recorder/windows/screen_recorder_plugin.cpp new file mode 100644 index 00000000..8d476468 --- /dev/null +++ b/packages/screen_recorder/windows/screen_recorder_plugin.cpp @@ -0,0 +1,48 @@ +#include "screen_recorder_plugin.h" +#include +#include +#include + +namespace screen_recorder { + +void ScreenRecorderPlugin::RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar) { + auto channel = std::make_unique>( + registrar->messenger(), "screen_recorder", + &flutter::StandardMethodCodec::GetInstance()); + auto plugin = std::make_unique(); + channel->SetMethodCallHandler( + [plugin_pointer = plugin.get()](const auto& call, auto result) { + plugin_pointer->HandleMethodCall(call, std::move(result)); + }); + registrar->AddPlugin(std::move(plugin)); +} + +ScreenRecorderPlugin::ScreenRecorderPlugin() {} +ScreenRecorderPlugin::~ScreenRecorderPlugin() {} + +void ScreenRecorderPlugin::HandleMethodCall( + const flutter::MethodCall& call, + std::unique_ptr> result) { + const std::string& method = call.method_name(); + if (method == "isSupported") { + result->Success(flutter::EncodableValue(CaptureRecorder::IsSupported())); + } else if (method == "hasPermission" || method == "requestPermission") { + result->Success(flutter::EncodableValue(true)); // WGC needs no prompt + } else if (method == "start") { + recorder_ = std::make_unique(); + bool ok = recorder_->Start(); + result->Success(flutter::EncodableValue(ok)); + } else if (method == "stop") { + if (recorder_) { + std::string path = recorder_->Stop(); + recorder_.reset(); + if (path.empty()) result->Success(flutter::EncodableValue()); + else result->Success(flutter::EncodableValue(path)); + } else { + result->Success(flutter::EncodableValue()); + } + } else { + result->NotImplemented(); + } +} +} // namespace screen_recorder diff --git a/packages/screen_recorder/windows/screen_recorder_plugin.h b/packages/screen_recorder/windows/screen_recorder_plugin.h new file mode 100644 index 00000000..b1d72e4b --- /dev/null +++ b/packages/screen_recorder/windows/screen_recorder_plugin.h @@ -0,0 +1,20 @@ +#ifndef FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_H_ +#define FLUTTER_PLUGIN_SCREEN_RECORDER_PLUGIN_H_ +#include +#include +#include +#include "capture_recorder.h" + +namespace screen_recorder { +class ScreenRecorderPlugin : public flutter::Plugin { + public: + static void RegisterWithRegistrar(flutter::PluginRegistrarWindows* registrar); + ScreenRecorderPlugin(); + virtual ~ScreenRecorderPlugin(); + private: + void HandleMethodCall(const flutter::MethodCall& call, + std::unique_ptr> result); + std::unique_ptr recorder_; +}; +} // namespace screen_recorder +#endif diff --git a/packages/screen_recorder/windows/screen_recorder_plugin_c_api.cpp b/packages/screen_recorder/windows/screen_recorder_plugin_c_api.cpp new file mode 100644 index 00000000..b0270e95 --- /dev/null +++ b/packages/screen_recorder/windows/screen_recorder_plugin_c_api.cpp @@ -0,0 +1,19 @@ +#include "include/screen_recorder/screen_recorder_plugin_c_api.h" +#include "include/screen_recorder/screen_recorder_plugin.h" +#include +#include "screen_recorder_plugin.h" + +// Called by Flutter's generated_plugin_registrant.cc (pluginClass without CApi suffix). +void ScreenRecorderPluginRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + screen_recorder::ScreenRecorderPlugin::RegisterWithRegistrar( + flutter::PluginRegistrarManager::GetInstance() + ->GetRegistrar(registrar)); +} + +// Legacy CApi-suffixed alias; kept for compatibility if pubspec pluginClass +// is ever changed to ScreenRecorderPluginCApi. +void ScreenRecorderPluginCApiRegisterWithRegistrar( + FlutterDesktopPluginRegistrarRef registrar) { + ScreenRecorderPluginRegisterWithRegistrar(registrar); +} diff --git a/pubspec.yaml b/pubspec.yaml index ba5207c4..35e13bb8 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -151,4 +151,4 @@ msix_config: logo_path: web/icons/Icon-512.png build_windows: false protocol_activation: https, bikecontrol - capabilities: internetClient,bluetooth,inputInjectionBrokered + capabilities: internetClient,bluetooth,inputInjectionBrokered,videosLibrary diff --git a/windows/flutter/generated_plugin_registrant.cc b/windows/flutter/generated_plugin_registrant.cc index c8e005eb..2c4073c5 100644 --- a/windows/flutter/generated_plugin_registrant.cc +++ b/windows/flutter/generated_plugin_registrant.cc @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -50,6 +51,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) { registry->GetRegistrarForPlugin("NsdWindowsPluginCApi")); PermissionHandlerWindowsPluginRegisterWithRegistrar( registry->GetRegistrarForPlugin("PermissionHandlerWindowsPlugin")); + ScreenRecorderPluginRegisterWithRegistrar( + registry->GetRegistrarForPlugin("ScreenRecorderPlugin")); ScreenRetrieverWindowsPluginCApiRegisterWithRegistrar( registry->GetRegistrarForPlugin("ScreenRetrieverWindowsPluginCApi")); SharePlusWindowsPluginCApiRegisterWithRegistrar( diff --git a/windows/flutter/generated_plugins.cmake b/windows/flutter/generated_plugins.cmake index f87a1ee4..db1313e4 100644 --- a/windows/flutter/generated_plugins.cmake +++ b/windows/flutter/generated_plugins.cmake @@ -15,6 +15,7 @@ list(APPEND FLUTTER_PLUGIN_LIST multi_window_native nsd_windows permission_handler_windows + screen_recorder screen_retriever_windows share_plus universal_ble From e90ed892439da0d9fb0455ad92b0a3c3b2c22ba7 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:52:22 +0200 Subject: [PATCH 050/106] feat(6.2): iOS screen recording backend (ReplayKit broadcast extension) [extension target needs Xcode wiring] Co-Authored-By: Claude Sonnet 4.6 --- ios/Podfile.lock | 18 +++ ios/Runner/Info.plist | 2 + ios/ScreenRecordBroadcast/Info.plist | 33 +++++ ios/ScreenRecordBroadcast/SampleHandler.swift | 122 ++++++++++++++++++ .../ios/Classes/ScreenRecorderPlugin.swift | 80 ++++++++++++ .../ios/screen_recorder.podspec | 15 +++ packages/screen_recorder/pubspec.yaml | 2 + 7 files changed, 272 insertions(+) create mode 100644 ios/ScreenRecordBroadcast/Info.plist create mode 100644 ios/ScreenRecordBroadcast/SampleHandler.swift create mode 100644 packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift create mode 100644 packages/screen_recorder/ios/screen_recorder.podspec diff --git a/ios/Podfile.lock b/ios/Podfile.lock index d6816b41..4dd9f638 100644 --- a/ios/Podfile.lock +++ b/ios/Podfile.lock @@ -1,5 +1,9 @@ PODS: - Flutter (1.0.0) + - flutter_foreground_task (0.0.1): + - Flutter + - flutter_screen_recording (0.0.1): + - Flutter - flutter_volume_controller (0.0.1): - Flutter - gamepads_ios (0.1.1): @@ -12,22 +16,31 @@ PODS: - Flutter - restart_app (0.0.1): - Flutter + - screen_recorder (0.0.1): + - Flutter - sign_in_with_apple (0.0.1): - Flutter DEPENDENCIES: - Flutter (from `Flutter`) + - flutter_foreground_task (from `.symlinks/plugins/flutter_foreground_task/ios`) + - flutter_screen_recording (from `.symlinks/plugins/flutter_screen_recording/ios`) - flutter_volume_controller (from `.symlinks/plugins/flutter_volume_controller/ios`) - gamepads_ios (from `.symlinks/plugins/gamepads_ios/ios`) - media_key_detector_ios (from `.symlinks/plugins/media_key_detector_ios/ios`) - nsd_ios (from `.symlinks/plugins/nsd_ios/ios`) - permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`) - restart_app (from `.symlinks/plugins/restart_app/ios`) + - screen_recorder (from `.symlinks/plugins/screen_recorder/ios`) - sign_in_with_apple (from `.symlinks/plugins/sign_in_with_apple/ios`) EXTERNAL SOURCES: Flutter: :path: Flutter + flutter_foreground_task: + :path: ".symlinks/plugins/flutter_foreground_task/ios" + flutter_screen_recording: + :path: ".symlinks/plugins/flutter_screen_recording/ios" flutter_volume_controller: :path: ".symlinks/plugins/flutter_volume_controller/ios" gamepads_ios: @@ -40,17 +53,22 @@ EXTERNAL SOURCES: :path: ".symlinks/plugins/permission_handler_apple/ios" restart_app: :path: ".symlinks/plugins/restart_app/ios" + screen_recorder: + :path: ".symlinks/plugins/screen_recorder/ios" sign_in_with_apple: :path: ".symlinks/plugins/sign_in_with_apple/ios" SPEC CHECKSUMS: Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467 + flutter_foreground_task: a159d2c2173b33699ddb3e6c2a067045d7cebb89 + flutter_screen_recording: d27b9073d122b618a07ef0e407470d051b265b26 flutter_volume_controller: c2be490cb0487e8b88d0d9fc2b7e1c139a4ebccb gamepads_ios: c75c6d31377d275b0effb9174c619e2705678c09 media_key_detector_ios: eb43ab957d4ef9084d079216b6dbac96c91d42eb nsd_ios: 596ad79109ddd3e52d665f650f36428049e3653e permission_handler_apple: 4ed2196e43d0651e8ff7ca3483a069d469701f2d restart_app: 9cda5378aacc5000e3f66ee76a9201534e7d3ecf + screen_recorder: 192d2308d545ace5676318ff0c1f2ee53231dbc1 sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418 PODFILE CHECKSUM: 7ebd5c9b932b3af79d5c67e3af873118b74e970f diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index d9a19ac9..b64d7681 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -56,6 +56,8 @@ BikeControl does not use the camera. This entry is required because the image picker plugin links camera APIs. NSPhotoLibraryUsageDescription Access your photo library to store screenshots. + NSPhotoLibraryAddUsageDescription + BikeControl saves your screen recordings to your photo library. NSSupportsLiveActivities UIApplicationSceneManifest diff --git a/ios/ScreenRecordBroadcast/Info.plist b/ios/ScreenRecordBroadcast/Info.plist new file mode 100644 index 00000000..ea47493e --- /dev/null +++ b/ios/ScreenRecordBroadcast/Info.plist @@ -0,0 +1,33 @@ + + + + + CFBundleDevelopmentRegion + $(DEVELOPMENT_LANGUAGE) + CFBundleDisplayName + ScreenRecordBroadcast + CFBundleExecutable + $(EXECUTABLE_NAME) + CFBundleIdentifier + $(PRODUCT_BUNDLE_IDENTIFIER) + CFBundleInfoDictionaryVersion + 6.0 + CFBundleName + $(PRODUCT_NAME) + CFBundlePackageType + $(PRODUCT_BUNDLE_PACKAGE_TYPE) + CFBundleShortVersionString + 1.0 + CFBundleVersion + 1 + NSExtension + + NSExtensionPointIdentifier + com.apple.broadcast-services-upload + NSExtensionPrincipalClass + $(PRODUCT_MODULE_NAME).SampleHandler + RPBroadcastProcessMode + RPBroadcastProcessModeSampleBuffer + + + diff --git a/ios/ScreenRecordBroadcast/SampleHandler.swift b/ios/ScreenRecordBroadcast/SampleHandler.swift new file mode 100644 index 00000000..36d3c7b1 --- /dev/null +++ b/ios/ScreenRecordBroadcast/SampleHandler.swift @@ -0,0 +1,122 @@ +import ReplayKit +import AVFoundation + +// IMPORTANT: This file belongs to the ScreenRecordBroadcast Broadcast Upload Extension target. +// It is NOT compiled by the Runner target. Manual Xcode steps required: +// +// 1. File ▸ New ▸ Target ▸ Broadcast Upload Extension +// - Name: ScreenRecordBroadcast +// - Bundle Identifier: de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast +// - Uncheck "Include UI Extension" +// 2. Replace the generated SampleHandler.swift with this file (or add this file to the target +// and delete the generated one). +// 3. In Apple Developer portal: create App Group "group.de.jonasbark.swiftcontrol.darwin" +// and enable it on BOTH Runner and ScreenRecordBroadcast targets. +// +// App Group: group.de.jonasbark.swiftcontrol.darwin (MUST match ScreenRecorderPlugin.swift) + +class SampleHandler: RPBroadcastSampleHandler { + // MUST match ScreenRecorderPlugin.appGroup + static let appGroup = "group.de.jonasbark.swiftcontrol.darwin" + + // MUST match ScreenRecorderPlugin.stopNotificationName + static let stopNotificationName = "de.jonasbark.swiftcontrol.darwin.stopBroadcast" + + private var writer: AVAssetWriter? + private var videoInput: AVAssetWriterInput? + private var sessionStarted = false + private var outputURL: URL? + + override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) { + guard let container = FileManager.default.containerURL( + forSecurityApplicationGroupIdentifier: SampleHandler.appGroup) else { + NSLog("SampleHandler: failed to get App Group container — check portal config") + return + } + + let timestamp = Int(Date().timeIntervalSince1970) + let url = container.appendingPathComponent("BikeControl_\(timestamp).mp4") + outputURL = url + try? FileManager.default.removeItem(at: url) + + // Use main screen size and scale for full-resolution capture. + let screen = UIScreen.main.bounds.size + let scale = UIScreen.main.scale + let videoSettings: [String: Any] = [ + AVVideoCodecKey: AVVideoCodecType.h264, + AVVideoWidthKey: Int(screen.width * scale), + AVVideoHeightKey: Int(screen.height * scale), + ] + + guard let assetWriter = try? AVAssetWriter(outputURL: url, fileType: .mp4) else { + NSLog("SampleHandler: failed to create AVAssetWriter at \(url.path)") + return + } + writer = assetWriter + + let input = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings) + input.expectsMediaDataInRealTime = true + videoInput = input + + if assetWriter.canAdd(input) { + assetWriter.add(input) + } + assetWriter.startWriting() + + // Listen for the app's stop signal via Darwin notification center. + // The host app posts this when the user triggers "stop recording". + CFNotificationCenterAddObserver( + CFNotificationCenterGetDarwinNotifyCenter(), + Unmanaged.passUnretained(self).toOpaque(), + { _, observer, _, _, _ in + guard let observer = observer else { return } + let handler = Unmanaged.fromOpaque(observer).takeUnretainedValue() + // Finish with an error to terminate the broadcast; broadcastFinished() will then run. + handler.finishBroadcastWithError( + NSError(domain: "de.jonasbark.swiftcontrol.darwin", code: 0, + userInfo: [NSLocalizedDescriptionKey: "Recording stopped by app"])) + }, + SampleHandler.stopNotificationName as CFString, + nil, + .deliverImmediately) + } + + override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) { + guard sampleBufferType == .video, + let writer = writer, + let input = videoInput, + CMSampleBufferDataIsReady(sampleBuffer) else { return } + + if !sessionStarted { + let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer) + writer.startSession(atSourceTime: pts) + sessionStarted = true + } + + if input.isReadyForMoreMediaData { + input.append(sampleBuffer) + } + } + + override func broadcastFinished() { + // Remove the Darwin observer to avoid dangling pointer after dealloc. + CFNotificationCenterRemoveObserver( + CFNotificationCenterGetDarwinNotifyCenter(), + Unmanaged.passUnretained(self).toOpaque(), + CFNotificationName(SampleHandler.stopNotificationName as CFString), + nil) + + let group = DispatchGroup() + group.enter() + videoInput?.markAsFinished() + writer?.finishWriting { group.leave() } + group.wait() + + // Write the output path into the shared App Group defaults so the host app + // can read it back when its stop() method channel call returns. + if let path = outputURL?.path { + UserDefaults(suiteName: SampleHandler.appGroup)?.set(path, forKey: "lastRecordingPath") + NSLog("SampleHandler: recording saved to \(path)") + } + } +} diff --git a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift new file mode 100644 index 00000000..53c90f62 --- /dev/null +++ b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift @@ -0,0 +1,80 @@ +import Flutter +import UIKit +import ReplayKit + +// IMPORTANT: The App Group identifier below MUST be created in the Apple Developer portal +// (Certificates, Identifiers & Profiles → App Groups) and enabled on BOTH the Runner target +// AND the ScreenRecordBroadcast extension target in Signing & Capabilities. +// +// App bundle ID: de.jonasbark.swiftcontrol.darwin +// App Group (derived): group.de.jonasbark.swiftcontrol.darwin +// Extension bundle ID: de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast + +public class ScreenRecorderPlugin: NSObject, FlutterPlugin { + // Derived from the app bundle id: group. + static let appGroup = "group.de.jonasbark.swiftcontrol.darwin" + + // Darwin notification name used to signal the extension to stop. + // Must match the string used in SampleHandler.swift. + static let stopNotificationName = "de.jonasbark.swiftcontrol.darwin.stopBroadcast" + + // The extension's bundle id. Must match the Target's Bundle Identifier set in Xcode. + static let extensionBundleId = "de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast" + + public static func register(with registrar: FlutterPluginRegistrar) { + let channel = FlutterMethodChannel(name: "screen_recorder", binaryMessenger: registrar.messenger()) + registrar.addMethodCallDelegate(ScreenRecorderPlugin(), channel: channel) + } + + public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) { + switch call.method { + case "isSupported": + result(true) + case "hasPermission", "requestPermission": + // Broadcast is user-initiated via system sheet; no separate permission required. + result(true) + case "start": + presentBroadcastPicker() + // Record intent in shared defaults; the extension reads it when it starts. + sharedDefaults()?.set(true, forKey: "recordingRequested") + result(true) + case "stop": + // Clear intent and signal the extension to finish via Darwin notification. + sharedDefaults()?.set(false, forKey: "recordingRequested") + CFNotificationCenterPostNotification( + CFNotificationCenterGetDarwinNotifyCenter(), + CFNotificationName(ScreenRecorderPlugin.stopNotificationName as CFString), + nil, nil, true) + // The extension writes the final output path into shared defaults when it finishes. + let path = sharedDefaults()?.string(forKey: "lastRecordingPath") + result(path) + default: + result(FlutterMethodNotImplemented) + } + } + + private func sharedDefaults() -> UserDefaults? { + UserDefaults(suiteName: ScreenRecorderPlugin.appGroup) + } + + private func presentBroadcastPicker() { + DispatchQueue.main.async { + let picker = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0, width: 1, height: 1)) + // Preselect our extension so the user's tap targets it immediately. + picker.preferredExtension = ScreenRecorderPlugin.extensionBundleId + picker.showsMicrophoneButton = false + // Add to the key window so the picker can present its sheet. + if let windowScene = UIApplication.shared.connectedScenes + .first(where: { $0.activationState == .foregroundActive }) as? UIWindowScene, + let window = windowScene.windows.first(where: { $0.isKeyWindow }) { + window.addSubview(picker) + } + // Programmatically tap the picker button — the user still sees and confirms the sheet. + for subview in picker.subviews { + if let button = subview as? UIButton { + button.sendActions(for: .touchUpInside) + } + } + } + } +} diff --git a/packages/screen_recorder/ios/screen_recorder.podspec b/packages/screen_recorder/ios/screen_recorder.podspec new file mode 100644 index 00000000..163a27e5 --- /dev/null +++ b/packages/screen_recorder/ios/screen_recorder.podspec @@ -0,0 +1,15 @@ +Pod::Spec.new do |s| + s.name = 'screen_recorder' + s.version = '0.0.1' + s.summary = 'In-repo screen recorder.' + s.description = 'iOS ReplayKit broadcast bridge.' + s.homepage = 'https://bikecontrol.app' + s.license = { :type => 'Proprietary' } + s.author = { 'BikeControl' => 'jonas@bikecontrol.app' } + s.source = { :path => '.' } + s.source_files = 'Classes/**/*' + s.dependency 'Flutter' + s.platform = :ios, '15.0' + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } + s.swift_version = '5.0' +end diff --git a/packages/screen_recorder/pubspec.yaml b/packages/screen_recorder/pubspec.yaml index 09c37f99..eddfa66a 100644 --- a/packages/screen_recorder/pubspec.yaml +++ b/packages/screen_recorder/pubspec.yaml @@ -19,6 +19,8 @@ dev_dependencies: flutter: plugin: platforms: + ios: + pluginClass: ScreenRecorderPlugin macos: pluginClass: ScreenRecorderPlugin windows: From 520bd9137f5c7a9696372af2e9b85516d8304c95 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:55:36 +0200 Subject: [PATCH 051/106] =?UTF-8?q?docs(6.2):=20native=20backend=20setup?= =?UTF-8?q?=20+=20status=20(mac=D0=9ES/iOS/Windows=20manual=20steps)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- packages/screen_recorder/NATIVE_SETUP.md | 40 ++++++++++++++++++++++++ 1 file changed, 40 insertions(+) create mode 100644 packages/screen_recorder/NATIVE_SETUP.md diff --git a/packages/screen_recorder/NATIVE_SETUP.md b/packages/screen_recorder/NATIVE_SETUP.md new file mode 100644 index 00000000..25d1b4d6 --- /dev/null +++ b/packages/screen_recorder/NATIVE_SETUP.md @@ -0,0 +1,40 @@ +# screen_recorder — native backend setup & status + +Video-only screen recording. Dart spine + Android are done and tested. The three native +backends below were implemented on the `feat/screen-recording` branch; macOS and the iOS +plugin compile here, Windows and the iOS extension target need your machines. + +## Status + +| Platform | Backend | Verified | +| --- | --- | --- | +| Android | `flutter_screen_recording` + `gal` (in `lib/services/.../android_screen_recorder.dart`) | ✅ builds APK, tested | +| macOS | ScreenCaptureKit → AVAssetWriter (`macos/Classes/`) | ✅ `flutter build macos` passes — runtime (TCC + capture) still needs a Mac | +| iOS | ReplayKit broadcast: plugin picker bridge + Broadcast Upload Extension | ⚠️ plugin compiles (`flutter build ios` passes); **extension target needs Xcode wiring** | +| Windows | Windows.Graphics.Capture + Media Foundation (`windows/`) | ❌ **never compiled — build on Windows and iterate** | + +## macOS — remaining +- Runtime test on a Mac: bind a key to "Record Screen", grant the Screen Recording TCC prompt (may need an app relaunch), record, confirm an mp4 in `~/Movies/BikeControl/`. +- If the App Sandbox blocks writing to `~/Movies`, fall back to an `NSOpenPanel`-selected folder or the app container's Movies dir (entitlement `com.apple.security.assets.movies.read-write` is already added). + +## iOS — remaining (manual Xcode + portal, can't be scripted) +Identifiers (derived from the real app bundle id `de.jonasbark.swiftcontrol.darwin`): +- App Group: `group.de.jonasbark.swiftcontrol.darwin` +- Extension bundle id: `de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast` + +Steps: +1. **Apple Developer portal:** create App Group `group.de.jonasbark.swiftcontrol.darwin`; enable it on both the app and the extension identifiers. +2. **Xcode:** File ▸ New ▸ Target ▸ Broadcast Upload Extension, name `ScreenRecordBroadcast`, bundle id `de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast`, **uncheck** "Include UI Extension". Replace the generated `SampleHandler.swift` with the repo's `ios/ScreenRecordBroadcast/SampleHandler.swift` (and use the repo's `Info.plist`). +3. **Signing & Capabilities:** add the App Groups capability (checked) to BOTH the Runner and the extension targets; set the team/provisioning on the extension. +4. Verify the `preferredExtension` string in `packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift` matches the extension bundle id. +5. Device test: bind a key, tap **Start Broadcast** on the system sheet (one unavoidable tap), switch to a game, stop, confirm the mp4 lands in Photos. +- **Known refinement:** `stop()` reads `lastRecordingPath` from the App Group right after posting the stop Darwin notification — the extension may not have finished writing yet, so it can return `nil` on the first call. Add a short poll (e.g. up to 2 s at 100 ms) for the path / a "finished" flag before returning. Verify timing on-device. + +## Windows — remaining (build + iterate, never compiled) +1. `flutter build windows --debug` — expect compile iteration on C++/WinRT headers and `windowsapp.lib`. +2. The `FrameArrived` D3D→Media Foundation path has `// VERIFY on Windows:` markers at the 5 likely trouble points (stride/orientation, even dimensions, thread safety, QPC, BGRA vs ARGB). Record 5 s, confirm a playable mp4; if upside-down, negate `MF_MT_DEFAULT_STRIDE`; if colors swapped, try `MFVideoFormat_ARGB32`. +3. Windows N/KN editions need the Media Feature Pack for the H.264 MFT — surface a message if `MFCreateSinkWriterFromURL` fails. +4. After `flutter pub run msix:create`, confirm `` is in the generated AppxManifest (added via `msix_config.capabilities`). + +## Plugin pubspec note +`pubspec.yaml` now declares ios/macos/windows. If you ever need to temporarily disable a platform whose native code doesn't yet build, remove just that entry (declaring a platform with no/broken native code breaks that platform's plugin registrant — this was the original cross-platform-build trap). From 625695e16dc226fe0da11018b32c094f45e61e04 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:01:06 +0200 Subject: [PATCH 052/106] refactor(ios): extract shared GearSnapshot + add GearReadoutView for PiP Co-Authored-By: Claude Opus 4.8 (1M context) --- ios/Shared/GearReadoutView.swift | 47 ++++++++++++ ios/Shared/GearSnapshot.swift | 94 +++++++++++++++++++++++ ios/TrainerActivity/TrainerActivity.swift | 77 ++----------------- 3 files changed, 147 insertions(+), 71 deletions(-) create mode 100644 ios/Shared/GearReadoutView.swift create mode 100644 ios/Shared/GearSnapshot.swift diff --git a/ios/Shared/GearReadoutView.swift b/ios/Shared/GearReadoutView.swift new file mode 100644 index 00000000..c9278c52 --- /dev/null +++ b/ios/Shared/GearReadoutView.swift @@ -0,0 +1,47 @@ +import SwiftUI + +/// Display-only gear readout rendered into the PiP window. Visually mirrors the +/// Live Activity's non-control layout (mode pill + opted-in metrics), scaled up +/// for the small floating window. No buttons — PiP is display-only. +@available(iOS 16.0, *) +struct GearReadoutView: View { + let snapshot: GearSnapshot + + var body: some View { + VStack(spacing: 8) { + Text(snapshot.primaryText) + .font(.system(size: 84, weight: .heavy)) + .monospacedDigit() + .foregroundStyle(.white) + .lineLimit(1) + .minimumScaleFactor(0.4) + HStack(spacing: 12) { + Self.modePill(snapshot.mode) + if snapshot.showPower, let w = snapshot.powerW { Self.metric("\(w) W") } + if snapshot.showCadence, let rpm = snapshot.cadenceRpm { Self.metric("\(rpm) rpm") } + if !snapshot.isErg && snapshot.showGearRatio { + Self.metric(String(format: "×%.2f", snapshot.gearRatio)) + } + } + .font(.system(size: 22, weight: .semibold).monospacedDigit()) + } + .frame(maxWidth: .infinity, maxHeight: .infinity) + .padding(20) + .background(Color.black) + .environment(\.colorScheme, .dark) + } + + static func modePill(_ mode: String) -> some View { + Text(mode.uppercased()) + .font(.system(size: 18, weight: .bold)) + .foregroundStyle(.white) + .padding(.horizontal, 10) + .padding(.vertical, 4) + .background(Color.accentColor) + .clipShape(Capsule()) + } + + static func metric(_ text: String) -> some View { + Text(text).foregroundStyle(.white).lineLimit(1) + } +} diff --git a/ios/Shared/GearSnapshot.swift b/ios/Shared/GearSnapshot.swift new file mode 100644 index 00000000..78b13460 --- /dev/null +++ b/ios/Shared/GearSnapshot.swift @@ -0,0 +1,94 @@ +import ActivityKit +import Foundation + +/// Shared gear readout model. Compiled into BOTH the Runner app (for PiP) and +/// the TrainerActivity extension (for the Live Activity), so the two surfaces +/// always agree on field semantics. +struct GearSnapshot { + let gear: Int + let maxGear: Int + let mode: String // "sim" | "erg" + let powerW: Int? + let cadenceRpm: Int? + let ergTargetW: Int? + let gearRatio: Double + let showPower: Bool + let showCadence: Bool + let showErgTarget: Bool + let showGearRatio: Bool + let showControls: Bool + + var isErg: Bool { mode == "erg" } + + /// Big primary value: target watts in ERG, gear N/M in SIM. + var primaryText: String { + if isErg { return ergTargetW.map { "\($0) W" } ?? "-- W" } + return "\(gear) / \(maxGear)" + } + + var compactTrailing: String { + isErg ? (ergTargetW.map { "\($0)W" } ?? "--W") : "\(gear)/\(maxGear)" + } + + var minimalText: String { + isErg ? (ergTargetW.map { "\($0)" } ?? "--") : "\(gear)" + } + + /// Cheap change-detection key so the PiP pump can skip identical frames. + var contentHash: Int { + var h = Hasher() + h.combine(gear); h.combine(maxGear); h.combine(mode) + h.combine(powerW); h.combine(cadenceRpm); h.combine(ergTargetW) + h.combine(gearRatio); h.combine(showPower); h.combine(showCadence) + h.combine(showErgTarget); h.combine(showGearRatio); h.combine(showControls) + return h.finalize() + } +} + +extension GearSnapshot { + /// Parse the map sent over `bike_control/pip_ios` — the same shape produced + /// by `overlayStateToActivityMap` on the Dart side. Missing keys fall back + /// to safe defaults so a malformed message can never crash the renderer. + static func fromMap(_ m: [String: Any]) -> GearSnapshot { + func optInt(_ key: String) -> Int? { m[key] as? Int } + return GearSnapshot( + gear: m["gear"] as? Int ?? 0, + maxGear: m["maxGear"] as? Int ?? 0, + mode: m["mode"] as? String ?? "sim", + powerW: optInt("powerW"), + cadenceRpm: optInt("cadenceRpm"), + ergTargetW: optInt("ergTargetW"), + gearRatio: m["gearRatio"] as? Double ?? 1.0, + showPower: m["showPower"] as? Bool ?? false, + showCadence: m["showCadence"] as? Bool ?? false, + showErgTarget: m["showErgTarget"] as? Bool ?? false, + showGearRatio: m["showGearRatio"] as? Bool ?? false, + showControls: m["showControls"] as? Bool ?? false + ) + } +} + +@available(iOS 16.1, *) +extension GearSnapshot { + /// Read the live_activities plugin's id-prefixed App Group keys (used by the + /// Lock-Screen / Dynamic Island widget). Replaces the extension's old + /// private `snapshot(for:)`. + static func fromLiveActivity(_ attrs: LiveActivitiesAppAttributes, defaults: UserDefaults) -> GearSnapshot { + func k(_ s: String) -> String { attrs.prefixedKey(s) } + func optInt(_ key: String) -> Int? { defaults.object(forKey: key) as? Int } + return GearSnapshot( + gear: defaults.integer(forKey: k("gear")), + maxGear: defaults.integer(forKey: k("maxGear")), + mode: defaults.string(forKey: k("mode")) ?? "sim", + powerW: optInt(k("powerW")), + cadenceRpm: optInt(k("cadenceRpm")), + ergTargetW: optInt(k("ergTargetW")), + gearRatio: defaults.double(forKey: k("gearRatio")), + showPower: defaults.bool(forKey: k("showPower")), + showCadence: defaults.bool(forKey: k("showCadence")), + showErgTarget: defaults.bool(forKey: k("showErgTarget")), + showGearRatio: defaults.bool(forKey: k("showGearRatio")), + showControls: defaults.bool(forKey: k("showControls")) + ) + } +} diff --git a/ios/TrainerActivity/TrainerActivity.swift b/ios/TrainerActivity/TrainerActivity.swift index d9c7067b..151b7ab4 100644 --- a/ios/TrainerActivity/TrainerActivity.swift +++ b/ios/TrainerActivity/TrainerActivity.swift @@ -8,57 +8,6 @@ import WidgetKit // `IosOverlayController`. let sharedDefault = UserDefaults(suiteName: "group.de.jonasbark.swiftcontrol.overlay")! -// MARK: - Snapshot - -private struct TrainerSnapshot { - let gear: Int - let maxGear: Int - let mode: String // "sim" | "erg" - let powerW: Int? - let cadenceRpm: Int? - let ergTargetW: Int? - let gearRatio: Double - let showPower: Bool - let showCadence: Bool - let showErgTarget: Bool - let showGearRatio: Bool - let showControls: Bool - - var isErg: Bool { mode == "erg" } - - /// Big primary value: target watts in ERG, gear N/M in SIM. - var primaryText: String { - if isErg { - if let w = ergTargetW { return "\(w) W" } - return "-- W" - } else { - return "\(gear) / \(maxGear)" - } - } -} - -@available(iOSApplicationExtension 16.1, *) -private func snapshot(for attrs: LiveActivitiesAppAttributes) -> TrainerSnapshot { - func k(_ s: String) -> String { attrs.prefixedKey(s) } - func optInt(_ key: String) -> Int? { - sharedDefault.object(forKey: key) as? Int - } - return TrainerSnapshot( - gear: sharedDefault.integer(forKey: k("gear")), - maxGear: sharedDefault.integer(forKey: k("maxGear")), - mode: sharedDefault.string(forKey: k("mode")) ?? "sim", - powerW: optInt(k("powerW")), - cadenceRpm: optInt(k("cadenceRpm")), - ergTargetW: optInt(k("ergTargetW")), - gearRatio: sharedDefault.double(forKey: k("gearRatio")), - showPower: sharedDefault.bool(forKey: k("showPower")), - showCadence: sharedDefault.bool(forKey: k("showCadence")), - showErgTarget: sharedDefault.bool(forKey: k("showErgTarget")), - showGearRatio: sharedDefault.bool(forKey: k("showGearRatio")), - showControls: sharedDefault.bool(forKey: k("showControls")) - ) -} - // MARK: - Bundle entry point @main @@ -80,7 +29,7 @@ struct TrainerActivity: Widget { // `.environment(\.colorScheme, .dark)` forces light-on-dark text on // every device regardless of the user's system appearance, matching // the dark `activityBackgroundTint`. - let s = snapshot(for: context.attributes) + let s = GearSnapshot.fromLiveActivity(context.attributes, defaults: sharedDefault) VStack(spacing: 4) { primaryRow(s) bottomRow(s) @@ -91,7 +40,7 @@ struct TrainerActivity: Widget { .activityBackgroundTint(Color.black.opacity(0.55)) .activitySystemActionForegroundColor(Color.white) } dynamicIsland: { context in - let s = snapshot(for: context.attributes) + let s = GearSnapshot.fromLiveActivity(context.attributes, defaults: sharedDefault) return DynamicIsland { DynamicIslandExpandedRegion(.leading) { Text(s.primaryText) @@ -116,13 +65,13 @@ struct TrainerActivity: Widget { .frame(width: 18, height: 18) .clipShape(RoundedRectangle(cornerRadius: 4)) } compactTrailing: { - Text(compactTrailing(s)) + Text(s.compactTrailing) .font(.caption2.monospacedDigit()) .foregroundStyle(.white) .lineLimit(1) .contentTransition(.numericText()) } minimal: { - Text(minimalText(s)) + Text(s.minimalText) .font(.caption2.bold()) .monospacedDigit() .foregroundStyle(.white) @@ -135,7 +84,7 @@ struct TrainerActivity: Widget { /// primary when `OverlayField.controls` is enabled (iOS 17+ only — the /// `AppIntent`-driven `Button(intent:)` initialiser requires it). @ViewBuilder - private func primaryRow(_ s: TrainerSnapshot) -> some View { + private func primaryRow(_ s: GearSnapshot) -> some View { if s.showControls, #available(iOSApplicationExtension 17.0, *) { HStack(spacing: 12) { Button(intent: ShiftPrimaryDecrementIntent()) { @@ -189,7 +138,7 @@ struct TrainerActivity: Widget { /// (The compact / minimal Dynamic Island layouts have no room for a /// secondary control.) @ViewBuilder - private func bottomRow(_ s: TrainerSnapshot) -> some View { + private func bottomRow(_ s: GearSnapshot) -> some View { HStack(spacing: 10) { modePill(s.mode) Spacer() @@ -231,18 +180,4 @@ struct TrainerActivity: Widget { .lineLimit(1) .contentTransition(.numericText()) } - - /// Compact-trailing on the Dynamic Island: very tight, ~8 chars max. - private func compactTrailing(_ s: TrainerSnapshot) -> String { - s.isErg - ? (s.ergTargetW.map { "\($0)W" } ?? "--W") - : "\(s.gear)/\(s.maxGear)" - } - - /// Minimal Dynamic Island: just the gear number or the watts target. - private func minimalText(_ s: TrainerSnapshot) -> String { - s.isErg - ? (s.ergTargetW.map { "\($0)" } ?? "--") - : "\(s.gear)" - } } From 898b0e8c3681463bd34e5eeddfd6be8859e3d3fd Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:17:04 +0200 Subject: [PATCH 053/106] feat(ios): add DeviceCapabilities (Dynamic Island detection, PiP eligibility) --- ios/Runner/DeviceCapabilities.swift | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 ios/Runner/DeviceCapabilities.swift diff --git a/ios/Runner/DeviceCapabilities.swift b/ios/Runner/DeviceCapabilities.swift new file mode 100644 index 00000000..7c4ab69d --- /dev/null +++ b/ios/Runner/DeviceCapabilities.swift @@ -0,0 +1,36 @@ +import AVKit +import UIKit + +enum DeviceCapabilities { + /// No public API exposes "has Dynamic Island". Heuristic: Dynamic Island + /// iPhones report a larger portrait top safe-area inset (~59pt) than notch + /// devices (≤48pt). iPads have no Dynamic Island. + /// + /// Misdetection is benign: the only false positive is a DI iPhone evaluated + /// in landscape (small top inset) being treated as non-DI, which merely adds + /// a (redundant) PiP alongside the Dynamic Island. A non-DI phone can never + /// be mistaken for DI (its inset never reaches the threshold). + static var hasDynamicIsland: Bool { + guard UIDevice.current.userInterfaceIdiom == .phone else { return false } + return keyWindowTopInset() >= 51 + } + + /// PiP is the chosen floating display on iPad and on iPhones WITHOUT a + /// Dynamic Island. Requires iOS 16+ (ImageRenderer) and device PiP support. + static var pipEligible: Bool { + guard #available(iOS 16.0, *) else { return false } + guard AVPictureInPictureController.isPictureInPictureSupported() else { return false } + if UIDevice.current.userInterfaceIdiom == .pad { return true } + return !hasDynamicIsland + } + + private static func keyWindowTopInset() -> CGFloat { + for scene in UIApplication.shared.connectedScenes { + guard let ws = scene as? UIWindowScene else { continue } + if let w = ws.windows.first(where: { $0.isKeyWindow }) ?? ws.windows.first { + return w.safeAreaInsets.top + } + } + return 0 + } +} From e6927bec76d8a982bffcb6df40842b29fc0a36f2 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:20:46 +0200 Subject: [PATCH 054/106] feat(ios): add PipGearController and Picture in Picture background mode Co-Authored-By: Claude Opus 4.8 (1M context) --- ios/Runner/Info.plist | 1 + ios/Runner/PipGearController.swift | 229 +++++++++++++++++++++++++++++ 2 files changed, 230 insertions(+) create mode 100644 ios/Runner/PipGearController.swift diff --git a/ios/Runner/Info.plist b/ios/Runner/Info.plist index d9a19ac9..bd5b3a58 100644 --- a/ios/Runner/Info.plist +++ b/ios/Runner/Info.plist @@ -86,6 +86,7 @@ bluetooth-peripheral bluetooth-central audio + picture-in-picture UILaunchStoryboardName LaunchScreen diff --git a/ios/Runner/PipGearController.swift b/ios/Runner/PipGearController.swift new file mode 100644 index 00000000..0c4349a8 --- /dev/null +++ b/ios/Runner/PipGearController.swift @@ -0,0 +1,229 @@ +import AVFoundation +import AVKit +import SwiftUI +import UIKit + +/// Renders the current-gear readout into a floating Picture-in-Picture window +/// that survives the trainer app going full-screen. Frames are drawn natively +/// from `GearReadoutView` (no Flutter render loop), so the window keeps updating +/// while BikeControl is backgrounded, riding on the active background audio +/// session that `SharedLogic.keepAlive` already maintains. +@available(iOS 16.0, *) +final class PipGearController: NSObject { + static let shared = PipGearController() + + private let displayLayer = AVSampleBufferDisplayLayer() + private var pipController: AVPictureInPictureController? + private var pump: DispatchSourceTimer? + private var hostView: UIView? + private var pool: CVPixelBufferPool? + private var ptsCount: Int64 = 0 + private var lastHash: Int? + private var snapshot: GearSnapshot? + + private let fps: Int32 = 2 + private let renderSize = CGSize(width: 480, height: 270) // 16:9 + + private override init() { super.init() } + + /// Prepare and arm PiP while the app is foreground. PiP becomes visible + /// automatically when the app is backgrounded (canStart...FromInline). + func start(initial: [String: Any]) { + guard AVPictureInPictureController.isPictureInPictureSupported() else { + NSLog("[PiP] unsupported device"); return + } + guard pipController == nil else { update(initial); return } // already armed + snapshot = GearSnapshot.fromMap(initial) + configureAudioSession() + guard attachLayer() else { NSLog("[PiP] no window to attach layer"); return } + makePool() + + displayLayer.videoGravity = .resizeAspect + let source = AVPictureInPictureController.ContentSource( + sampleBufferDisplayLayer: displayLayer, + playbackDelegate: self + ) + let controller = AVPictureInPictureController(contentSource: source) + controller.canStartPictureInPictureAutomaticallyFromInline = true + controller.delegate = self + pipController = controller + + startPump() + } + + func update(_ map: [String: Any]) { + snapshot = GearSnapshot.fromMap(map) + } + + func stop() { + pump?.cancel(); pump = nil + if pipController?.isPictureInPictureActive == true { + pipController?.stopPictureInPicture() + } + pipController = nil + displayLayer.flushAndRemoveImage() + hostView?.removeFromSuperview() + hostView = nil + pool = nil + snapshot = nil + lastHash = nil + ptsCount = 0 + } + + // MARK: - Audio session + + private func configureAudioSession() { + let session = AVAudioSession.sharedInstance() + do { + // .mixWithOthers so we never duck/stop the trainer app's audio. + try session.setCategory(.playback, mode: .default, options: [.mixWithOthers]) + try session.setActive(true) + } catch { + NSLog("[PiP] audio session error: \(error)") + } + } + + // MARK: - Layer hosting + + private func attachLayer() -> Bool { + guard let rootView = Self.keyRootView() else { return false } + let container = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1)) + container.isUserInteractionEnabled = false + container.layer.addSublayer(displayLayer) + displayLayer.frame = container.bounds + rootView.insertSubview(container, at: 0) // behind Flutter; effectively invisible + hostView = container + return true + } + + private static func keyRootView() -> UIView? { + for scene in UIApplication.shared.connectedScenes { + guard let ws = scene as? UIWindowScene else { continue } + if let w = ws.windows.first(where: { $0.isKeyWindow }) ?? ws.windows.first { + return w.rootViewController?.view + } + } + return nil + } + + // MARK: - Pixel buffer pool + + private func makePool() { + let attrs: [String: Any] = [ + kCVPixelBufferPixelFormatTypeKey as String: kCVPixelFormatType_32BGRA, + kCVPixelBufferWidthKey as String: Int(renderSize.width), + kCVPixelBufferHeightKey as String: Int(renderSize.height), + kCVPixelBufferCGBitmapContextCompatibilityKey as String: true, + ] + CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attrs as CFDictionary, &pool) + } + + // MARK: - Frame pump + + private func startPump() { + let timer = DispatchSource.makeTimerSource(queue: .main) + timer.schedule(deadline: .now(), repeating: .milliseconds(Int(1000 / fps))) + timer.setEventHandler { [weak self] in self?.renderTick() } + timer.resume() + pump = timer + } + + private func renderTick() { + guard let snapshot = snapshot else { return } + let hash = snapshot.contentHash + // Skip identical frames, but always emit the first one. + if hash == lastHash, ptsCount > 0 { return } + lastHash = hash + + guard let pb = makePixelBuffer(for: snapshot), + let sample = makeSampleBuffer(from: pb) else { return } + if displayLayer.status == .failed { displayLayer.flush() } + displayLayer.enqueue(sample) + } + + private func makePixelBuffer(for snapshot: GearSnapshot) -> CVPixelBuffer? { + guard let pool = pool else { return nil } + var pbOut: CVPixelBuffer? + guard CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pbOut) == kCVReturnSuccess, + let pb = pbOut else { return nil } + + let renderer = ImageRenderer(content: + GearReadoutView(snapshot: snapshot) + .frame(width: renderSize.width, height: renderSize.height) + ) + renderer.scale = 2.0 + guard let cgImage = renderer.cgImage else { return nil } + + CVPixelBufferLockBaseAddress(pb, []) + defer { CVPixelBufferUnlockBaseAddress(pb, []) } + guard let ctx = CGContext( + data: CVPixelBufferGetBaseAddress(pb), + width: CVPixelBufferGetWidth(pb), + height: CVPixelBufferGetHeight(pb), + bitsPerComponent: 8, + bytesPerRow: CVPixelBufferGetBytesPerRow(pb), + space: CGColorSpaceCreateDeviceRGB(), + bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue + ) else { return nil } + ctx.draw(cgImage, in: CGRect(x: 0, y: 0, + width: CVPixelBufferGetWidth(pb), + height: CVPixelBufferGetHeight(pb))) + return pb + } + + private func makeSampleBuffer(from pixelBuffer: CVPixelBuffer) -> CMSampleBuffer? { + var fmt: CMVideoFormatDescription? + guard CMVideoFormatDescriptionCreateForImageBuffer( + allocator: kCFAllocatorDefault, imageBuffer: pixelBuffer, formatDescriptionOut: &fmt + ) == noErr, let fmt = fmt else { return nil } + + let scale = CMTimeScale(fps) + var timing = CMSampleTimingInfo( + duration: CMTime(value: 1, timescale: scale), + presentationTimeStamp: CMTime(value: ptsCount, timescale: scale), + decodeTimeStamp: .invalid + ) + ptsCount += 1 + var sampleOut: CMSampleBuffer? + guard CMSampleBufferCreateForImageBuffer( + allocator: kCFAllocatorDefault, + imageBuffer: pixelBuffer, + dataReady: true, + makeDataReadyCallback: nil, + refcon: nil, + formatDescription: fmt, + sampleTiming: &timing, + sampleBufferOut: &sampleOut + ) == noErr else { return nil } + return sampleOut + } +} + +@available(iOS 16.0, *) +extension PipGearController: AVPictureInPictureControllerDelegate { + func pictureInPictureController(_ c: AVPictureInPictureController, + failedToStartPictureInPictureWithError error: Error) { + NSLog("[PiP] failed to start: \(error)") + } + + func pictureInPictureController( + _ c: AVPictureInPictureController, + restoreUserInterfaceForPictureInPictureStopWithCompletionHandler completionHandler: @escaping (Bool) -> Void + ) { + completionHandler(true) // tapping the window brings BikeControl forward + } +} + +@available(iOS 16.0, *) +extension PipGearController: AVPictureInPictureSampleBufferPlaybackDelegate { + func pictureInPictureController(_ c: AVPictureInPictureController, setPlaying playing: Bool) {} + func pictureInPictureControllerTimeRangeForPlayback(_ c: AVPictureInPictureController) -> CMTimeRange { + CMTimeRange(start: .negativeInfinity, duration: .positiveInfinity) // live, no scrubber + } + func pictureInPictureControllerIsPlaybackPaused(_ c: AVPictureInPictureController) -> Bool { false } + func pictureInPictureController(_ c: AVPictureInPictureController, + didTransitionToRenderSize newRenderSize: CMVideoDimensions) {} + func pictureInPictureController(_ c: AVPictureInPictureController, + skipByInterval skipInterval: CMTime, + completion: @escaping () -> Void) { completion() } +} From 38c6c701e11b8d63cbb9b74bacbb9cd9f98a0cb1 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:26:34 +0200 Subject: [PATCH 055/106] fix(ios): check pixel buffer pool creation; document main-actor pump invariant --- ios/Runner/PipGearController.swift | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/ios/Runner/PipGearController.swift b/ios/Runner/PipGearController.swift index 0c4349a8..0fc4cb0d 100644 --- a/ios/Runner/PipGearController.swift +++ b/ios/Runner/PipGearController.swift @@ -115,7 +115,10 @@ final class PipGearController: NSObject { kCVPixelBufferHeightKey as String: Int(renderSize.height), kCVPixelBufferCGBitmapContextCompatibilityKey as String: true, ] - CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attrs as CFDictionary, &pool) + let status = CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attrs as CFDictionary, &pool) + if status != kCVReturnSuccess { + NSLog("[PiP] CVPixelBufferPoolCreate failed: \(status)") + } } // MARK: - Frame pump @@ -128,6 +131,11 @@ final class PipGearController: NSObject { pump = timer } + // MUST run on the main queue: `ImageRenderer.cgImage` (in makePixelBuffer) is + // @MainActor-isolated. The pump timer is scheduled on `.main` for this reason. + // If the pump is ever moved off-main to survive backgrounding, split rendering + // so the CGImage is produced on the main actor and only the finished + // CVPixelBuffer/CMSampleBuffer is enqueued off-main. private func renderTick() { guard let snapshot = snapshot else { return } let hash = snapshot.contentHash From 0a1f4851a5ab632c177ed0bd974cb6e27b36874e Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:28:35 +0200 Subject: [PATCH 056/106] feat(ios): wire bike_control/pip_ios method channel --- ios/Runner/AppDelegate.swift | 38 ++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index fd74026f..a71342a4 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -8,8 +8,10 @@ import UIKit /// a MethodCallHandler on this channel; native code below forwards Darwin /// notifications posted by the extension's `AppIntent`s. private static let overlayActionsChannel = "bike_control/overlay_actions_ios" + private static let pipChannelName = "bike_control/pip_ios" private var actionChannel: FlutterMethodChannel? + private var pipChannel: FlutterMethodChannel? override func application( _ application: UIApplication, @@ -39,6 +41,42 @@ import UIKit binaryMessenger: registrar.messenger() ) } + + if pipChannel == nil, + let registrar = engineBridge.pluginRegistry.registrar(forPlugin: "BikeControlPip") { + let channel = FlutterMethodChannel( + name: AppDelegate.pipChannelName, + binaryMessenger: registrar.messenger() + ) + channel.setMethodCallHandler { call, result in + switch call.method { + case "isSupported": + if #available(iOS 16.0, *) { + result(DeviceCapabilities.pipEligible) + } else { + result(false) + } + case "start": + if #available(iOS 16.0, *) { + PipGearController.shared.start(initial: call.arguments as? [String: Any] ?? [:]) + } + result(nil) + case "update": + if #available(iOS 16.0, *) { + PipGearController.shared.update(call.arguments as? [String: Any] ?? [:]) + } + result(nil) + case "stop": + if #available(iOS 16.0, *) { + PipGearController.shared.stop() + } + result(nil) + default: + result(FlutterMethodNotImplemented) + } + } + pipChannel = channel + } } // MARK: - Live Activity Darwin notification bridge From be6334077dc93b1a6ebef0000a956eba8eb41cba Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:33:15 +0200 Subject: [PATCH 057/106] feat(overlay): add IosPipController + shared overlayStateToActivityMap --- .../overlay/ios_overlay_controller.dart | 22 +------ lib/services/overlay/ios_pip_controller.dart | 44 +++++++++++++ lib/services/overlay/overlay_state.dart | 23 +++++++ .../overlay/ios_pip_controller_test.dart | 61 +++++++++++++++++++ .../overlay/overlay_state_map_test.dart | 49 +++++++++++++++ 5 files changed, 178 insertions(+), 21 deletions(-) create mode 100644 lib/services/overlay/ios_pip_controller.dart create mode 100644 test/services/overlay/ios_pip_controller_test.dart create mode 100644 test/services/overlay/overlay_state_map_test.dart diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index 18bc2d98..21eb9cad 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -153,27 +153,7 @@ class IosOverlayController implements TrainerOverlayController { ); } - // live_activities routes the map through NSUserDefaults in the App Group, - // which crashes on null values (NSInvalidArgumentException). Optional Swift - // fields (Int?) decode missing keys as nil via Codable, so omitting nulls - // yields the same ContentState. - Map _toMap(TrainerOverlayState s) { - final m = { - 'gear': s.gear, - 'maxGear': s.maxGear, - 'mode': s.mode == TrainerMode.ergMode ? 'erg' : 'sim', - 'showPower': s.fields.contains(OverlayField.power), - 'showCadence': s.fields.contains(OverlayField.cadence), - 'showErgTarget': s.fields.contains(OverlayField.ergTarget), - 'showGearRatio': s.fields.contains(OverlayField.gearRatio), - 'showControls': s.fields.contains(OverlayField.controls), - 'gearRatio': s.gearRatio, - }; - if (s.powerW != null) m['powerW'] = s.powerW; - if (s.cadenceRpm != null) m['cadenceRpm'] = s.cadenceRpm; - if (s.ergTargetW != null) m['ergTargetW'] = s.ergTargetW; - return m; - } + Map _toMap(TrainerOverlayState s) => overlayStateToActivityMap(s); Future _push({bool force = false}) async { final id = _activityId; diff --git a/lib/services/overlay/ios_pip_controller.dart b/lib/services/overlay/ios_pip_controller.dart new file mode 100644 index 00000000..99d5eed3 --- /dev/null +++ b/lib/services/overlay/ios_pip_controller.dart @@ -0,0 +1,44 @@ +import 'package:bike_control/main.dart'; +import 'package:flutter/services.dart'; + +/// Thin Dart wrapper over the native `bike_control/pip_ios` channel. PiP runs +/// in the app process, so gear state is pushed straight over the channel into +/// `PipGearController`'s memory — no App Group UserDefaults round-trip. +class IosPipController { + static const _channel = MethodChannel('bike_control/pip_ios'); + + /// True on iPad and non-Dynamic-Island iPhones (iOS 16+). False on + /// Dynamic-Island iPhones and where PiP is unsupported. + Future isSupported() async { + try { + return await _channel.invokeMethod('isSupported') ?? false; + } catch (e, s) { + recordError(e, s, context: 'pip.ios.isSupported'); + return false; + } + } + + Future start(Map state) async { + try { + await _channel.invokeMethod('start', state); + } catch (e, s) { + recordError(e, s, context: 'pip.ios.start'); + } + } + + Future update(Map state) async { + try { + await _channel.invokeMethod('update', state); + } catch (e, s) { + recordError(e, s, context: 'pip.ios.update'); + } + } + + Future stop() async { + try { + await _channel.invokeMethod('stop'); + } catch (e, s) { + recordError(e, s, context: 'pip.ios.stop'); + } + } +} diff --git a/lib/services/overlay/overlay_state.dart b/lib/services/overlay/overlay_state.dart index 3b28d607..06a8e439 100644 --- a/lib/services/overlay/overlay_state.dart +++ b/lib/services/overlay/overlay_state.dart @@ -108,3 +108,26 @@ class TrainerOverlayState { return true; } } + +/// Serialize overlay state to the map shape consumed by the iOS Live Activity +/// (via the live_activities plugin's App Group UserDefaults) AND by the PiP +/// channel. Omits null optional metrics: the Live Activity path routes through +/// NSUserDefaults which crashes on null values, and Swift's optional `Int?` +/// fields decode missing keys as nil either way. +Map overlayStateToActivityMap(TrainerOverlayState s) { + final m = { + 'gear': s.gear, + 'maxGear': s.maxGear, + 'mode': s.mode == TrainerMode.ergMode ? 'erg' : 'sim', + 'showPower': s.fields.contains(OverlayField.power), + 'showCadence': s.fields.contains(OverlayField.cadence), + 'showErgTarget': s.fields.contains(OverlayField.ergTarget), + 'showGearRatio': s.fields.contains(OverlayField.gearRatio), + 'showControls': s.fields.contains(OverlayField.controls), + 'gearRatio': s.gearRatio, + }; + if (s.powerW != null) m['powerW'] = s.powerW; + if (s.cadenceRpm != null) m['cadenceRpm'] = s.cadenceRpm; + if (s.ergTargetW != null) m['ergTargetW'] = s.ergTargetW; + return m; +} diff --git a/test/services/overlay/ios_pip_controller_test.dart b/test/services/overlay/ios_pip_controller_test.dart new file mode 100644 index 00000000..3e80ce6f --- /dev/null +++ b/test/services/overlay/ios_pip_controller_test.dart @@ -0,0 +1,61 @@ +import 'package:bike_control/services/overlay/ios_pip_controller.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + TestWidgetsFlutterBinding.ensureInitialized(); + + const channel = MethodChannel('bike_control/pip_ios'); + final calls = []; + + setUp(() { + calls.clear(); + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (call) async { + calls.add(call); + if (call.method == 'isSupported') return true; + return null; + }); + }); + + tearDown(() { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, null); + }); + + test('isSupported returns the native boolean', () async { + final pip = IosPipController(); + expect(await pip.isSupported(), true); + expect(calls.single.method, 'isSupported'); + }); + + test('start forwards the state map', () async { + final pip = IosPipController(); + await pip.start({'gear': 7, 'maxGear': 12}); + expect(calls.single.method, 'start'); + expect(calls.single.arguments, {'gear': 7, 'maxGear': 12}); + }); + + test('update forwards the state map', () async { + final pip = IosPipController(); + await pip.update({'gear': 8}); + expect(calls.single.method, 'update'); + expect(calls.single.arguments, {'gear': 8}); + }); + + test('stop invokes stop with no arguments', () async { + final pip = IosPipController(); + await pip.stop(); + expect(calls.single.method, 'stop'); + expect(calls.single.arguments, isNull); + }); + + test('isSupported returns false when the channel throws', () async { + TestDefaultBinaryMessengerBinding.instance.defaultBinaryMessenger + .setMockMethodCallHandler(channel, (call) async { + throw PlatformException(code: 'boom'); + }); + final pip = IosPipController(); + expect(await pip.isSupported(), false); + }); +} diff --git a/test/services/overlay/overlay_state_map_test.dart b/test/services/overlay/overlay_state_map_test.dart new file mode 100644 index 00000000..d970c5db --- /dev/null +++ b/test/services/overlay/overlay_state_map_test.dart @@ -0,0 +1,49 @@ +import 'package:bike_control/services/overlay/overlay_state.dart'; +import 'package:flutter_test/flutter_test.dart'; +import 'package:prop/emulators/definitions/fitness_bike_definition.dart'; + +void main() { + group('overlayStateToActivityMap', () { + test('maps sim mode and omits null optional metrics', () { + final s = TrainerOverlayState( + gear: 7, + maxGear: 12, + gearRatio: 2.04, + mode: TrainerMode.simMode, + powerW: null, + cadenceRpm: null, + ergTargetW: null, + fields: {OverlayField.gearRatio}, + ); + final m = overlayStateToActivityMap(s); + expect(m['gear'], 7); + expect(m['maxGear'], 12); + expect(m['mode'], 'sim'); + expect(m['gearRatio'], 2.04); + expect(m['showGearRatio'], true); + expect(m['showPower'], false); + expect(m.containsKey('powerW'), false); + expect(m.containsKey('cadenceRpm'), false); + expect(m.containsKey('ergTargetW'), false); + }); + + test('maps erg mode and includes present optional metrics', () { + final s = TrainerOverlayState( + gear: 1, + maxGear: 24, + gearRatio: 1.0, + mode: TrainerMode.ergMode, + powerW: 210, + cadenceRpm: 88, + ergTargetW: 250, + fields: {OverlayField.power, OverlayField.cadence, OverlayField.ergTarget}, + ); + final m = overlayStateToActivityMap(s); + expect(m['mode'], 'erg'); + expect(m['powerW'], 210); + expect(m['cadenceRpm'], 88); + expect(m['ergTargetW'], 250); + expect(m['showErgTarget'], true); + }); + }); +} From 52252bfa0f92925a74b2e466c64164fdea0c26be Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:38:00 +0200 Subject: [PATCH 058/106] feat(overlay): drive PiP gear window from IosOverlayController on eligible devices --- .../overlay/ios_overlay_controller.dart | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index 21eb9cad..6cbce237 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -2,6 +2,7 @@ import 'dart:async'; import 'dart:math'; import 'package:bike_control/main.dart'; +import 'package:bike_control/services/overlay/ios_pip_controller.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/services/overlay/trainer_overlay_controller.dart'; import 'package:bike_control/utils/core.dart'; @@ -23,6 +24,8 @@ class IosOverlayController implements TrainerOverlayController { final ValueNotifier _showing = ValueNotifier(false); final LiveActivities _la = LiveActivities(); String? _activityId; + final IosPipController _pip = IosPipController(); + bool _pipActive = false; FitnessBikeDefinition? _def; LiveDefinitionLookup? _liveDef; @@ -79,6 +82,14 @@ class IosOverlayController implements TrainerOverlayController { } _showing.value = true; + try { + if (await _pip.isSupported()) { + await _pip.start(_toMap(s)); + _pipActive = true; + } + } catch (e, st) { + recordError(e, st, context: 'overlay.ios.pip.start'); + } return const OverlayShowResult.ok(); } @@ -101,6 +112,10 @@ class IosOverlayController implements TrainerOverlayController { _activityId = null; } _showing.value = false; + if (_pipActive) { + await _pip.stop(); + _pipActive = false; + } } @override @@ -167,6 +182,9 @@ class IosOverlayController implements TrainerOverlayController { _lastPushAt = DateTime.now(); try { await _la.updateActivity(id, _toMap(s)); + if (_pipActive) { + await _pip.update(_toMap(s)); + } } catch (error, stack) { recordError(error, stack, context: 'overlay.ios.updateActivity'); } From 5dd0a3855737d9949e8a337a1b05d03a38c408aa Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 16:41:05 +0200 Subject: [PATCH 059/106] fix(overlay): guard PiP stop() in hide() so _pipActive always resets Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/services/overlay/ios_overlay_controller.dart | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index 6cbce237..a81172b8 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -113,7 +113,11 @@ class IosOverlayController implements TrainerOverlayController { } _showing.value = false; if (_pipActive) { - await _pip.stop(); + try { + await _pip.stop(); + } catch (e, s) { + recordError(e, s, context: 'overlay.ios.pip.stop'); + } _pipActive = false; } } From adaef40fddffa249821beb2a8ead2e33a625d0b5 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:08:59 +0200 Subject: [PATCH 060/106] fix(ios): move fromLiveActivity to extension-only file so Runner compiles without ActivityKit --- ios/Shared/GearSnapshot+LiveActivity.swift | 29 ++++++++++++++++++++++ ios/Shared/GearSnapshot.swift | 26 ------------------- 2 files changed, 29 insertions(+), 26 deletions(-) create mode 100644 ios/Shared/GearSnapshot+LiveActivity.swift diff --git a/ios/Shared/GearSnapshot+LiveActivity.swift b/ios/Shared/GearSnapshot+LiveActivity.swift new file mode 100644 index 00000000..273b167c --- /dev/null +++ b/ios/Shared/GearSnapshot+LiveActivity.swift @@ -0,0 +1,29 @@ +import ActivityKit +import Foundation + +@available(iOS 16.1, *) +extension GearSnapshot { + /// Read the live_activities plugin's id-prefixed App Group keys (used by the + /// Lock-Screen / Dynamic Island widget). Lives in a TrainerActivity-target-ONLY + /// file (NOT compiled into Runner) because `LiveActivitiesAppAttributes` is + /// defined in the widget extension target. Keeping it out of the shared + /// `GearSnapshot.swift` lets that file compile into Runner without ActivityKit. + static func fromLiveActivity(_ attrs: LiveActivitiesAppAttributes, defaults: UserDefaults) -> GearSnapshot { + func k(_ s: String) -> String { attrs.prefixedKey(s) } + func optInt(_ key: String) -> Int? { defaults.object(forKey: key) as? Int } + return GearSnapshot( + gear: defaults.integer(forKey: k("gear")), + maxGear: defaults.integer(forKey: k("maxGear")), + mode: defaults.string(forKey: k("mode")) ?? "sim", + powerW: optInt(k("powerW")), + cadenceRpm: optInt(k("cadenceRpm")), + ergTargetW: optInt(k("ergTargetW")), + gearRatio: defaults.double(forKey: k("gearRatio")), + showPower: defaults.bool(forKey: k("showPower")), + showCadence: defaults.bool(forKey: k("showCadence")), + showErgTarget: defaults.bool(forKey: k("showErgTarget")), + showGearRatio: defaults.bool(forKey: k("showGearRatio")), + showControls: defaults.bool(forKey: k("showControls")) + ) + } +} diff --git a/ios/Shared/GearSnapshot.swift b/ios/Shared/GearSnapshot.swift index 78b13460..08f9fba1 100644 --- a/ios/Shared/GearSnapshot.swift +++ b/ios/Shared/GearSnapshot.swift @@ -1,4 +1,3 @@ -import ActivityKit import Foundation /// Shared gear readout model. Compiled into BOTH the Runner app (for PiP) and @@ -67,28 +66,3 @@ extension GearSnapshot { ) } } - -@available(iOS 16.1, *) -extension GearSnapshot { - /// Read the live_activities plugin's id-prefixed App Group keys (used by the - /// Lock-Screen / Dynamic Island widget). Replaces the extension's old - /// private `snapshot(for:)`. - static func fromLiveActivity(_ attrs: LiveActivitiesAppAttributes, defaults: UserDefaults) -> GearSnapshot { - func k(_ s: String) -> String { attrs.prefixedKey(s) } - func optInt(_ key: String) -> Int? { defaults.object(forKey: key) as? Int } - return GearSnapshot( - gear: defaults.integer(forKey: k("gear")), - maxGear: defaults.integer(forKey: k("maxGear")), - mode: defaults.string(forKey: k("mode")) ?? "sim", - powerW: optInt(k("powerW")), - cadenceRpm: optInt(k("cadenceRpm")), - ergTargetW: optInt(k("ergTargetW")), - gearRatio: defaults.double(forKey: k("gearRatio")), - showPower: defaults.bool(forKey: k("showPower")), - showCadence: defaults.bool(forKey: k("showCadence")), - showErgTarget: defaults.bool(forKey: k("showErgTarget")), - showGearRatio: defaults.bool(forKey: k("showGearRatio")), - showControls: defaults.bool(forKey: k("showControls")) - ) - } -} From 9b070f0a659bf4bed8cfcfd1eef286c54d6350cd Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 17:21:40 +0200 Subject: [PATCH 061/106] fix(ios): run PiP render path on the main actor (ImageRenderer is @MainActor) --- ios/Runner/PipGearController.swift | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/ios/Runner/PipGearController.swift b/ios/Runner/PipGearController.swift index 0fc4cb0d..21a2f7ae 100644 --- a/ios/Runner/PipGearController.swift +++ b/ios/Runner/PipGearController.swift @@ -126,17 +126,18 @@ final class PipGearController: NSObject { private func startPump() { let timer = DispatchSource.makeTimerSource(queue: .main) timer.schedule(deadline: .now(), repeating: .milliseconds(Int(1000 / fps))) - timer.setEventHandler { [weak self] in self?.renderTick() } + timer.setEventHandler { [weak self] in Task { @MainActor in self?.renderTick() } } timer.resume() pump = timer } - // MUST run on the main queue: `ImageRenderer.cgImage` (in makePixelBuffer) is - // @MainActor-isolated. The pump timer is scheduled on `.main` for this reason. - // If the pump is ever moved off-main to survive backgrounding, split rendering - // so the CGImage is produced on the main actor and only the finished - // CVPixelBuffer/CMSampleBuffer is enqueued off-main. - private func renderTick() { + // Runs on the main actor: `ImageRenderer` (in makePixelBuffer) is + // @MainActor-isolated. The pump's DispatchSource timer fires on `.main`, then + // hops onto the main actor via `Task { @MainActor in }` (MainActor.assumeIsolated + // would be tidier but is iOS 17+; this feature targets iOS 16). If the pump is + // ever moved off-main to survive backgrounding, keep the CGImage render on the + // main actor and enqueue the finished CMSampleBuffer off-main. + @MainActor private func renderTick() { guard let snapshot = snapshot else { return } let hash = snapshot.contentHash // Skip identical frames, but always emit the first one. @@ -149,7 +150,7 @@ final class PipGearController: NSObject { displayLayer.enqueue(sample) } - private func makePixelBuffer(for snapshot: GearSnapshot) -> CVPixelBuffer? { + @MainActor private func makePixelBuffer(for snapshot: GearSnapshot) -> CVPixelBuffer? { guard let pool = pool else { return nil } var pbOut: CVPixelBuffer? guard CVPixelBufferPoolCreatePixelBuffer(kCFAllocatorDefault, pool, &pbOut) == kCVReturnSuccess, From 2d15f80e1c03f46d995fb44fa94b8dc2cdfdd1bd Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 18:10:52 +0200 Subject: [PATCH 062/106] =?UTF-8?q?fix(ios):=20render=20PiP=20frames=20?= =?UTF-8?q?=E2=80=94=20IOSurface-backed=20pixel=20buffers=20+=20DisplayImm?= =?UTF-8?q?ediately?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit AVSampleBufferDisplayLayer only presents IOSurface-backed CVPixelBuffers; the pool omitted kCVPixelBufferIOSurfacePropertiesKey, so frames were accepted (status=.rendering, no error) but never rendered — the PiP window stayed black. Add IOSurface backing and mark each sample buffer DisplayImmediately (no control timebase, live HUD feed). Also wires the PiP Swift files into the Runner / TrainerActivity Xcode targets (GearSnapshot in both; GearSnapshot+LiveActivity in the extension only so Runner needs no ActivityKit). Co-Authored-By: Claude Opus 4.8 (1M context) --- ios/Runner.xcodeproj/project.pbxproj | 36 ++++++++++++++++++++-------- ios/Runner/PipGearController.swift | 26 ++++++++++++++++---- 2 files changed, 48 insertions(+), 14 deletions(-) diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index 0949dd52..d522c652 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -17,6 +17,12 @@ 97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; }; 97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; }; 9DEFD285994D09CFCE400F36 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5CE7ADD07A99710C0FB974A8 /* Pods_Runner.framework */; }; + F02276C12FEC277800C2B6F1 /* GearSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276BF2FEC277800C2B6F1 /* GearSnapshot.swift */; }; + F02276C22FEC277800C2B6F1 /* GearReadoutView.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276C02FEC277800C2B6F1 /* GearReadoutView.swift */; }; + F02276C52FEC278C00C2B6F1 /* DeviceCapabilities.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276C32FEC278C00C2B6F1 /* DeviceCapabilities.swift */; }; + F02276C62FEC278C00C2B6F1 /* PipGearController.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276C42FEC278C00C2B6F1 /* PipGearController.swift */; }; + F02276F12FEC2ADC00C2B6F1 /* GearSnapshot+LiveActivity.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276F02FEC2ADC00C2B6F1 /* GearSnapshot+LiveActivity.swift */; }; + F02277062FEC2B6500C2B6F1 /* GearSnapshot.swift in Sources */ = {isa = PBXBuildFile; fileRef = F02276BF2FEC277800C2B6F1 /* GearSnapshot.swift */; }; F068794F2FAF1F5700395E5C /* WidgetKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F068794E2FAF1F5700395E5C /* WidgetKit.framework */; }; F06879512FAF1F5700395E5C /* SwiftUI.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F06879502FAF1F5700395E5C /* SwiftUI.framework */; }; F06879602FAF1F5900395E5C /* TrainerActivityExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = F068794D2FAF1F5700395E5C /* TrainerActivityExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; }; @@ -88,6 +94,11 @@ 97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; DFFDC4B9C4D6EF6A3BDE2E73 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = ""; }; EFDECED99A47773C293F8819 /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = ""; }; + F02276BF2FEC277800C2B6F1 /* GearSnapshot.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GearSnapshot.swift; path = Shared/GearSnapshot.swift; sourceTree = ""; }; + F02276C02FEC277800C2B6F1 /* GearReadoutView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = GearReadoutView.swift; path = Shared/GearReadoutView.swift; sourceTree = ""; }; + F02276C32FEC278C00C2B6F1 /* DeviceCapabilities.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = DeviceCapabilities.swift; path = Runner/DeviceCapabilities.swift; sourceTree = ""; }; + F02276C42FEC278C00C2B6F1 /* PipGearController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = PipGearController.swift; path = Runner/PipGearController.swift; sourceTree = ""; }; + F02276F02FEC2ADC00C2B6F1 /* GearSnapshot+LiveActivity.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = "GearSnapshot+LiveActivity.swift"; path = "Shared/GearSnapshot+LiveActivity.swift"; sourceTree = ""; }; F068794D2FAF1F5700395E5C /* TrainerActivityExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = TrainerActivityExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; }; F068794E2FAF1F5700395E5C /* WidgetKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = WidgetKit.framework; path = System/Library/Frameworks/WidgetKit.framework; sourceTree = SDKROOT; }; F06879502FAF1F5700395E5C /* SwiftUI.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = SwiftUI.framework; path = System/Library/Frameworks/SwiftUI.framework; sourceTree = SDKROOT; }; @@ -197,6 +208,11 @@ 97C146E51CF9000F007C117D = { isa = PBXGroup; children = ( + F02276F02FEC2ADC00C2B6F1 /* GearSnapshot+LiveActivity.swift */, + F02276C32FEC278C00C2B6F1 /* DeviceCapabilities.swift */, + F02276C42FEC278C00C2B6F1 /* PipGearController.swift */, + F02276C02FEC277800C2B6F1 /* GearReadoutView.swift */, + F02276BF2FEC277800C2B6F1 /* GearSnapshot.swift */, F068796C2FAF203C00395E5C /* TrainerActivityExtension.entitlements */, 9740EEB11CF90186004384FC /* Flutter */, 97C146F01CF9000F007C117D /* Runner */, @@ -504,6 +520,10 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F02276C52FEC278C00C2B6F1 /* DeviceCapabilities.swift in Sources */, + F02276C62FEC278C00C2B6F1 /* PipGearController.swift in Sources */, + F02276C12FEC277800C2B6F1 /* GearSnapshot.swift in Sources */, + F02276C22FEC277800C2B6F1 /* GearReadoutView.swift in Sources */, 74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */, 1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */, ); @@ -513,6 +533,8 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( + F02277062FEC2B6500C2B6F1 /* GearSnapshot.swift in Sources */, + F02276F12FEC2ADC00C2B6F1 /* GearSnapshot+LiveActivity.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -804,11 +826,9 @@ CLANG_ENABLE_MODULES = YES; CODE_SIGN_ENTITLEMENTS = Runner/Runner.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)"; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = UZRHKPVWN9; + DEVELOPMENT_TEAM = UZRHKPVWN9; ENABLE_BITCODE = NO; INFOPLIST_FILE = Runner/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 15.6; @@ -819,7 +839,6 @@ PRODUCT_BUNDLE_IDENTIFIER = de.jonasbark.swiftcontrol.darwin; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "BikeControl Dev"; SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -872,11 +891,9 @@ CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; CODE_SIGN_ENTITLEMENTS = TrainerActivityExtension.entitlements; CODE_SIGN_IDENTITY = "Apple Development"; - "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; - CODE_SIGN_STYLE = Manual; + CODE_SIGN_STYLE = Automatic; CURRENT_PROJECT_VERSION = 1; - DEVELOPMENT_TEAM = ""; - "DEVELOPMENT_TEAM[sdk=iphoneos*]" = UZRHKPVWN9; + DEVELOPMENT_TEAM = UZRHKPVWN9; ENABLE_USER_SCRIPT_SANDBOXING = YES; GCC_C_LANGUAGE_STANDARD = gnu17; GENERATE_INFOPLIST_FILE = YES; @@ -897,7 +914,6 @@ PRODUCT_BUNDLE_IDENTIFIER = de.jonasbark.swiftcontrol.darwin.TrainerActivity; PRODUCT_NAME = "$(TARGET_NAME)"; PROVISIONING_PROFILE_SPECIFIER = ""; - "PROVISIONING_PROFILE_SPECIFIER[sdk=iphoneos*]" = "LiveActivity Debug"; SKIP_INSTALL = YES; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; diff --git a/ios/Runner/PipGearController.swift b/ios/Runner/PipGearController.swift index 21a2f7ae..ef949ceb 100644 --- a/ios/Runner/PipGearController.swift +++ b/ios/Runner/PipGearController.swift @@ -87,11 +87,13 @@ final class PipGearController: NSObject { private func attachLayer() -> Bool { guard let rootView = Self.keyRootView() else { return false } + // 1×1 and behind Flutter — effectively invisible. PiP renders from the + // enqueued sample buffers, not from this inline layer's size. let container = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1)) container.isUserInteractionEnabled = false - container.layer.addSublayer(displayLayer) displayLayer.frame = container.bounds - rootView.insertSubview(container, at: 0) // behind Flutter; effectively invisible + container.layer.addSublayer(displayLayer) + rootView.insertSubview(container, at: 0) hostView = container return true } @@ -114,6 +116,10 @@ final class PipGearController: NSObject { kCVPixelBufferWidthKey as String: Int(renderSize.width), kCVPixelBufferHeightKey as String: Int(renderSize.height), kCVPixelBufferCGBitmapContextCompatibilityKey as String: true, + // REQUIRED: AVSampleBufferDisplayLayer can only present IOSurface-backed + // pixel buffers. Without this the layer accepts frames (status=.rendering, + // no error) but renders nothing — only its backgroundColor shows. + kCVPixelBufferIOSurfacePropertiesKey as String: [String: Any](), ] let status = CVPixelBufferPoolCreate(kCFAllocatorDefault, nil, attrs as CFDictionary, &pool) if status != kCVReturnSuccess { @@ -203,8 +209,20 @@ final class PipGearController: NSObject { formatDescription: fmt, sampleTiming: &timing, sampleBufferOut: &sampleOut - ) == noErr else { return nil } - return sampleOut + ) == noErr, let sample = sampleOut else { return nil } + + // Present each frame the instant it's enqueued, bypassing timebase + // scheduling (we run no control timebase) — correct for a live HUD feed. + if let attachments = CMSampleBufferGetSampleAttachmentsArray(sample, createIfNecessary: true), + CFArrayGetCount(attachments) > 0 { + let dict = unsafeBitCast(CFArrayGetValueAtIndex(attachments, 0), to: CFMutableDictionary.self) + CFDictionarySetValue( + dict, + Unmanaged.passUnretained(kCMSampleAttachmentKey_DisplayImmediately).toOpaque(), + Unmanaged.passUnretained(kCFBooleanTrue).toOpaque() + ) + } + return sample } } From b1f0e25ba505beb95d19d2fa29dc644f33ff005c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 18:24:44 +0200 Subject: [PATCH 063/106] docs(pip): changelog entry + overlay subtitle reflects floating PiP window The iOS "Show overlay during ride" subtitle said the overlay shows on the Dynamic Island; on iPad and non-Dynamic-Island iPhones it now uses a floating Picture-in-Picture window. Updated overlayDisabledIos in all 6 languages to describe the floating window (with the Dynamic Island where available) + Lock Screen, and added a 6.2.0 changelog entry. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 1 + lib/i10n/intl_de.arb | 2 +- lib/i10n/intl_en.arb | 2 +- lib/i10n/intl_es.arb | 2 +- lib/i10n/intl_fr.arb | 2 +- lib/i10n/intl_it.arb | 2 +- lib/i10n/intl_pl.arb | 2 +- 7 files changed, 7 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8b23f0c8..7959e623 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ ### 6.2.0 (24-06-2026) **Features**: - SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Pressing both shift buttons at once also triggers it (Zwift Ride and Click; Zwift Play via a short simultaneous-press window). Set your chainring sizes per trainer in the gear settings. +- Gear overlay on iPad: your current gear now appears in a floating Picture-in-Picture window over your trainer app during a ride, so it stays visible even while BikeControl is in the background. iPhones with a Dynamic Island keep using it; iPad and older iPhones get the new floating window. ### 6.1.0 (19-06-2026) **Features**: diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 0bce81a0..c31e3291 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -3,7 +3,7 @@ "batterySaverTitle": "Energiesparmodus", "controllersDisconnectedInactivity": "Controller nach {minutes} Minuten Inaktivität getrennt, um Akku zu sparen", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, - "overlayDisabledIos": "Das Trainer-Overlay erscheint während der Fahrt auf der Dynamic Island und dem Sperrbildschirm.", + "overlayDisabledIos": "Während der Fahrt schwebt das Trainer-Overlay über deiner Trainer-App – oder auf der Dynamic Island bei unterstützten iPhones – sowie auf dem Sperrbildschirm.", "overlayEnabled": "Overlay während der Fahrt anzeigen", "overlayFieldCadence": "Trittfrequenz", "overlayFieldErgTarget": "ERG-Ziel", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index d5550a4a..bf07ec29 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -461,7 +461,7 @@ "notConnected": "Not connected", "notificationDescription": "This keeps the app alive in background and updates you when the connection to your devices changes.", "officiallySupported": "Officially supported", - "overlayDisabledIos": "Trainer overlay shows on Dynamic Island and the Lock Screen during a ride.", + "overlayDisabledIos": "During a ride the trainer overlay floats over your trainer app — or the Dynamic Island on supported iPhones — and the Lock Screen.", "overlayEnabled": "Show overlay during ride", "overlayFieldCadence": "Cadence", "overlayFieldControls": "Shift / power buttons", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 27451ecd..83a904a2 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -3,7 +3,7 @@ "batterySaverTitle": "Ahorro de batería", "controllersDisconnectedInactivity": "Mandos desconectados tras {minutes} minutos de inactividad para ahorrar batería", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, - "overlayDisabledIos": "El Overlay del rodillo se muestra en la Dynamic Island y en la pantalla de bloqueo durante la sesión.", + "overlayDisabledIos": "Durante la sesión, el Overlay del rodillo flota sobre tu app de entrenamiento (o en la Dynamic Island en iPhones compatibles) y en la pantalla de bloqueo.", "overlayEnabled": "Mostrar el Overlay durante la sesión", "overlayFieldCadence": "Cadencia", "overlayFieldErgTarget": "Objetivo ERG", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 44c519e9..938dd2c4 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -3,7 +3,7 @@ "batterySaverTitle": "Économiseur de batterie", "controllersDisconnectedInactivity": "Manettes déconnectées après {minutes} minutes d'inactivité pour économiser la batterie", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, - "overlayDisabledIos": "L'Overlay du home-trainer s'affiche sur la Dynamic Island et l'écran verrouillé pendant la séance.", + "overlayDisabledIos": "Pendant la séance, l'Overlay du home-trainer flotte au-dessus de ton app d'entraînement (ou sur la Dynamic Island sur les iPhone compatibles) et sur l'écran verrouillé.", "overlayEnabled": "Afficher l'Overlay pendant la séance", "overlayFieldCadence": "Cadence", "overlayFieldErgTarget": "Cible ERG", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 1101b140..3cc9baab 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -3,7 +3,7 @@ "batterySaverTitle": "Risparmio batteria", "controllersDisconnectedInactivity": "Controller disconnessi dopo {minutes} minuti di inattività per risparmiare batteria", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, - "overlayDisabledIos": "L'Overlay del rullo viene mostrato sulla Dynamic Island e sulla schermata di blocco durante la sessione.", + "overlayDisabledIos": "Durante la sessione, l'Overlay del rullo galleggia sopra la tua app di allenamento (o sulla Dynamic Island sugli iPhone supportati) e sulla schermata di blocco.", "overlayEnabled": "Mostra l'Overlay durante la sessione", "overlayFieldCadence": "Cadenza", "overlayFieldErgTarget": "Obiettivo ERG", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index bfd2e431..f6e702a7 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -3,7 +3,7 @@ "batterySaverTitle": "Oszczędzanie baterii", "controllersDisconnectedInactivity": "Kontrolery rozłączone po {minutes} minutach bezczynności, aby oszczędzać baterię", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, - "overlayDisabledIos": "Overlay trenażera jest wyświetlany na Dynamic Island i ekranie blokady podczas jazdy.", + "overlayDisabledIos": "Podczas jazdy Overlay trenażera unosi się nad aplikacją treningową (lub na Dynamic Island w obsługiwanych iPhone'ach) oraz na ekranie blokady.", "overlayEnabled": "Pokaż Overlay podczas jazdy", "overlayFieldCadence": "Kadencja", "overlayFieldErgTarget": "Cel ERG", From b43a7fd3482e341e3e2a497de7b34f9aada8f375 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 18:48:22 +0200 Subject: [PATCH 064/106] feat(6.2): move Record Screen under Weitere Aktionen (below screenshot) + open-folder action on saved recording --- lib/i10n/intl_de.arb | 2 +- lib/i10n/intl_en.arb | 2 +- lib/i10n/intl_es.arb | 2 +- lib/i10n/intl_fr.arb | 2 +- lib/i10n/intl_it.arb | 2 +- lib/i10n/intl_pl.arb | 2 +- lib/pages/button_edit.dart | 41 +++++++++++++---------------- lib/pages/overview.dart | 28 +++++++++++++++++++- lib/utils/actions/base_actions.dart | 12 +++++---- 9 files changed, 59 insertions(+), 34 deletions(-) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index e9b2309e..3fd20bff 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -70,7 +70,7 @@ "actionTrainerIntensityDown": "Trainer: Intensität verringern", "actionWorkoutPauseResume": "Training: Pause/Fortsetzen", "actionScreenRecording": "Bildschirm aufnehmen", - "deviceActions": "Gerät", + "openFolder": "Ordner öffnen", "screenRecordingStarted": "Bildschirmaufnahme gestartet", "screenRecordingStopped": "Bildschirmaufnahme gespeichert", "screenRecordingFailed": "Bildschirmaufnahme konnte nicht gestartet werden", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 476b1b56..e7ae3a8a 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -47,7 +47,7 @@ "actionTrainerIntensityDown": "Trainer: Intensity Down", "actionWorkoutPauseResume": "Workout: Pause/Resume", "actionScreenRecording": "Record Screen", - "deviceActions": "Device", + "openFolder": "Open folder", "screenRecordingStarted": "Screen recording started", "screenRecordingStopped": "Screen recording saved", "screenRecordingFailed": "Could not start screen recording", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index f71fd8f2..d748d962 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -70,7 +70,7 @@ "actionTrainerIntensityDown": "Rodillo: bajar intensidad", "actionWorkoutPauseResume": "Entrenamiento: pausar/reanudar", "actionScreenRecording": "Grabar pantalla", - "deviceActions": "Dispositivo", + "openFolder": "Abrir carpeta", "screenRecordingStarted": "Grabación de pantalla iniciada", "screenRecordingStopped": "Grabación de pantalla guardada", "screenRecordingFailed": "No se pudo iniciar la grabación de pantalla", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 1f735aa0..872bbf3e 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -70,7 +70,7 @@ "actionTrainerIntensityDown": "Home-trainer : réduire l’intensité", "actionWorkoutPauseResume": "Séance : pause/reprendre", "actionScreenRecording": "Enregistrer l'écran", - "deviceActions": "Appareil", + "openFolder": "Ouvrir le dossier", "screenRecordingStarted": "Enregistrement d'écran démarré", "screenRecordingStopped": "Enregistrement d'écran enregistré", "screenRecordingFailed": "Impossible de démarrer l'enregistrement d'écran", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index c388c40d..625fdcba 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -70,7 +70,7 @@ "actionTrainerIntensityDown": "Rullo: riduci intensità", "actionWorkoutPauseResume": "Allenamento: pausa/riprendi", "actionScreenRecording": "Registra schermo", - "deviceActions": "Dispositivo", + "openFolder": "Apri cartella", "screenRecordingStarted": "Registrazione dello schermo avviata", "screenRecordingStopped": "Registrazione dello schermo salvata", "screenRecordingFailed": "Impossibile avviare la registrazione dello schermo", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 2bc30dad..804961a4 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -70,7 +70,7 @@ "actionTrainerIntensityDown": "Trenażer: zmniejsz intensywność", "actionWorkoutPauseResume": "Trening: pauza/wznów", "actionScreenRecording": "Nagraj ekran", - "deviceActions": "Urządzenie", + "openFolder": "Otwórz folder", "screenRecordingStarted": "Rozpoczęto nagrywanie ekranu", "screenRecordingStopped": "Zapisano nagranie ekranu", "screenRecordingFailed": "Nie można rozpocząć nagrywania ekranu", diff --git a/lib/pages/button_edit.dart b/lib/pages/button_edit.dart index e7c4b96e..6e2b6e5f 100644 --- a/lib/pages/button_edit.dart +++ b/lib/pages/button_edit.dart @@ -588,35 +588,32 @@ class _ButtonEditPageState extends State { ), ], - if (!kIsWeb && (Platform.isMacOS || Platform.isWindows || Platform.isIOS)) ...[ + if (!kIsWeb) ...[ SizedBox(height: 8), ColoredTitle(text: context.i18n.otherActions), - SelectableCard( - isProOnly: true, - title: Text(Platform.isMacOS || Platform.isIOS ? 'Launch Shortcut' : 'Run Command'), - icon: Platform.isMacOS || Platform.isIOS ? Icons.rocket_launch_outlined : Icons.terminal, - isActive: _keyPair.command?.trim().isNotEmpty == true, - value: _keyPair.command, - onPressed: () async { - await _showCommandDialog(context); - }, - ), - if (Platform.isMacOS || Platform.isWindows) + if (Platform.isMacOS || Platform.isWindows || Platform.isIOS) ...[ SelectableCard( isProOnly: true, - title: Text(context.i18n.takeScreenshot), - icon: Icons.image_outlined, - isActive: _keyPair.screenshotPath?.trim().isNotEmpty == true, - value: _keyPair.screenshotPath, + title: Text(Platform.isMacOS || Platform.isIOS ? 'Launch Shortcut' : 'Run Command'), + icon: Platform.isMacOS || Platform.isIOS ? Icons.rocket_launch_outlined : Icons.terminal, + isActive: _keyPair.command?.trim().isNotEmpty == true, + value: _keyPair.command, onPressed: () async { - await _showScreenshotDialog(); + await _showCommandDialog(context); }, ), - ], - - if (!kIsWeb) ...[ - SizedBox(height: 8), - ColoredTitle(text: context.i18n.deviceActions), + if (Platform.isMacOS || Platform.isWindows) + SelectableCard( + isProOnly: true, + title: Text(context.i18n.takeScreenshot), + icon: Icons.image_outlined, + isActive: _keyPair.screenshotPath?.trim().isNotEmpty == true, + value: _keyPair.screenshotPath, + onPressed: () async { + await _showScreenshotDialog(); + }, + ), + ], SelectableCard( icon: LucideIcons.video, title: Text(context.i18n.actionScreenRecording), diff --git a/lib/pages/overview.dart b/lib/pages/overview.dart index d331e42c..9bfebcdd 100644 --- a/lib/pages/overview.dart +++ b/lib/pages/overview.dart @@ -1,4 +1,5 @@ import 'dart:async'; +import 'dart:io'; import 'dart:math'; import 'package:bike_control/bluetooth/devices/base_device.dart'; @@ -229,7 +230,18 @@ class _OverviewPageState extends State with TickerProviderStateMix } void _onActionResult(ActionResult result, ControllerButton button) { - final entry = _ActivityEntry(button: button, time: DateTime.now(), result: result); + // A screen recording that saved a file to a real folder (desktop) gets an + // "open folder" action on its activity entry. + final savedPath = result is Success ? result.filePath : null; + final canOpenFolder = + savedPath != null && savedPath.isNotEmpty && !kIsWeb && (Platform.isMacOS || Platform.isWindows); + final entry = _ActivityEntry( + button: button, + time: DateTime.now(), + result: result, + buttonTitle: canOpenFolder ? AppLocalizations.of(context).openFolder : null, + onTap: canOpenFolder ? () => _openContainingFolder(savedPath) : null, + ); _insertActivityEntry(entry); if (entry.isError) { @@ -264,6 +276,20 @@ class _OverviewPageState extends State with TickerProviderStateMix } } + /// Reveals the folder containing a saved recording in Finder / Explorer. + Future _openContainingFolder(String filePath) async { + try { + final folder = File(filePath).parent.path; + if (Platform.isMacOS) { + await Process.run('open', [folder]); + } else if (Platform.isWindows) { + await Process.run('explorer', [folder]); + } + } catch (e, s) { + recordError(e, s, context: 'open recording folder'); + } + } + void _onAlert(AlertNotification notification) { final isInForeground = navigatorKey.currentState?.canPop() == false; diff --git a/lib/utils/actions/base_actions.dart b/lib/utils/actions/base_actions.dart index 9612ae83..757c509a 100644 --- a/lib/utils/actions/base_actions.dart +++ b/lib/utils/actions/base_actions.dart @@ -29,7 +29,10 @@ sealed class ActionResult { } class Success extends ActionResult { - const Success(super.message, {required super.button}); + /// Saved file path for results that produced a file (e.g. a screen + /// recording). Lets the UI offer an "open folder" action. + final String? filePath; + const Success(super.message, {required super.button, this.filePath}); } class NotHandled extends ActionResult { @@ -216,12 +219,11 @@ abstract class BaseActions { if (result.ok) { await IAPManager.instance.incrementCommandCount(); final stopped = !result.startedRecording; - final stoppedMsg = result.savedPath != null && result.savedPath!.isNotEmpty - ? '${AppLocalizations.current.screenRecordingStopped}: ${result.savedPath}' - : AppLocalizations.current.screenRecordingStopped; return Success( - stopped ? stoppedMsg : AppLocalizations.current.screenRecordingStarted, + stopped ? AppLocalizations.current.screenRecordingStopped : AppLocalizations.current.screenRecordingStarted, button: keyPair.buttons.firstOrNull ?? button, + // Carries the saved path so the activity log can offer "open folder". + filePath: stopped ? result.savedPath : null, ); } return Error( From f4039647c56e5f030c26d6f4c5ca6a8ceb6584b6 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 18:50:33 +0200 Subject: [PATCH 065/106] feat(pip): opt-in on Dynamic-Island iPhones + immediate floating window on iPad MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - New "Floating window (Picture-in-Picture)" overlay setting (iOS 16+). Default follows the per-device auto behavior (on for iPad / non-DI iPhones, off for Dynamic-Island iPhones); DI-iPhone users can opt in. The Live Activity keeps running alongside it (additive). - iPad: start PiP immediately on activation (foreground) instead of only when backgrounded — there's screen room (DeviceCapabilities.prefersForegroundPip + scheduleForegroundStart poll). - DeviceCapabilities.isPipCapable (any iOS 16+ PiP device) + bike_control/pip_ios "isCapable"; settings.getOverlayUsePip/setOverlayUsePip; show() resolves the preference. - requiresLinearPlayback = true to drop the PiP skip/scrub (next/prev) controls (it's a live HUD; central play/pause is system chrome, harmless no-op). - overlayUsePip + overlayUsePipSubtitle in all 6 languages; changelog updated. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 2 +- ios/Runner/AppDelegate.swift | 6 +++ ios/Runner/DeviceCapabilities.swift | 22 ++++++++-- ios/Runner/PipGearController.swift | 27 +++++++++++++ lib/i10n/intl_de.arb | 2 + lib/i10n/intl_en.arb | 2 + lib/i10n/intl_es.arb | 2 + lib/i10n/intl_fr.arb | 2 + lib/i10n/intl_it.arb | 2 + lib/i10n/intl_pl.arb | 2 + .../overlay_settings_section.dart | 40 +++++++++++++++++++ .../overlay/ios_overlay_controller.dart | 7 +++- lib/services/overlay/ios_pip_controller.dart | 17 +++++++- lib/utils/settings/settings.dart | 14 +++++++ 14 files changed, 139 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7959e623..24783693 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,7 +1,7 @@ ### 6.2.0 (24-06-2026) **Features**: - SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Pressing both shift buttons at once also triggers it (Zwift Ride and Click; Zwift Play via a short simultaneous-press window). Set your chainring sizes per trainer in the gear settings. -- Gear overlay on iPad: your current gear now appears in a floating Picture-in-Picture window over your trainer app during a ride, so it stays visible even while BikeControl is in the background. iPhones with a Dynamic Island keep using it; iPad and older iPhones get the new floating window. +- Floating gear overlay (Picture-in-Picture): your current gear can now show in a floating window over your trainer app during a ride. It's automatic on iPad — shown right away, since there's screen room — and on iPhones without a Dynamic Island; iPhones with a Dynamic Island can switch it on in the overlay settings. The Lock Screen / Dynamic Island display stays available alongside it. ### 6.1.0 (19-06-2026) **Features**: diff --git a/ios/Runner/AppDelegate.swift b/ios/Runner/AppDelegate.swift index a71342a4..3ce8f1d8 100644 --- a/ios/Runner/AppDelegate.swift +++ b/ios/Runner/AppDelegate.swift @@ -56,6 +56,12 @@ import UIKit } else { result(false) } + case "isCapable": + if #available(iOS 16.0, *) { + result(DeviceCapabilities.isPipCapable) + } else { + result(false) + } case "start": if #available(iOS 16.0, *) { PipGearController.shared.start(initial: call.arguments as? [String: Any] ?? [:]) diff --git a/ios/Runner/DeviceCapabilities.swift b/ios/Runner/DeviceCapabilities.swift index 7c4ab69d..70f22b83 100644 --- a/ios/Runner/DeviceCapabilities.swift +++ b/ios/Runner/DeviceCapabilities.swift @@ -15,15 +15,29 @@ enum DeviceCapabilities { return keyWindowTopInset() >= 51 } - /// PiP is the chosen floating display on iPad and on iPhones WITHOUT a - /// Dynamic Island. Requires iOS 16+ (ImageRenderer) and device PiP support. - static var pipEligible: Bool { + /// Whether PiP is technically possible at all: iOS 16+ (ImageRenderer) and + /// the device supports PiP — regardless of the Dynamic Island. Drives the + /// opt-in toggle and honoring it on Dynamic-Island iPhones. + static var isPipCapable: Bool { guard #available(iOS 16.0, *) else { return false } - guard AVPictureInPictureController.isPictureInPictureSupported() else { return false } + return AVPictureInPictureController.isPictureInPictureSupported() + } + + /// PiP is the AUTOMATIC floating display on iPad and on iPhones WITHOUT a + /// Dynamic Island (Dynamic-Island iPhones default to the Live Activity, but + /// can opt into PiP via settings). + static var pipEligible: Bool { + guard isPipCapable else { return false } if UIDevice.current.userInterfaceIdiom == .pad { return true } return !hasDynamicIsland } + /// iPad has room to show the floating window immediately (foreground), rather + /// than only once BikeControl is backgrounded. + static var prefersForegroundPip: Bool { + UIDevice.current.userInterfaceIdiom == .pad + } + private static func keyWindowTopInset() -> CGFloat { for scene in UIApplication.shared.connectedScenes { guard let ws = scene as? UIWindowScene else { continue } diff --git a/ios/Runner/PipGearController.swift b/ios/Runner/PipGearController.swift index ef949ceb..a1658d56 100644 --- a/ios/Runner/PipGearController.swift +++ b/ios/Runner/PipGearController.swift @@ -45,10 +45,37 @@ final class PipGearController: NSObject { ) let controller = AVPictureInPictureController(contentSource: source) controller.canStartPictureInPictureAutomaticallyFromInline = true + // It's a live gear HUD, not a video: disable the skip / scrub (next/prev) + // transport controls. (The central play/pause is system chrome with no + // public API to hide for sample-buffer PiP; tapping it is a harmless no-op.) + controller.requiresLinearPlayback = true controller.delegate = self pipController = controller startPump() + + // iPad: there's screen room, so show the floating window right away + // (foreground) instead of waiting for the app to be backgrounded. On + // iPhone we rely on canStartPictureInPictureAutomaticallyFromInline. + if DeviceCapabilities.prefersForegroundPip { + scheduleForegroundStart(attempt: 0) + } + } + + /// Poll until PiP becomes possible (a frame has been enqueued), then start it + /// in the foreground. Gives up after ~2.4s; background auto-start still covers + /// the normal case if foreground start never becomes possible. + private func scheduleForegroundStart(attempt: Int) { + guard attempt < 8 else { return } + DispatchQueue.main.asyncAfter(deadline: .now() + 0.3) { [weak self] in + guard let self, let controller = self.pipController, + !controller.isPictureInPictureActive else { return } + if controller.isPictureInPicturePossible { + controller.startPictureInPicture() + } else { + self.scheduleForegroundStart(attempt: attempt + 1) + } + } } func update(_ map: [String: Any]) { diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index c31e3291..ef10c79e 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -4,6 +4,8 @@ "controllersDisconnectedInactivity": "Controller nach {minutes} Minuten Inaktivität getrennt, um Akku zu sparen", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, "overlayDisabledIos": "Während der Fahrt schwebt das Trainer-Overlay über deiner Trainer-App – oder auf der Dynamic Island bei unterstützten iPhones – sowie auf dem Sperrbildschirm.", + "overlayUsePip": "Schwebendes Fenster (Bild-in-Bild)", + "overlayUsePipSubtitle": "Zeigt deinen Gang in einem schwebenden Fenster über deiner Trainer-App – zusätzlich zum Sperrbildschirm (und der Dynamic Island, sofern vorhanden).", "overlayEnabled": "Overlay während der Fahrt anzeigen", "overlayFieldCadence": "Trittfrequenz", "overlayFieldErgTarget": "ERG-Ziel", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index bf07ec29..ada5d622 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -462,6 +462,8 @@ "notificationDescription": "This keeps the app alive in background and updates you when the connection to your devices changes.", "officiallySupported": "Officially supported", "overlayDisabledIos": "During a ride the trainer overlay floats over your trainer app — or the Dynamic Island on supported iPhones — and the Lock Screen.", + "overlayUsePip": "Floating window (Picture-in-Picture)", + "overlayUsePipSubtitle": "Show your gear in a floating window over your trainer app, in addition to the Lock Screen (and the Dynamic Island where available).", "overlayEnabled": "Show overlay during ride", "overlayFieldCadence": "Cadence", "overlayFieldControls": "Shift / power buttons", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 83a904a2..5ab6a6ee 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -4,6 +4,8 @@ "controllersDisconnectedInactivity": "Mandos desconectados tras {minutes} minutos de inactividad para ahorrar batería", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, "overlayDisabledIos": "Durante la sesión, el Overlay del rodillo flota sobre tu app de entrenamiento (o en la Dynamic Island en iPhones compatibles) y en la pantalla de bloqueo.", + "overlayUsePip": "Ventana flotante (Picture-in-Picture)", + "overlayUsePipSubtitle": "Muestra tu marcha en una ventana flotante sobre tu app de entrenamiento, además de en la pantalla de bloqueo (y en la Dynamic Island cuando esté disponible).", "overlayEnabled": "Mostrar el Overlay durante la sesión", "overlayFieldCadence": "Cadencia", "overlayFieldErgTarget": "Objetivo ERG", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 938dd2c4..767b72bd 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -4,6 +4,8 @@ "controllersDisconnectedInactivity": "Manettes déconnectées après {minutes} minutes d'inactivité pour économiser la batterie", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, "overlayDisabledIos": "Pendant la séance, l'Overlay du home-trainer flotte au-dessus de ton app d'entraînement (ou sur la Dynamic Island sur les iPhone compatibles) et sur l'écran verrouillé.", + "overlayUsePip": "Fenêtre flottante (Picture-in-Picture)", + "overlayUsePipSubtitle": "Affiche ta vitesse dans une fenêtre flottante au-dessus de ton app d'entraînement, en plus de l'écran verrouillé (et de la Dynamic Island si disponible).", "overlayEnabled": "Afficher l'Overlay pendant la séance", "overlayFieldCadence": "Cadence", "overlayFieldErgTarget": "Cible ERG", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 3cc9baab..02ebef9b 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -4,6 +4,8 @@ "controllersDisconnectedInactivity": "Controller disconnessi dopo {minutes} minuti di inattività per risparmiare batteria", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, "overlayDisabledIos": "Durante la sessione, l'Overlay del rullo galleggia sopra la tua app di allenamento (o sulla Dynamic Island sugli iPhone supportati) e sulla schermata di blocco.", + "overlayUsePip": "Finestra mobile (Picture-in-Picture)", + "overlayUsePipSubtitle": "Mostra la marcia in una finestra mobile sopra la tua app di allenamento, oltre alla schermata di blocco (e alla Dynamic Island se disponibile).", "overlayEnabled": "Mostra l'Overlay durante la sessione", "overlayFieldCadence": "Cadenza", "overlayFieldErgTarget": "Obiettivo ERG", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index f6e702a7..53121d66 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -4,6 +4,8 @@ "controllersDisconnectedInactivity": "Kontrolery rozłączone po {minutes} minutach bezczynności, aby oszczędzać baterię", "@controllersDisconnectedInactivity": {"placeholders": {"minutes": {"type": "int"}}}, "overlayDisabledIos": "Podczas jazdy Overlay trenażera unosi się nad aplikacją treningową (lub na Dynamic Island w obsługiwanych iPhone'ach) oraz na ekranie blokady.", + "overlayUsePip": "Pływające okno (Picture-in-Picture)", + "overlayUsePipSubtitle": "Pokazuje bieg w pływającym oknie nad aplikacją treningową, oprócz ekranu blokady (i Dynamic Island, jeśli jest dostępna).", "overlayEnabled": "Pokaż Overlay podczas jazdy", "overlayFieldCadence": "Kadencja", "overlayFieldErgTarget": "Cel ERG", diff --git a/lib/pages/proxy_device_details/overlay_settings_section.dart b/lib/pages/proxy_device_details/overlay_settings_section.dart index 1d1fee94..6e251f5f 100644 --- a/lib/pages/proxy_device_details/overlay_settings_section.dart +++ b/lib/pages/proxy_device_details/overlay_settings_section.dart @@ -2,6 +2,7 @@ import 'dart:io' show Platform; import 'package:bike_control/bluetooth/devices/proxy/proxy_device.dart'; import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/services/overlay/ios_pip_controller.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/services/overlay/trainer_overlay_controller.dart'; import 'package:bike_control/services/overlay/trainer_overlay_service.dart'; @@ -30,6 +31,9 @@ class _OverlaySettingsSectionState extends State { late bool _enabled; late Set _fields; bool _androidPermissionGranted = false; + bool _pipCapable = false; + bool _pipAutoDefault = false; + bool? _pipPref; @override void initState() { @@ -41,6 +45,35 @@ class _OverlaySettingsSectionState extends State { _fields = core.settings.getOverlayFields(); _controller.isShowing.addListener(_syncFromController); _refreshAndroidPermission(); + _pipPref = core.settings.getOverlayUsePip(); + _loadPipCapability(); + } + + Future _loadPipCapability() async { + if (kIsWeb || !Platform.isIOS) return; + final pip = IosPipController(); + final capable = await pip.isCapable(); + final auto = await pip.isSupported(); + if (!mounted) return; + setState(() { + _pipCapable = capable; + _pipAutoDefault = auto; + }); + } + + Future _togglePip(bool v) async { + await core.settings.setOverlayUsePip(v); + if (mounted) setState(() => _pipPref = v); + // Re-apply immediately if the overlay is already showing. + if (_enabled) { + await _controller.hide(); + final res = await _controller.show( + widget.definition, + _fields, + liveDef: () => widget.device.fitnessBike, + ); + if (mounted) setState(() => _enabled = res.ok); + } } Future _refreshAndroidPermission() async { @@ -125,6 +158,13 @@ class _OverlaySettingsSectionState extends State { trailing: Switch(value: _enabled, onChanged: _toggle), child: _enabled ? _fieldsCard(l10n) : null, ), + if (isIos && _pipCapable) + SettingTile( + icon: LucideIcons.appWindow, + title: l10n.overlayUsePip, + subtitle: l10n.overlayUsePipSubtitle, + trailing: Switch(value: _pipPref ?? _pipAutoDefault, onChanged: _togglePip), + ), if (!kIsWeb && Platform.isWindows && _enabled) _tipCard(l10n.overlayWindowsTip), if (isAndroid && !_androidPermissionGranted) _androidPermissionTile(l10n), ], diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index a81172b8..b05c8d66 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -83,7 +83,12 @@ class IosOverlayController implements TrainerOverlayController { _showing.value = true; try { - if (await _pip.isSupported()) { + // null pref = automatic device default (iPad / non-Dynamic-Island iPhones); + // an explicit true opts in everywhere PiP is capable (e.g. DI iPhones), an + // explicit false opts out. The Live Activity keeps running either way. + final pref = core.settings.getOverlayUsePip(); + final usePip = pref == null ? await _pip.isSupported() : (pref && await _pip.isCapable()); + if (usePip) { await _pip.start(_toMap(s)); _pipActive = true; } diff --git a/lib/services/overlay/ios_pip_controller.dart b/lib/services/overlay/ios_pip_controller.dart index 99d5eed3..e4211dae 100644 --- a/lib/services/overlay/ios_pip_controller.dart +++ b/lib/services/overlay/ios_pip_controller.dart @@ -7,8 +7,9 @@ import 'package:flutter/services.dart'; class IosPipController { static const _channel = MethodChannel('bike_control/pip_ios'); - /// True on iPad and non-Dynamic-Island iPhones (iOS 16+). False on - /// Dynamic-Island iPhones and where PiP is unsupported. + /// Automatic default: true on iPad and non-Dynamic-Island iPhones (iOS 16+). + /// False on Dynamic-Island iPhones (they default to the Live Activity) and + /// where PiP is unsupported. Future isSupported() async { try { return await _channel.invokeMethod('isSupported') ?? false; @@ -18,6 +19,18 @@ class IosPipController { } } + /// Whether PiP is technically possible at all (iOS 16+ and device supports it), + /// regardless of the Dynamic Island. Used to honor the opt-in on DI iPhones and + /// to decide whether to show the setting. + Future isCapable() async { + try { + return await _channel.invokeMethod('isCapable') ?? false; + } catch (e, s) { + recordError(e, s, context: 'pip.ios.isCapable'); + return false; + } + } + Future start(Map state) async { try { await _channel.invokeMethod('start', state); diff --git a/lib/utils/settings/settings.dart b/lib/utils/settings/settings.dart index 39d27db5..9d93afce 100644 --- a/lib/utils/settings/settings.dart +++ b/lib/utils/settings/settings.dart @@ -651,6 +651,20 @@ class Settings { await prefs.setBool('overlay_enabled', enabled); } + /// iOS only: whether to use the floating Picture-in-Picture overlay. + /// `null` = automatic (device default — on for iPad and non-Dynamic-Island + /// iPhones, off for Dynamic-Island iPhones, which use the Live Activity). + /// `true`/`false` = explicit user override. + bool? getOverlayUsePip() => prefs.getBool('overlay_use_pip'); + + Future setOverlayUsePip(bool? value) async { + if (value == null) { + await prefs.remove('overlay_use_pip'); + } else { + await prefs.setBool('overlay_use_pip', value); + } + } + /// Get overlay display fields (set of OverlayField enum values). /// Defaults to {power, cadence}. Set getOverlayFields() { From 4befad7171bbfc4919efbe6a9f886bb39526f4b0 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 18:59:37 +0200 Subject: [PATCH 066/106] feat(6.2): show reveal-recording action on mobile too (opens gallery via gal); platform-aware label --- lib/i10n/intl_de.arb | 1 + lib/i10n/intl_en.arb | 1 + lib/i10n/intl_es.arb | 1 + lib/i10n/intl_fr.arb | 1 + lib/i10n/intl_it.arb | 1 + lib/i10n/intl_pl.arb | 1 + lib/pages/overview.dart | 29 +++++++++++++++++------------ 7 files changed, 23 insertions(+), 12 deletions(-) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 3fd20bff..94c2311f 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -71,6 +71,7 @@ "actionWorkoutPauseResume": "Training: Pause/Fortsetzen", "actionScreenRecording": "Bildschirm aufnehmen", "openFolder": "Ordner öffnen", + "openGallery": "Galerie öffnen", "screenRecordingStarted": "Bildschirmaufnahme gestartet", "screenRecordingStopped": "Bildschirmaufnahme gespeichert", "screenRecordingFailed": "Bildschirmaufnahme konnte nicht gestartet werden", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index e7ae3a8a..fc275aab 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -48,6 +48,7 @@ "actionWorkoutPauseResume": "Workout: Pause/Resume", "actionScreenRecording": "Record Screen", "openFolder": "Open folder", + "openGallery": "Open gallery", "screenRecordingStarted": "Screen recording started", "screenRecordingStopped": "Screen recording saved", "screenRecordingFailed": "Could not start screen recording", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index d748d962..c49de550 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -71,6 +71,7 @@ "actionWorkoutPauseResume": "Entrenamiento: pausar/reanudar", "actionScreenRecording": "Grabar pantalla", "openFolder": "Abrir carpeta", + "openGallery": "Abrir galería", "screenRecordingStarted": "Grabación de pantalla iniciada", "screenRecordingStopped": "Grabación de pantalla guardada", "screenRecordingFailed": "No se pudo iniciar la grabación de pantalla", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 872bbf3e..77303bd9 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -71,6 +71,7 @@ "actionWorkoutPauseResume": "Séance : pause/reprendre", "actionScreenRecording": "Enregistrer l'écran", "openFolder": "Ouvrir le dossier", + "openGallery": "Ouvrir la galerie", "screenRecordingStarted": "Enregistrement d'écran démarré", "screenRecordingStopped": "Enregistrement d'écran enregistré", "screenRecordingFailed": "Impossible de démarrer l'enregistrement d'écran", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 625fdcba..4d2a997d 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -71,6 +71,7 @@ "actionWorkoutPauseResume": "Allenamento: pausa/riprendi", "actionScreenRecording": "Registra schermo", "openFolder": "Apri cartella", + "openGallery": "Apri galleria", "screenRecordingStarted": "Registrazione dello schermo avviata", "screenRecordingStopped": "Registrazione dello schermo salvata", "screenRecordingFailed": "Impossibile avviare la registrazione dello schermo", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 804961a4..70ac7928 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -71,6 +71,7 @@ "actionWorkoutPauseResume": "Trening: pauza/wznów", "actionScreenRecording": "Nagraj ekran", "openFolder": "Otwórz folder", + "openGallery": "Otwórz galerię", "screenRecordingStarted": "Rozpoczęto nagrywanie ekranu", "screenRecordingStopped": "Zapisano nagranie ekranu", "screenRecordingFailed": "Nie można rozpocząć nagrywania ekranu", diff --git a/lib/pages/overview.dart b/lib/pages/overview.dart index 9bfebcdd..ecc9fa8a 100644 --- a/lib/pages/overview.dart +++ b/lib/pages/overview.dart @@ -33,6 +33,7 @@ import 'package:bike_control/widgets/ui/connection_method.dart' show ConnectionM import 'package:bike_control/widgets/ui/toast.dart'; import 'package:flutter/foundation.dart'; import 'package:flutter/services.dart'; +import 'package:gal/gal.dart'; import 'package:prop/prop.dart' show LogLevel, Logger, RetrofitMode; import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:universal_ble/universal_ble.dart'; @@ -230,17 +231,19 @@ class _OverviewPageState extends State with TickerProviderStateMix } void _onActionResult(ActionResult result, ControllerButton button) { - // A screen recording that saved a file to a real folder (desktop) gets an - // "open folder" action on its activity entry. + // A saved screen recording gets a "reveal" action on its activity entry: + // open the containing folder on desktop, or the gallery on mobile. final savedPath = result is Success ? result.filePath : null; - final canOpenFolder = - savedPath != null && savedPath.isNotEmpty && !kIsWeb && (Platform.isMacOS || Platform.isWindows); + final hasRecording = savedPath != null && savedPath.isNotEmpty && !kIsWeb; + final isDesktop = !kIsWeb && (Platform.isMacOS || Platform.isWindows); final entry = _ActivityEntry( button: button, time: DateTime.now(), result: result, - buttonTitle: canOpenFolder ? AppLocalizations.of(context).openFolder : null, - onTap: canOpenFolder ? () => _openContainingFolder(savedPath) : null, + buttonTitle: hasRecording + ? (isDesktop ? AppLocalizations.of(context).openFolder : AppLocalizations.of(context).openGallery) + : null, + onTap: hasRecording ? () => _openRecordingLocation(savedPath) : null, ); _insertActivityEntry(entry); @@ -276,17 +279,19 @@ class _OverviewPageState extends State with TickerProviderStateMix } } - /// Reveals the folder containing a saved recording in Finder / Explorer. - Future _openContainingFolder(String filePath) async { + /// Reveals a saved recording: the containing folder in Finder / Explorer on + /// desktop, or the system gallery on mobile (where it was saved via `gal`). + Future _openRecordingLocation(String filePath) async { try { - final folder = File(filePath).parent.path; if (Platform.isMacOS) { - await Process.run('open', [folder]); + await Process.run('open', [File(filePath).parent.path]); } else if (Platform.isWindows) { - await Process.run('explorer', [folder]); + await Process.run('explorer', [File(filePath).parent.path]); + } else { + await Gal.open(); } } catch (e, s) { - recordError(e, s, context: 'open recording folder'); + recordError(e, s, context: 'open recording location'); } } From 756a4c81d3f4035a9db5e5f49e18b25ca12a3edc Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 19:06:37 +0200 Subject: [PATCH 067/106] =?UTF-8?q?fix(6.2):=20iOS=20broadcast=20stop=20?= =?UTF-8?q?=E2=80=94=20reuse=20existing=20App=20Group=20+=20register=20sto?= =?UTF-8?q?p=20observer=20before=20container=20guard=20+=20diagnostics?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ios/ScreenRecordBroadcast/SampleHandler.swift | 30 ++++++++++++++----- packages/screen_recorder/NATIVE_SETUP.md | 14 ++++----- .../ios/Classes/ScreenRecorderPlugin.swift | 15 ++++++---- 3 files changed, 38 insertions(+), 21 deletions(-) diff --git a/ios/ScreenRecordBroadcast/SampleHandler.swift b/ios/ScreenRecordBroadcast/SampleHandler.swift index 36d3c7b1..031df9d8 100644 --- a/ios/ScreenRecordBroadcast/SampleHandler.swift +++ b/ios/ScreenRecordBroadcast/SampleHandler.swift @@ -10,14 +10,15 @@ import AVFoundation // - Uncheck "Include UI Extension" // 2. Replace the generated SampleHandler.swift with this file (or add this file to the target // and delete the generated one). -// 3. In Apple Developer portal: create App Group "group.de.jonasbark.swiftcontrol.darwin" -// and enable it on BOTH Runner and ScreenRecordBroadcast targets. +// 3. App Group: reuse the app's EXISTING "group.de.jonasbark.swiftcontrol.overlay". In the +// extension target's Signing & Capabilities, add the App Groups capability and CHECK that +// existing group (no new portal App Group needed — it is already on the Runner target). // -// App Group: group.de.jonasbark.swiftcontrol.darwin (MUST match ScreenRecorderPlugin.swift) +// App Group: group.de.jonasbark.swiftcontrol.overlay (MUST match ScreenRecorderPlugin.swift) class SampleHandler: RPBroadcastSampleHandler { - // MUST match ScreenRecorderPlugin.appGroup - static let appGroup = "group.de.jonasbark.swiftcontrol.darwin" + // MUST match ScreenRecorderPlugin.appGroup (the app's existing shared group). + static let appGroup = "group.de.jonasbark.swiftcontrol.overlay" // MUST match ScreenRecorderPlugin.stopNotificationName static let stopNotificationName = "de.jonasbark.swiftcontrol.darwin.stopBroadcast" @@ -28,9 +29,17 @@ class SampleHandler: RPBroadcastSampleHandler { private var outputURL: URL? override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) { + NSLog("SampleHandler: broadcastStarted") + + // Register the stop observer FIRST — before any setup that can fail — so the + // broadcast is always stoppable from the app even if the App Group container + // (used for the output file) cannot be resolved. + registerStopObserver() + guard let container = FileManager.default.containerURL( forSecurityApplicationGroupIdentifier: SampleHandler.appGroup) else { - NSLog("SampleHandler: failed to get App Group container — check portal config") + NSLog("SampleHandler: ERROR — no App Group container for %@. Enable that App Group on the " + + "ScreenRecordBroadcast target. Stop still works, but nothing can be saved.", SampleHandler.appGroup) return } @@ -62,13 +71,18 @@ class SampleHandler: RPBroadcastSampleHandler { assetWriter.add(input) } assetWriter.startWriting() + NSLog("SampleHandler: writer ready, recording to %@", url.path) + } - // Listen for the app's stop signal via Darwin notification center. - // The host app posts this when the user triggers "stop recording". + /// Registers the Darwin observer that finishes the broadcast when the host app + /// posts the stop notification. Called before any fallible setup so the + /// broadcast is always stoppable. + private func registerStopObserver() { CFNotificationCenterAddObserver( CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), { _, observer, _, _, _ in + NSLog("SampleHandler: stop notification received -> finishBroadcastWithError") guard let observer = observer else { return } let handler = Unmanaged.fromOpaque(observer).takeUnretainedValue() // Finish with an error to terminate the broadcast; broadcastFinished() will then run. diff --git a/packages/screen_recorder/NATIVE_SETUP.md b/packages/screen_recorder/NATIVE_SETUP.md index 25d1b4d6..b14a78b8 100644 --- a/packages/screen_recorder/NATIVE_SETUP.md +++ b/packages/screen_recorder/NATIVE_SETUP.md @@ -19,16 +19,16 @@ plugin compile here, Windows and the iOS extension target need your machines. ## iOS — remaining (manual Xcode + portal, can't be scripted) Identifiers (derived from the real app bundle id `de.jonasbark.swiftcontrol.darwin`): -- App Group: `group.de.jonasbark.swiftcontrol.darwin` +- App Group: **reuse the app's existing** `group.de.jonasbark.swiftcontrol.overlay` (already on Runner + TrainerActivityExtension; no new portal group needed) - Extension bundle id: `de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast` Steps: -1. **Apple Developer portal:** create App Group `group.de.jonasbark.swiftcontrol.darwin`; enable it on both the app and the extension identifiers. -2. **Xcode:** File ▸ New ▸ Target ▸ Broadcast Upload Extension, name `ScreenRecordBroadcast`, bundle id `de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast`, **uncheck** "Include UI Extension". Replace the generated `SampleHandler.swift` with the repo's `ios/ScreenRecordBroadcast/SampleHandler.swift` (and use the repo's `Info.plist`). -3. **Signing & Capabilities:** add the App Groups capability (checked) to BOTH the Runner and the extension targets; set the team/provisioning on the extension. -4. Verify the `preferredExtension` string in `packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift` matches the extension bundle id. -5. Device test: bind a key, tap **Start Broadcast** on the system sheet (one unavoidable tap), switch to a game, stop, confirm the mp4 lands in Photos. -- **Known refinement:** `stop()` reads `lastRecordingPath` from the App Group right after posting the stop Darwin notification — the extension may not have finished writing yet, so it can return `nil` on the first call. Add a short poll (e.g. up to 2 s at 100 ms) for the path / a "finished" flag before returning. Verify timing on-device. +1. **Xcode:** File ▸ New ▸ Target ▸ Broadcast Upload Extension, name `ScreenRecordBroadcast`, bundle id `de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast`, **uncheck** "Include UI Extension". Replace the generated `SampleHandler.swift` with the repo's `ios/ScreenRecordBroadcast/SampleHandler.swift` (and use the repo's `Info.plist`). +2. **App Group (the critical step):** in the extension target's **Signing & Capabilities**, add the **App Groups** capability and **check the existing** `group.de.jonasbark.swiftcontrol.overlay`. The Runner target already has it. If this is missing on the extension, `broadcastStarted` can't resolve its container — the recording cannot be stopped from the app or saved. +3. **Signing:** set the team/provisioning on the extension target. +4. Verify the `preferredExtension` string in `packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift` matches the extension's bundle id. +5. Device test: bind a key, tap **Start Broadcast** on the system sheet (one unavoidable tap), switch to a game, stop, confirm the broadcast ends and the mp4 lands in Photos. Watch Console.app (filter `SampleHandler`/`ScreenRecorderPlugin`) — you should see `posting stop notification` → `stop notification received -> finishBroadcastWithError` → `broadcastFinished`. +- **Known follow-up (save handoff):** `stop()` reads `lastRecordingPath` from the App Group right after posting the stop notification, but the extension writes it in `broadcastFinished` (async) — so the path can come back `nil` on the first stop even when the recording itself stops fine. Add a short poll (e.g. up to 2 s at 100 ms) for the path before returning. Tackle this after confirming stop works. ## Windows — remaining (build + iterate, never compiled) 1. `flutter build windows --debug` — expect compile iteration on C++/WinRT headers and `windowsapp.lib`. diff --git a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift index 53c90f62..1ea1e6ab 100644 --- a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift +++ b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift @@ -2,17 +2,19 @@ import Flutter import UIKit import ReplayKit -// IMPORTANT: The App Group identifier below MUST be created in the Apple Developer portal -// (Certificates, Identifiers & Profiles → App Groups) and enabled on BOTH the Runner target -// AND the ScreenRecordBroadcast extension target in Signing & Capabilities. +// IMPORTANT: This reuses the app's EXISTING App Group "group.de.jonasbark.swiftcontrol.overlay" +// (already configured on the Runner target and in the portal). It must ALSO be enabled on the +// ScreenRecordBroadcast extension target (Signing & Capabilities → App Groups → check the +// existing group). Without it the extension can't resolve its shared container, and the +// broadcast can be neither stopped nor saved. // // App bundle ID: de.jonasbark.swiftcontrol.darwin -// App Group (derived): group.de.jonasbark.swiftcontrol.darwin +// Shared App Group: group.de.jonasbark.swiftcontrol.overlay // Extension bundle ID: de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast public class ScreenRecorderPlugin: NSObject, FlutterPlugin { - // Derived from the app bundle id: group. - static let appGroup = "group.de.jonasbark.swiftcontrol.darwin" + // Reuse the app's existing shared App Group (already on the Runner target). + static let appGroup = "group.de.jonasbark.swiftcontrol.overlay" // Darwin notification name used to signal the extension to stop. // Must match the string used in SampleHandler.swift. @@ -41,6 +43,7 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { case "stop": // Clear intent and signal the extension to finish via Darwin notification. sharedDefaults()?.set(false, forKey: "recordingRequested") + NSLog("ScreenRecorderPlugin: posting stop notification %@", ScreenRecorderPlugin.stopNotificationName) CFNotificationCenterPostNotification( CFNotificationCenterGetDarwinNotifyCenter(), CFNotificationName(ScreenRecorderPlugin.stopNotificationName as CFString), From ed99c081e1e745ad9afc1bbe3d5d160dbb0f6f05 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 19:35:24 +0200 Subject: [PATCH 068/106] fix(6.2): iOS broadcast stop via App Group stop-flag poll + heartbeat (Darwin as backup) --- ios/ScreenRecordBroadcast/SampleHandler.swift | 29 +++++++++++++-- .../ScreenRecordBroadcast.entitlements | 5 +++ .../ios/Classes/ScreenRecorderPlugin.swift | 36 +++++++++++++++++-- 3 files changed, 66 insertions(+), 4 deletions(-) create mode 100644 ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements diff --git a/ios/ScreenRecordBroadcast/SampleHandler.swift b/ios/ScreenRecordBroadcast/SampleHandler.swift index 031df9d8..1cd0efea 100644 --- a/ios/ScreenRecordBroadcast/SampleHandler.swift +++ b/ios/ScreenRecordBroadcast/SampleHandler.swift @@ -27,6 +27,9 @@ class SampleHandler: RPBroadcastSampleHandler { private var videoInput: AVAssetWriterInput? private var sessionStarted = false private var outputURL: URL? + private var stopFlagURL: URL? + private var activeFlagURL: URL? + private var finishing = false override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) { NSLog("SampleHandler: broadcastStarted") @@ -43,6 +46,13 @@ class SampleHandler: RPBroadcastSampleHandler { return } + // Cross-process stop flag (app drops this file; we poll it per frame) + a + // heartbeat file the app reads back to confirm the App Group is shared. + stopFlagURL = container.appendingPathComponent("screen_recorder_stop") + activeFlagURL = container.appendingPathComponent("screen_recorder_active") + if let stop = stopFlagURL { try? FileManager.default.removeItem(at: stop) } + if let active = activeFlagURL { FileManager.default.createFile(atPath: active.path, contents: Data()) } + let timestamp = Int(Date().timeIntervalSince1970) let url = container.appendingPathComponent("BikeControl_\(timestamp).mp4") outputURL = url @@ -82,10 +92,11 @@ class SampleHandler: RPBroadcastSampleHandler { CFNotificationCenterGetDarwinNotifyCenter(), Unmanaged.passUnretained(self).toOpaque(), { _, observer, _, _, _ in - NSLog("SampleHandler: stop notification received -> finishBroadcastWithError") guard let observer = observer else { return } let handler = Unmanaged.fromOpaque(observer).takeUnretainedValue() - // Finish with an error to terminate the broadcast; broadcastFinished() will then run. + guard !handler.finishing else { return } + handler.finishing = true + NSLog("SampleHandler: stop notification received -> finishBroadcastWithError") handler.finishBroadcastWithError( NSError(domain: "de.jonasbark.swiftcontrol.darwin", code: 0, userInfo: [NSLocalizedDescriptionKey: "Recording stopped by app"])) @@ -96,6 +107,16 @@ class SampleHandler: RPBroadcastSampleHandler { } override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) { + // Poll the app's stop flag every frame — reliable cross-process stop signal. + if !finishing, let stop = stopFlagURL, FileManager.default.fileExists(atPath: stop.path) { + finishing = true + NSLog("SampleHandler: stop flag detected -> finishBroadcastWithError") + finishBroadcastWithError( + NSError(domain: "de.jonasbark.swiftcontrol.darwin", code: 0, + userInfo: [NSLocalizedDescriptionKey: "Recording stopped by app"])) + return + } + guard sampleBufferType == .video, let writer = writer, let input = videoInput, @@ -120,6 +141,10 @@ class SampleHandler: RPBroadcastSampleHandler { CFNotificationName(SampleHandler.stopNotificationName as CFString), nil) + // Clear the cross-process flags so the next recording starts clean. + if let active = activeFlagURL { try? FileManager.default.removeItem(at: active) } + if let stop = stopFlagURL { try? FileManager.default.removeItem(at: stop) } + let group = DispatchGroup() group.enter() videoInput?.markAsFinished() diff --git a/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements b/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements new file mode 100644 index 00000000..0c67376e --- /dev/null +++ b/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements @@ -0,0 +1,5 @@ + + + + + diff --git a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift index 1ea1e6ab..49e5af39 100644 --- a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift +++ b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift @@ -36,13 +36,18 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { // Broadcast is user-initiated via system sheet; no separate permission required. result(true) case "start": + // Clear any stale stop flag so a fresh recording isn't immediately stopped. + clearStopFlag() + sharedDefaults()?.removeObject(forKey: "lastRecordingPath") presentBroadcastPicker() - // Record intent in shared defaults; the extension reads it when it starts. sharedDefaults()?.set(true, forKey: "recordingRequested") result(true) case "stop": - // Clear intent and signal the extension to finish via Darwin notification. sharedDefaults()?.set(false, forKey: "recordingRequested") + // Primary stop: drop a flag file in the shared App Group container that the + // extension polls on every frame (reliable cross-process). Backup: a Darwin + // notification (immediate, but delivery to broadcast extensions is flaky). + writeStopFlag() NSLog("ScreenRecorderPlugin: posting stop notification %@", ScreenRecorderPlugin.stopNotificationName) CFNotificationCenterPostNotification( CFNotificationCenterGetDarwinNotifyCenter(), @@ -60,6 +65,33 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { UserDefaults(suiteName: ScreenRecorderPlugin.appGroup) } + private func appGroupContainer() -> URL? { + FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: ScreenRecorderPlugin.appGroup) + } + + private func stopFlagURL() -> URL? { + appGroupContainer()?.appendingPathComponent("screen_recorder_stop") + } + + private func clearStopFlag() { + if let url = stopFlagURL() { try? FileManager.default.removeItem(at: url) } + } + + private func writeStopFlag() { + guard let container = appGroupContainer(), let stop = stopFlagURL() else { + NSLog("ScreenRecorderPlugin: WARNING no App Group container in app — is %@ enabled on the Runner target?", + ScreenRecorderPlugin.appGroup) + return + } + FileManager.default.createFile(atPath: stop.path, contents: Data()) + // Heartbeat: the extension writes this file in broadcastStarted. If it's MISSING, + // the extension isn't sharing the App Group (capability not enabled on the extension + // target) or isn't running our SampleHandler — so it can never be stopped/saved. + let alive = FileManager.default.fileExists(atPath: container.appendingPathComponent("screen_recorder_active").path) + NSLog("ScreenRecorderPlugin: stop flag written; extension heartbeat = %@", + alive ? "ALIVE" : "MISSING (App Group not shared with extension, or extension not running our code)") + } + private func presentBroadcastPicker() { DispatchQueue.main.async { let picker = RPSystemBroadcastPickerView(frame: CGRect(x: 0, y: 0, width: 1, height: 1)) From bc6867e492329405a2f920c0b057b401f2e21474 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 20:11:48 +0200 Subject: [PATCH 069/106] cleanup --- ios/ScreenRecordBroadcast/Info.plist | 33 ---- ios/ScreenRecordBroadcast/SampleHandler.swift | 161 ------------------ .../ScreenRecordBroadcast.entitlements | 5 - packages/screen_recorder/NATIVE_SETUP.md | 12 +- prop | 2 +- 5 files changed, 7 insertions(+), 206 deletions(-) delete mode 100644 ios/ScreenRecordBroadcast/Info.plist delete mode 100644 ios/ScreenRecordBroadcast/SampleHandler.swift delete mode 100644 ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements diff --git a/ios/ScreenRecordBroadcast/Info.plist b/ios/ScreenRecordBroadcast/Info.plist deleted file mode 100644 index ea47493e..00000000 --- a/ios/ScreenRecordBroadcast/Info.plist +++ /dev/null @@ -1,33 +0,0 @@ - - - - - CFBundleDevelopmentRegion - $(DEVELOPMENT_LANGUAGE) - CFBundleDisplayName - ScreenRecordBroadcast - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - $(PRODUCT_BUNDLE_PACKAGE_TYPE) - CFBundleShortVersionString - 1.0 - CFBundleVersion - 1 - NSExtension - - NSExtensionPointIdentifier - com.apple.broadcast-services-upload - NSExtensionPrincipalClass - $(PRODUCT_MODULE_NAME).SampleHandler - RPBroadcastProcessMode - RPBroadcastProcessModeSampleBuffer - - - diff --git a/ios/ScreenRecordBroadcast/SampleHandler.swift b/ios/ScreenRecordBroadcast/SampleHandler.swift deleted file mode 100644 index 1cd0efea..00000000 --- a/ios/ScreenRecordBroadcast/SampleHandler.swift +++ /dev/null @@ -1,161 +0,0 @@ -import ReplayKit -import AVFoundation - -// IMPORTANT: This file belongs to the ScreenRecordBroadcast Broadcast Upload Extension target. -// It is NOT compiled by the Runner target. Manual Xcode steps required: -// -// 1. File ▸ New ▸ Target ▸ Broadcast Upload Extension -// - Name: ScreenRecordBroadcast -// - Bundle Identifier: de.jonasbark.swiftcontrol.darwin.ScreenRecordBroadcast -// - Uncheck "Include UI Extension" -// 2. Replace the generated SampleHandler.swift with this file (or add this file to the target -// and delete the generated one). -// 3. App Group: reuse the app's EXISTING "group.de.jonasbark.swiftcontrol.overlay". In the -// extension target's Signing & Capabilities, add the App Groups capability and CHECK that -// existing group (no new portal App Group needed — it is already on the Runner target). -// -// App Group: group.de.jonasbark.swiftcontrol.overlay (MUST match ScreenRecorderPlugin.swift) - -class SampleHandler: RPBroadcastSampleHandler { - // MUST match ScreenRecorderPlugin.appGroup (the app's existing shared group). - static let appGroup = "group.de.jonasbark.swiftcontrol.overlay" - - // MUST match ScreenRecorderPlugin.stopNotificationName - static let stopNotificationName = "de.jonasbark.swiftcontrol.darwin.stopBroadcast" - - private var writer: AVAssetWriter? - private var videoInput: AVAssetWriterInput? - private var sessionStarted = false - private var outputURL: URL? - private var stopFlagURL: URL? - private var activeFlagURL: URL? - private var finishing = false - - override func broadcastStarted(withSetupInfo setupInfo: [String : NSObject]?) { - NSLog("SampleHandler: broadcastStarted") - - // Register the stop observer FIRST — before any setup that can fail — so the - // broadcast is always stoppable from the app even if the App Group container - // (used for the output file) cannot be resolved. - registerStopObserver() - - guard let container = FileManager.default.containerURL( - forSecurityApplicationGroupIdentifier: SampleHandler.appGroup) else { - NSLog("SampleHandler: ERROR — no App Group container for %@. Enable that App Group on the " - + "ScreenRecordBroadcast target. Stop still works, but nothing can be saved.", SampleHandler.appGroup) - return - } - - // Cross-process stop flag (app drops this file; we poll it per frame) + a - // heartbeat file the app reads back to confirm the App Group is shared. - stopFlagURL = container.appendingPathComponent("screen_recorder_stop") - activeFlagURL = container.appendingPathComponent("screen_recorder_active") - if let stop = stopFlagURL { try? FileManager.default.removeItem(at: stop) } - if let active = activeFlagURL { FileManager.default.createFile(atPath: active.path, contents: Data()) } - - let timestamp = Int(Date().timeIntervalSince1970) - let url = container.appendingPathComponent("BikeControl_\(timestamp).mp4") - outputURL = url - try? FileManager.default.removeItem(at: url) - - // Use main screen size and scale for full-resolution capture. - let screen = UIScreen.main.bounds.size - let scale = UIScreen.main.scale - let videoSettings: [String: Any] = [ - AVVideoCodecKey: AVVideoCodecType.h264, - AVVideoWidthKey: Int(screen.width * scale), - AVVideoHeightKey: Int(screen.height * scale), - ] - - guard let assetWriter = try? AVAssetWriter(outputURL: url, fileType: .mp4) else { - NSLog("SampleHandler: failed to create AVAssetWriter at \(url.path)") - return - } - writer = assetWriter - - let input = AVAssetWriterInput(mediaType: .video, outputSettings: videoSettings) - input.expectsMediaDataInRealTime = true - videoInput = input - - if assetWriter.canAdd(input) { - assetWriter.add(input) - } - assetWriter.startWriting() - NSLog("SampleHandler: writer ready, recording to %@", url.path) - } - - /// Registers the Darwin observer that finishes the broadcast when the host app - /// posts the stop notification. Called before any fallible setup so the - /// broadcast is always stoppable. - private func registerStopObserver() { - CFNotificationCenterAddObserver( - CFNotificationCenterGetDarwinNotifyCenter(), - Unmanaged.passUnretained(self).toOpaque(), - { _, observer, _, _, _ in - guard let observer = observer else { return } - let handler = Unmanaged.fromOpaque(observer).takeUnretainedValue() - guard !handler.finishing else { return } - handler.finishing = true - NSLog("SampleHandler: stop notification received -> finishBroadcastWithError") - handler.finishBroadcastWithError( - NSError(domain: "de.jonasbark.swiftcontrol.darwin", code: 0, - userInfo: [NSLocalizedDescriptionKey: "Recording stopped by app"])) - }, - SampleHandler.stopNotificationName as CFString, - nil, - .deliverImmediately) - } - - override func processSampleBuffer(_ sampleBuffer: CMSampleBuffer, with sampleBufferType: RPSampleBufferType) { - // Poll the app's stop flag every frame — reliable cross-process stop signal. - if !finishing, let stop = stopFlagURL, FileManager.default.fileExists(atPath: stop.path) { - finishing = true - NSLog("SampleHandler: stop flag detected -> finishBroadcastWithError") - finishBroadcastWithError( - NSError(domain: "de.jonasbark.swiftcontrol.darwin", code: 0, - userInfo: [NSLocalizedDescriptionKey: "Recording stopped by app"])) - return - } - - guard sampleBufferType == .video, - let writer = writer, - let input = videoInput, - CMSampleBufferDataIsReady(sampleBuffer) else { return } - - if !sessionStarted { - let pts = CMSampleBufferGetPresentationTimeStamp(sampleBuffer) - writer.startSession(atSourceTime: pts) - sessionStarted = true - } - - if input.isReadyForMoreMediaData { - input.append(sampleBuffer) - } - } - - override func broadcastFinished() { - // Remove the Darwin observer to avoid dangling pointer after dealloc. - CFNotificationCenterRemoveObserver( - CFNotificationCenterGetDarwinNotifyCenter(), - Unmanaged.passUnretained(self).toOpaque(), - CFNotificationName(SampleHandler.stopNotificationName as CFString), - nil) - - // Clear the cross-process flags so the next recording starts clean. - if let active = activeFlagURL { try? FileManager.default.removeItem(at: active) } - if let stop = stopFlagURL { try? FileManager.default.removeItem(at: stop) } - - let group = DispatchGroup() - group.enter() - videoInput?.markAsFinished() - writer?.finishWriting { group.leave() } - group.wait() - - // Write the output path into the shared App Group defaults so the host app - // can read it back when its stop() method channel call returns. - if let path = outputURL?.path { - UserDefaults(suiteName: SampleHandler.appGroup)?.set(path, forKey: "lastRecordingPath") - NSLog("SampleHandler: recording saved to \(path)") - } - } -} diff --git a/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements b/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements deleted file mode 100644 index 0c67376e..00000000 --- a/ios/ScreenRecordBroadcast/ScreenRecordBroadcast.entitlements +++ /dev/null @@ -1,5 +0,0 @@ - - - - - diff --git a/packages/screen_recorder/NATIVE_SETUP.md b/packages/screen_recorder/NATIVE_SETUP.md index b14a78b8..ae0b543b 100644 --- a/packages/screen_recorder/NATIVE_SETUP.md +++ b/packages/screen_recorder/NATIVE_SETUP.md @@ -6,12 +6,12 @@ plugin compile here, Windows and the iOS extension target need your machines. ## Status -| Platform | Backend | Verified | -| --- | --- | --- | -| Android | `flutter_screen_recording` + `gal` (in `lib/services/.../android_screen_recorder.dart`) | ✅ builds APK, tested | -| macOS | ScreenCaptureKit → AVAssetWriter (`macos/Classes/`) | ✅ `flutter build macos` passes — runtime (TCC + capture) still needs a Mac | -| iOS | ReplayKit broadcast: plugin picker bridge + Broadcast Upload Extension | ⚠️ plugin compiles (`flutter build ios` passes); **extension target needs Xcode wiring** | -| Windows | Windows.Graphics.Capture + Media Foundation (`windows/`) | ❌ **never compiled — build on Windows and iterate** | +| Platform | Backend | Verified | +|----------|-----------------------------------------------------------------------------------------|------------------------------------------------------------------------------------------| +| Android | `flutter_screen_recording` + `gal` (in `lib/services/.../android_screen_recorder.dart`) | ✅ builds APK, tested | +| macOS | ScreenCaptureKit → AVAssetWriter (`macos/Classes/`) | ✅ `flutter build macos` passes — runtime (TCC + capture) still needs a Mac | +| iOS | ReplayKit broadcast: plugin picker bridge + Broadcast Upload Extension | ⚠️ plugin compiles (`flutter build ios` passes); **extension target needs Xcode wiring** | +| Windows | Windows.Graphics.Capture + Media Foundation (`windows/`) | ❌ **never compiled — build on Windows and iterate** | ## macOS — remaining - Runtime test on a Mac: bind a key to "Record Screen", grant the Screen Recording TCC prompt (may need an app relaunch), record, confirm an mp4 in `~/Movies/BikeControl/`. diff --git a/prop b/prop index 61b5c934..45ed0b97 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 61b5c9342fe68a2fb688643054b61dae204cf6c3 +Subproject commit 45ed0b97e4a85dd86e2fb04292bc8298e92dde5b From 29edc8320af3745ddc4a4049256ff698da7cc1d8 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 20:27:36 +0200 Subject: [PATCH 070/106] refactor: remove dead supportsNativeFrontShift getter Re-introduced by a merge; the forward path emits the both-shifters combo regardless of app, so the capability flag is unused. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/utils/keymap/apps/supported_app.dart | 5 ----- lib/utils/keymap/apps/zwift.dart | 3 --- 2 files changed, 8 deletions(-) diff --git a/lib/utils/keymap/apps/supported_app.dart b/lib/utils/keymap/apps/supported_app.dart index b7219bb1..47b48925 100644 --- a/lib/utils/keymap/apps/supported_app.dart +++ b/lib/utils/keymap/apps/supported_app.dart @@ -70,11 +70,6 @@ abstract class SupportedApp { /// (e.g. MyWhoosh → 30). int get virtualGearAmount => 24; - /// Whether this app performs its own front-chainring (SRAM-style) shift when - /// it receives a simultaneous both-shifter press. When true, the emulator - /// forwards the combo natively; when false, it approximates with N rear shifts. - bool get supportsNativeFrontShift => false; - /// Default OpenBikeControl supported buttons used by the ButtonEditor /// before (or without) a live OBP connection. Overridden by trainer-app /// subclasses that ship a known-good list. diff --git a/lib/utils/keymap/apps/zwift.dart b/lib/utils/keymap/apps/zwift.dart index e9fa44b4..9bd79b9d 100644 --- a/lib/utils/keymap/apps/zwift.dart +++ b/lib/utils/keymap/apps/zwift.dart @@ -12,9 +12,6 @@ class Zwift extends SupportedApp { (AppConnectionMethod.zwiftBle, ConnectionSupport.beta), ]; - @override - bool get supportsNativeFrontShift => true; - Zwift() : super( name: 'Zwift', From 4bdd0bb93ef0c44ad5cc68e2d734de2ed6ca92e0 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Wed, 24 Jun 2026 20:28:38 +0200 Subject: [PATCH 071/106] feat(6.2): make Record Screen a Pro-only action (proGuard + editor badge) --- lib/pages/button_edit.dart | 1 + lib/utils/iap/iap_manager.dart | 8 ++++++++ lib/utils/keymap/keymap.dart | 1 + test/integration/screen_recording_action_test.dart | 11 +++++++++++ 4 files changed, 21 insertions(+) diff --git a/lib/pages/button_edit.dart b/lib/pages/button_edit.dart index 6e2b6e5f..af7ff3aa 100644 --- a/lib/pages/button_edit.dart +++ b/lib/pages/button_edit.dart @@ -616,6 +616,7 @@ class _ButtonEditPageState extends State { ], SelectableCard( icon: LucideIcons.video, + isProOnly: true, title: Text(context.i18n.actionScreenRecording), isActive: _keyPair.inGameAction == InGameAction.screenRecording, onPressed: () { diff --git a/lib/utils/iap/iap_manager.dart b/lib/utils/iap/iap_manager.dart index d0ea08e9..985b8a48 100644 --- a/lib/utils/iap/iap_manager.dart +++ b/lib/utils/iap/iap_manager.dart @@ -74,6 +74,14 @@ class IAPManager { return isProEnabledForCurrentDevice || hasPurchasedBefore50RVC; } + /// Test-only: force the Pro entitlement state so Pro-gated actions/UI can be + /// exercised without a live subscription or device registration. + @visibleForTesting + void setProForTesting({required bool enabled}) { + _isInitialized = true; + isLocalPro.value = enabled; + } + bool get hasPurchasedBefore50RVC => isPurchased.value && ((_revenueCatService?.hasPurchasedBefore50 ?? false) || (_windowsIapService?.hasPurchasedBefore50 ?? false)); diff --git a/lib/utils/keymap/keymap.dart b/lib/utils/keymap/keymap.dart index 649d28a0..7312dcb2 100644 --- a/lib/utils/keymap/keymap.dart +++ b/lib/utils/keymap/keymap.dart @@ -636,6 +636,7 @@ class KeyPair { command != null && command!.trim().isNotEmpty || screenshotPath != null && screenshotPath!.trim().isNotEmpty || isSpecialKey || + inGameAction == InGameAction.screenRecording || (androidAction != null && core.logic.showLocalControl && core.actionHandler is AndroidActions) || (androidIntentAction != null && androidIntentAction!.trim().isNotEmpty && diff --git a/test/integration/screen_recording_action_test.dart b/test/integration/screen_recording_action_test.dart index 05979f28..eda05216 100644 --- a/test/integration/screen_recording_action_test.dart +++ b/test/integration/screen_recording_action_test.dart @@ -2,6 +2,7 @@ import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/iap/iap_manager.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/utils/keymap/apps/zwift.dart'; @@ -47,6 +48,8 @@ Future main() async { setUp(() async { await env.resetState(); + // Screen recording is a Pro action; enable Pro so proGuard lets the handler run. + IAPManager.instance.setProForTesting(enabled: true); backend = _FakeBackend(); core.screenRecording = ScreenRecordingService(backend: backend); @@ -84,4 +87,12 @@ Future main() async { expect(result, isA()); expect(result.message, AppLocalizations.current.screenRecordingNotSupported); }); + + test('non-Pro user is blocked by the Pro gate (recording never starts)', () async { + IAPManager.instance.setProForTesting(enabled: false); + final result = await actions.performAction(button, isKeyDown: true, isKeyUp: false); + expect(result, isA()); + expect((result as Error).type, ErrorType.proRequired); + expect(backend.starts, 0); + }); } From 157d9d12032adc1a1966ddaac911ac5829616107 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 06:57:29 +0200 Subject: [PATCH 072/106] update changelog --- CHANGELOG.md | 8 ++++---- pubspec.yaml | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4cb5dad..c56fece7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,8 @@ -### 6.2.0 (24-06-2026) +### 6.2.0 (unreleased) **Features**: -- SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Pressing both shift buttons at once also triggers it (Zwift Ride and Click; Zwift Play via a short simultaneous-press window). Set your chainring sizes per trainer in the gear settings. -- Floating gear overlay (Picture-in-Picture): your current gear can now show in a floating window over your trainer app during a ride. It's automatic on iPad — shown right away, since there's screen room — and on iPhones without a Dynamic Island; iPhones with a Dynamic Island can switch it on in the overlay settings. The Lock Screen / Dynamic Island display stays available alongside it. -- Screen recording: a new assignable "Record Screen" action starts and stops a screen recording from a controller button. On Android the clip is saved to your gallery; on macOS it's saved to a folder you can open straight from the activity log. +- SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Set your chainring sizes per trainer in the gear settings. +- iOS / iPadOS: Floating gear overlay (Picture-in-Picture): your current gear can now show in a floating window over your trainer app during a ride. +- Screen recording: a new assignable "Record Screen" action starts and stops a screen recording from a controller button. ### 6.1.0 (19-06-2026) **Features**: diff --git a/pubspec.yaml b/pubspec.yaml index 35e13bb8..1b5520dd 100755 --- a/pubspec.yaml +++ b/pubspec.yaml @@ -1,7 +1,7 @@ name: bike_control description: "BikeControl - Control your virtual riding" publish_to: 'none' # Remove this line if you wish to publish to pub.dev -version: 6.1.0+138 +version: 6.2.0+139 environment: sdk: ^3.9.0 From 9300138b5e7334cf1712da4d54c9a6d59b05ef73 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 07:34:47 +0200 Subject: [PATCH 073/106] fix(obc): resolve "Address already in use" on the OpenBikeControl server The OpenBikeControl mDNS emulator hit EADDRINUSE on its fixed port 36867 when "Connect directly over network" was toggled off then on: the un-awaited stop() hadn't released the socket before start() rebound it. - Bump prop submodule: ResilientTcpServer now supersedes a stale same-port instance before binding and defaults to walking ports (portAttempts: 5). - OBC advertises the ACTUAL bound port via mDNS instead of a hardcoded 36867, so it can walk to a free port and stay reachable (mirrors the DirCon emulator). Companion apps read the port from the SRV record. - Reset isStarted on every start-failure path so a genuinely blocked port no longer leaves the feature showing as "running". - Pin MyWhoosh Link to portAttempts: 1 (fixed-port contract preserved). Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/mywhoosh/link.dart | 2 ++ .../openbikecontrol/obc_mdns_emulator.dart | 26 ++++++++++++++----- prop | 2 +- 3 files changed, 22 insertions(+), 8 deletions(-) diff --git a/lib/bluetooth/devices/mywhoosh/link.dart b/lib/bluetooth/devices/mywhoosh/link.dart index 77ad4c5f..1de380a7 100644 --- a/lib/bluetooth/devices/mywhoosh/link.dart +++ b/lib/bluetooth/devices/mywhoosh/link.dart @@ -51,6 +51,8 @@ class WhooshLink extends TrainerConnection { // blocked port must fail loudly (the caller surfaces the error). final server = ResilientTcpServer( preferredPort: 21587, + // Fixed-port contract (see above): never walk off 21587. + portAttempts: 1, onClientConnected: (socket) { if (kDebugMode) { print('Client connected: ${socket.remoteAddress.address}:${socket.remotePort}'); diff --git a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart index e15403a5..ea71e20b 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_mdns_emulator.dart @@ -52,10 +52,15 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage // Android's 192.0.0.8 CLAT dummy address). final localIP = await AdvertisedAddressPicker.pick(); if (localIP == null) { + isStarted.value = false; throw 'Could not find network interface'; } await _createTcpServer(); + // The port walks under contention (ResilientTcpServer's default fallback), + // so advertise the ACTUAL bound port — companion apps read it from the SRV + // record. Hardcoding 36867 here would point clients at the wrong port. + final boundPort = _server!.boundPort; try { // Create service @@ -63,7 +68,7 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage AdvertisedService( name: 'BikeControl', type: _useDirCon ? '_wahoo-fitness-tnp._tcp' : '_openbikecontrol._tcp', - port: 36867, + port: boundPort, address: localIP, txt: _useDirCon ? { @@ -81,10 +86,13 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage }, ), ); - _registeredEntry = (name: 'BikeControl', port: 36867); - SelfAdvertisementRegistry.instance.add(name: 'BikeControl', port: 36867); - print('Server started - advertising service at ${localIP.address}:36867!'); + _registeredEntry = (name: 'BikeControl', port: boundPort); + SelfAdvertisementRegistry.instance.add(name: 'BikeControl', port: boundPort); + print('Server started - advertising service at ${localIP.address}:$boundPort!'); } catch (e, s) { + // Keep the flag honest so the UI doesn't show a phantom-running server + // and the user can cleanly retry. + isStarted.value = false; core.connection.signalNotification(AlertNotification(LogLevel.LOGLEVEL_ERROR, 'Failed to start mDNS server: $e')); rethrow; } @@ -115,9 +123,10 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage connectedApp.value = null; } - /// OpenBikeControl is a fixed-port protocol contract (36867): companion - /// apps may connect without reading the port from the advertisement, so - /// there is NO port fallback here — a blocked port must fail loudly. + /// Binds the OpenBikeControl TCP server. The preferred port is 36867 but it + /// walks to the next free port under contention (ResilientTcpServer's default + /// fallback); [startServer] advertises whichever port was actually bound, so + /// companion apps must read the port from the mDNS SRV record. Future _createTcpServer() async { final server = ResilientTcpServer( preferredPort: 36867, @@ -157,6 +166,9 @@ class OpenBikeControlMdnsEmulator extends TrainerConnection implements OnMessage try { await server.start(); } catch (e) { + // A blocked fixed port (foreign holder) reaches here — reset the flag so + // the start is honestly reported as failed and can be retried. + isStarted.value = false; core.connection.signalNotification(AlertNotification(LogLevel.LOGLEVEL_ERROR, 'Failed to start server: $e')); rethrow; } diff --git a/prop b/prop index 61b5c934..fe8f1513 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit 61b5c9342fe68a2fb688643054b61dae204cf6c3 +Subproject commit fe8f1513bbcb9838d4af72b6aa54cbbcd72f44f2 From 38ea17138bbabb836f7bc163b48e8a60efa36710 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 08:16:08 +0200 Subject: [PATCH 074/106] fix(ui): guard async setState/context against disposed widgets Symbolicating a Rouvy user's 6.1 crashes (Shorebird patch build_id 4b7026f5fbf44e52452ba9e557c2c5a0) surfaced two "Null check operator used on a null value" crashes: async UI callbacks running after their widget was disposed (the user rapidly re-toggled the Zwift BLE option as advertising kept failing). - ZwiftTile.onChange: setState() ran after `await stopAllBleConnections` on an unmounted state -> guard with `mounted`. - ConnectionMethod: openPermissionSheet(context, ...) and setState() ran after `await Future.wait(requirements)` on a defunct context -> guard both async gaps with `context.mounted` (matching the existing guard at line 315). The underlying trigger (Zwift emulator "Data too large" advertise failure on Rouvy) is tracked separately for the 6.2 branch. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/widgets/apps/zwift_tile.dart | 6 +++++- lib/widgets/ui/connection_method.dart | 5 +++++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/lib/widgets/apps/zwift_tile.dart b/lib/widgets/apps/zwift_tile.dart index 65491863..527a4577 100644 --- a/lib/widgets/apps/zwift_tile.dart +++ b/lib/widgets/apps/zwift_tile.dart @@ -53,7 +53,11 @@ class _ZwiftTileState extends State { core.connection.signalNotification(AlertNotification(LogLevel.LOGLEVEL_ERROR, e.toString())); }); } - setState(() {}); + // onChange awaits stopAllBleConnections above; the tile can + // be disposed mid-await (rapid toggling while advertising + // keeps failing), so guard setState — calling it unmounted + // throws "Null check operator used on a null value". + if (mounted) setState(() {}); }, title: context.i18n.connectUsingBluetooth, description: !isStarted diff --git a/lib/widgets/ui/connection_method.dart b/lib/widgets/ui/connection_method.dart index c225b836..fe529a2c 100644 --- a/lib/widgets/ui/connection_method.dart +++ b/lib/widgets/ui/connection_method.dart @@ -112,11 +112,16 @@ class _ConnectionMethodState extends State with WidgetsBinding widget.onChange(!widget.isEnabled); } else { Future.wait(widget.requirements.map((e) => e.getStatus())).then((_) async { + // The widget can be disposed across these async gaps; using a defunct + // context (openPermissionSheet) or setState then throws "Null check + // operator used on a null value". + if (!context.mounted) return; final notDone = widget.requirements.filter((e) => !e.status).toList(); if (notDone.isEmpty) { widget.onChange(!widget.isEnabled); } else { await openPermissionSheet(context, notDone); + if (!context.mounted) return; _recheckRequirements(); setState(() {}); } From b619d942fa8a70c40afe399e5d17f207b29542c6 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 08:27:39 +0200 Subject: [PATCH 075/106] fix(zwift): put Rouvy advertisement service UUIDs in the scan response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Rouvy Zwift-BLE advertisement (Zwift fc82 + OBC 128-bit UUID + name "BikeControl" = ~38 bytes) overflows Android's 31-byte primary packet, so startAdvertising fails with "Data too large" — Rouvy users on 6.1 can't connect (the bluetooth_low_energy -> universal_ble migration stopped splitting service UUIDs into the scan response). Bump universal_ble to the fork commit that adds PeripheralAndroidOptions.addServicesInScanResponse, expose it through PeripheralServer.startAdvertising, and enable it for the Rouvy branch of the Zwift emulator. Primary packet becomes flags+name (~16B), scan response carries the UUIDs (~22B); active scanners still see everything. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/zwift/zwift_emulator.dart | 4 ++++ lib/bluetooth/peripheral_server.dart | 9 ++++++++- pubspec.lock | 4 ++-- 3 files changed, 14 insertions(+), 3 deletions(-) diff --git a/lib/bluetooth/devices/zwift/zwift_emulator.dart b/lib/bluetooth/devices/zwift/zwift_emulator.dart index 7866be9e..a487de64 100644 --- a/lib/bluetooth/devices/zwift/zwift_emulator.dart +++ b/lib/bluetooth/devices/zwift/zwift_emulator.dart @@ -257,6 +257,10 @@ class ZwiftEmulator extends TrainerConnection { if (isRouvy) OpenBikeControlConstants.SERVICE_UUID, ], localName: isRouvy ? 'BikeControl' : 'KICKR BIKE PRO 1337', + // The Rouvy variant adds a 128-bit UUID which, with the name, overflows + // the 31-byte primary advertisement (Android "Data too large"); move the + // service UUIDs to the scan response there. Only Rouvy needs it. + servicesInScanResponse: isRouvy, ); _isLoading = false; onUpdate(); diff --git a/lib/bluetooth/peripheral_server.dart b/lib/bluetooth/peripheral_server.dart index 9331aeba..3bdef648 100644 --- a/lib/bluetooth/peripheral_server.dart +++ b/lib/bluetooth/peripheral_server.dart @@ -71,11 +71,18 @@ class PeripheralServer { Future startAdvertising({ required List services, String? localName, + // Put service UUIDs in the Android scan response instead of the primary + // advertisement. Needed when a 128-bit UUID + name would overflow the + // 31-byte primary packet (e.g. the Rouvy Zwift emulator advertisement). + bool servicesInScanResponse = false, }) => UniversalBlePeripheral.startAdvertising( services: services, localName: localName, platformConfig: PeripheralPlatformConfig( - android: PeripheralAndroidOptions(addManufacturerDataInScanResponse: true), + android: PeripheralAndroidOptions( + addManufacturerDataInScanResponse: true, + addServicesInScanResponse: servicesInScanResponse, + ), ), ); diff --git a/pubspec.lock b/pubspec.lock index c1e3831e..d27a4a8a 100755 --- a/pubspec.lock +++ b/pubspec.lock @@ -1922,10 +1922,10 @@ packages: description: path: "." ref: changes - resolved-ref: "3beb8b6d18ac857fba578416857455d55aa788f9" + resolved-ref: "767ebddd95d324e57634a5e551867db31d22f379" url: "https://github.com/jonasbark/universal_ble.git" source: git - version: "2.0.4" + version: "2.1.0" url_launcher: dependency: "direct main" description: From 1488406ea156f2ebced9a5fcf283a731c41b8bb0 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 09:08:18 +0200 Subject: [PATCH 076/106] refactor: share BLE advertising "already started" recovery via mixin Extracts the recovery added for OpenBikeControl (d3f72dbe) into PeripheralAdvertisingRecovery and applies it to ZwiftEmulator too. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../openbikecontrol/obc_ble_emulator.dart | 30 ++++--------- .../devices/zwift/zwift_emulator.dart | 21 +++++++--- .../peripheral_advertising_recovery.dart | 42 +++++++++++++++++++ 3 files changed, 67 insertions(+), 26 deletions(-) create mode 100644 lib/bluetooth/peripheral_advertising_recovery.dart diff --git a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart index dd52cdcc..483df7ad 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart @@ -7,6 +7,7 @@ import 'package:bike_control/bluetooth/devices/openbikecontrol/openbikecontrol_d import 'package:bike_control/bluetooth/devices/openbikecontrol/protocol_parser.dart'; import 'package:bike_control/bluetooth/devices/trainer_connection.dart'; import 'package:bike_control/bluetooth/messages/notification.dart' show AlertNotification, LogNotification; +import 'package:bike_control/bluetooth/peripheral_advertising_recovery.dart'; import 'package:bike_control/bluetooth/peripheral_server.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; @@ -22,14 +23,16 @@ import 'package:prop/prop.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart' hide ButtonState; import 'package:universal_ble/universal_ble.dart'; -class OpenBikeControlBluetoothEmulator extends TrainerConnection { +class OpenBikeControlBluetoothEmulator extends TrainerConnection with PeripheralAdvertisingRecovery { final _server = PeripheralServer(); final ValueNotifier connectedApp = ValueNotifier(null); bool _isServiceAdded = false; bool _isSubscribedToEvents = false; - bool _recoveringAdvertising = false; String? _currentDeviceId; + @override + PeripheralServer get advertisingServer => _server; + OpenBikeControlBluetoothEmulator() : super( title: () => AppLocalizations.current.connectUsingBluetooth, @@ -59,22 +62,7 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { print('OpenBikeControl advertising state: ${state.name}${error != null ? ' — $error' : ''}'); } if (state == PeripheralAdvertisingState.error) { - // The shared CBPeripheralManager (or a stale advertisement from a prior - // session that wasn't torn down cleanly) can already be advertising, - // making CoreBluetooth reject startAdvertising with "Advertising has - // already started." Recover by stopping and restarting our own service - // once — guarded so a persistent error can't loop. - final alreadyStarted = error?.toLowerCase().contains('already') ?? false; - if (alreadyStarted && !_recoveringAdvertising) { - _recoveringAdvertising = true; - try { - await _server.stopAdvertising(); - await _startAdvertising(); - } finally { - _recoveringAdvertising = false; - } - return; - } + if (await recoverIfAlreadyAdvertising(error)) return; core.connection.signalNotification( AlertNotification( LogLevel.LOGLEVEL_WARNING, @@ -202,11 +190,11 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection { // Drop any stale/foreign advertisement (e.g. left over from a previous // session or another peripheral role) before claiming the shared manager. // stopAdvertising is idempotent on Darwin, so this is safe when idle. - await _server.stopAdvertising(); - await _startAdvertising(); + await restartAdvertising(); } - Future _startAdvertising() => _server.startAdvertising( + @override + Future startServiceAdvertising() => _server.startAdvertising( services: [OpenBikeControlConstants.SERVICE_UUID], localName: 'BikeControl', ); diff --git a/lib/bluetooth/devices/zwift/zwift_emulator.dart b/lib/bluetooth/devices/zwift/zwift_emulator.dart index a487de64..1790b81f 100644 --- a/lib/bluetooth/devices/zwift/zwift_emulator.dart +++ b/lib/bluetooth/devices/zwift/zwift_emulator.dart @@ -8,6 +8,7 @@ import 'package:bike_control/bluetooth/devices/trainer_connection.dart'; import 'package:bike_control/bluetooth/devices/zwift/constants.dart'; import 'package:bike_control/bluetooth/devices/zwift/zwift_ride.dart'; import 'package:bike_control/bluetooth/messages/notification.dart'; +import 'package:bike_control/bluetooth/peripheral_advertising_recovery.dart'; import 'package:bike_control/bluetooth/peripheral_server.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; @@ -25,7 +26,7 @@ import 'package:prop/prop.dart' hide RideButtonMask; import 'package:shadcn_flutter/shadcn_flutter.dart'; import 'package:universal_ble/universal_ble.dart'; -class ZwiftEmulator extends TrainerConnection { +class ZwiftEmulator extends TrainerConnection with PeripheralAdvertisingRecovery { bool get isLoading => _isLoading; final _server = PeripheralServer(); @@ -34,6 +35,9 @@ class ZwiftEmulator extends TrainerConnection { bool _isSubscribedToEvents = false; String? _currentDeviceId; + @override + PeripheralServer get advertisingServer => _server; + ZwiftEmulator() : super( title: () => AppLocalizations.current.connectUsingBluetooth, @@ -83,11 +87,12 @@ class ZwiftEmulator extends TrainerConnection { } }); - _server.onAdvertisingStateChanged((state, error) { + _server.onAdvertisingStateChanged((state, error) async { if (kDebugMode) { print('Zwift advertising state: ${state.name}${error != null ? ' — $error' : ''}'); } if (state == PeripheralAdvertisingState.error) { + if (await recoverIfAlreadyAdvertising(error)) return; core.connection.signalNotification( AlertNotification( LogLevel.LOGLEVEL_WARNING, @@ -251,7 +256,15 @@ class ZwiftEmulator extends TrainerConnection { print('Starting advertising with Zwift service...'); - await _server.startAdvertising( + await restartAdvertising(); + _isLoading = false; + onUpdate(); + } + + @override + Future startServiceAdvertising() { + final isRouvy = core.settings.getTrainerApp() is Rouvy; + return _server.startAdvertising( services: [ ZwiftConstants.ZWIFT_RIDE_CUSTOM_SERVICE_UUID_SHORT, if (isRouvy) OpenBikeControlConstants.SERVICE_UUID, @@ -262,8 +275,6 @@ class ZwiftEmulator extends TrainerConnection { // service UUIDs to the scan response there. Only Rouvy needs it. servicesInScanResponse: isRouvy, ); - _isLoading = false; - onUpdate(); } Future stopAdvertising() async { diff --git a/lib/bluetooth/peripheral_advertising_recovery.dart b/lib/bluetooth/peripheral_advertising_recovery.dart new file mode 100644 index 00000000..12a6db49 --- /dev/null +++ b/lib/bluetooth/peripheral_advertising_recovery.dart @@ -0,0 +1,42 @@ +import 'package:bike_control/bluetooth/peripheral_server.dart'; + +/// Shared recovery for BLE peripheral emulators that advertise via a +/// [PeripheralServer]. The shared CoreBluetooth manager (or a stale +/// advertisement from a prior session) can already be advertising, making +/// CoreBluetooth reject `startAdvertising` with "Advertising has already +/// started." Mixing this in gives an emulator a one-shot stop+restart recovery +/// and a pre-emptive restart helper, without each emulator duplicating the guard. +/// +/// Implementers provide the server and their own service-advertising call +/// (which carries that emulator's services / localName / scan-response config). +mixin PeripheralAdvertisingRecovery { + PeripheralServer get advertisingServer; + + /// Start advertising THIS emulator's service(s) with its own config. + Future startServiceAdvertising(); + + bool _recoveringAdvertising = false; + + /// Drop any stale/foreign advertisement, then (re)start ours. `stopAdvertising` + /// is idempotent on Darwin, so this is safe to call when idle. + Future restartAdvertising() async { + await advertisingServer.stopAdvertising(); + await startServiceAdvertising(); + } + + /// Recover from an "Advertising has already started" error by stopping and + /// restarting our service once. Guarded so a persistent error cannot loop. + /// Returns true if it handled the error (caller should then NOT also warn). + Future recoverIfAlreadyAdvertising(String? error) async { + final alreadyStarted = error?.toLowerCase().contains('already') ?? false; + if (!alreadyStarted || _recoveringAdvertising) return false; + _recoveringAdvertising = true; + try { + await advertisingServer.stopAdvertising(); + await startServiceAdvertising(); + } finally { + _recoveringAdvertising = false; + } + return true; + } +} From 7c2a5040d31dd3d92f4e52657a1e77ef59c65438 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 09:32:07 +0200 Subject: [PATCH 077/106] Bump prop submodule: fix Zwift Sync grade double sign-decode MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit prop ffdb6c5 — simulatedGrade (protobuf sint32) was sign-decoded twice, flipping every odd grade negative, so a Rouvy ride's steady ~+2% grade lurched between climb and descent. Fixes the user-reported "resistance all over the place / flat feels like climbing". Co-Authored-By: Claude Opus 4.8 (1M context) --- prop | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/prop b/prop index fe8f1513..ffdb6c5e 160000 --- a/prop +++ b/prop @@ -1 +1 @@ -Subproject commit fe8f1513bbcb9838d4af72b6aa54cbbcd72f44f2 +Subproject commit ffdb6c5e7a0166221c22160114af1bc865ac695f From 5e7eff0aff6694bf379af118807e961d707701f4 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 09:39:38 +0200 Subject: [PATCH 078/106] feat(proxy): show transport icon to disambiguate same-named trainers When the same trainer is discovered over both WiFi (DirCon) and Bluetooth, two proxy entries appear with an identical name (both already Beta). Add a small WiFi/Bluetooth icon left of the Beta pill, shown only when a same-named sibling exists, so the duplicates can be told apart. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/base_device.dart | 8 ++++++++ lib/bluetooth/devices/proxy/proxy_device.dart | 17 +++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/lib/bluetooth/devices/base_device.dart b/lib/bluetooth/devices/base_device.dart index 95933473..579ec1c3 100644 --- a/lib/bluetooth/devices/base_device.dart +++ b/lib/bluetooth/devices/base_device.dart @@ -485,8 +485,15 @@ abstract class BaseDevice { return []; } + /// An optional small badge rendered immediately to the left of the Beta pill + /// in the device header. Smart trainers use it to show a transport icon when + /// the same trainer is discovered over both WiFi and Bluetooth, so the two + /// identically-named entries can be told apart. Returns null by default. + Widget? nameBadge(BuildContext context) => null; + Widget showInformation(BuildContext context, {required bool showFull, Widget? footer}) { final meta = showMetaInformation(context, showFull: showFull); + final badge = nameBadge(context); // Hero the entire header Row so the icon, title and meta fly together // when navigating between the overview's compact card and the // ControllerSettingsPage's expanded card — the same Row shape is rendered @@ -520,6 +527,7 @@ abstract class BaseDevice { toString(), style: const TextStyle(fontSize: 16, fontWeight: FontWeight.w600, letterSpacing: -0.2), ), + if (badge != null) badge, if (isBeta) BetaPill(), Expanded(child: SizedBox()), if (!showFull) diff --git a/lib/bluetooth/devices/proxy/proxy_device.dart b/lib/bluetooth/devices/proxy/proxy_device.dart index e09684e2..701e7f60 100644 --- a/lib/bluetooth/devices/proxy/proxy_device.dart +++ b/lib/bluetooth/devices/proxy/proxy_device.dart @@ -455,6 +455,23 @@ class ProxyDevice extends BluetoothDevice { emulator.processCharacteristic(characteristic, bytes); } + @override + Widget? nameBadge(BuildContext context) { + // The same physical trainer can be discovered over both WiFi (DirCon) and + // Bluetooth, producing two entries with an identical name. When that + // happens, show a transport icon so the duplicates can be told apart at a + // glance — WiFi on the DirCon entry, Bluetooth on the BLE one. + final hasDuplicateName = core.connection.proxyDevices.any( + (d) => d.uniqueId != uniqueId && d.name == name, + ); + if (!hasDuplicateName) return null; + return Icon( + isWifiUpstream ? LucideIcons.wifi : LucideIcons.bluetooth, + size: 14, + color: Theme.of(context).colorScheme.mutedForeground, + ); + } + @override List showMetaInformation(BuildContext context, {required bool showFull}) { if (isConnected) { From 4602ba929a79f7f9eb24e86113021a05ff1fc291 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 11:46:31 +0200 Subject: [PATCH 079/106] fix(screen_recorder): qualify IDirect3DDxgiInterfaceAccess to fix Windows build The interop interface lives in the ABI namespace ::Windows::Graphics::DirectX::Direct3D11, not the winrt projection namespace pulled in via `using namespace`. The bare name was undeclared (C2065), cascading into C2672 and C3536. Fully qualify it (with leading :: so `using namespace winrt;` doesn't misroute it). Co-Authored-By: Claude Opus 4.8 (1M context) --- packages/screen_recorder/windows/capture_recorder.cpp | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/packages/screen_recorder/windows/capture_recorder.cpp b/packages/screen_recorder/windows/capture_recorder.cpp index 746ce830..9c78cfe0 100644 --- a/packages/screen_recorder/windows/capture_recorder.cpp +++ b/packages/screen_recorder/windows/capture_recorder.cpp @@ -163,9 +163,14 @@ bool CaptureRecorder::Start() { auto surface = frame.Surface(); com_ptr frameTexture; { - // VERIFY on Windows: surface.as<>() may need the IID_PPV_ARGS form; - // alternatively use surface.try_as<> and check for null. - auto dxgiAccess = surface.as(); + // IDirect3DDxgiInterfaceAccess lives in the ABI namespace + // ::Windows::Graphics::DirectX::Direct3D11 (declared by + // ), NOT the winrt + // projection namespace brought in by `using namespace` above. It must + // be fully qualified with a leading :: so `using namespace winrt;` + // doesn't misroute it to a non-existent winrt::Windows::... type. + auto dxgiAccess = surface.as< + ::Windows::Graphics::DirectX::Direct3D11::IDirect3DDxgiInterfaceAccess>(); HRESULT hr = dxgiAccess->GetInterface(IID_PPV_ARGS(frameTexture.put())); if (FAILED(hr)) return; } From 9e60e53d52fd1972e54c90fdbb946a4d319da383 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 11:55:49 +0200 Subject: [PATCH 080/106] fix(screen_recorder): correct upside-down Windows recording WGC/D3D surfaces are top-down, but the MF SinkWriter's RGB32->NV12 conversion treats uncompressed RGB as bottom-up, so feeding our top-down buffer through produced a vertically-flipped (upside-down) recording. Cancel the fixed flip by writing each source row into the mirrored destination row, handing MF a bottom-up buffer. Same number of memcpys, no extra cost. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../screen_recorder/windows/capture_recorder.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/packages/screen_recorder/windows/capture_recorder.cpp b/packages/screen_recorder/windows/capture_recorder.cpp index 9c78cfe0..20d6511d 100644 --- a/packages/screen_recorder/windows/capture_recorder.cpp +++ b/packages/screen_recorder/windows/capture_recorder.cpp @@ -238,13 +238,17 @@ bool CaptureRecorder::Start() { } // Copy row-by-row in case the GPU stride (RowPitch) > bytesPerRow. - // WGC surfaces are top-down; MF RGB32 also expects top-down. - // VERIFY on Windows: if the encoder produces an upside-down image, - // either set MF_MT_DEFAULT_STRIDE to a negative value on the input - // type, or reverse the row copy here. + // + // Orientation: WGC/D3D surfaces are top-down (row 0 = top), but the MF + // SinkWriter's RGB->NV12 conversion treats uncompressed RGB32 as + // bottom-up (legacy DIB convention) when no stride sign says otherwise. + // Feeding our top-down buffer straight through produced an upside-down + // recording. We cancel that fixed vertical flip by writing each source + // row into the mirrored destination row, i.e. handing MF a bottom-up + // buffer. Same number of memcpys, so no extra cost. const BYTE* pSrc = static_cast(mapped.pData); for (UINT row = 0; row < frameHeight; ++row) { - memcpy(pDst + row * bytesPerRow, + memcpy(pDst + (frameHeight - 1 - row) * bytesPerRow, pSrc + row * mapped.RowPitch, bytesPerRow); } From f22ab69cb707bcc1a0fb36fbbfc85c39f6e5f4f8 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 15:40:02 +0200 Subject: [PATCH 081/106] chore(deps): point universal_ble fork at rebased 2.1.0 + iOS patch The fork's `changes` branch was rebased onto upstream universal_ble 2.1.0 and reduced to the single iOS/macOS background-connect Swift patch. The Windows shared-mode/hresult fixes and addServicesInScanResponse have all landed upstream, so they are no longer carried by the fork. Co-Authored-By: Claude Opus 4.8 (1M context) --- pubspec.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pubspec.lock b/pubspec.lock index d27a4a8a..996d34af 100755 --- a/pubspec.lock +++ b/pubspec.lock @@ -1922,7 +1922,7 @@ packages: description: path: "." ref: changes - resolved-ref: "767ebddd95d324e57634a5e551867db31d22f379" + resolved-ref: d8961d78cb733526915eeb8a0530218a88d5649b url: "https://github.com/jonasbark/universal_ble.git" source: git version: "2.1.0" From c9c17105e5e65337801af94dedffd9d891a8df95 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 20:39:41 +0200 Subject: [PATCH 082/106] test(obc): cover PeripheralAdvertisingRecovery advertising recovery Regression tests for the "Advertising has already started" fix (shared by the OpenBikeControl and Zwift BLE emulators): unrelated/null errors are ignored, an already-advertising collision stops then restarts once, the match is case-insensitive, and the re-entrancy guard prevents a restart loop on a persistent error. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../peripheral_advertising_recovery_test.dart | 118 ++++++++++++++++++ 1 file changed, 118 insertions(+) create mode 100644 test/peripheral_advertising_recovery_test.dart diff --git a/test/peripheral_advertising_recovery_test.dart b/test/peripheral_advertising_recovery_test.dart new file mode 100644 index 00000000..1da7bda9 --- /dev/null +++ b/test/peripheral_advertising_recovery_test.dart @@ -0,0 +1,118 @@ +import 'package:bike_control/bluetooth/peripheral_advertising_recovery.dart'; +import 'package:bike_control/bluetooth/peripheral_server.dart'; +import 'package:flutter_test/flutter_test.dart'; + +/// A [PeripheralServer] whose advertising calls are recorded instead of hitting +/// the real CoreBluetooth/universal_ble platform. The recovery mixin only ever +/// calls [stopAdvertising], so that is all we override (never calling `super`, +/// which would touch the global peripheral platform). +class _FakePeripheralServer extends PeripheralServer { + _FakePeripheralServer(this._log); + final List _log; + int stopAdvertisingCalls = 0; + + @override + Future stopAdvertising() async { + stopAdvertisingCalls++; + _log.add('stop'); + } +} + +/// Minimal host mixing in the recovery behaviour. Records each service +/// (re)start and can optionally re-enter recovery mid-restart to exercise the +/// re-entrancy guard. +class _RecoveryHost with PeripheralAdvertisingRecovery { + _RecoveryHost(this._server, this._log); + final PeripheralServer _server; + final List _log; + + int startServiceCalls = 0; + + /// If set, invoked while a restart is in flight (i.e. while recovery still + /// holds its guard) — used to prove a nested recovery is rejected. + Future Function()? duringStart; + + @override + PeripheralServer get advertisingServer => _server; + + @override + Future startServiceAdvertising() async { + startServiceCalls++; + _log.add('start'); + final hook = duringStart; + if (hook != null) await hook(); + } +} + +void main() { + late List log; + late _FakePeripheralServer server; + late _RecoveryHost host; + + setUp(() { + log = []; + server = _FakePeripheralServer(log); + host = _RecoveryHost(server, log); + }); + + group('recoverIfAlreadyAdvertising', () { + test('ignores a null error', () async { + expect(await host.recoverIfAlreadyAdvertising(null), isFalse); + expect(server.stopAdvertisingCalls, 0); + expect(host.startServiceCalls, 0); + }); + + test('ignores an unrelated error (no "already")', () async { + // e.g. the Zwift "Data too large" advertise failure must NOT be treated + // as an already-advertising collision. + expect(await host.recoverIfAlreadyAdvertising('Data too large'), isFalse); + expect(log, isEmpty); + }); + + test('recovers an "already started" error: stop then restart, exactly once', () async { + final handled = await host.recoverIfAlreadyAdvertising('Advertising has already started'); + + expect(handled, isTrue, reason: 'caller should then NOT also warn'); + expect(server.stopAdvertisingCalls, 1); + expect(host.startServiceCalls, 1); + expect(log, ['stop', 'start'], reason: 'must stop the stale advertisement before restarting ours'); + }); + + test('matches "already" case-insensitively', () async { + expect(await host.recoverIfAlreadyAdvertising('ALREADY ADVERTISING'), isTrue); + expect(log, ['stop', 'start']); + }); + + test('is re-entrancy guarded: a nested recovery while restarting is rejected', () async { + bool? nested; + host.duringStart = () async { + // Runs while the first recovery still holds the guard — a persistent + // error re-firing here must not trigger a second stop/restart loop. + nested = await host.recoverIfAlreadyAdvertising('already started'); + }; + + final outer = await host.recoverIfAlreadyAdvertising('already started'); + + expect(outer, isTrue); + expect(nested, isFalse, reason: 'a recovery already in flight must not re-enter'); + expect(server.stopAdvertisingCalls, 1, reason: 'guard prevents a second stop'); + expect(host.startServiceCalls, 1, reason: 'guard prevents a second restart'); + }); + + test('releases the guard after recovery, so a later error recovers again', () async { + await host.recoverIfAlreadyAdvertising('already started'); + final second = await host.recoverIfAlreadyAdvertising('already started'); + + expect(second, isTrue); + expect(server.stopAdvertisingCalls, 2); + expect(host.startServiceCalls, 2); + }); + }); + + group('restartAdvertising', () { + test('unconditionally stops the stale advertisement then restarts ours', () async { + await host.restartAdvertising(); + expect(log, ['stop', 'start']); + }); + }); +} From 1cadf458bdef62bacadbe0f3e903d3a4d44aa216 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Thu, 25 Jun 2026 20:45:36 +0200 Subject: [PATCH 083/106] test(obc): cover app-info fragment reassembly; extract AppInfoReassembler MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract the OpenBikeControl app-info fragment-stitching out of the BLE emulator's write handler into a small, behavior-preserving AppInfoReassembler so it can be unit-tested directly (the emulator's startServer() is otherwise only reachable through the live peripheral platform). Adds regression tests for the multi-packet app-info write (TrainingPeaks on macOS), including the three-fragment case the previous single prior-fragment buffer dropped — it kept only the first failed fragment, so a message split across three packets never reassembled. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../openbikecontrol/app_info_reassembler.dart | 43 ++++++++ .../openbikecontrol/obc_ble_emulator.dart | 42 ++++---- ...bikecontrol_app_info_reassembler_test.dart | 97 +++++++++++++++++++ 3 files changed, 160 insertions(+), 22 deletions(-) create mode 100644 lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart create mode 100644 test/openbikecontrol_app_info_reassembler_test.dart diff --git a/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart b/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart new file mode 100644 index 00000000..6d52c051 --- /dev/null +++ b/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart @@ -0,0 +1,43 @@ +import 'dart:typed_data'; + +import 'package:bike_control/bluetooth/devices/openbikecontrol/protocol_parser.dart'; +import 'package:dartx/dartx.dart'; + +/// Reassembles an OpenBikeControl app-info message that a central may split +/// across several BLE write packets (e.g. TrainingPeaks on macOS). +/// +/// Feed each write payload to [offer]. It returns the parsed [AppInfo] once the +/// accumulated buffer parses successfully, or null while the message is still +/// incomplete — in which case the fragment is retained and prepended to the +/// next write. +/// +/// Every incomplete fragment is accumulated. A single prior-fragment buffer +/// could only ever stitch TWO writes together (it kept the first failed +/// fragment and dropped the middle one), so a message split across three or +/// more packets never reassembled; this keeps all fragments until one parses. +class AppInfoReassembler { + final List _fragments = []; + + /// The error from the most recent incomplete [offer], for diagnostics/logging. + Object? lastError; + + /// Fragments currently buffered awaiting completion. + int get pendingFragments => _fragments.length; + + /// Offer the next write payload. Returns the parsed [AppInfo] once the + /// accumulated buffer parses, or null while still incomplete. + AppInfo? offer(Uint8List value) { + try { + final appInfo = OpenBikeProtocolParser.parseAppInfo( + Uint8List.fromList([..._fragments.flatten(), ...value]), + ); + _fragments.clear(); + lastError = null; + return appInfo; + } catch (e) { + lastError = e; + _fragments.add(value); + return null; + } + } +} diff --git a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart index 483df7ad..991b2223 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart @@ -3,6 +3,7 @@ import 'dart:io'; import 'dart:typed_data'; import 'package:bike_control/bluetooth/ble.dart'; +import 'package:bike_control/bluetooth/devices/openbikecontrol/app_info_reassembler.dart'; import 'package:bike_control/bluetooth/devices/openbikecontrol/openbikecontrol_device.dart'; import 'package:bike_control/bluetooth/devices/openbikecontrol/protocol_parser.dart'; import 'package:bike_control/bluetooth/devices/trainer_connection.dart'; @@ -98,10 +99,9 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral }); // Some apps (e.g. TrainingPeaks on macOS) split the app-info write - // across several BLE packets. Accumulate every fragment that fails to - // parse and retry the flattened buffer until it's complete — a single - // prior-fragment buffer only ever stitches two writes together. - final firstAppInfoMessages = []; + // across several BLE packets; the reassembler accumulates fragments + // until the flattened buffer parses. + final appInfoReassembler = AppInfoReassembler(); _server.setWriteHandler(OpenBikeControlConstants.APPINFO_CHARACTERISTIC_UUID, ( deviceId, characteristicId, @@ -112,27 +112,25 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral if (kDebugMode) { print('Write request for characteristic: $characteristicId: ${bytesToReadableHex(value)}'); } - try { - AppInfo appInfo = OpenBikeProtocolParser.parseAppInfo( - Uint8List.fromList([...firstAppInfoMessages.flatten(), ...value]), - ); - firstAppInfoMessages.clear(); - isConnected.value = true; - _currentDeviceId = deviceId; - connectedApp.value = appInfo; - supportedActions = appInfo.supportedButtons.mapNotNull((b) => b.action).toList(); - final trainerApp = core.settings.getTrainerApp(); - if (trainerApp != null) { - unawaited(core.settings.setObpSupportedButtons(trainerApp.name, appInfo.supportedButtons)); - } + final appInfo = appInfoReassembler.offer(value); + if (appInfo == null) { core.connection.signalNotification( - AlertNotification(LogLevel.LOGLEVEL_INFO, 'Connected to app: ${appInfo.appId}'), + LogNotification('Error parsing App Info ${bytesToHex(value)}: ${appInfoReassembler.lastError}'), ); - core.connection.signalNotification(LogNotification('Parsed App Info: $appInfo')); - } catch (e) { - core.connection.signalNotification(LogNotification('Error parsing App Info ${bytesToHex(value)}: $e')); - firstAppInfoMessages.add(value); + return PeripheralWriteRequestResult(); + } + isConnected.value = true; + _currentDeviceId = deviceId; + connectedApp.value = appInfo; + supportedActions = appInfo.supportedButtons.mapNotNull((b) => b.action).toList(); + final trainerApp = core.settings.getTrainerApp(); + if (trainerApp != null) { + unawaited(core.settings.setObpSupportedButtons(trainerApp.name, appInfo.supportedButtons)); } + core.connection.signalNotification( + AlertNotification(LogLevel.LOGLEVEL_INFO, 'Connected to app: ${appInfo.appId}'), + ); + core.connection.signalNotification(LogNotification('Parsed App Info: $appInfo')); return PeripheralWriteRequestResult(); }); } diff --git a/test/openbikecontrol_app_info_reassembler_test.dart b/test/openbikecontrol_app_info_reassembler_test.dart new file mode 100644 index 00000000..38f9147e --- /dev/null +++ b/test/openbikecontrol_app_info_reassembler_test.dart @@ -0,0 +1,97 @@ +import 'dart:typed_data'; + +import 'package:bike_control/bluetooth/devices/openbikecontrol/app_info_reassembler.dart'; +import 'package:bike_control/bluetooth/devices/openbikecontrol/protocol_parser.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + // A complete, valid app-info message. No buttons keeps the fixture + // independent of the button-id table while still exercising appId/version. + final complete = OpenBikeProtocolParser.encodeAppInfo( + appId: 'TrainingPeaks', + appVersion: '6.0', + supportedButtons: [], + ); + + /// Split [data] into [count] roughly-equal fragments, mimicking an app that + /// dribbles the app-info write across several BLE packets. Each strict prefix + /// fails to parse, so feeding the fragments in order drives the reassembler. + List fragment(Uint8List data, int count) { + final size = (data.length / count).ceil(); + return [ + for (var i = 0; i < data.length; i += size) + Uint8List.sublistView(data, i, (i + size) > data.length ? data.length : i + size), + ]; + } + + test('parses a complete single write immediately', () { + final r = AppInfoReassembler(); + + final info = r.offer(complete); + + expect(info, isNotNull); + expect(info!.appId, 'TrainingPeaks'); + expect(info.appVersion, '6.0'); + expect(r.pendingFragments, 0, reason: 'buffer is cleared on success'); + }); + + test('reassembles a message split across two writes', () { + final parts = fragment(complete, 2); + expect(parts.length, 2); + final r = AppInfoReassembler(); + + expect(r.offer(parts[0]), isNull, reason: 'first fragment is incomplete'); + expect(r.pendingFragments, 1); + + final info = r.offer(parts[1]); + expect(info, isNotNull); + expect(info!.appId, 'TrainingPeaks'); + expect(r.pendingFragments, 0); + }); + + test('reassembles a message split across THREE writes (single-buffer regression)', () { + // The previous single prior-fragment buffer kept only the FIRST failed + // fragment and dropped the middle one, so a three-packet app-info + // (TrainingPeaks on macOS) never reconnected. Every fragment must be kept. + final parts = fragment(complete, 3); + expect(parts.length, 3); + final r = AppInfoReassembler(); + + expect(r.offer(parts[0]), isNull); + expect(r.offer(parts[1]), isNull); + expect(r.pendingFragments, 2, reason: 'every incomplete fragment is retained'); + + final info = r.offer(parts[2]); + expect(info, isNotNull, reason: 'all three fragments reassemble'); + expect(info!.appId, 'TrainingPeaks'); + expect(r.pendingFragments, 0); + }); + + test('resets after a success so the next message is not polluted by old fragments', () { + final r = AppInfoReassembler(); + + final first = fragment(complete, 2); + expect(r.offer(first[0]), isNull); + expect(r.offer(first[1]), isNotNull); + + // A different message reusing the same reassembler must parse cleanly. + final second = OpenBikeProtocolParser.encodeAppInfo( + appId: 'Rouvy', + appVersion: '1.2', + supportedButtons: [], + ); + final secondParts = fragment(second, 2); + expect(r.offer(secondParts[0]), isNull); + + final info = r.offer(secondParts[1]); + expect(info, isNotNull); + expect(info!.appId, 'Rouvy'); + }); + + test('exposes the parse error while a message is incomplete', () { + final r = AppInfoReassembler(); + + expect(r.offer(fragment(complete, 2)[0]), isNull); + expect(r.lastError, isA()); + }); +} From acb32a24d8f65055320d906347297135a7d27405 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 15:02:26 +0200 Subject: [PATCH 084/106] feat(shifting): rename "SRAM-style front shift" to "Virtual front derailleur" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The toggle named the SRAM AXS input gesture (press both shifters) rather than what the feature actually is — a virtual second chainring. Rename the label across all 6 languages and move the both-paddles / SRAM-AXS detail into the description. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/i10n/intl_de.arb | 4 ++-- lib/i10n/intl_en.arb | 4 ++-- lib/i10n/intl_es.arb | 4 ++-- lib/i10n/intl_fr.arb | 4 ++-- lib/i10n/intl_it.arb | 4 ++-- lib/i10n/intl_pl.arb | 4 ++-- 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 4292b30c..4e7acf26 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -1004,8 +1004,8 @@ "vsIntroFeedbackBody": "Wir freuen uns über dein Feedback und helfen dir jederzeit, deine Einrichtung perfekt abzustimmen.", "vsIntroSupportedTrainersCta": "Unterstützte Trainer ansehen", "vsIntroGotIt": "Verstanden", - "frontShiftEnableLabel": "SRAM-Frontschalter", - "frontShiftEnableDesc": "Simuliert das vordere Kettenblatt eines 2×-Antriebs", + "frontShiftEnableLabel": "Virtueller Umwerfer", + "frontShiftEnableDesc": "Fügt ein zweites Kettenblatt hinzu (2×-Antrieb). Zum Wechseln beide Schalthebel gleichzeitig drücken – wie bei SRAM AXS.", "frontShiftSmallRingLabel": "Kleines Kettenblatt (Zähne)", "frontShiftLargeRingLabel": "Großes Kettenblatt (Zähne)" } diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 08b6119d..0b5e4e78 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -1171,8 +1171,8 @@ "vsIntroFeedbackBody": "We love your feedback and are always happy to help get your setup dialed in just right.", "vsIntroSupportedTrainersCta": "See supported trainers", "vsIntroGotIt": "Got it", - "frontShiftEnableLabel": "SRAM-style front shift", - "frontShiftEnableDesc": "Simulates 2× drivetrain front chainring switching", + "frontShiftEnableLabel": "Virtual front derailleur", + "frontShiftEnableDesc": "Adds a second chainring (2× drivetrain). Press both shifters together to change ring, like SRAM AXS.", "frontShiftSmallRingLabel": "Small chainring (teeth)", "frontShiftLargeRingLabel": "Large chainring (teeth)" } diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 8c17e344..69ef2374 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -1004,8 +1004,8 @@ "vsIntroFeedbackBody": "Nos encantan tus comentarios y siempre estaremos encantados de ayudarte a dejar tu configuración perfecta.", "vsIntroSupportedTrainersCta": "Ver Smart Trainers compatibles", "vsIntroGotIt": "Entendido", - "frontShiftEnableLabel": "Cambio frontal estilo SRAM", - "frontShiftEnableDesc": "Simula el cambio de plato delantero en una transmisión 2×", + "frontShiftEnableLabel": "Desviador delantero virtual", + "frontShiftEnableDesc": "Añade un segundo plato (transmisión 2×). Pulsa ambos mandos a la vez para cambiar de plato, como en SRAM AXS.", "frontShiftSmallRingLabel": "Plato pequeño (dientes)", "frontShiftLargeRingLabel": "Plato grande (dientes)" } diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 487a0692..7e7f38c7 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -1005,8 +1005,8 @@ "vsIntroFeedbackBody": "Vos retours nous tiennent à cœur et nous sommes toujours ravis de vous aider à régler votre configuration aux petits oignons.", "vsIntroSupportedTrainersCta": "Voir les Smart Trainers compatibles", "vsIntroGotIt": "J'ai compris", - "frontShiftEnableLabel": "Changement frontal style SRAM", - "frontShiftEnableDesc": "Simule le changement de plateau avant sur un groupe 2×", + "frontShiftEnableLabel": "Dérailleur avant virtuel", + "frontShiftEnableDesc": "Ajoute un second plateau (transmission 2×). Appuyez sur les deux manettes en même temps pour changer de plateau, comme sur SRAM AXS.", "frontShiftSmallRingLabel": "Petit plateau (dents)", "frontShiftLargeRingLabel": "Grand plateau (dents)" } diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 2f8412c5..4998ea2c 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -1004,8 +1004,8 @@ "vsIntroFeedbackBody": "Adoriamo i tuoi feedback e siamo sempre felici di aiutarti a configurare tutto al meglio.", "vsIntroSupportedTrainersCta": "Vedi gli Smart Trainer supportati", "vsIntroGotIt": "Ho capito", - "frontShiftEnableLabel": "Cambio frontale stile SRAM", - "frontShiftEnableDesc": "Simula il cambio della corona anteriore su un gruppo 2×", + "frontShiftEnableLabel": "Deragliatore anteriore virtuale", + "frontShiftEnableDesc": "Aggiunge una seconda corona (trasmissione 2×). Premi entrambe le leve insieme per cambiare corona, come su SRAM AXS.", "frontShiftSmallRingLabel": "Corona piccola (denti)", "frontShiftLargeRingLabel": "Corona grande (denti)" } diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index 74f86bab..bf8e14a5 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -1004,8 +1004,8 @@ "vsIntroFeedbackBody": "Uwielbiamy Twoją opinię i zawsze chętnie pomożemy idealnie skonfigurować Twój sprzęt.", "vsIntroSupportedTrainersCta": "Zobacz obsługiwane trenażery", "vsIntroGotIt": "Rozumiem", - "frontShiftEnableLabel": "Przedni przerzutnik w stylu SRAM", - "frontShiftEnableDesc": "Symuluje zmianę tarczy przedniej w napędzie 2×", + "frontShiftEnableLabel": "Wirtualna przerzutka przednia", + "frontShiftEnableDesc": "Dodaje drugą tarczę (napęd 2×). Aby zmienić tarczę, naciśnij obie manetki jednocześnie – jak w SRAM AXS.", "frontShiftSmallRingLabel": "Mała tarcza (zęby)", "frontShiftLargeRingLabel": "Duża tarcza (zęby)" } From c5a7fcd581d3b393cb0fb11b8ef175f9b7ddb785 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 15:02:40 +0200 Subject: [PATCH 085/106] =?UTF-8?q?feat(shifting):=20show=202=C3=97N=20gea?= =?UTF-8?q?r=20position=20when=20the=20front=20derailleur=20is=20active?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the virtual front derailleur on, the compact gear readout switches from rear gear/total (14/25) to head-unit-style front×rear position notation (small ring 1×N, large ring 2×N, e.g. 2×14) — matching how Garmin/Wahoo display Di2/AXS gearing. With it off, it stays 14/25. - Add tested formatGearReadout helper. - Wire into the proxy card, debug menu, desktop second window + Android PiP/overlay (trainer_overlay_view), and the gear hero card (2× · 50T). - Carry frontShiftEnabled + frontRingLarge through TrainerOverlayState (json, ==, hashCode, activity map) so the snapshot reaches the overlay and the iOS surfaces. - iOS PiP + Live Activity: format 2×N centrally in GearSnapshot. - Standardize the off-state readout to 14/25 across all surfaces. Co-Authored-By: Claude Opus 4.8 (1M context) --- ios/Shared/GearSnapshot+LiveActivity.swift | 4 +- ios/Shared/GearSnapshot.swift | 24 ++++++++--- lib/bluetooth/devices/proxy/proxy_device.dart | 3 +- .../proxy_device_details/gear_hero_card.dart | 4 +- .../overlay/android_overlay_controller.dart | 2 + .../overlay/desktop_overlay_controller.dart | 2 + .../overlay/ios_overlay_controller.dart | 2 + lib/services/overlay/overlay_state.dart | 14 ++++++- lib/utils/gear_readout.dart | 16 ++++++++ lib/widgets/menu.dart | 5 ++- lib/widgets/overlay/trainer_overlay_view.dart | 10 ++++- test/gear_readout_test.dart | 40 +++++++++++++++++++ .../overlay/trainer_overlay_view_test.dart | 22 +++++++++- 13 files changed, 134 insertions(+), 14 deletions(-) create mode 100644 lib/utils/gear_readout.dart create mode 100644 test/gear_readout_test.dart diff --git a/ios/Shared/GearSnapshot+LiveActivity.swift b/ios/Shared/GearSnapshot+LiveActivity.swift index 273b167c..08fdd68d 100644 --- a/ios/Shared/GearSnapshot+LiveActivity.swift +++ b/ios/Shared/GearSnapshot+LiveActivity.swift @@ -23,7 +23,9 @@ extension GearSnapshot { showCadence: defaults.bool(forKey: k("showCadence")), showErgTarget: defaults.bool(forKey: k("showErgTarget")), showGearRatio: defaults.bool(forKey: k("showGearRatio")), - showControls: defaults.bool(forKey: k("showControls")) + showControls: defaults.bool(forKey: k("showControls")), + frontShiftEnabled: defaults.bool(forKey: k("frontShiftEnabled")), + frontRingLarge: defaults.bool(forKey: k("frontRingLarge")) ) } } diff --git a/ios/Shared/GearSnapshot.swift b/ios/Shared/GearSnapshot.swift index 08f9fba1..db596104 100644 --- a/ios/Shared/GearSnapshot.swift +++ b/ios/Shared/GearSnapshot.swift @@ -16,21 +16,32 @@ struct GearSnapshot { let showErgTarget: Bool let showGearRatio: Bool let showControls: Bool + let frontShiftEnabled: Bool + let frontRingLarge: Bool var isErg: Bool { mode == "erg" } - /// Big primary value: target watts in ERG, gear N/M in SIM. + /// Head-unit-style `front×rear` position notation used when the virtual + /// front derailleur is on (small ring = 1, large ring = 2, e.g. `2×14`). + private var positionGear: String { "\(frontRingLarge ? 2 : 1)×\(gear)" } + + /// Big primary value: target watts in ERG, gear in SIM. var primaryText: String { if isErg { return ergTargetW.map { "\($0) W" } ?? "-- W" } - return "\(gear) / \(maxGear)" + if frontShiftEnabled { return positionGear } + return "\(gear)/\(maxGear)" } var compactTrailing: String { - isErg ? (ergTargetW.map { "\($0)W" } ?? "--W") : "\(gear)/\(maxGear)" + if isErg { return ergTargetW.map { "\($0)W" } ?? "--W" } + if frontShiftEnabled { return positionGear } + return "\(gear)/\(maxGear)" } var minimalText: String { - isErg ? (ergTargetW.map { "\($0)" } ?? "--") : "\(gear)" + if isErg { return ergTargetW.map { "\($0)" } ?? "--" } + if frontShiftEnabled { return positionGear } + return "\(gear)" } /// Cheap change-detection key so the PiP pump can skip identical frames. @@ -40,6 +51,7 @@ struct GearSnapshot { h.combine(powerW); h.combine(cadenceRpm); h.combine(ergTargetW) h.combine(gearRatio); h.combine(showPower); h.combine(showCadence) h.combine(showErgTarget); h.combine(showGearRatio); h.combine(showControls) + h.combine(frontShiftEnabled); h.combine(frontRingLarge) return h.finalize() } } @@ -62,7 +74,9 @@ extension GearSnapshot { showCadence: m["showCadence"] as? Bool ?? false, showErgTarget: m["showErgTarget"] as? Bool ?? false, showGearRatio: m["showGearRatio"] as? Bool ?? false, - showControls: m["showControls"] as? Bool ?? false + showControls: m["showControls"] as? Bool ?? false, + frontShiftEnabled: m["frontShiftEnabled"] as? Bool ?? false, + frontRingLarge: m["frontRingLarge"] as? Bool ?? false ) } } diff --git a/lib/bluetooth/devices/proxy/proxy_device.dart b/lib/bluetooth/devices/proxy/proxy_device.dart index 701e7f60..cb13630d 100644 --- a/lib/bluetooth/devices/proxy/proxy_device.dart +++ b/lib/bluetooth/devices/proxy/proxy_device.dart @@ -8,6 +8,7 @@ import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/gear_readout.dart'; import 'package:bike_control/utils/iap/iap_manager.dart'; import 'package:bike_control/utils/keymap/apps/rouvy.dart'; import 'package:bike_control/utils/keymap/apps/supported_app.dart' show TrainerConnectionType; @@ -520,7 +521,7 @@ class ProxyDevice extends BluetoothDevice { _addTextMetric( parts, context, - 'Gear ${fitnessDef.currentGear.value}/${fitnessDef.maxGear}', + 'Gear ${formatGearReadout(currentGear: fitnessDef.currentGear.value, maxGear: fitnessDef.maxGear, frontShiftEnabled: fitnessDef.frontShiftEnabled, largeRing: fitnessDef.frontRing.value == FrontRing.large)}', LucideIcons.settings2, ); } diff --git a/lib/pages/proxy_device_details/gear_hero_card.dart b/lib/pages/proxy_device_details/gear_hero_card.dart index 87d705bc..af1c2b5b 100644 --- a/lib/pages/proxy_device_details/gear_hero_card.dart +++ b/lib/pages/proxy_device_details/gear_hero_card.dart @@ -176,8 +176,8 @@ class _GearHeroCardState extends State { if (widget.definition.frontShiftEnabled) Text( widget.definition.frontRing.value == FrontRing.large - ? '${widget.definition.largeChainringTeeth}T' - : '${widget.definition.smallChainringTeeth}T', + ? '2× · ${widget.definition.largeChainringTeeth}T' + : '1× · ${widget.definition.smallChainringTeeth}T', style: TextStyle(fontSize: 13, color: cs.mutedForeground), ), ], diff --git a/lib/services/overlay/android_overlay_controller.dart b/lib/services/overlay/android_overlay_controller.dart index 5d14243a..65856119 100644 --- a/lib/services/overlay/android_overlay_controller.dart +++ b/lib/services/overlay/android_overlay_controller.dart @@ -236,6 +236,8 @@ class AndroidOverlayController implements TrainerOverlayController { cadenceRpm: def.cadenceRpm.value, ergTargetW: def.ergTargetPower.value, fields: _fields, + frontShiftEnabled: def.frontShiftEnabled, + frontRingLarge: def.frontRing.value == FrontRing.large, ); if (!force && s == _lastPushed) return; _lastPushed = s; diff --git a/lib/services/overlay/desktop_overlay_controller.dart b/lib/services/overlay/desktop_overlay_controller.dart index 8abb409a..5ecc9074 100644 --- a/lib/services/overlay/desktop_overlay_controller.dart +++ b/lib/services/overlay/desktop_overlay_controller.dart @@ -316,6 +316,8 @@ class DesktopOverlayController implements TrainerOverlayController { cadenceRpm: def.cadenceRpm.value, ergTargetW: def.ergTargetPower.value, fields: _fields, + frontShiftEnabled: def.frontShiftEnabled, + frontRingLarge: def.frontRing.value == FrontRing.large, ); if (!force && s == _lastPushed) return; _lastPushed = s; diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index b05c8d66..d584a780 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -174,6 +174,8 @@ class IosOverlayController implements TrainerOverlayController { cadenceRpm: def.cadenceRpm.value, ergTargetW: def.ergTargetPower.value, fields: _fields, + frontShiftEnabled: def.frontShiftEnabled, + frontRingLarge: def.frontRing.value == FrontRing.large, ); } diff --git a/lib/services/overlay/overlay_state.dart b/lib/services/overlay/overlay_state.dart index 06a8e439..d62a085d 100644 --- a/lib/services/overlay/overlay_state.dart +++ b/lib/services/overlay/overlay_state.dart @@ -28,6 +28,8 @@ class TrainerOverlayState { final int? cadenceRpm; final int? ergTargetW; final Set fields; + final bool frontShiftEnabled; + final bool frontRingLarge; const TrainerOverlayState({ required this.gear, @@ -38,6 +40,8 @@ class TrainerOverlayState { required this.cadenceRpm, required this.ergTargetW, required this.fields, + this.frontShiftEnabled = false, + this.frontRingLarge = false, }); Map toJson() => { @@ -49,6 +53,8 @@ class TrainerOverlayState { 'cadenceRpm': cadenceRpm, 'ergTargetW': ergTargetW, 'fields': fields.map((f) => f.name).toList(), + 'frontShiftEnabled': frontShiftEnabled, + 'frontRingLarge': frontRingLarge, }; /// Permissive parse — silently fills missing/wrong-typed fields with sane @@ -77,6 +83,8 @@ class TrainerOverlayState { cadenceRpm: (json['cadenceRpm'] as num?)?.toInt(), ergTargetW: (json['ergTargetW'] as num?)?.toInt(), fields: fields, + frontShiftEnabled: (json['frontShiftEnabled'] as bool?) ?? false, + frontRingLarge: (json['frontRingLarge'] as bool?) ?? false, ); } @@ -91,13 +99,15 @@ class TrainerOverlayState { other.powerW == powerW && other.cadenceRpm == cadenceRpm && other.ergTargetW == ergTargetW && + other.frontShiftEnabled == frontShiftEnabled && + other.frontRingLarge == frontRingLarge && _setEquals(other.fields, fields); } @override int get hashCode => Object.hash( gear, maxGear, gearRatio, mode, powerW, cadenceRpm, ergTargetW, - Object.hashAllUnordered(fields), + Object.hashAllUnordered(fields), frontShiftEnabled, frontRingLarge, ); static bool _setEquals(Set a, Set b) { @@ -125,6 +135,8 @@ Map overlayStateToActivityMap(TrainerOverlayState s) { 'showGearRatio': s.fields.contains(OverlayField.gearRatio), 'showControls': s.fields.contains(OverlayField.controls), 'gearRatio': s.gearRatio, + 'frontShiftEnabled': s.frontShiftEnabled, + 'frontRingLarge': s.frontRingLarge, }; if (s.powerW != null) m['powerW'] = s.powerW; if (s.cadenceRpm != null) m['cadenceRpm'] = s.cadenceRpm; diff --git a/lib/utils/gear_readout.dart b/lib/utils/gear_readout.dart new file mode 100644 index 00000000..c9eed5ed --- /dev/null +++ b/lib/utils/gear_readout.dart @@ -0,0 +1,16 @@ +/// Formats the compact gear readout shown in the proxy card, desktop overlay, +/// PiP, and live-gear surfaces. +/// +/// Without front shift it's the familiar rear `gear/total` (e.g. `14/25`). +/// With the virtual front derailleur on, it switches to head-unit-style +/// position notation `front×rear` — small ring is position 1, large ring is +/// position 2 (e.g. `2×14`), matching how Garmin/Wahoo show Di2/AXS gearing. +String formatGearReadout({ + required int currentGear, + required int maxGear, + required bool frontShiftEnabled, + required bool largeRing, +}) { + if (!frontShiftEnabled) return '$currentGear/$maxGear'; + return '${largeRing ? 2 : 1}×$currentGear'; +} diff --git a/lib/widgets/menu.dart b/lib/widgets/menu.dart index bb8a7d01..bd20cbff 100644 --- a/lib/widgets/menu.dart +++ b/lib/widgets/menu.dart @@ -6,6 +6,7 @@ import 'package:bike_control/pages/paywall.dart'; import 'package:bike_control/pages/subscription.dart'; import 'package:bike_control/services/telemetry_snapshot.dart'; import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/gear_readout.dart'; import 'package:bike_control/utils/i18n_extension.dart'; import 'package:bike_control/widgets/logviewer.dart'; import 'package:bike_control/widgets/title.dart'; @@ -155,7 +156,9 @@ String _describeProxyDevice(ProxyDevice device) { if (device.firmwareVersion != null) parts.add('fw=${device.firmwareVersion}'); if (device.manufacturerName != null) parts.add('mfg=${device.manufacturerName}'); if (def != null) { - parts.add('gear=${def.currentGear.value}/${def.maxGear}'); + parts.add( + 'gear=${formatGearReadout(currentGear: def.currentGear.value, maxGear: def.maxGear, frontShiftEnabled: def.frontShiftEnabled, largeRing: def.frontRing.value == FrontRing.large)}', + ); parts.add('trainerMode=${def.trainerMode.value.name}'); } diff --git a/lib/widgets/overlay/trainer_overlay_view.dart b/lib/widgets/overlay/trainer_overlay_view.dart index 5079e20d..64f0f647 100644 --- a/lib/widgets/overlay/trainer_overlay_view.dart +++ b/lib/widgets/overlay/trainer_overlay_view.dart @@ -1,4 +1,5 @@ import 'package:bike_control/services/overlay/overlay_state.dart'; +import 'package:bike_control/utils/gear_readout.dart'; import 'package:flutter/foundation.dart'; import 'package:prop/emulators/definitions/fitness_bike_definition.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; @@ -72,7 +73,14 @@ class TrainerOverlayView extends StatelessWidget { /// edge. Drag handle is always trailing. Widget _primaryRow(BuildContext context, ColorScheme cs, TrainerOverlayState s) { final isErg = s.mode == TrainerMode.ergMode; - final primary = isErg ? '${s.ergTargetW ?? '--'} W' : '${s.gear} / ${s.maxGear}'; + final primary = isErg + ? '${s.ergTargetW ?? '--'} W' + : formatGearReadout( + currentGear: s.gear, + maxGear: s.maxGear, + frontShiftEnabled: s.frontShiftEnabled, + largeRing: s.frontRingLarge, + ); final showControls = s.fields.contains(OverlayField.controls); final primaryText = FittedBox( diff --git a/test/gear_readout_test.dart b/test/gear_readout_test.dart new file mode 100644 index 00000000..7e9416e9 --- /dev/null +++ b/test/gear_readout_test.dart @@ -0,0 +1,40 @@ +import 'package:bike_control/utils/gear_readout.dart'; +import 'package:flutter_test/flutter_test.dart'; + +void main() { + group('formatGearReadout', () { + test('shows rear gear / total when front shift is off', () { + expect( + formatGearReadout(currentGear: 14, maxGear: 25, frontShiftEnabled: false, largeRing: false), + '14/25', + ); + }); + + test('largeRing is ignored when front shift is off', () { + expect( + formatGearReadout(currentGear: 14, maxGear: 25, frontShiftEnabled: false, largeRing: true), + '14/25', + ); + }); + + test('small ring shows position 1 × rear gear when front shift is on', () { + expect( + formatGearReadout(currentGear: 14, maxGear: 25, frontShiftEnabled: true, largeRing: false), + '1×14', + ); + }); + + test('large ring shows position 2 × rear gear when front shift is on', () { + expect( + formatGearReadout(currentGear: 14, maxGear: 25, frontShiftEnabled: true, largeRing: true), + '2×14', + ); + }); + + test('drops the total when front shift is on (position notation only)', () { + final out = formatGearReadout(currentGear: 7, maxGear: 30, frontShiftEnabled: true, largeRing: true); + expect(out, '2×7'); + expect(out.contains('/'), isFalse); + }); + }); +} diff --git a/test/widgets/overlay/trainer_overlay_view_test.dart b/test/widgets/overlay/trainer_overlay_view_test.dart index c2467da6..77f4403a 100644 --- a/test/widgets/overlay/trainer_overlay_view_test.dart +++ b/test/widgets/overlay/trainer_overlay_view_test.dart @@ -13,14 +13,17 @@ void main() { int? cadenceRpm = 86, Set fields = const {OverlayField.power, OverlayField.cadence}, TrainerMode mode = TrainerMode.simMode, + bool frontShiftEnabled = false, + bool frontRingLarge = false, }) { return ValueNotifier(TrainerOverlayState( gear: gear, maxGear: maxGear, gearRatio: 2.43, mode: mode, powerW: powerW, cadenceRpm: cadenceRpm, ergTargetW: null, fields: fields, + frontShiftEnabled: frontShiftEnabled, frontRingLarge: frontRingLarge, )); } - testWidgets('renders gear N / M and mode pill', (tester) async { + testWidgets('renders gear/total and mode pill', (tester) async { await tester.pumpWidget( ShadcnApp( home: Scaffold( @@ -28,10 +31,25 @@ void main() { ), ), ); - expect(find.text('14 / 24'), findsOneWidget); + expect(find.text('14/24'), findsOneWidget); expect(find.text('SIM'), findsOneWidget); }); + testWidgets('renders 2×N position notation when front shift is on', (tester) async { + await tester.pumpWidget( + ShadcnApp( + home: Scaffold( + child: TrainerOverlayView( + state: mkState(frontShiftEnabled: true, frontRingLarge: true), + onModeToggle: null, + ), + ), + ), + ); + expect(find.text('2×14'), findsOneWidget); + expect(find.text('14/24'), findsNothing); + }); + testWidgets('hides power when not selected', (tester) async { await tester.pumpWidget( ShadcnApp( From e905591904b04ddf80edb3d56cef21d6872e797c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 15:57:49 +0200 Subject: [PATCH 086/106] docs(changelog): reword front shift as "Virtual front derailleur" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Align the 6.2 entry with the new wording and the 2×N gear notation. Co-Authored-By: Claude Opus 4.8 (1M context) --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c56fece7..30e8354a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,6 @@ ### 6.2.0 (unreleased) **Features**: -- SRAM-style front shifting: a new assignable "Front Shift (Chainring)" action toggles a virtual front chainring between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. Set your chainring sizes per trainer in the gear settings. +- Virtual front derailleur: adds a second chainring (2× drivetrain) for more realism. The new assignable "Front Shift (Chainring)" action — or pressing both shifters together, SRAM-AXS style — toggles between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. While it's active your current gear reads as head-unit-style position notation (e.g. 2×14) in the app, the gear overlay, and the iOS Live Activity. Set your chainring sizes per trainer in the gear settings. - iOS / iPadOS: Floating gear overlay (Picture-in-Picture): your current gear can now show in a floating window over your trainer app during a ride. - Screen recording: a new assignable "Record Screen" action starts and stops a screen recording from a controller button. From 7cfc8fa94fe4c0384ab3b162f1f76582e5d8674b Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 15:57:49 +0200 Subject: [PATCH 087/106] fix(overlay): centre the gear value and even out padding MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Equal-width leading/trailing slots keep the primary readout centred whether or not the app icon / drag handle is shown; the container's horizontal padding is now symmetric and the bottom row no longer carries an extra inset — so the value lines up over the metrics row. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/widgets/overlay/trainer_overlay_view.dart | 50 +++++++++++-------- 1 file changed, 30 insertions(+), 20 deletions(-) diff --git a/lib/widgets/overlay/trainer_overlay_view.dart b/lib/widgets/overlay/trainer_overlay_view.dart index 64f0f647..068b8378 100644 --- a/lib/widgets/overlay/trainer_overlay_view.dart +++ b/lib/widgets/overlay/trainer_overlay_view.dart @@ -52,7 +52,7 @@ class TrainerOverlayView extends StatelessWidget { border: Border.all(color: cs.border), ) : null, - padding: const EdgeInsets.fromLTRB(10, 6, 6, 8), + padding: const EdgeInsets.fromLTRB(8, 6, 8, 8), child: Column( mainAxisSize: MainAxisSize.min, crossAxisAlignment: CrossAxisAlignment.stretch, @@ -115,25 +115,35 @@ class TrainerOverlayView extends StatelessWidget { height: showControls ? 48 : 36, child: Row( children: [ - if (!showControls) - const Padding( - padding: EdgeInsets.only(right: 6), - child: Image( - image: AssetImage('icon.png'), - width: 18, - height: 18, - ), - ), + // Equal-width leading/trailing slots keep the primary value centred + // whether or not the app icon / drag handle is present. + SizedBox( + width: 24, + child: showControls + ? null + : const Align( + alignment: Alignment.centerLeft, + child: Image( + image: AssetImage('icon.png'), + width: 18, + height: 18, + ), + ), + ), Expanded(child: Center(child: primaryBlock)), - if (onDragStart != null) - GestureDetector( - behavior: HitTestBehavior.opaque, - onPanStart: (_) => onDragStart!(), - child: Padding( - padding: const EdgeInsets.all(2), - child: Icon(Icons.drag_indicator, size: 14, color: cs.mutedForeground), - ), - ), + SizedBox( + width: 24, + child: onDragStart != null + ? Align( + alignment: Alignment.centerRight, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onPanStart: (_) => onDragStart!(), + child: Icon(Icons.drag_indicator, size: 14, color: cs.mutedForeground), + ), + ) + : null, + ), ], ), ); @@ -207,7 +217,7 @@ class TrainerOverlayView extends StatelessWidget { } return Padding( - padding: const EdgeInsets.symmetric(horizontal: 10.0), + padding: const EdgeInsets.symmetric(horizontal: 2.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, crossAxisAlignment: CrossAxisAlignment.center, From eaf972f466865e22a6ce737bbf4580900e72368a Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 15:57:49 +0200 Subject: [PATCH 088/106] test(screenshot): blog widget snapshots for the front derailleur MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extract FrontShiftCard from the gear-ratios page so it can render in isolation, and add two golden scenes that capture single widgets for the 6.2 blog: the front-derailleur setting card and the second-window gear overlay (2×N notation). Each renders the widget in a keyed RepaintBoundary for a tight, page-free capture. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../front_shift_card.dart | 97 ++++++++++++++ .../gear_ratios_editor_page.dart | 78 +----------- screenshots/en/frontderailleur-gear.png | Bin 0 -> 4949 bytes screenshots/en/frontderailleur-setting.png | Bin 0 -> 21264 bytes test/screenshot_test.dart | 118 ++++++++++++++++++ 5 files changed, 217 insertions(+), 76 deletions(-) create mode 100644 lib/pages/proxy_device_details/front_shift_card.dart create mode 100644 screenshots/en/frontderailleur-gear.png create mode 100644 screenshots/en/frontderailleur-setting.png diff --git a/lib/pages/proxy_device_details/front_shift_card.dart b/lib/pages/proxy_device_details/front_shift_card.dart new file mode 100644 index 00000000..045918b5 --- /dev/null +++ b/lib/pages/proxy_device_details/front_shift_card.dart @@ -0,0 +1,97 @@ +import 'package:bike_control/bluetooth/devices/proxy/proxy_device.dart'; +import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/models/shifting_config.dart'; +import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/widgets/ui/setting_tile.dart'; +import 'package:bike_control/widgets/ui/stepper_control.dart'; +import 'package:shadcn_flutter/shadcn_flutter.dart'; + +/// The "Virtual front derailleur" setting: an enable toggle plus small/large +/// chainring steppers and the resulting ratio factor. Reads and writes the +/// active [ShiftingConfig] for [device]. +class FrontShiftCard extends StatelessWidget { + const FrontShiftCard({super.key, required this.device}); + + final ProxyDevice device; + + Future _update(ShiftingConfig Function(ShiftingConfig) mutate) async { + final current = core.shiftingConfigs.activeFor(device.trainerKey); + await core.shiftingConfigs.upsert(mutate(current)); + } + + @override + Widget build(BuildContext context) { + final config = core.shiftingConfigs.activeFor(device.trainerKey); + final enabled = config.frontShiftEnabled; + final small = config.smallChainringTeeth; + final large = config.largeChainringTeeth; + final factor = large / small; + final cs = Theme.of(context).colorScheme; + return SettingTile( + icon: LucideIcons.bike, + title: AppLocalizations.of(context).frontShiftEnableLabel, + subtitle: AppLocalizations.of(context).frontShiftEnableDesc, + trailing: Switch( + value: enabled, + onChanged: (v) async { + await _update((c) => c.copyWith(frontShiftEnabled: v)); + }, + ), + child: enabled + ? Column( + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 12, + children: [ + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of(context).frontShiftSmallRingLabel, + style: const TextStyle(fontSize: 13), + ), + ), + StepperControl( + value: small.toDouble(), + step: 1.0, + min: ShiftingConfig.chainringTeethMin.toDouble(), + max: ShiftingConfig.chainringTeethMax.toDouble(), + format: (v) => v.toStringAsFixed(0), + onChanged: (v) async { + final next = v.toInt(); + await _update((c) => c.copyWith(smallChainringTeeth: next)); + }, + ), + ], + ), + Row( + children: [ + Expanded( + child: Text( + AppLocalizations.of(context).frontShiftLargeRingLabel, + style: const TextStyle(fontSize: 13), + ), + ), + StepperControl( + value: large.toDouble(), + step: 1.0, + min: small.toDouble(), + max: ShiftingConfig.chainringTeethMax.toDouble(), + format: (v) => v.toStringAsFixed(0), + onChanged: (v) async { + final next = v.toInt(); + await _update((c) => c.copyWith(largeChainringTeeth: next)); + }, + ), + ], + ), + Text( + '${factor.toStringAsFixed(2)}×', + style: TextStyle(fontSize: 12, color: cs.mutedForeground), + textAlign: TextAlign.end, + ), + ], + ) + : null, + ); + } +} diff --git a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart index b5e41e08..7fe3ae7d 100644 --- a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart +++ b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart @@ -4,6 +4,7 @@ import 'package:bike_control/bluetooth/devices/proxy/proxy_device.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/models/shifting_config.dart'; +import 'package:bike_control/pages/proxy_device_details/front_shift_card.dart'; import 'package:bike_control/pages/proxy_device_details/gear_hero_card.dart'; import 'package:bike_control/pages/proxy_device_details/gear_ratio_curve.dart'; import 'package:bike_control/utils/core.dart'; @@ -113,7 +114,7 @@ class _GearRatiosEditorPageState extends State { _vsModeCard(), _gradeSmoothingCard(context), _cadenceFilterCard(context), - _frontShiftCard(context), + FrontShiftCard(device: widget.device), ], _gearCountCard(context), _heroCurve(context), @@ -272,81 +273,6 @@ class _GearRatiosEditorPageState extends State { ); } - Widget _frontShiftCard(BuildContext context) { - final config = core.shiftingConfigs.activeFor(widget.device.trainerKey); - final enabled = config.frontShiftEnabled; - final small = config.smallChainringTeeth; - final large = config.largeChainringTeeth; - final factor = large / small; - final cs = Theme.of(context).colorScheme; - return SettingTile( - icon: LucideIcons.bike, - title: AppLocalizations.of(context).frontShiftEnableLabel, - subtitle: AppLocalizations.of(context).frontShiftEnableDesc, - trailing: Switch( - value: enabled, - onChanged: (v) async { - await _updateActive((c) => c.copyWith(frontShiftEnabled: v)); - }, - ), - child: enabled - ? Column( - crossAxisAlignment: CrossAxisAlignment.stretch, - spacing: 12, - children: [ - Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(context).frontShiftSmallRingLabel, - style: const TextStyle(fontSize: 13), - ), - ), - StepperControl( - value: small.toDouble(), - step: 1.0, - min: ShiftingConfig.chainringTeethMin.toDouble(), - max: ShiftingConfig.chainringTeethMax.toDouble(), - format: (v) => v.toStringAsFixed(0), - onChanged: (v) async { - final next = v.toInt(); - await _updateActive((c) => c.copyWith(smallChainringTeeth: next)); - }, - ), - ], - ), - Row( - children: [ - Expanded( - child: Text( - AppLocalizations.of(context).frontShiftLargeRingLabel, - style: const TextStyle(fontSize: 13), - ), - ), - StepperControl( - value: large.toDouble(), - step: 1.0, - min: small.toDouble(), - max: ShiftingConfig.chainringTeethMax.toDouble(), - format: (v) => v.toStringAsFixed(0), - onChanged: (v) async { - final next = v.toInt(); - await _updateActive((c) => c.copyWith(largeChainringTeeth: next)); - }, - ), - ], - ), - Text( - '${factor.toStringAsFixed(2)}×', - style: TextStyle(fontSize: 12, color: cs.mutedForeground), - textAlign: TextAlign.end, - ), - ], - ) - : null, - ); - } - // ---------- Presets ---------- static List _evenSteps(double lo, double hi, int count) => diff --git a/screenshots/en/frontderailleur-gear.png b/screenshots/en/frontderailleur-gear.png new file mode 100644 index 0000000000000000000000000000000000000000..82a90fa25ed21b4059278dae0167e39e9edc679b GIT binary patch literal 4949 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
  • P_j_wmB3)|HG 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 main() async { } } + // Blog screenshot: a single clean frameless (noFrame) English shot written to + // ../screenshots/en/-noFrame-1100x2390.png — used for the website blog, + // not the localized App Store matrix that [shoot] produces. + Future shootOne( + WidgetTester tester, + String scene, + Widget Function() home, { + Finder Function()? capture, + Future Function(WidgetTester tester)? afterPump, + TargetPlatform platform = TargetPlatform.android, + }) async { + final nf = sizes.firstWhere((s) => s.type == DeviceType.noFrame); + await AppLocalizations.load(const Locale('en')); + screenshotLocale = const Locale('en'); + await tester.pumpWidget( + ScreenshotApp( + locale: const Locale('en'), + device: ScreenshotDevice( + // Default Android, never the entry's Windows platform: shadcn's theme + // queries the Windows accent colour via advapi32.dll, which can't load + // on a macOS test host. + platform: platform, + resolution: nf.size, + pixelRatio: 3, + goldenSubFolder: 'iphoneScreenshots/', + frameBuilder: + ({ + required ScreenshotDevice device, + required ScreenshotFrameColors? frameColors, + required Widget child, + }) => CustomFrame(platform: DeviceType.noFrame, title: '', device: device, child: child), + ), + home: home(), + ), + ); + await tester.pump(); + if (afterPump != null) await afterPump(tester); + await tester.loadAssets(); + await tester.pump(); + await expectLater( + capture?.call() ?? find.byType(ma.Scaffold), + matchesGoldenFile('../screenshots/en/$scene.png'), + ); + } + testGoldens('Device', (WidgetTester tester) async { await shoot(tester, 'device', () => BikeControlApp()); }); @@ -333,4 +381,74 @@ Future main() async { ), ); }); + + // --- 6.2 Virtual front derailleur (blog widget snapshots) --- + // Each widget is rendered standalone inside a keyed RepaintBoundary so the + // golden captures ONLY that widget (no page chrome). + + // The second-window / desktop gear overlay (TrainerOverlayView), as shown on + // Windows & macOS. Large ring → the primary readout uses the 2×N position + // notation (here 2×14). Mirrors desktop_overlay_window: bare overlay on white. + testGoldens('Front Derailleur Gear', (WidgetTester tester) async { + const k = ValueKey('shot'); + final state = ValueNotifier( + const TrainerOverlayState( + gear: 14, + maxGear: 24, + gearRatio: 3.53, + mode: TrainerMode.simMode, + powerW: 250, + cadenceRpm: 90, + ergTargetW: null, + fields: {OverlayField.power, OverlayField.cadence}, + frontShiftEnabled: true, + frontRingLarge: true, + ), + ); + await shootOne( + tester, + 'frontderailleur-gear', + () => BikeControlApp( + customChild: Center( + child: RepaintBoundary( + key: k, + child: ColoredBox( + color: const Color(0xFFFFFFFF), + child: SizedBox( + width: 240, + child: TrainerOverlayView(state: state, onModeToggle: null), + ), + ), + ), + ), + ), + capture: () => find.byKey(k), + platform: TargetPlatform.macOS, + ); + }); + + // The front-derailleur setting card, enabled so the chainring steppers show. + testGoldens('Front Derailleur Setting', (WidgetTester tester) async { + await core.shiftingConfigs.upsert( + core.shiftingConfigs.activeFor(proxy.trainerKey).copyWith( + frontShiftEnabled: true, + smallChainringTeeth: 34, + largeChainringTeeth: 50, + ), + ); + const k = ValueKey('shot'); + await shootOne( + tester, + 'frontderailleur-setting', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary(key: k, child: FrontShiftCard(device: proxy)), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); } From dacdec580f7bcf42a4d54e63e98af20d2826b36f Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 17:04:20 +0200 Subject: [PATCH 089/106] test: golden scenes for MyWhoosh setup widgets Extract the trainer-app picker into a public TrainerAppSelect widget so it renders standalone, and add mywhoosh-trainer-select and mywhoosh-network-connection golden scenes for the website setup guide. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/pages/configuration.dart | 246 +++++++++++++++++++---------------- test/screenshot_test.dart | 65 +++++++++ 2 files changed, 201 insertions(+), 110 deletions(-) diff --git a/lib/pages/configuration.dart b/lib/pages/configuration.dart index c5209c4f..837fd03b 100644 --- a/lib/pages/configuration.dart +++ b/lib/pages/configuration.dart @@ -42,122 +42,14 @@ class _ConfigurationPageState extends State { ColoredTitle(text: context.i18n.setupTrainer), Builder( builder: (context) { - final groupedByOfficial = SupportedApp.supportedApps.groupBy((e) => e.officialIntegration); return StatefulBuilder( builder: (c, setState) => Column( spacing: 8, mainAxisAlignment: MainAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start, children: [ - Select( - constraints: BoxConstraints(maxWidth: 400, minWidth: 400), - popupConstraints: BoxConstraints(maxWidth: 400, minWidth: 400, minHeight: 300), - itemBuilder: (c, app) => Row( - spacing: 8, - children: [ - if (app.logoAsset != null) - ClipRRect( - borderRadius: BorderRadius.circular(6), - child: Image.asset(app.logoAsset!, width: 22, height: 22), - ), - Expanded(child: Text(screenshotMode ? 'Trainer app' : app.name)), - if (app.supports(AppConnectionMethod.obpBle) || - app.supports(AppConnectionMethod.obpMdns) || - app.supports(AppConnectionMethod.obpDirCon)) - OpenBikeControlLogo(), - ], - ), - popup: SelectPopup( - items: SelectItemList( - children: [ - if (groupedByOfficial.get(true)?.isNotEmpty == true) - Container( - color: Theme.of(context).colorScheme.accent, - padding: const EdgeInsets.all(8.0), - child: GradientText(AppLocalizations.of(context).officiallySupported).xSmall, - ), - ...groupedByOfficial.get(true)?.map((app) { - final supportsObp = - app.supports(AppConnectionMethod.obpBle) || - app.supports(AppConnectionMethod.obpMdns) || - app.supports(AppConnectionMethod.obpDirCon); - return SelectItemButton( - value: app, - child: Row( - spacing: 8, - children: [ - if (app.logoAsset != null) - ClipRRect( - borderRadius: BorderRadius.circular(6), - child: Image.asset(app.logoAsset!, width: 22, height: 22), - ), - Expanded( - child: app == core.settings.getTrainerApp() - ? Text(app.name).semiBold - : Text(app.name), - ), - if (supportsObp) OpenBikeControlLogo(), - ], - ), - ); - }), - if (groupedByOfficial.get(true)?.isNotEmpty == true) - Container( - color: Theme.of(context).colorScheme.accent, - padding: const EdgeInsets.all(8.0), - child: GradientText(AppLocalizations.of(context).otherTrainerApps).xSmall, - ), - ...groupedByOfficial.get(false)?.map((app) { - return SelectItemButton( - value: app, - child: app == core.settings.getTrainerApp() ? Text(app.name).semiBold : Text(app.name), - ); - }), - ], - ), - ).call, - placeholder: Text(context.i18n.selectTrainerAppPlaceholder), - value: core.settings.getTrainerApp(), - onChanged: (selectedApp) async { - if (selectedApp is! MyWhoosh) { - if (core.whooshLink.isStarted.value) { - core.whooshLink.stopServer(); - } - } - if (!selectedApp!.supports(AppConnectionMethod.zwiftMdns)) { - if (core.zwiftMdnsEmulator.isStarted.value) { - core.zwiftMdnsEmulator.stop(); - } - // TODO restart mDNS when advertisementName changes - } - if (!selectedApp.supports(AppConnectionMethod.zwiftBle)) { - if (core.zwiftEmulator.isStarted.value) { - core.zwiftEmulator.stopAdvertising(); - } - } - if (!selectedApp.supports(AppConnectionMethod.rouvyMdns)) { - if (core.rouvyMdnsEmulator.isStarted.value) { - core.rouvyMdnsEmulator.stop(); - } - } - if (core.obpMdnsEmulator.isStarted.value) { - core.obpMdnsEmulator.stopServer(); - } - if (core.obpBluetoothEmulator.isStarted.value) { - core.obpBluetoothEmulator.stopServer(); - } - - core.settings.setTrainerApp(selectedApp); - if (core.actionHandler.supportedApp == null || - (core.actionHandler.supportedApp is! CustomApp && selectedApp is! CustomApp)) { - core.actionHandler.init(selectedApp); - core.settings.setKeyMap(selectedApp); - } - core.logic.startEnabledConnectionMethod(); - - if (selectedApp is BikeControl) { - core.settings.setLastTarget(Target.thisDevice); - } + TrainerAppSelect( + onUpdate: () { widget.onUpdate(); setState(() {}); }, @@ -272,3 +164,137 @@ class _ConfigurationPageState extends State { core.logic.startEnabledConnectionMethod(); } } + +/// The trainer-app picker: a [Select] over [SupportedApp.supportedApps] that +/// reads/writes [core.settings.getTrainerApp]. Extracted from +/// [ConfigurationPage] so it can be rendered standalone (e.g. golden +/// snapshots). Behaviour is unchanged — it mutates the same `core.*` +/// singletons and notifies via [onUpdate]. +class TrainerAppSelect extends StatelessWidget { + /// Called after the trainer app changes so the host can rebuild. + final VoidCallback onUpdate; + + /// Forces the real trainer-app name to show in the closed control even when + /// [screenshotMode] is on (which otherwise replaces it with a generic + /// "Trainer app" label for the anonymized marketing screenshots). Used by the + /// MyWhoosh setup-guide snapshot, which needs the actual "MyWhoosh" name. + final bool showRealName; + const TrainerAppSelect({super.key, required this.onUpdate, this.showRealName = false}); + + @override + Widget build(BuildContext context) { + final groupedByOfficial = SupportedApp.supportedApps.groupBy((e) => e.officialIntegration); + return Select( + constraints: BoxConstraints(maxWidth: 400, minWidth: 400), + popupConstraints: BoxConstraints(maxWidth: 400, minWidth: 400, minHeight: 300), + itemBuilder: (c, app) => Row( + spacing: 8, + children: [ + if (app.logoAsset != null) + ClipRRect( + borderRadius: BorderRadius.circular(6), + child: Image.asset(app.logoAsset!, width: 22, height: 22), + ), + Expanded(child: Text(screenshotMode && !showRealName ? 'Trainer app' : app.name)), + if (app.supports(AppConnectionMethod.obpBle) || + app.supports(AppConnectionMethod.obpMdns) || + app.supports(AppConnectionMethod.obpDirCon)) + OpenBikeControlLogo(), + ], + ), + popup: SelectPopup( + items: SelectItemList( + children: [ + if (groupedByOfficial.get(true)?.isNotEmpty == true) + Container( + color: Theme.of(context).colorScheme.accent, + padding: const EdgeInsets.all(8.0), + child: GradientText(AppLocalizations.of(context).officiallySupported).xSmall, + ), + ...groupedByOfficial.get(true)?.map((app) { + final supportsObp = + app.supports(AppConnectionMethod.obpBle) || + app.supports(AppConnectionMethod.obpMdns) || + app.supports(AppConnectionMethod.obpDirCon); + return SelectItemButton( + value: app, + child: Row( + spacing: 8, + children: [ + if (app.logoAsset != null) + ClipRRect( + borderRadius: BorderRadius.circular(6), + child: Image.asset(app.logoAsset!, width: 22, height: 22), + ), + Expanded( + child: app == core.settings.getTrainerApp() + ? Text(app.name).semiBold + : Text(app.name), + ), + if (supportsObp) OpenBikeControlLogo(), + ], + ), + ); + }), + if (groupedByOfficial.get(true)?.isNotEmpty == true) + Container( + color: Theme.of(context).colorScheme.accent, + padding: const EdgeInsets.all(8.0), + child: GradientText(AppLocalizations.of(context).otherTrainerApps).xSmall, + ), + ...groupedByOfficial.get(false)?.map((app) { + return SelectItemButton( + value: app, + child: app == core.settings.getTrainerApp() ? Text(app.name).semiBold : Text(app.name), + ); + }), + ], + ), + ).call, + placeholder: Text(context.i18n.selectTrainerAppPlaceholder), + value: core.settings.getTrainerApp(), + onChanged: (selectedApp) async { + if (selectedApp is! MyWhoosh) { + if (core.whooshLink.isStarted.value) { + core.whooshLink.stopServer(); + } + } + if (!selectedApp!.supports(AppConnectionMethod.zwiftMdns)) { + if (core.zwiftMdnsEmulator.isStarted.value) { + core.zwiftMdnsEmulator.stop(); + } + // TODO restart mDNS when advertisementName changes + } + if (!selectedApp.supports(AppConnectionMethod.zwiftBle)) { + if (core.zwiftEmulator.isStarted.value) { + core.zwiftEmulator.stopAdvertising(); + } + } + if (!selectedApp.supports(AppConnectionMethod.rouvyMdns)) { + if (core.rouvyMdnsEmulator.isStarted.value) { + core.rouvyMdnsEmulator.stop(); + } + } + if (core.obpMdnsEmulator.isStarted.value) { + core.obpMdnsEmulator.stopServer(); + } + if (core.obpBluetoothEmulator.isStarted.value) { + core.obpBluetoothEmulator.stopServer(); + } + + core.settings.setTrainerApp(selectedApp); + if (core.actionHandler.supportedApp == null || + (core.actionHandler.supportedApp is! CustomApp && selectedApp is! CustomApp)) { + core.actionHandler.init(selectedApp); + core.settings.setKeyMap(selectedApp); + } + core.logic.startEnabledConnectionMethod(); + + if (selectedApp is BikeControl) { + core.settings.setLastTarget(Target.thisDevice); + } + onUpdate(); + }, + ); + } +} diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index 56805539..b4c586eb 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -4,6 +4,7 @@ import 'package:bike_control/bluetooth/devices/zwift/zwift_clickv2.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/pages/button_simulator.dart'; +import 'package:bike_control/pages/configuration.dart'; import 'package:bike_control/pages/controller_settings.dart'; import 'package:bike_control/pages/proxy_device_details.dart'; import 'package:bike_control/pages/proxy_device_details/front_shift_card.dart'; @@ -18,6 +19,7 @@ import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/utils/requirements/multi.dart'; +import 'package:bike_control/widgets/apps/openbikecontrol_mdns_tile.dart'; import 'package:bike_control/widgets/overlay/trainer_overlay_view.dart'; import 'package:flutter/material.dart' as ma; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; @@ -451,4 +453,67 @@ Future main() async { capture: () => find.byKey(k), ); }); + + // --- MyWhoosh setup-guide widget snapshots (website setup guide) --- + // Tight single-widget captures of the two BikeControl controls the MyWhoosh + // setup guide walks through: the trainer-app picker (showing MyWhoosh) and the + // "Connect directly over Network" connection method. Rendered standalone inside + // a keyed RepaintBoundary so the golden captures ONLY the widget. + + // The trainer-app picker with MyWhoosh selected. screenshotMode stays on (it + // suppresses the real BLE bootstrap) and TrainerAppSelect.showRealName forces + // the closed Select to show the real "MyWhoosh" name + logo instead of the + // generic "Trainer app" placeholder the marketing screenshots use. + testGoldens('mywhoosh-trainer-select', (WidgetTester tester) async { + core.settings.setTrainerApp(MyWhoosh()); + core.settings.setKeyMap(MyWhoosh()); + const k = ValueKey('shot'); + await shootOne( + tester, + 'mywhoosh-trainer-select', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: TrainerAppSelect(onUpdate: () {}, showRealName: true), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); + + // The Network connection method (OpenBikeControl over mDNS), as shown for + // MyWhoosh, in its disabled/off state. The tile passes no requirements, so no + // real BLE is touched even though screenshotMode hides the "Recommended" badge. + testGoldens('mywhoosh-network-connection', (WidgetTester tester) async { + core.settings.setTrainerApp(MyWhoosh()); + core.settings.setKeyMap(MyWhoosh()); + core.settings.setObpMdnsEnabled(false); + // Force the off / not-yet-connected state so the captured card is identical + // regardless of any emulator state a prior scene left behind (the shown + // description and height depend on isStarted/connectedApp). + core.obpMdnsEmulator.isStarted.value = false; + core.obpMdnsEmulator.connectedApp.value = null; + const k = ValueKey('shot'); + await shootOne( + tester, + 'mywhoosh-network-connection', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: OpenBikeControlMdnsTile(small: false), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); } From b24a6c5a928c08135df179eca314eafc6bc0d2ab Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 17:40:40 +0200 Subject: [PATCH 090/106] test: generate MyWhoosh setup widgets per locale (en,de,es,fr,it) Co-Authored-By: Claude Opus 4.8 (1M context) --- test/screenshot_test.dart | 54 +++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index b4c586eb..4152dd1e 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -316,6 +316,56 @@ Future main() async { ); } + // Localized widget snapshot: like [shootOne], but renders the (frameless, + // noFrame) widget once per locale and writes ../screenshots//.png. + // Used for the website setup guides, which show the matching-language widget + // screenshots. The website uses the en/de/es/fr/it intersection of the app's + // and the site's supported locales; Czech falls back to en on the website. + Future shootLocalized( + WidgetTester tester, + String scene, + Widget Function() home, { + Finder Function()? capture, + Future Function(WidgetTester tester)? afterPump, + TargetPlatform platform = TargetPlatform.android, + }) async { + const widgetLocales = ['en', 'de', 'es', 'fr', 'it']; + final nf = sizes.firstWhere((s) => s.type == DeviceType.noFrame); + for (final loc in widgetLocales) { + await AppLocalizations.load(Locale(loc)); + screenshotLocale = Locale(loc); + await tester.pumpWidget( + ScreenshotApp( + locale: Locale(loc), + device: ScreenshotDevice( + // Default Android, never the entry's Windows platform: shadcn's theme + // queries the Windows accent colour via advapi32.dll, which can't load + // on a macOS test host. + platform: platform, + resolution: nf.size, + pixelRatio: 3, + goldenSubFolder: 'iphoneScreenshots/', + frameBuilder: + ({ + required ScreenshotDevice device, + required ScreenshotFrameColors? frameColors, + required Widget child, + }) => CustomFrame(platform: DeviceType.noFrame, title: '', device: device, child: child), + ), + home: home(), + ), + ); + await tester.pump(); + if (afterPump != null) await afterPump(tester); + await tester.loadAssets(); + await tester.pump(); + await expectLater( + capture?.call() ?? find.byType(ma.Scaffold), + matchesGoldenFile('../screenshots/$loc/$scene.png'), + ); + } + } + testGoldens('Device', (WidgetTester tester) async { await shoot(tester, 'device', () => BikeControlApp()); }); @@ -468,7 +518,7 @@ Future main() async { core.settings.setTrainerApp(MyWhoosh()); core.settings.setKeyMap(MyWhoosh()); const k = ValueKey('shot'); - await shootOne( + await shootLocalized( tester, 'mywhoosh-trainer-select', () => BikeControlApp( @@ -499,7 +549,7 @@ Future main() async { core.obpMdnsEmulator.isStarted.value = false; core.obpMdnsEmulator.connectedApp.value = null; const k = ValueKey('shot'); - await shootOne( + await shootLocalized( tester, 'mywhoosh-network-connection', () => BikeControlApp( From 83e6ca53484db5da83156158f1366ec3e74aded6 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 18:14:08 +0200 Subject: [PATCH 091/106] test: full connection-card goldens (with action badges) for 8 controllers Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/bluetooth/devices/base_device.dart | 10 +- lib/bluetooth/devices/hid/hid_device.dart | 13 +- test/screenshot_test.dart | 182 ++++++++++++++++++++++ 3 files changed, 200 insertions(+), 5 deletions(-) diff --git a/lib/bluetooth/devices/base_device.dart b/lib/bluetooth/devices/base_device.dart index 579ec1c3..41cadf34 100644 --- a/lib/bluetooth/devices/base_device.dart +++ b/lib/bluetooth/devices/base_device.dart @@ -491,7 +491,11 @@ abstract class BaseDevice { /// identically-named entries can be told apart. Returns null by default. Widget? nameBadge(BuildContext context) => null; - Widget showInformation(BuildContext context, {required bool showFull, Widget? footer}) { + Widget showInformation(BuildContext context, + {required bool showFull, + Widget? footer, + bool showSettingsIcon = true, + bool showAdditionalInfo = true}) { final meta = showMetaInformation(context, showFull: showFull); final badge = nameBadge(context); // Hero the entire header Row so the icon, title and meta fly together @@ -530,7 +534,7 @@ abstract class BaseDevice { if (badge != null) badge, if (isBeta) BetaPill(), Expanded(child: SizedBox()), - if (!showFull) + if (!showFull && showSettingsIcon) Icon( LucideIcons.settings, size: 16, @@ -554,7 +558,7 @@ abstract class BaseDevice { ), ), if (footer != null) footer, - ...showAdditionalInformation(context), + if (showAdditionalInfo) ...showAdditionalInformation(context), ], ); } diff --git a/lib/bluetooth/devices/hid/hid_device.dart b/lib/bluetooth/devices/hid/hid_device.dart index 1aae640d..4eb03610 100644 --- a/lib/bluetooth/devices/hid/hid_device.dart +++ b/lib/bluetooth/devices/hid/hid_device.dart @@ -24,10 +24,19 @@ class HidDevice extends BaseDevice { } @override - Widget showInformation(BuildContext context, {required bool showFull, Widget? footer}) { + Widget showInformation(BuildContext context, + {required bool showFull, + Widget? footer, + bool showSettingsIcon = true, + bool showAdditionalInfo = true}) { return Row( children: [ - Expanded(child: super.showInformation(context, showFull: true, footer: footer)), + Expanded( + child: super.showInformation(context, + showFull: true, + footer: footer, + showSettingsIcon: showSettingsIcon, + showAdditionalInfo: showAdditionalInfo)), PopupMenuButton( itemBuilder: (c) => [ PopupMenuItem( diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index 4152dd1e..ff3b0034 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -1,6 +1,16 @@ +import 'package:bike_control/bluetooth/devices/base_device.dart'; +import 'package:bike_control/bluetooth/devices/bluetooth_device.dart'; +import 'package:bike_control/bluetooth/devices/cycplus/cycplus_bc2.dart'; +import 'package:bike_control/bluetooth/devices/elite/elite_sterzo.dart'; +import 'package:bike_control/bluetooth/devices/gyroscope/gyroscope_steering.dart'; import 'package:bike_control/bluetooth/devices/proxy/proxy_device.dart'; +import 'package:bike_control/bluetooth/devices/thinkrider/thinkrider_vs200.dart'; import 'package:bike_control/bluetooth/devices/zwift/constants.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_click.dart'; import 'package:bike_control/bluetooth/devices/zwift/zwift_clickv2.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_play.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_ride.dart'; +import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/main.dart'; import 'package:bike_control/pages/button_simulator.dart'; @@ -20,7 +30,9 @@ import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/utils/requirements/multi.dart'; import 'package:bike_control/widgets/apps/openbikecontrol_mdns_tile.dart'; +import 'package:bike_control/widgets/controller/controller_canvas.dart'; import 'package:bike_control/widgets/overlay/trainer_overlay_view.dart'; +import 'package:bike_control/widgets/ui/animated_button_widget.dart'; import 'package:flutter/material.dart' as ma; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -134,6 +146,54 @@ Future main() async { core.connection.addDevices([device, proxy]); + // Connected instances of every controller we shoot a full connection-card + // golden for. Each is given a real advertised name (so the card header shows + // the actual product name) and the connected meta (battery/rssi/firmware) the + // overview list would display. `device` above is the Zwift Click v2 instance. + BleDevice scan(String name) => BleDevice(name: name, deviceId: '00:11:22:33:44:55'); + // BLE controllers carry battery / rssi / firmware meta (defined on + // BluetoothDevice); set it so the card header shows the connected status line. + T connectedBle(T d) { + d + ..firmwareVersion = '1.2.0' + ..isConnected = true + ..rssi = -51 + ..batteryLevel = 81; + return d; + } + + final zwiftClick = connectedBle(ZwiftClick(scan('Zwift Click'))); + final zwiftRide = connectedBle(ZwiftRide(scan('Zwift Ride'))); + final zwiftPlay = connectedBle( + ZwiftPlay(scan('Zwift Play'), deviceType: ZwiftDeviceType.playLeft), + ); + final cycplusBc2 = connectedBle(CycplusBc2(scan('CYCPLUS BC2'))); + final thinkriderVs200 = connectedBle(ThinkRiderVs200(scan('THINK VS200'))); + final eliteSterzo = connectedBle(EliteSterzo(scan('STERZO'))); + // GyroscopeSteering extends BaseDevice directly (no BLE), so it has no + // battery/rssi/firmware — just mark it connected. + final gyroSteering = GyroscopeSteering()..isConnected = true; + + // All controllers must live in core.connection.devices so the MyWhoosh + // action handler (initialized below) seeds each button's default in-game + // action into the keymap — that's what renders the action badges. + core.connection.addDevices([ + zwiftClick, + zwiftRide, + zwiftPlay, + cycplusBc2, + thinkriderVs200, + eliteSterzo, + gyroSteering, + ]); + + // core.actionHandler is `late` (assigned in the app's main(), which the test + // harness never runs). Provide a StubActions and init it with MyWhoosh so + // core.actionHandler.supportedApp?.keymap is the populated MyWhoosh keymap the + // connected-Controllers footer passes to AnimatedButtonWidget. + core.actionHandler = StubActions(); + core.actionHandler.init(MyWhoosh()); + final firstButton = ZwiftButtons.b.copyWith(sourceDeviceId: device.uniqueId); final keyEntry = keymap.keymap.getOrCreateKeyPair(firstButton, trigger: ButtonTrigger.longPress); keyEntry.inGameAction = InGameAction.steerRight; @@ -566,4 +626,126 @@ Future main() async { capture: () => find.byKey(k), ); }); + + // --- Full connection card (connected-controller list entry) --- + // The complete card the overview's Controllers list renders for a connected + // controller: `device.showInformation` draws the header Row (StatusIcon + + // name + Beta pill + status meta) and, below it, the footer — the + // `ControllerCanvas` contour with its buttons. Two deviations from the live + // app, both deliberate so the image is chrome-free: + // * `showSettingsIcon: false` hides the small header gear (settings live on + // a separate page, not in this card). + // * `showAdditionalInfo: false` drops the device's own state chrome (e.g. + // the Zwift Click unlock warning) so the card is state-agnostic. + // The footer's buttons DO carry the MyWhoosh keymap (via + // `core.actionHandler.supportedApp?.keymap`), so each button that maps to an + // in-game action renders its supported-action badge — exactly like the + // connected-Controllers list. Buttons with no action (e.g. pure steering on + // the Sterzo / phone) render as bare buttons. + // + // `ZwiftClickV2.toString()` anonymizes its name to "Controller" while the + // marketing `screenshotMode` is on; we flip it off *synchronously* around just + // the `showInformation` build so the header shows the real product name — and + // restore it immediately, before any async (the app's connection-init scan + // reads `screenshotMode` on a later microtask, by which point it is true + // again, so no BLE scan fires). Only ClickV2 needs this, but doing it + // uniformly is harmless for the other devices. + // + // Rendered inside `BikeControlApp` so the card has the real theme and an + // `i18n` context, standalone in a keyed RepaintBoundary (captured tight) at a + // fixed list-card width. + Future shootCard(WidgetTester tester, String scene, BaseDevice cardDevice) async { + const k = ValueKey('shot'); + final savedScreenshotMode = screenshotMode; + try { + await shootOne( + tester, + scene, + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Center( + child: SizedBox( + width: 340, + child: Padding( + padding: const EdgeInsets.all(16), + child: Builder( + builder: (context) { + // Footer mirrors overview.dart's footerBuilder: the + // active app's keymap drives the per-button action badges. + final keymap = core.actionHandler.supportedApp?.keymap; + final size = 56 / Theme.of(context).scaling; + Widget btnFor(ControllerButton btn) => AnimatedButtonWidget( + key: ValueKey(btn.name), + button: btn, + pressGeneration: 0, + keymap: keymap, + device: cardDevice, + size: size, + onUpdate: () {}, + ); + final footer = ControllerCanvas( + layout: cardDevice.controllerLayout!, + availableButtons: cardDevice.availableButtons, + buttonBuilder: btnFor, + buttonSize: size, + ); + // Flip screenshotMode off only for this synchronous build + // so the header shows the real product name, then restore + // it before control returns to the framework. + final saved = screenshotMode; + screenshotMode = false; + final card = cardDevice.showInformation( + context, + showFull: false, + showSettingsIcon: false, + showAdditionalInfo: false, + footer: footer, + ); + screenshotMode = saved; + return RepaintBoundary(key: k, child: card); + }, + ), + ), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + } finally { + screenshotMode = savedScreenshotMode; + } + } + + testGoldens('controller-zwift-click', (WidgetTester tester) async { + await shootCard(tester, 'controller-zwift-click', zwiftClick); + }); + + testGoldens('controller-zwift-click-v2', (WidgetTester tester) async { + await shootCard(tester, 'controller-zwift-click-v2', device); + }); + + testGoldens('controller-zwift-ride', (WidgetTester tester) async { + await shootCard(tester, 'controller-zwift-ride', zwiftRide); + }); + + testGoldens('controller-zwift-play', (WidgetTester tester) async { + await shootCard(tester, 'controller-zwift-play', zwiftPlay); + }); + + testGoldens('controller-cycplus-bc2', (WidgetTester tester) async { + await shootCard(tester, 'controller-cycplus-bc2', cycplusBc2); + }); + + testGoldens('controller-thinkrider-vs200', (WidgetTester tester) async { + await shootCard(tester, 'controller-thinkrider-vs200', thinkriderVs200); + }); + + testGoldens('controller-elite-sterzo', (WidgetTester tester) async { + await shootCard(tester, 'controller-elite-sterzo', eliteSterzo); + }); + + testGoldens('controller-phone-steering', (WidgetTester tester) async { + await shootCard(tester, 'controller-phone-steering', gyroSteering); + }); } From bbb663bb54664848231937fc10a1d8ae4b79037c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 18:28:28 +0200 Subject: [PATCH 092/106] test: localized Rouvy & TrainingPeaks setup widget goldens Co-Authored-By: Claude Opus 4.8 (1M context) --- test/screenshot_test.dart | 140 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 140 insertions(+) diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index ff3b0034..9425dfed 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -24,11 +24,15 @@ import 'package:bike_control/utils/core.dart' show core; import 'package:bike_control/utils/iap/iap_manager.dart'; import 'package:bike_control/utils/keymap/apps/bike_control.dart'; import 'package:bike_control/utils/keymap/apps/my_whoosh.dart'; +import 'package:bike_control/utils/keymap/apps/rouvy.dart'; +import 'package:bike_control/utils/keymap/apps/supported_app.dart'; +import 'package:bike_control/utils/keymap/apps/training_peaks.dart'; import 'package:bike_control/utils/keymap/apps/zwift.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/utils/requirements/multi.dart'; +import 'package:bike_control/widgets/apps/openbikecontrol_ble_tile.dart'; import 'package:bike_control/widgets/apps/openbikecontrol_mdns_tile.dart'; import 'package:bike_control/widgets/controller/controller_canvas.dart'; import 'package:bike_control/widgets/overlay/trainer_overlay_view.dart'; @@ -748,4 +752,140 @@ Future main() async { testGoldens('controller-phone-steering', (WidgetTester tester) async { await shootCard(tester, 'controller-phone-steering', gyroSteering); }); + + // --- Rouvy & TrainingPeaks setup-guide widget snapshots (website setup guide) --- + // Tight single-widget captures mirroring the MyWhoosh setup-guide scenes above: + // the trainer-app picker (showing the active app's real name + logo) and the + // connection methods the guide walks through. Rouvy and TrainingPeaks both offer + // a Network (OpenBikeControl over mDNS) and a Bluetooth (OpenBikeControl over BLE) + // method, so the connection-methods scene stacks `OpenBikeControlMdnsTile` and + // `OpenBikeControlBluetoothTile` in a Column. The active app is set the same way + // as the MyWhoosh scenes (`core.settings.setTrainerApp/​setKeyMap`) so the tile + // descriptions read "Lets connect…" with the active app's name. + + // Helper: set the active app (drives TrainerAppSelect's closed display and the + // connection tiles' {appName} interpolation) and force the off / not-yet-connected + // emulator state so the captured cards are identical regardless of any emulator + // state a prior scene left behind (the shown description and height depend on + // isStarted/connectedApp for both the mDNS and BLE tiles). + void setActiveApp(SupportedApp app) { + core.settings.setTrainerApp(app); + core.settings.setKeyMap(app); + core.settings.setObpMdnsEnabled(false); + core.settings.setObpBleEnabled(false); + core.obpMdnsEmulator.isStarted.value = false; + core.obpMdnsEmulator.connectedApp.value = null; + core.obpBluetoothEmulator.isStarted.value = false; + core.obpBluetoothEmulator.connectedApp.value = null; + } + + // The trainer-app picker with Rouvy selected (showRealName forces the real + // "Rouvy" name + logo instead of the generic "Trainer app" placeholder). + testGoldens('rouvy-trainer-select', (WidgetTester tester) async { + setActiveApp(Rouvy()); + const k = ValueKey('shot'); + await shootLocalized( + tester, + 'rouvy-trainer-select', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: TrainerAppSelect(onUpdate: () {}, showRealName: true), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); + + // The connection methods for Rouvy: Network (mDNS) and Bluetooth (BLE) stacked, + // both in their off / not-yet-connected state. Descriptions read + // "Lets Rouvy connect…". + testGoldens('rouvy-connection-methods', (WidgetTester tester) async { + setActiveApp(Rouvy()); + const k = ValueKey('shot'); + await shootLocalized( + tester, + 'rouvy-connection-methods', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 12, + children: const [ + OpenBikeControlMdnsTile(small: false), + OpenBikeControlBluetoothTile(small: false), + ], + ), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); + + // The trainer-app picker with TrainingPeaks selected. Note: TrainingPeaks's + // app name is "TrainingPeaks Virtual", so the closed Select (and the + // connection-method descriptions below) show "TrainingPeaks Virtual". + testGoldens('trainingpeaks-trainer-select', (WidgetTester tester) async { + setActiveApp(TrainingPeaks()); + const k = ValueKey('shot'); + await shootLocalized( + tester, + 'trainingpeaks-trainer-select', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: TrainerAppSelect(onUpdate: () {}, showRealName: true), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); + + // The connection methods for TrainingPeaks: Network (mDNS) and Bluetooth (BLE) + // stacked, both off. Descriptions read "Lets TrainingPeaks Virtual connect…". + testGoldens('trainingpeaks-connection-methods', (WidgetTester tester) async { + setActiveApp(TrainingPeaks()); + const k = ValueKey('shot'); + await shootLocalized( + tester, + 'trainingpeaks-connection-methods', + () => BikeControlApp( + customChild: SingleChildScrollView( + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + spacing: 12, + children: const [ + OpenBikeControlMdnsTile(small: false), + OpenBikeControlBluetoothTile(small: false), + ], + ), + ), + ), + ), + ), + capture: () => find.byKey(k), + ); + }); } From 5fd2a7ae0d55b8c7e0e483b1f78f46adcabe5f5c Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 18:36:59 +0200 Subject: [PATCH 093/106] test: render real per-app connection-method tiles for Rouvy & TrainingPeaks snapshots Co-Authored-By: Claude Opus 4.8 (1M context) --- test/screenshot_test.dart | 190 +++++++++++++++++++++++++------------- 1 file changed, 126 insertions(+), 64 deletions(-) diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index 9425dfed..ad121242 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -10,6 +10,7 @@ import 'package:bike_control/bluetooth/devices/zwift/zwift_click.dart'; import 'package:bike_control/bluetooth/devices/zwift/zwift_clickv2.dart'; import 'package:bike_control/bluetooth/devices/zwift/zwift_play.dart'; import 'package:bike_control/bluetooth/devices/zwift/zwift_ride.dart'; +import 'package:bike_control/bluetooth/messages/notification.dart'; import 'package:bike_control/utils/actions/base_actions.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/main.dart'; @@ -32,8 +33,13 @@ import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; import 'package:bike_control/utils/requirements/multi.dart'; +import 'package:bike_control/widgets/apps/di2_ble_tile.dart'; +import 'package:bike_control/widgets/apps/local_tile.dart'; +import 'package:bike_control/widgets/apps/mywhoosh_link_tile.dart'; import 'package:bike_control/widgets/apps/openbikecontrol_ble_tile.dart'; import 'package:bike_control/widgets/apps/openbikecontrol_mdns_tile.dart'; +import 'package:bike_control/widgets/apps/zwift_mdns_tile.dart'; +import 'package:bike_control/widgets/apps/zwift_tile.dart'; import 'package:bike_control/widgets/controller/controller_canvas.dart'; import 'package:bike_control/widgets/overlay/trainer_overlay_view.dart'; import 'package:bike_control/widgets/ui/animated_button_widget.dart'; @@ -756,76 +762,145 @@ Future main() async { // --- Rouvy & TrainingPeaks setup-guide widget snapshots (website setup guide) --- // Tight single-widget captures mirroring the MyWhoosh setup-guide scenes above: // the trainer-app picker (showing the active app's real name + logo) and the - // connection methods the guide walks through. Rouvy and TrainingPeaks both offer - // a Network (OpenBikeControl over mDNS) and a Bluetooth (OpenBikeControl over BLE) - // method, so the connection-methods scene stacks `OpenBikeControlMdnsTile` and - // `OpenBikeControlBluetoothTile` in a Column. The active app is set the same way - // as the MyWhoosh scenes (`core.settings.setTrainerApp/​setKeyMap`) so the tile - // descriptions read "Lets connect…" with the active app's name. - - // Helper: set the active app (drives TrainerAppSelect's closed display and the - // connection tiles' {appName} interpolation) and force the off / not-yet-connected - // emulator state so the captured cards are identical regardless of any emulator - // state a prior scene left behind (the shown description and height depend on - // isStarted/connectedApp for both the mDNS and BLE tiles). + // connection methods the guide walks through. The connection-methods scene + // reproduces `trainer.dart`'s `recommendedTiles` conditional expression VERBATIM + // (see [recommendedConnectionTiles]) so the snapshot shows exactly the tiles the + // live app renders for whichever app is active — driven by `core.logic.show*`. + // These flags are derived from the selected app's declared `connections`: + // * Rouvy supports (rouvyMdns, zwiftBle) → ZwiftMdnsTile + ZwiftTile. + // * TrainingPeaks supports (obpBle, obpDirCon) → OpenBikeControlMdnsTile + + // OpenBikeControlBluetoothTile. + // The BLE-backed flags (showZwiftBleEmulator / showObpBluetoothEmulator) ALSO + // require `getLastTarget() != Target.thisDevice`, so [setActiveApp] persists + // `Target.otherDevice` (the "run the app on another device" setup-guide path). + + // Helper: set the active app exactly as selecting it in the app would, so the + // `core.logic.show*` flags become what the live app uses, then force every + // emulator into its off / not-yet-connected state so the captured cards are + // identical regardless of any emulator state a prior scene left behind (the + // shown description and height depend on isStarted/isConnected/connectedApp). void setActiveApp(SupportedApp app) { core.settings.setTrainerApp(app); core.settings.setKeyMap(app); + // Selecting "another device" as the target is what enables the Bluetooth + // connection methods (showZwiftBleEmulator / showObpBluetoothEmulator both + // gate on getLastTarget() != Target.thisDevice). Without a non-null, + // non-thisDevice target the BLE tiles — and the whole tile block — are hidden. + core.settings.setLastTarget(Target.otherDevice); + // OBC (TrainingPeaks) tiles. core.settings.setObpMdnsEnabled(false); core.settings.setObpBleEnabled(false); core.obpMdnsEmulator.isStarted.value = false; core.obpMdnsEmulator.connectedApp.value = null; + core.obpMdnsEmulator.isConnected.value = false; core.obpBluetoothEmulator.isStarted.value = false; core.obpBluetoothEmulator.connectedApp.value = null; + core.obpBluetoothEmulator.isConnected.value = false; + // Zwift-protocol (Rouvy) tiles. + core.settings.setZwiftMdnsEmulatorEnabled(false); + core.settings.setZwiftBleEmulatorEnabled(false); + core.rouvyMdnsEmulator.isStarted.value = false; + core.rouvyMdnsEmulator.isConnected.value = false; + core.zwiftMdnsEmulator.isStarted.value = false; + core.zwiftMdnsEmulator.isConnected.value = false; + core.zwiftEmulator.isStarted.value = false; + core.zwiftEmulator.isConnected.value = false; } - // The trainer-app picker with Rouvy selected (showRealName forces the real - // "Rouvy" name + logo instead of the generic "Trainer app" placeholder). - testGoldens('rouvy-trainer-select', (WidgetTester tester) async { - setActiveApp(Rouvy()); + // The connection-method tiles the live app renders for the active app. This is + // `trainer.dart`'s `recommendedTiles` expression reproduced VERBATIM (same + // `if (core.logic.showX) XTile(small: false)` set, same order) so the snapshot + // matches the live app for whatever app `setActiveApp` selected. The onUpdate + // callbacks mirror trainer.dart's (signal a log notification); they never fire + // in the static snapshot. + List recommendedConnectionTiles() { + // Verbatim from trainer.dart: the leading `false &&` is intentional (the + // "show Local as an Other method" path is currently disabled there). + // ignore: dead_code + final showLocalAsOther = false && core.logic.showLocalControl && !core.settings.getLocalEnabled(); + final showWhooshLinkAsOther = + (core.logic.showObpBluetoothEmulator || core.logic.showObpMdnsEmulator) && core.logic.showMyWhooshLink; + return [ + if (core.logic.showObpMdnsEmulator) OpenBikeControlMdnsTile(small: false), + if (core.logic.showObpBluetoothEmulator) OpenBikeControlBluetoothTile(small: false), + if (core.logic.showZwiftMsdnEmulator) + ZwiftMdnsTile( + small: false, + onUpdate: () { + core.connection.signalNotification( + LogNotification('Zwift Emulator status changed to ${core.zwiftEmulator.isConnected.value}'), + ); + }, + ), + if (core.logic.showZwiftBleEmulator) + ZwiftTile( + small: false, + onUpdate: () { + core.connection.signalNotification( + LogNotification('Zwift Emulator status changed to ${core.zwiftEmulator.isConnected.value}'), + ); + }, + ), + if (core.logic.showDi2Ble) Di2BleTile(small: false), + if (core.logic.showLocalControl && !showLocalAsOther) LocalTile(small: false), + if (core.logic.showMyWhooshLink && !showWhooshLinkAsOther) MyWhooshLinkTile(small: false), + ]; + } + + // Render the recommended connection-method tiles for the active app the same + // way the trainer page lays them out (each tile in an IntrinsicHeight, stacked + // in a Column with 12px gaps), inside a keyed RepaintBoundary so the golden + // captures only the tile stack at a fixed setup-guide width. + Future shootConnectionMethods(WidgetTester tester, String scene) async { const k = ValueKey('shot'); await shootLocalized( tester, - 'rouvy-trainer-select', + scene, () => BikeControlApp( customChild: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(24), - child: RepaintBoundary( - key: k, - child: TrainerAppSelect(onUpdate: () {}, showRealName: true), + child: Center( + child: SizedBox( + width: 340, + child: Padding( + padding: const EdgeInsets.all(24), + child: RepaintBoundary( + key: k, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + for (final tile in recommendedConnectionTiles()) + Padding( + padding: const EdgeInsets.only(bottom: 12.0), + child: IntrinsicHeight(child: tile), + ), + ], + ), + ), + ), ), ), ), ), capture: () => find.byKey(k), ); - }); + } - // The connection methods for Rouvy: Network (mDNS) and Bluetooth (BLE) stacked, - // both in their off / not-yet-connected state. Descriptions read - // "Lets Rouvy connect…". - testGoldens('rouvy-connection-methods', (WidgetTester tester) async { + // The trainer-app picker with Rouvy selected (showRealName forces the real + // "Rouvy" name + logo instead of the generic "Trainer app" placeholder). + testGoldens('rouvy-trainer-select', (WidgetTester tester) async { setActiveApp(Rouvy()); const k = ValueKey('shot'); await shootLocalized( tester, - 'rouvy-connection-methods', + 'rouvy-trainer-select', () => BikeControlApp( customChild: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24), child: RepaintBoundary( key: k, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - spacing: 12, - children: const [ - OpenBikeControlMdnsTile(small: false), - OpenBikeControlBluetoothTile(small: false), - ], - ), + child: TrainerAppSelect(onUpdate: () {}, showRealName: true), ), ), ), @@ -834,6 +909,15 @@ Future main() async { ); }); + // The connection methods the live app renders for Rouvy. Rouvy supports + // (rouvyMdns, zwiftBle), so this captures ZwiftMdnsTile (Network, over the + // Rouvy mDNS emulator) + ZwiftTile (Bluetooth) — NOT the OBC tiles — both in + // their off / not-yet-connected state. + testGoldens('rouvy-connection-methods', (WidgetTester tester) async { + setActiveApp(Rouvy()); + await shootConnectionMethods(tester, 'rouvy-connection-methods'); + }); + // The trainer-app picker with TrainingPeaks selected. Note: TrainingPeaks's // app name is "TrainingPeaks Virtual", so the closed Select (and the // connection-method descriptions below) show "TrainingPeaks Virtual". @@ -858,34 +942,12 @@ Future main() async { ); }); - // The connection methods for TrainingPeaks: Network (mDNS) and Bluetooth (BLE) - // stacked, both off. Descriptions read "Lets TrainingPeaks Virtual connect…". + // The connection methods the live app renders for TrainingPeaks. TrainingPeaks + // supports (obpBle, obpDirCon), so this captures OpenBikeControlMdnsTile + // (Network) + OpenBikeControlBluetoothTile (Bluetooth), both off. Descriptions + // read "Lets TrainingPeaks Virtual connect…". testGoldens('trainingpeaks-connection-methods', (WidgetTester tester) async { setActiveApp(TrainingPeaks()); - const k = ValueKey('shot'); - await shootLocalized( - tester, - 'trainingpeaks-connection-methods', - () => BikeControlApp( - customChild: SingleChildScrollView( - child: Padding( - padding: const EdgeInsets.all(24), - child: RepaintBoundary( - key: k, - child: Column( - mainAxisSize: MainAxisSize.min, - crossAxisAlignment: CrossAxisAlignment.stretch, - spacing: 12, - children: const [ - OpenBikeControlMdnsTile(small: false), - OpenBikeControlBluetoothTile(small: false), - ], - ), - ), - ), - ), - ), - capture: () => find.byKey(k), - ); + await shootConnectionMethods(tester, 'trainingpeaks-connection-methods'); }); } From 364eecbb1be61cd91a80fee3906458a0eb9ae22d Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 18:55:54 +0200 Subject: [PATCH 094/106] test: localized overview/main-screen goldens (real device names) for 6 controllers Co-Authored-By: Claude Opus 4.8 (1M context) --- test/screenshot_test.dart | 141 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 141 insertions(+) diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index ad121242..55492397 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -17,6 +17,8 @@ import 'package:bike_control/main.dart'; import 'package:bike_control/pages/button_simulator.dart'; import 'package:bike_control/pages/configuration.dart'; import 'package:bike_control/pages/controller_settings.dart'; +import 'package:bike_control/pages/navigation.dart'; +import 'package:bike_control/pages/overview.dart'; import 'package:bike_control/pages/proxy_device_details.dart'; import 'package:bike_control/pages/proxy_device_details/front_shift_card.dart'; import 'package:bike_control/pages/proxy_device_details/gear_ratios_editor_page.dart'; @@ -32,6 +34,7 @@ import 'package:bike_control/utils/keymap/apps/zwift.dart'; import 'package:bike_control/utils/keymap/buttons.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/services/overlay/overlay_state.dart'; +import 'package:bike_control/services/overview_screenshot.dart'; import 'package:bike_control/utils/requirements/multi.dart'; import 'package:bike_control/widgets/apps/di2_ble_tile.dart'; import 'package:bike_control/widgets/apps/local_tile.dart'; @@ -950,4 +953,142 @@ Future main() async { setActiveApp(TrainingPeaks()); await shootConnectionMethods(tester, 'trainingpeaks-connection-methods'); }); + + // --- Overview / main screen (website setup-guide step 1) --------------------- + // A clean capture of the app's OVERVIEW page (Controllers card + Trainer + // Connection) showing ONLY a single connected controller with its REAL product + // name (not the anonymized "Controller" the App-Store `Device` shot uses). No + // device frame, no marketing title banner — just the app's own UI inside the + // frameless `noFrame` ScreenshotApp, localized one shot per locale. + // + // Two tricks make this work: + // * We render the full `Navigation()` (the overview Scaffold + its AppBar) + // while `screenshotMode == true`, so `Navigation.initState` → + // `core.logic.startEnabledConnectionMethod()` early-returns (no BLE/mDNS + // emulators start) and the page is laid out without any real connection. + // * To get the REAL device name we flip `screenshotMode` off *synchronously* + // for just the final `pump()` that produces the captured frame, then + // restore it. e.g. `ZwiftClickV2.toString()` is read during that build and + // returns "Zwift Click V2"; every async callback that re-reads the flag + // (timers, the connection-init scan) runs on a later microtask, by which + // point it is `true` again, so nothing scans. Harmless for the controllers + // whose names are never anonymized. + // + // `core.connection.devices` is reduced to exactly the given controller + the + // smart-trainer proxy (so the Trainer Connection card shows a connected + // trainer). The active trainer app is MyWhoosh (the harness default). + // + // The frameless `noFrame` size entry's logical width (~367 px) is just narrow + // enough that the AppBar wraps the "BikeControl" title to two lines. The + // overview here is rendered slightly wider — `overviewNoFrameSize`, ~500 + // logical px — so the title fits on one line while staying well under the + // overview's 800-logical-px two-column breakpoint (so it remains a phone-style + // single-column portrait main screen). + // + // Captured via the Navigation Scaffold's existing `overviewScreenshotKey` + // RepaintBoundary → tight, no surrounding chrome. + final overviewNf = sizes.firstWhere((s) => s.type == DeviceType.noFrame); + // Widen just the overview shots so "BikeControl" no longer wraps. 1500 device + // px / pixelRatio 3 = 500 logical px — comfortably below the 800-logical-px + // two-column breakpoint, so it stays single-column portrait. + final overviewNoFrameSize = Size(1500, overviewNf.size.height); + + Future shootOverview( + WidgetTester tester, + String scene, + BaseDevice overviewDevice, + ) async { + const overviewLocales = ['en', 'de', 'es', 'fr', 'it']; + + // Only the given controller + the smart-trainer proxy. + final savedDevices = core.connection.devices.toList(); + core.connection.devices + ..clear() + ..addAll([overviewDevice, proxy]); + core.connection.hasDevices.value = true; + // core.settings.reset() (in main) clears this, so re-assert the Base version + // is active — otherwise the overview shows the "trial available" IAP banner. + IAPManager.instance.isPurchased.value = true; + + final savedScreenshotMode = screenshotMode; + try { + for (final loc in overviewLocales) { + await AppLocalizations.load(Locale(loc)); + screenshotLocale = Locale(loc); + await tester.pumpWidget( + ScreenshotApp( + locale: Locale(loc), + device: ScreenshotDevice( + // Android, never the entry's Windows platform (advapi32.dll can't + // load on a macOS test host). + platform: TargetPlatform.android, + resolution: overviewNoFrameSize, + pixelRatio: 3, + goldenSubFolder: 'iphoneScreenshots/', + frameBuilder: + ({ + required ScreenshotDevice device, + required ScreenshotFrameColors? frameColors, + required Widget child, + }) => CustomFrame(platform: DeviceType.noFrame, title: '', device: device, child: child), + ), + // Full overview Scaffold (header + Controllers card + Trainer + // Connection). screenshotMode is still true here, so initState does + // not start any connection method. + home: BikeControlApp(customChild: Navigation()), + ), + ); + await tester.pump(); + await tester.loadAssets(); + // Flip screenshotMode off only for the synchronous build/pump that + // produces the captured frame, so the Controllers card header shows the + // real product name, then restore it before any async work continues. + // initState already ran (with the flag true → no connection method + // started); mark the mounted OverviewPage element dirty so only its + // build() re-runs with the flag off, picking up the real device name. + screenshotMode = false; + tester.element(find.byType(OverviewPage)).markNeedsBuild(); + await tester.pump(); + try { + await expectLater( + find.byKey(overviewScreenshotKey), + matchesGoldenFile('../screenshots/$loc/$scene.png'), + ); + } finally { + screenshotMode = savedScreenshotMode; + await tester.pump(); + } + } + } finally { + screenshotMode = savedScreenshotMode; + core.connection.devices + ..clear() + ..addAll(savedDevices); + core.connection.hasDevices.value = core.connection.devices.isNotEmpty; + } + } + + testGoldens('overview-zwift-click', (WidgetTester tester) async { + await shootOverview(tester, 'overview-zwift-click', zwiftClick); + }); + + testGoldens('overview-zwift-click-v2', (WidgetTester tester) async { + await shootOverview(tester, 'overview-zwift-click-v2', device); + }); + + testGoldens('overview-zwift-ride', (WidgetTester tester) async { + await shootOverview(tester, 'overview-zwift-ride', zwiftRide); + }); + + testGoldens('overview-zwift-play', (WidgetTester tester) async { + await shootOverview(tester, 'overview-zwift-play', zwiftPlay); + }); + + testGoldens('overview-cycplus-bc2', (WidgetTester tester) async { + await shootOverview(tester, 'overview-cycplus-bc2', cycplusBc2); + }); + + testGoldens('overview-thinkrider-vs200', (WidgetTester tester) async { + await shootOverview(tester, 'overview-thinkrider-vs200', thinkriderVs200); + }); } From 24948d0c7bc853ae6236c4e6beee443ed8cd00b3 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 19:57:50 +0200 Subject: [PATCH 095/106] adjust changelog --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 30e8354a..31429eea 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,8 +1,9 @@ ### 6.2.0 (unreleased) **Features**: - Virtual front derailleur: adds a second chainring (2× drivetrain) for more realism. The new assignable "Front Shift (Chainring)" action — or pressing both shifters together, SRAM-AXS style — toggles between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. While it's active your current gear reads as head-unit-style position notation (e.g. 2×14) in the app, the gear overlay, and the iOS Live Activity. Set your chainring sizes per trainer in the gear settings. +- SRAM style shifting: when you click shift up & down at the same time, the front chainring switches - iOS / iPadOS: Floating gear overlay (Picture-in-Picture): your current gear can now show in a floating window over your trainer app during a ride. -- Screen recording: a new assignable "Record Screen" action starts and stops a screen recording from a controller button. +- Screen recording: a new assignable "Record Screen" action starts a screen recording from a controller button. ### 6.1.0 (19-06-2026) **Features**: From 2ffde874064e152f57b2f58cfde9ac27d98879f0 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 19:58:26 +0200 Subject: [PATCH 096/106] fix(shifting): apply front-derailleur settings live; bound chainrings; handle combo errors MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - FrontShiftCard now applies its toggle/chainring changes to the live FitnessBikeDefinition (not just the persisted config), so enabling the virtual front derailleur takes effect immediately instead of only after a reconnect/mode-switch — the combo gate read the config while the action checked the def, so the just-enabled feature reported itself disabled. - Bound the small-ring stepper to the large ring so small can't exceed large (which inverted the ratio and made the shift a no-op). - Error-handle the fire-and-forget front-shift combo so a throw is recorded instead of becoming an unobserved async error. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../proxy_device_details/front_shift_card.dart | 17 +++++++++++++---- .../gear_ratios_editor_page.dart | 2 +- lib/utils/actions/base_actions.dart | 9 ++++++++- test/screenshot_test.dart | 2 +- 4 files changed, 23 insertions(+), 7 deletions(-) diff --git a/lib/pages/proxy_device_details/front_shift_card.dart b/lib/pages/proxy_device_details/front_shift_card.dart index 045918b5..5c9bc2a8 100644 --- a/lib/pages/proxy_device_details/front_shift_card.dart +++ b/lib/pages/proxy_device_details/front_shift_card.dart @@ -4,15 +4,19 @@ import 'package:bike_control/models/shifting_config.dart'; import 'package:bike_control/utils/core.dart'; import 'package:bike_control/widgets/ui/setting_tile.dart'; import 'package:bike_control/widgets/ui/stepper_control.dart'; +import 'package:prop/emulators/definitions/fitness_bike_definition.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; /// The "Virtual front derailleur" setting: an enable toggle plus small/large -/// chainring steppers and the resulting ratio factor. Reads and writes the -/// active [ShiftingConfig] for [device]. +/// chainring steppers and the resulting ratio factor. Persists to the active +/// [ShiftingConfig] for [device] AND applies to the live [definition] so the +/// change takes effect immediately (mirroring the other cards on this page — +/// otherwise the gear settings only apply after a reconnect/mode-switch). class FrontShiftCard extends StatelessWidget { - const FrontShiftCard({super.key, required this.device}); + const FrontShiftCard({super.key, required this.device, required this.definition}); final ProxyDevice device; + final FitnessBikeDefinition definition; Future _update(ShiftingConfig Function(ShiftingConfig) mutate) async { final current = core.shiftingConfigs.activeFor(device.trainerKey); @@ -34,6 +38,7 @@ class FrontShiftCard extends StatelessWidget { trailing: Switch( value: enabled, onChanged: (v) async { + definition.setFrontShiftEnabled(v); await _update((c) => c.copyWith(frontShiftEnabled: v)); }, ), @@ -54,10 +59,13 @@ class FrontShiftCard extends StatelessWidget { value: small.toDouble(), step: 1.0, min: ShiftingConfig.chainringTeethMin.toDouble(), - max: ShiftingConfig.chainringTeethMax.toDouble(), + // Keep small <= large: the large ring must stay the bigger + // (harder) one, else the front shift inverts or no-ops. + max: large.toDouble(), format: (v) => v.toStringAsFixed(0), onChanged: (v) async { final next = v.toInt(); + definition.setChainringTeeth(next, large); await _update((c) => c.copyWith(smallChainringTeeth: next)); }, ), @@ -79,6 +87,7 @@ class FrontShiftCard extends StatelessWidget { format: (v) => v.toStringAsFixed(0), onChanged: (v) async { final next = v.toInt(); + definition.setChainringTeeth(small, next); await _update((c) => c.copyWith(largeChainringTeeth: next)); }, ), diff --git a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart index 7fe3ae7d..ca0b5368 100644 --- a/lib/pages/proxy_device_details/gear_ratios_editor_page.dart +++ b/lib/pages/proxy_device_details/gear_ratios_editor_page.dart @@ -114,7 +114,7 @@ class _GearRatiosEditorPageState extends State { _vsModeCard(), _gradeSmoothingCard(context), _cadenceFilterCard(context), - FrontShiftCard(device: widget.device), + FrontShiftCard(device: widget.device, definition: def), ], _gearCountCard(context), _heroCurve(context), diff --git a/lib/utils/actions/base_actions.dart b/lib/utils/actions/base_actions.dart index fe4f68a2..656a3239 100644 --- a/lib/utils/actions/base_actions.dart +++ b/lib/utils/actions/base_actions.dart @@ -6,6 +6,7 @@ import 'package:accessibility/accessibility.dart'; import 'package:bike_control/bluetooth/devices/gyroscope/gyroscope_steering.dart'; import 'package:bike_control/bluetooth/messages/notification.dart'; import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/main.dart'; import 'package:bike_control/services/workout/workout_recorder.dart'; import 'package:bike_control/utils/actions/android.dart'; import 'package:bike_control/utils/actions/desktop.dart'; @@ -228,7 +229,13 @@ abstract class BaseActions { isKeyDown && (keyPair.inGameAction == InGameAction.shiftUp || keyPair.inGameAction == InGameAction.shiftDown)) { if (noteShiftAndCheckCoincidence(keyPair.inGameAction!)) { - unawaited(performInGameAction(InGameAction.frontShift)); + unawaited(() async { + try { + await performInGameAction(InGameAction.frontShift); + } catch (e, s) { + recordError(e, s, context: 'frontShiftCombo'); + } + }()); } } diff --git a/test/screenshot_test.dart b/test/screenshot_test.dart index 55492397..8fded0c4 100644 --- a/test/screenshot_test.dart +++ b/test/screenshot_test.dart @@ -569,7 +569,7 @@ Future main() async { customChild: SingleChildScrollView( child: Padding( padding: const EdgeInsets.all(24), - child: RepaintBoundary(key: k, child: FrontShiftCard(device: proxy)), + child: RepaintBoundary(key: k, child: FrontShiftCard(device: proxy, definition: fbd)), ), ), ), From de7f914cd1698d0c13d2450a887adc76701d0d68 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 19:58:26 +0200 Subject: [PATCH 097/106] fix(obc): reset app-info reassembler on disconnect and bound the buffer A half-received or corrupt app-info write was retained forever (cleared only on a successful parse), poisoning every later parse so OpenBikeControl never reported "Connected to app" again until app restart. Reset the reassembler on disconnect and cap the buffer at 512 bytes so a stuck/corrupt stream recovers and can't leak. Adds regression tests for reset and the bound. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../openbikecontrol/app_info_reassembler.dart | 21 +++++++++++++++ .../openbikecontrol/obc_ble_emulator.dart | 11 +++++--- ...bikecontrol_app_info_reassembler_test.dart | 27 +++++++++++++++++++ 3 files changed, 55 insertions(+), 4 deletions(-) diff --git a/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart b/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart index 6d52c051..e9475b94 100644 --- a/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart +++ b/lib/bluetooth/devices/openbikecontrol/app_info_reassembler.dart @@ -16,6 +16,12 @@ import 'package:dartx/dartx.dart'; /// fragment and dropped the middle one), so a message split across three or /// more packets never reassembled; this keeps all fragments until one parses. class AppInfoReassembler { + /// Upper bound on buffered bytes. A valid app-info is ~100 bytes (32B appId + + /// 32B version + headers + a handful of button ids), so anything past this is + /// a corrupt/stuck stream — drop the stale prefix instead of poisoning every + /// future parse and growing without bound. + static const int _maxBufferedBytes = 512; + final List _fragments = []; /// The error from the most recent incomplete [offer], for diagnostics/logging. @@ -24,6 +30,13 @@ class AppInfoReassembler { /// Fragments currently buffered awaiting completion. int get pendingFragments => _fragments.length; + /// Drop any buffered fragments — call when the central disconnects so a + /// half-sent message can't bleed into the next connection. + void reset() { + _fragments.clear(); + lastError = null; + } + /// Offer the next write payload. Returns the parsed [AppInfo] once the /// accumulated buffer parses, or null while still incomplete. AppInfo? offer(Uint8List value) { @@ -37,6 +50,14 @@ class AppInfoReassembler { } catch (e) { lastError = e; _fragments.add(value); + // Bound the buffer: once the accumulation can no longer be any valid + // message, restart from this write so a stuck/corrupt stream recovers + // (and can't leak memory). + if (_fragments.fold(0, (sum, f) => sum + f.length) > _maxBufferedBytes) { + _fragments + ..clear() + ..add(value); + } return null; } } diff --git a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart index 991b2223..c549efdb 100644 --- a/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart +++ b/lib/bluetooth/devices/openbikecontrol/obc_ble_emulator.dart @@ -30,6 +30,7 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral bool _isServiceAdded = false; bool _isSubscribedToEvents = false; String? _currentDeviceId; + final _appInfoReassembler = AppInfoReassembler(); @override PeripheralServer get advertisingServer => _server; @@ -55,6 +56,8 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral isConnected.value = false; connectedApp.value = null; _currentDeviceId = null; + // Drop any half-received app-info so it can't poison the next central. + _appInfoReassembler.reset(); } }); @@ -100,8 +103,8 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral // Some apps (e.g. TrainingPeaks on macOS) split the app-info write // across several BLE packets; the reassembler accumulates fragments - // until the flattened buffer parses. - final appInfoReassembler = AppInfoReassembler(); + // until the flattened buffer parses. It's a field so disconnect can + // reset it (see onConnectionChanged) and so it outlives this closure. _server.setWriteHandler(OpenBikeControlConstants.APPINFO_CHARACTERISTIC_UUID, ( deviceId, characteristicId, @@ -112,10 +115,10 @@ class OpenBikeControlBluetoothEmulator extends TrainerConnection with Peripheral if (kDebugMode) { print('Write request for characteristic: $characteristicId: ${bytesToReadableHex(value)}'); } - final appInfo = appInfoReassembler.offer(value); + final appInfo = _appInfoReassembler.offer(value); if (appInfo == null) { core.connection.signalNotification( - LogNotification('Error parsing App Info ${bytesToHex(value)}: ${appInfoReassembler.lastError}'), + LogNotification('Error parsing App Info ${bytesToHex(value)}: ${_appInfoReassembler.lastError}'), ); return PeripheralWriteRequestResult(); } diff --git a/test/openbikecontrol_app_info_reassembler_test.dart b/test/openbikecontrol_app_info_reassembler_test.dart index 38f9147e..3e365d33 100644 --- a/test/openbikecontrol_app_info_reassembler_test.dart +++ b/test/openbikecontrol_app_info_reassembler_test.dart @@ -94,4 +94,31 @@ void main() { expect(r.offer(fragment(complete, 2)[0]), isNull); expect(r.lastError, isA()); }); + + test('reset() drops a half-received message so the next one parses clean', () { + final r = AppInfoReassembler(); + + // A central sends a partial app-info, then disconnects. + expect(r.offer(fragment(complete, 2)[0]), isNull); + expect(r.pendingFragments, 1); + r.reset(); // emulator calls this on disconnect + expect(r.pendingFragments, 0); + + // A freshly-connected central's complete write must parse — without reset + // the stale prefix would poison it forever. + final info = r.offer(complete); + expect(info, isNotNull); + expect(info!.appId, 'TrainingPeaks'); + }); + + test('bounds the buffer under a flood of unparseable writes', () { + final r = AppInfoReassembler(); + final junk = Uint8List.fromList(List.filled(64, 0xFF)); // never a valid app-info + + for (var i = 0; i < 100; i++) { + expect(r.offer(junk), isNull); + } + // 100 × 64B = 6400B if unbounded; the 512B cap keeps it small (no leak). + expect(r.pendingFragments, lessThanOrEqualTo(8)); + }); } From 2bc2489415609405f4bf95b4c9c16f07ea3fcc37 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 19:58:26 +0200 Subject: [PATCH 098/106] fix(screen-recording): guard re-entrant toggle; recover native start failures - Ignore toggles during the transient starting/stopping states (in-flight guard) so a double-press can't double-start or stop-during-start. - macOS: reset the recorder handle when start() throws, so one failure no longer permanently blocks recording (only stop() nilled it before). - iOS: remove the broadcast picker view after triggering so a 1x1 view doesn't accumulate on the key window on every start. - Report failures via recordError (was debugPrintStack, which vanishes in release builds). Adds an in-flight-toggle guard test. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../screen_recording_service.dart | 12 +++++++-- .../ios/Classes/ScreenRecorderPlugin.swift | 6 +++++ .../macos/Classes/ScreenRecorderPlugin.swift | 8 +++++- .../screen_recording_service_test.dart | 26 +++++++++++++++++++ 4 files changed, 49 insertions(+), 3 deletions(-) diff --git a/lib/services/screen_recording/screen_recording_service.dart b/lib/services/screen_recording/screen_recording_service.dart index f8ab26ea..d5006380 100644 --- a/lib/services/screen_recording/screen_recording_service.dart +++ b/lib/services/screen_recording/screen_recording_service.dart @@ -1,5 +1,7 @@ +import 'dart:async'; import 'dart:io'; +import 'package:bike_control/main.dart'; import 'package:bike_control/services/screen_recording/backends/android_screen_recorder.dart'; import 'package:bike_control/services/screen_recording/backends/native_channel_screen_recorder.dart'; import 'package:bike_control/services/screen_recording/backends/unsupported_screen_recorder.dart'; @@ -56,6 +58,12 @@ class ScreenRecordingService { /// Toggle recording. Never throws — failures map to `ok: false`. Future toggle() async { + final state = _state.value; + if (state == ScreenRecordingState.starting || state == ScreenRecordingState.stopping) { + // A start/stop is already in flight (e.g. awaiting the permission sheet); + // ignore re-entrant presses so we don't double-start or stop-during-start. + return const RecordingResult(ok: false, startedRecording: false); + } if (isRecording) { return _stop(); } @@ -78,7 +86,7 @@ class ScreenRecordingService { return RecordingResult(ok: started, startedRecording: true); } catch (e, s) { _state.value = ScreenRecordingState.error; - debugPrintStack(label: 'screen recording: $e', stackTrace: s); + unawaited(recordError(e, s, context: 'screen recording')); return RecordingResult(ok: false, startedRecording: false, errorMessage: e.toString()); } } @@ -91,7 +99,7 @@ class ScreenRecordingService { return RecordingResult(ok: true, startedRecording: false, savedPath: path); } catch (e, s) { _state.value = ScreenRecordingState.error; - debugPrintStack(label: 'screen recording: $e', stackTrace: s); + unawaited(recordError(e, s, context: 'screen recording')); return RecordingResult(ok: false, startedRecording: false, errorMessage: e.toString()); } } diff --git a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift index 49e5af39..e7824973 100644 --- a/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift +++ b/packages/screen_recorder/ios/Classes/ScreenRecorderPlugin.swift @@ -110,6 +110,12 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { button.sendActions(for: .touchUpInside) } } + // The picker is only a host for the trigger; once the system sheet is up + // it's no longer needed. Remove it so a new 1×1 view doesn't accumulate on + // the key window on every recording start. + DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) { + picker.removeFromSuperview() + } } } } diff --git a/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift index b3c3965e..4390c155 100644 --- a/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift +++ b/packages/screen_recorder/macos/Classes/ScreenRecorderPlugin.swift @@ -31,7 +31,13 @@ public class ScreenRecorderPlugin: NSObject, FlutterPlugin { DispatchQueue.main.async { result(true) } } catch { NSLog("screen_recorder start error: \(error)") - DispatchQueue.main.async { result(false) } + // Reset so a failed start doesn't leave `recorder` non-nil, which + // would trip the `guard recorder == nil` on every later start + // (recording stays dead until app relaunch, since only stop() nils it). + DispatchQueue.main.async { + self.recorder = nil + result(false) + } } } } else { result(false) } diff --git a/test/services/screen_recording/screen_recording_service_test.dart b/test/services/screen_recording/screen_recording_service_test.dart index c21e8d8d..e9c6d3b3 100644 --- a/test/services/screen_recording/screen_recording_service_test.dart +++ b/test/services/screen_recording/screen_recording_service_test.dart @@ -1,3 +1,5 @@ +import 'dart:async'; + import 'package:bike_control/services/screen_recording/screen_recording_service.dart'; import 'package:flutter_test/flutter_test.dart'; @@ -14,9 +16,14 @@ class FakeScreenRecorderBackend implements ScreenRecorderBackend { Future isAvailable() async => available; @override Future ensurePermission() async => permission; + /// When set, start() awaits this before returning, so a test can hold the + /// service in the `starting` state. + Completer? startGate; + @override Future start() async { startCalls++; + if (startGate != null) await startGate!.future; return startResult; } @@ -94,6 +101,25 @@ void main() { expect(result.ok, isFalse); expect(throwingService.state.value, ScreenRecordingState.error); }); + + test('ignores a re-entrant toggle while a start is in flight', () async { + backend.startGate = Completer(); + + final first = service.toggle(); // enters 'starting', then blocks in start() + // Let it advance through isAvailable/ensurePermission into the gated start(). + await Future.delayed(Duration.zero); + await Future.delayed(Duration.zero); + expect(service.state.value, ScreenRecordingState.starting); + + final second = await service.toggle(); // must be ignored, not a 2nd start + expect(second.ok, isFalse); + expect(backend.startCalls, 1, reason: 'the in-flight guard prevents a second start'); + + backend.startGate!.complete(); + await first; + expect(service.state.value, ScreenRecordingState.recording); + expect(backend.startCalls, 1); + }); } /// Backend whose start() always throws, to verify the never-throws contract. From 73b62b86db45a28cb1fc8ebf66c73ac8aaa1ecbe Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 19:58:26 +0200 Subject: [PATCH 099/106] fix(overlay): widen drag hit area; fix PiP show/hide race; orientation-safe DI detection - The floating overlay's drag handle now fills the full 24px trailing slot instead of only the 14px icon. - iOS overlay: arm PiP only while still showing and tear it down if a hide lands mid-start(), so a show/hide race can't orphan a frozen PiP window. - Detect Dynamic Island via the max safe-area inset instead of the top inset, which collapsed in landscape and could auto-start an unwanted PiP. Co-Authored-By: Claude Opus 4.8 (1M context) --- ios/Runner/DeviceCapabilities.swift | 19 ++++++++++--------- .../overlay/ios_overlay_controller.dart | 9 ++++++++- lib/widgets/overlay/trainer_overlay_view.dart | 12 +++++++----- 3 files changed, 25 insertions(+), 15 deletions(-) diff --git a/ios/Runner/DeviceCapabilities.swift b/ios/Runner/DeviceCapabilities.swift index 70f22b83..6e26ef5b 100644 --- a/ios/Runner/DeviceCapabilities.swift +++ b/ios/Runner/DeviceCapabilities.swift @@ -3,16 +3,16 @@ import UIKit enum DeviceCapabilities { /// No public API exposes "has Dynamic Island". Heuristic: Dynamic Island - /// iPhones report a larger portrait top safe-area inset (~59pt) than notch - /// devices (≤48pt). iPads have no Dynamic Island. + /// iPhones report a larger safe-area inset (~59pt) on the cutout edge than + /// notch devices (≤48pt). iPads have no Dynamic Island. /// - /// Misdetection is benign: the only false positive is a DI iPhone evaluated - /// in landscape (small top inset) being treated as non-DI, which merely adds - /// a (redundant) PiP alongside the Dynamic Island. A non-DI phone can never - /// be mistaken for DI (its inset never reaches the threshold). + /// We use the MAX of all four insets, not just `top`: in landscape the + /// cutout moves to a side edge and the top inset collapses to ~0, so a + /// top-only check would misread a Dynamic-Island iPhone as non-DI and + /// auto-start a redundant PiP. The max inset stays orientation-independent. static var hasDynamicIsland: Bool { guard UIDevice.current.userInterfaceIdiom == .phone else { return false } - return keyWindowTopInset() >= 51 + return keyWindowMaxInset() >= 51 } /// Whether PiP is technically possible at all: iOS 16+ (ImageRenderer) and @@ -38,11 +38,12 @@ enum DeviceCapabilities { UIDevice.current.userInterfaceIdiom == .pad } - private static func keyWindowTopInset() -> CGFloat { + private static func keyWindowMaxInset() -> CGFloat { for scene in UIApplication.shared.connectedScenes { guard let ws = scene as? UIWindowScene else { continue } if let w = ws.windows.first(where: { $0.isKeyWindow }) ?? ws.windows.first { - return w.safeAreaInsets.top + let i = w.safeAreaInsets + return max(max(i.top, i.bottom), max(i.left, i.right)) } } return 0 diff --git a/lib/services/overlay/ios_overlay_controller.dart b/lib/services/overlay/ios_overlay_controller.dart index d584a780..7493a160 100644 --- a/lib/services/overlay/ios_overlay_controller.dart +++ b/lib/services/overlay/ios_overlay_controller.dart @@ -88,9 +88,16 @@ class IosOverlayController implements TrainerOverlayController { // explicit false opts out. The Live Activity keeps running either way. final pref = core.settings.getOverlayUsePip(); final usePip = pref == null ? await _pip.isSupported() : (pref && await _pip.isCapable()); - if (usePip) { + // hide() may have run during the awaits above (Live Activity 'stop', + // trainer disconnect, …) and set _showing=false; only arm PiP if we're + // still showing, and tear it back down if a hide lands during start(). + if (usePip && _showing.value) { await _pip.start(_toMap(s)); _pipActive = true; + if (!_showing.value) { + _pipActive = false; + await _pip.stop(); + } } } catch (e, st) { recordError(e, st, context: 'overlay.ios.pip.start'); diff --git a/lib/widgets/overlay/trainer_overlay_view.dart b/lib/widgets/overlay/trainer_overlay_view.dart index 068b8378..c5f12f21 100644 --- a/lib/widgets/overlay/trainer_overlay_view.dart +++ b/lib/widgets/overlay/trainer_overlay_view.dart @@ -134,11 +134,13 @@ class TrainerOverlayView extends StatelessWidget { SizedBox( width: 24, child: onDragStart != null - ? Align( - alignment: Alignment.centerRight, - child: GestureDetector( - behavior: HitTestBehavior.opaque, - onPanStart: (_) => onDragStart!(), + // GestureDetector fills the whole slot (opaque) so the entire + // 24px trailing area is draggable, not just the 14px icon. + ? GestureDetector( + behavior: HitTestBehavior.opaque, + onPanStart: (_) => onDragStart!(), + child: Align( + alignment: Alignment.centerRight, child: Icon(Icons.drag_indicator, size: 14, color: cs.mutedForeground), ), ) From 57207e33f52c01ae2045fa2f6f2ea4b2e027fa42 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 20:22:01 +0200 Subject: [PATCH 100/106] changelog date --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 31429eea..e1b1f824 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,4 @@ -### 6.2.0 (unreleased) +### 6.2.0 (26-06-2026) **Features**: - Virtual front derailleur: adds a second chainring (2× drivetrain) for more realism. The new assignable "Front Shift (Chainring)" action — or pressing both shifters together, SRAM-AXS style — toggles between your small and large rings, changing resistance by the exact chainring ratio while staying on the same rear cog. While it's active your current gear reads as head-unit-style position notation (e.g. 2×14) in the app, the gear overlay, and the iOS Live Activity. Set your chainring sizes per trainer in the gear settings. - SRAM style shifting: when you click shift up & down at the same time, the front chainring switches From 7978a12950c9059f2679073cc53bf31174242e2a Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 20:31:23 +0200 Subject: [PATCH 101/106] feat(help): link to the bikecontrol.app setup guide for the controller + app Adds a "Use {controller} with {app}" link that opens the matching bikecontrol.app/use--with-/ how-to page: - as the first entry in the Help & Support dropdown (above Instruction Videos), using the connected controller + selected trainer app; - on the controller detail page, for that controller + the selected app. Each controller device and trainer app maps to its website slug (SupportedApp.helpSlug + a controller lookup in help_article.dart), with a generic "other-training-app" fallback when a combination has no dedicated page and no entry when the controller type has none. New localized string useControllerWithApp across all 6 languages. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/i10n/intl_de.arb | 1 + lib/i10n/intl_en.arb | 7 +++ lib/i10n/intl_es.arb | 1 + lib/i10n/intl_fr.arb | 1 + lib/i10n/intl_it.arb | 1 + lib/i10n/intl_pl.arb | 1 + lib/pages/controller_settings.dart | 14 +++++ lib/utils/help_article.dart | 64 +++++++++++++++++++++++ lib/utils/keymap/apps/biketerra.dart | 3 ++ lib/utils/keymap/apps/my_whoosh.dart | 3 ++ lib/utils/keymap/apps/rouvy.dart | 3 ++ lib/utils/keymap/apps/supported_app.dart | 4 ++ lib/utils/keymap/apps/training_peaks.dart | 3 ++ lib/utils/keymap/apps/zwift.dart | 3 ++ lib/widgets/ui/help_button.dart | 13 +++++ 15 files changed, 122 insertions(+) create mode 100644 lib/utils/help_article.dart diff --git a/lib/i10n/intl_de.arb b/lib/i10n/intl_de.arb index 4e7acf26..05a0eca6 100644 --- a/lib/i10n/intl_de.arb +++ b/lib/i10n/intl_de.arb @@ -1004,6 +1004,7 @@ "vsIntroFeedbackBody": "Wir freuen uns über dein Feedback und helfen dir jederzeit, deine Einrichtung perfekt abzustimmen.", "vsIntroSupportedTrainersCta": "Unterstützte Trainer ansehen", "vsIntroGotIt": "Verstanden", + "useControllerWithApp": "{controller} mit {app} verwenden", "frontShiftEnableLabel": "Virtueller Umwerfer", "frontShiftEnableDesc": "Fügt ein zweites Kettenblatt hinzu (2×-Antrieb). Zum Wechseln beide Schalthebel gleichzeitig drücken – wie bei SRAM AXS.", "frontShiftSmallRingLabel": "Kleines Kettenblatt (Zähne)", diff --git a/lib/i10n/intl_en.arb b/lib/i10n/intl_en.arb index 0b5e4e78..eb715dfa 100644 --- a/lib/i10n/intl_en.arb +++ b/lib/i10n/intl_en.arb @@ -1171,6 +1171,13 @@ "vsIntroFeedbackBody": "We love your feedback and are always happy to help get your setup dialed in just right.", "vsIntroSupportedTrainersCta": "See supported trainers", "vsIntroGotIt": "Got it", + "useControllerWithApp": "Use {controller} with {app}", + "@useControllerWithApp": { + "placeholders": { + "controller": {"type": "String"}, + "app": {"type": "String"} + } + }, "frontShiftEnableLabel": "Virtual front derailleur", "frontShiftEnableDesc": "Adds a second chainring (2× drivetrain). Press both shifters together to change ring, like SRAM AXS.", "frontShiftSmallRingLabel": "Small chainring (teeth)", diff --git a/lib/i10n/intl_es.arb b/lib/i10n/intl_es.arb index 69ef2374..2ce4827a 100644 --- a/lib/i10n/intl_es.arb +++ b/lib/i10n/intl_es.arb @@ -1004,6 +1004,7 @@ "vsIntroFeedbackBody": "Nos encantan tus comentarios y siempre estaremos encantados de ayudarte a dejar tu configuración perfecta.", "vsIntroSupportedTrainersCta": "Ver Smart Trainers compatibles", "vsIntroGotIt": "Entendido", + "useControllerWithApp": "Usar {controller} con {app}", "frontShiftEnableLabel": "Desviador delantero virtual", "frontShiftEnableDesc": "Añade un segundo plato (transmisión 2×). Pulsa ambos mandos a la vez para cambiar de plato, como en SRAM AXS.", "frontShiftSmallRingLabel": "Plato pequeño (dientes)", diff --git a/lib/i10n/intl_fr.arb b/lib/i10n/intl_fr.arb index 7e7f38c7..86ad219f 100644 --- a/lib/i10n/intl_fr.arb +++ b/lib/i10n/intl_fr.arb @@ -1005,6 +1005,7 @@ "vsIntroFeedbackBody": "Vos retours nous tiennent à cœur et nous sommes toujours ravis de vous aider à régler votre configuration aux petits oignons.", "vsIntroSupportedTrainersCta": "Voir les Smart Trainers compatibles", "vsIntroGotIt": "J'ai compris", + "useControllerWithApp": "Utiliser {controller} avec {app}", "frontShiftEnableLabel": "Dérailleur avant virtuel", "frontShiftEnableDesc": "Ajoute un second plateau (transmission 2×). Appuyez sur les deux manettes en même temps pour changer de plateau, comme sur SRAM AXS.", "frontShiftSmallRingLabel": "Petit plateau (dents)", diff --git a/lib/i10n/intl_it.arb b/lib/i10n/intl_it.arb index 4998ea2c..14c279f5 100644 --- a/lib/i10n/intl_it.arb +++ b/lib/i10n/intl_it.arb @@ -1004,6 +1004,7 @@ "vsIntroFeedbackBody": "Adoriamo i tuoi feedback e siamo sempre felici di aiutarti a configurare tutto al meglio.", "vsIntroSupportedTrainersCta": "Vedi gli Smart Trainer supportati", "vsIntroGotIt": "Ho capito", + "useControllerWithApp": "Usa {controller} con {app}", "frontShiftEnableLabel": "Deragliatore anteriore virtuale", "frontShiftEnableDesc": "Aggiunge una seconda corona (trasmissione 2×). Premi entrambe le leve insieme per cambiare corona, come su SRAM AXS.", "frontShiftSmallRingLabel": "Corona piccola (denti)", diff --git a/lib/i10n/intl_pl.arb b/lib/i10n/intl_pl.arb index bf8e14a5..8a6a067e 100644 --- a/lib/i10n/intl_pl.arb +++ b/lib/i10n/intl_pl.arb @@ -1004,6 +1004,7 @@ "vsIntroFeedbackBody": "Uwielbiamy Twoją opinię i zawsze chętnie pomożemy idealnie skonfigurować Twój sprzęt.", "vsIntroSupportedTrainersCta": "Zobacz obsługiwane trenażery", "vsIntroGotIt": "Rozumiem", + "useControllerWithApp": "Użyj {controller} z {app}", "frontShiftEnableLabel": "Wirtualna przerzutka przednia", "frontShiftEnableDesc": "Dodaje drugą tarczę (napęd 2×). Aby zmienić tarczę, naciśnij obie manetki jednocześnie – jak w SRAM AXS.", "frontShiftSmallRingLabel": "Mała tarcza (zęby)", diff --git a/lib/pages/controller_settings.dart b/lib/pages/controller_settings.dart index 4d651d4d..410f1299 100644 --- a/lib/pages/controller_settings.dart +++ b/lib/pages/controller_settings.dart @@ -2,6 +2,7 @@ import 'package:bike_control/bluetooth/devices/base_device.dart'; import 'package:bike_control/gen/l10n.dart'; import 'package:bike_control/pages/customize.dart'; import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/help_article.dart'; import 'package:bike_control/utils/iap/iap_manager.dart'; import 'package:bike_control/utils/keymap/keymap.dart'; import 'package:bike_control/widgets/device_script_drawer.dart'; @@ -10,6 +11,7 @@ import 'package:bike_control/widgets/ui/pro_badge.dart'; import 'package:bike_control/widgets/ui/small_progress_indicator.dart'; import 'package:bike_control/widgets/ui/trainer_label.dart'; import 'package:shadcn_flutter/shadcn_flutter.dart'; +import 'package:url_launcher/url_launcher_string.dart'; class ControllerSettingsPage extends StatefulWidget { final BaseDevice device; @@ -26,6 +28,7 @@ class _ControllerSettingsPageState extends State { final device = widget.device; final trainerApp = core.settings.getTrainerApp(); final keymap = core.actionHandler.supportedApp?.keymap; + final helpArticle = helpArticleFor(context, controller: device, app: trainerApp); return Scaffold( headers: [ @@ -61,6 +64,17 @@ class _ControllerSettingsPageState extends State { children: [ // Device card _buildDeviceCard(device), + + // How-to-connect guide for this controller + the selected app + if (helpArticle != null) ...[ + const Gap(12), + _buildActionButton( + icon: LucideIcons.bookOpen, + label: helpArticle.label, + onTap: () => launchUrlString(helpArticle.url), + trailing: Icon(LucideIcons.externalLink, size: 16), + ), + ], const Gap(24), // Button mapping diff --git a/lib/utils/help_article.dart b/lib/utils/help_article.dart new file mode 100644 index 00000000..a60e0b00 --- /dev/null +++ b/lib/utils/help_article.dart @@ -0,0 +1,64 @@ +import 'package:bike_control/bluetooth/devices/base_device.dart'; +import 'package:bike_control/bluetooth/devices/cycplus/cycplus_bc2.dart'; +import 'package:bike_control/bluetooth/devices/elite/elite_square.dart'; +import 'package:bike_control/bluetooth/devices/elite/elite_sterzo.dart'; +import 'package:bike_control/bluetooth/devices/gamepad/gamepad_device.dart'; +import 'package:bike_control/bluetooth/devices/hid/hid_device.dart'; +import 'package:bike_control/bluetooth/devices/shimano/shimano_di2.dart'; +import 'package:bike_control/bluetooth/devices/sram/sram_axs.dart'; +import 'package:bike_control/bluetooth/devices/thinkrider/thinkrider_vs200.dart'; +import 'package:bike_control/bluetooth/devices/wahoo/wahoo_kickr_bike_shift.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_click.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_clickv2.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_play.dart'; +import 'package:bike_control/bluetooth/devices/zwift/zwift_ride.dart'; +import 'package:bike_control/gen/l10n.dart'; +import 'package:bike_control/utils/keymap/apps/supported_app.dart'; +import 'package:flutter/widgets.dart'; + +/// A link to a bikecontrol.app how-to article for a controller + trainer app. +class HelpArticle { + const HelpArticle({required this.url, required this.label}); + final String url; + final String label; +} + +/// The how-to-connect article for [controller] + the active trainer [app], or +/// null when [controller] is null or has no dedicated page (so callers can hide +/// the entry). The trainer app falls back to the generic "other-training-app" +/// page when [app] is null or has no page of its own. +HelpArticle? helpArticleFor( + BuildContext context, { + required BaseDevice? controller, + required SupportedApp? app, +}) { + if (controller == null) return null; + final ctrl = _controllerArticle(controller); + if (ctrl == null) return null; + final appSlug = app?.helpSlug ?? 'other-training-app'; + final appName = app?.name ?? 'your trainer app'; + return HelpArticle( + url: 'https://bikecontrol.app/use-${ctrl.slug}-with-$appSlug/', + label: AppLocalizations.of(context).useControllerWithApp(ctrl.name, appName), + ); +} + +/// Maps a controller device to its bikecontrol.app slug + display name, or null +/// for device types without a dedicated page (e.g. gyroscope steering, a smart +/// trainer proxy). `ZwiftClickV2 extends ZwiftRide` — keep the V2 check first. +({String slug, String name})? _controllerArticle(BaseDevice device) { + if (device is ZwiftClickV2) return (slug: 'zwift-click-v2', name: 'Zwift Click V2'); + if (device is ZwiftClick) return (slug: 'zwift-click', name: 'Zwift Click'); + if (device is ZwiftPlay) return (slug: 'zwift-play', name: 'Zwift Play'); + if (device is ZwiftRide) return (slug: 'zwift-ride', name: 'Zwift Ride'); + if (device is ShimanoDi2) return (slug: 'shimano-di2', name: 'Shimano Di2'); + if (device is SramAxs) return (slug: 'sram-axs-etap', name: 'SRAM AXS'); + if (device is WahooKickrBikeShift) return (slug: 'wahoo-kickr-bike-shift', name: 'Wahoo KICKR Bike Shift'); + if (device is CycplusBc2) return (slug: 'cycplus-bc2-virtual-shifter', name: 'CYCPLUS BC2'); + if (device is EliteSquare) return (slug: 'elite-square-smart-frame', name: 'Elite Square'); + if (device is EliteSterzo) return (slug: 'elite-sterzo-smart', name: 'Elite Sterzo'); + if (device is ThinkRiderVs200) return (slug: 'thinkrider-vs200', name: 'ThinkRider VS200'); + if (device is GamepadDevice) return (slug: 'gamepads', name: 'Gamepad'); + if (device is HidDevice) return (slug: 'keyboard-input', name: 'Keyboard'); + return null; +} diff --git a/lib/utils/keymap/apps/biketerra.dart b/lib/utils/keymap/apps/biketerra.dart index d2af2933..892739d1 100644 --- a/lib/utils/keymap/apps/biketerra.dart +++ b/lib/utils/keymap/apps/biketerra.dart @@ -6,6 +6,9 @@ import '../buttons.dart'; import '../keymap.dart'; class Biketerra extends SupportedApp { + @override + String get helpSlug => 'biketerra'; + @override List<(AppConnectionMethod, ConnectionSupport)> get connections => [ (AppConnectionMethod.zwiftMdns, ConnectionSupport.supported), diff --git a/lib/utils/keymap/apps/my_whoosh.dart b/lib/utils/keymap/apps/my_whoosh.dart index 5ea1fadf..d4f3f63e 100644 --- a/lib/utils/keymap/apps/my_whoosh.dart +++ b/lib/utils/keymap/apps/my_whoosh.dart @@ -16,6 +16,9 @@ class MyWhoosh extends SupportedApp { @override String? get logoAsset => 'assets/mywhoosh.png'; + @override + String get helpSlug => 'mywhoosh'; + @override int get virtualGearAmount => 30; diff --git a/lib/utils/keymap/apps/rouvy.dart b/lib/utils/keymap/apps/rouvy.dart index 1288ba15..2403ab70 100644 --- a/lib/utils/keymap/apps/rouvy.dart +++ b/lib/utils/keymap/apps/rouvy.dart @@ -16,6 +16,9 @@ class Rouvy extends SupportedApp { @override String? get logoAsset => 'assets/rouvy.png'; + @override + String get helpSlug => 'rouvy'; + /// Maps Zwift Click V2 button actions to Rouvy-specific actions. /// See: https://support.rouvy.com/hc/de/articles/32452137189393-Virtuelles-Schalten @override diff --git a/lib/utils/keymap/apps/supported_app.dart b/lib/utils/keymap/apps/supported_app.dart index 47b48925..14d4dbb0 100644 --- a/lib/utils/keymap/apps/supported_app.dart +++ b/lib/utils/keymap/apps/supported_app.dart @@ -60,6 +60,10 @@ abstract class SupportedApp { /// Optional asset path for the trainer app logo (only for officially supported apps). String? get logoAsset => null; + /// Slug for the bikecontrol.app `use--with-` how-to article. + /// Apps without a dedicated page fall back to the generic guide. + String get helpSlug => 'other-training-app'; + /// Maps Zwift Click V2 actions to this app's corresponding actions. /// E.g. for Rouvy: {InGameAction.usePowerUp: InGameAction.pause, InGameAction.select: InGameAction.kudos} Map get inGameActionsMapping => const {}; diff --git a/lib/utils/keymap/apps/training_peaks.dart b/lib/utils/keymap/apps/training_peaks.dart index 51d3f016..474435d6 100644 --- a/lib/utils/keymap/apps/training_peaks.dart +++ b/lib/utils/keymap/apps/training_peaks.dart @@ -18,6 +18,9 @@ class TrainingPeaks extends SupportedApp { @override String? get logoAsset => 'assets/trainingpeaks.png'; + @override + String get helpSlug => 'trainingpeaks'; + @override List get defaultObpSupportedButtons => const [ 0x01, // Shift Up diff --git a/lib/utils/keymap/apps/zwift.dart b/lib/utils/keymap/apps/zwift.dart index 9bd79b9d..c5247772 100644 --- a/lib/utils/keymap/apps/zwift.dart +++ b/lib/utils/keymap/apps/zwift.dart @@ -6,6 +6,9 @@ import 'package:flutter/services.dart'; import '../keymap.dart'; class Zwift extends SupportedApp { + @override + String get helpSlug => 'zwift'; + @override List<(AppConnectionMethod, ConnectionSupport)> get connections => [ (AppConnectionMethod.zwiftMdns, ConnectionSupport.supported), diff --git a/lib/widgets/ui/help_button.dart b/lib/widgets/ui/help_button.dart index 78b354c5..5bce4a92 100644 --- a/lib/widgets/ui/help_button.dart +++ b/lib/widgets/ui/help_button.dart @@ -6,6 +6,7 @@ import 'package:bike_control/services/support_chat_models.dart'; import 'package:bike_control/services/support_chat_service.dart'; import 'package:bike_control/services/telemetry_snapshot.dart'; import 'package:bike_control/utils/core.dart'; +import 'package:bike_control/utils/help_article.dart'; import 'package:bike_control/utils/i18n_extension.dart'; import 'package:bike_control/widgets/menu.dart'; import 'package:bike_control/widgets/ui/colored_title.dart'; @@ -69,11 +70,23 @@ class _HelpButtonState extends State { builder: (context) { return Button( onPressed: () { + final controllers = core.connection.controllerDevices; + final article = helpArticleFor( + context, + controller: controllers.isEmpty ? null : controllers.first, + app: core.settings.getTrainerApp(), + ); showDropdown( context: context, builder: (c) => DropdownMenu( children: [ MenuLabel(child: Text(context.i18n.instructions)), + if (article != null) + MenuButton( + leading: Icon(Icons.menu_book_outlined), + child: Text(article.label), + onPressed: (c) => launchUrlString(article.url), + ), MenuButton( leading: Icon(Icons.ondemand_video), child: const Text('Instruction Videos'), From 71d04dc0ca488d93752b7e45438b5bfa23cdb4f5 Mon Sep 17 00:00:00 2001 From: Jonas Bark Date: Fri, 26 Jun 2026 20:31:23 +0200 Subject: [PATCH 102/106] test(screenshots): refresh Customization goldens for the setup-guide link Co-Authored-By: Claude Opus 4.8 (1M context) --- .../de/customization-android-1320x2868.png | Bin 262873 -> 271906 bytes .../customization-androidTablet-3840x2400.png | Bin 336995 -> 336044 bytes .../de/customization-desktop-2560x1600.png | Bin 183828 -> 191820 bytes .../de/customization-iPad-2752x2064.png | Bin 282279 -> 280353 bytes .../de/customization-iPhone-1242x2688.png | Bin 230142 -> 235521 bytes .../de/customization-noFrame-1100x2390.png | Bin 174548 -> 180862 bytes .../en/customization-android-1320x2868.png | Bin 247483 -> 252317 bytes .../customization-androidTablet-3840x2400.png | Bin 313925 -> 328775 bytes .../en/customization-desktop-2560x1600.png | Bin 176877 -> 187791 bytes .../en/customization-iPad-2752x2064.png | Bin 270213 -> 278506 bytes .../en/customization-iPhone-1242x2688.png | Bin 228136 -> 241139 bytes .../en/customization-noFrame-1100x2390.png | Bin 162797 -> 165103 bytes .../es/customization-android-1320x2868.png | Bin 266505 -> 271189 bytes .../customization-androidTablet-3840x2400.png | Bin 337324 -> 328383 bytes .../es/customization-desktop-2560x1600.png | Bin 179773 -> 188713 bytes .../es/customization-iPad-2752x2064.png | Bin 285079 -> 286227 bytes .../es/customization-iPhone-1242x2688.png | Bin 236882 -> 244355 bytes .../es/customization-noFrame-1100x2390.png | Bin 169342 -> 177274 bytes .../fr/customization-android-1320x2868.png | Bin 269287 -> 285999 bytes .../customization-androidTablet-3840x2400.png | Bin 338811 -> 334888 bytes .../fr/customization-desktop-2560x1600.png | Bin 189156 -> 199346 bytes .../fr/customization-iPad-2752x2064.png | Bin 292499 -> 294247 bytes .../fr/customization-iPhone-1242x2688.png | Bin 240218 -> 249352 bytes .../fr/customization-noFrame-1100x2390.png | Bin 168092 -> 174514 bytes .../it/customization-android-1320x2868.png | Bin 272906 -> 281498 bytes .../customization-androidTablet-3840x2400.png | Bin 346416 -> 342025 bytes .../it/customization-desktop-2560x1600.png | Bin 191138 -> 197327 bytes .../it/customization-iPad-2752x2064.png | Bin 296805 -> 295962 bytes .../it/customization-iPhone-1242x2688.png | Bin 241736 -> 248420 bytes .../it/customization-noFrame-1100x2390.png | Bin 171279 -> 181174 bytes .../pl/customization-android-1320x2868.png | Bin 287420 -> 306019 bytes .../customization-androidTablet-3840x2400.png | Bin 361488 -> 358567 bytes .../pl/customization-desktop-2560x1600.png | Bin 192540 -> 198673 bytes .../pl/customization-iPad-2752x2064.png | Bin 310943 -> 305191 bytes .../pl/customization-iPhone-1242x2688.png | Bin 255662 -> 266023 bytes .../pl/customization-noFrame-1100x2390.png | Bin 183458 -> 186075 bytes 36 files changed, 0 insertions(+), 0 deletions(-) diff --git a/screenshots/de/customization-android-1320x2868.png b/screenshots/de/customization-android-1320x2868.png index 48411d1d8d766bc5fa36e7f198d7e880aa75b65b..b69269d989234f0134f8c45210a3652e741c1caf 100644 GIT binary patch delta 176368 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%0D`-uJc)j3UVAe+{iR%$PIQ@HB&n)j)mG?9#{(V> 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 diff --git a/screenshots/de/customization-androidTablet-3840x2400.png b/screenshots/de/customization-androidTablet-3840x2400.png index 63ccc08ca8444faa1e5dbc933cbb7d1c83612f67..355a9fd2808dd2ed9082f0623c321d3965ed5ad7 100644 GIT binary patch delta 253045 zcmagG2|Uz!{69WrtKAAIqJ)j2!;zdh+odE)$dPM`BzNv}eC)R6CW#552stO@Hbyzd z5mT;lPwrzd24gU0=KmgLcfbGd{(isDuR|$%etTXb*nSHh&oLq9;Lr|IfRHg$=p&xo)}r$)*tc^VsDf;W^$bbtrYJpyDmf zpZ450Jtn#J=jCGtZ`o#ESL+Vu%LGBE1hhL^R9fQH5a_}PVh7z%ecDe=)xP3kOA03p zT$jyGt70;9&lcQ-8TY&?WPJoK|Q6Qd)_k`DC}DLu2hzAy9r&(3qR8xm->Oa!d9kCCsh?czDOz4lkzi>4^N39{(wE}ru*)&#_0$ix%> zm#w_t-Vi2Ia^{iHPrHx){6GFBE^mE*`rKM}pfBUt1=ZcTNBMCYXKv>Q;h9>X^#lcw=rZN8#>&|8{%H+@!Gq`cHR_jPgwW z_o0n+-4-@}`ZiPlD8oV$#X2z$d-zJK9xPhW3OqvqZhLnKCkD&QRjSzk@5P@PYvWvV z9Ks#tuV+d|_@iqbRR8_!@5X`8uE1Rp?ea6#2O2;L?LOb@6q=oSN7-}Rfd2lzfo)?_ zl!nLn+v)PvO>SzxMBGOKUMJPF+lE5lwx6SrOWXZN$cSoPj<(6=plOZQE;pPbg%tcB zx^Vox4*1L4jy~ziH$u)&+~E60#Q(prkTE~)-p7d$uCTeNSf(cGYbf&?(M^iH!1v^N^)dO?a+rImT zBI?oZM_I_0d%$(G|I>9}nJDfuHR{Q|{qOU9my(g8Mfoe(2}{u@6o2}+0OW;TyN|NF z?S6DtxGeP`OHH%eUdj&OAyG2!qd5hf`rG!t9Ev2xT@{@_bP~U<6AqS6;&jSWe`Uea zchCB{Z0r7eD-`NF((y!$4_9#i}gUdR}&T|APmY0hasNqQx+cKUB%LL#F)>Tstfr$Q{y$u?|X zMEiN`9N|iol$z@XcFOoqTOLsvoQ=ruwl!d3`x}<*x!FC}1la1fZ3V#-fPAL4i(ASr zZMd_+n0FS4Z1ta`fxm47r&ZdBTD7gT@Wt;2_UreXIDy`o?`(?x$KsIZT4iW-%Qpk8 z^@~-1M2|lVHk15&5x4Wk?-MJH&Abu%XSg$NiBm@7ceY_OiEG!?)s=VecbahT=Znt^ zbLypj+ztD}DdLc-gVNI@sKJKpw_{W3K3MR6dHM1yI*w{)1Iu3%q(spIKh_Bj4Sm;c zYXf;YOJ0p>ZS0dS)piA6kCprp8O!L8qtm{;=wFRX0_UQz&gEp|VJ?2>E8ls%OC&|N z;3@P2%YwNwCE%=2irg2POpDW{!Ir1dr(v+GAGVR#b8SHkrj>&z!m_+o?LE-vK7vO|PV!xh7@>1J=ykBjI)}T_nx_85S~|&m`Rh

    #4Ab0?q>V9u<*60; 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

    Dp=hyB;WWk0rYA`w`}7d6rVuR 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 AbN~PV delta 255217 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

    M=L`G{bzR#k|kdSeVucKXgC?PfXf# zF9`&l+?G`On<4>@lMW9vYyDI^TL(&+4x|X6v2XJ8#eDH^bj^7?_>>>oglu+0vunD# zy1h#X7s(WUGE=$I*?hj|+fZp%od;wqvh$^wLD3=sS)1ofr>gjGe0&^XO{?w>sqcRc zqIfRDXFPu0(?T*Mey>1TRpi4O4slcORHTlG;9^=ra79q5q1$6dfM84ihyD$dId}@7gqH|S7khMtjh3h zP4jNu#T{5>Ba5$rt^vlfSTeam06|JcCzRyzNcxc}f7)>~J-u<5zp5?ro`ueDb{F3{+7cdai%01<#>-&C(?)eA(^PgXQ zYdl%iD$u*$c9I`!D6U4YKqvZEjVGl^XA`enyLLdiCK$4;qR=zalrCjT?FkAwFb~z) zZ)b+z-;MoVRHY(!OE{KD_1J*HN{EzxiK^CiJmXg1=v-ns+|&6}2Gc5FK4KO`f`J#^ zY_x8soH%nm}%tFQSri+a)&i#177AfwUfI97dL8DnT@EB#{29{?{<)fu?fDQ2C~ zK$;_zdyl=E{IJ1@J1Q$aFX7ntg)53Q#`z*ECVFv5OXQ>>uwM#n1@`o)OwRf_PwqW* z84z?Gl@Sg{c;tE7HHE79N^T4JfTTtb1TbrU$-OK7z0(zta?SxM=Ss=WM2VP~bUy>I zwbIO1lUZn;gjoZ^PBhE74HRIk= zoifMpHM!!O4;(HZ^!q7HgYQ(c0U;ZnBH{e}d)*aFiPsth=}LnI#_{X2ev1x}CDWkK zbk18)k+_rJj!B<(X<9vO4!^W!ZJ)|nQIQSNV=gVML<#Do-KPHf6{Sq>A&(w;5(MCf zBMHG2IbD90O{JvMe~CRx3n53l^q`N8-ww{0FRt`qR!JcXrl`8=0!I=O5*kKK4ZEJJ zR7_F3pjzt)k_w1%SP3#HI)k~oQ2njNn3XAMf-{Ntl}NNPm7xbc2dck)zL~QY2+JEn zc0K3@Wd?eBv+(fd?hIYY7dLI5uq~zhLw8wuSWpnCf>z3^9=58}xCd}~65w*BbQNYK z@R1A9Hv+{S&L1y~k`@KNKc!1mHa_YmBwS8VSA9pV&JAz2;xc`Lk_|8uKazDzTosfI z1OTiEP_Zy6yMTn6VGvY?gXdc)YgK308K0 zsVqXWMoHyShsJs5#piJ(3@bZ@X9iT;crDrmkEFfLH^mmxWiPxFe4;Yn#5n;;Q7!6- zSaWad)WDHFlMr#w682ji*0nEWqPI2OF=?qBy-XmXFqpyyV#24Ad%9)~3iD2mcS`%U z3#nFDuUh%fhc9l7s=uRnm;s*3se*Dl*}%bdK2 z`8=6F9p?@y5d73AHTydErk+R(GdP-=c zRWX9?p|=$wUWcK`z@aSShmdiP21Qg%++gxTtaF#9<;{APz<}v&!joY3$o6=zvFE^v z`OJN5o%o~^i0qH|m!b~(7E(`K6`dS&?~c?#Y;-OarLhu6WN#$Ah&n$F749xgNlu<% zh1QLTbZV@gRh41aVqZ_ySkBEr+jio9DTYP;g1(F?qPqi>#A%CNg4Kh_Yl!($u2l=g z)X)Eb3k_wZ@=|HY{u?STK)wV9DecQciIlFy`i*YjF-9tIR!yPbz&T8gaaHpJLFH_H zBuMDBuuKCgzmZDzpJ*41wq#C(%TFELQ(+>-wU02|1653|fO9i@6(UFiYOr<~r0s9` z@y3EQXGbtw_@}l(?9fY)e7Evn2p`M07|4?vM7y|x^i^hwqp_;Bb(5Wl@vPUV#IX)# zn39*HamLR)Qt;^I=aaVw)(6HeLqmUqvdCXx?+3GxNaPgN!J^y+h0hjiiQ?tmTx?Ju zbH~#Q2XTYmc$@wUL#`o96Mwk`ob9H6r0`p;z0!jp<>25HiHxCdjEW^n8V`OuTb80o zDz|5?ZP1y%6R&s{xmv-D0&Hxl%owUYDXfJRiT3F~Q97D$*8)zdpa~3$Cc%pA+r7Vl zR5=>CS|hQXT@2#Pw^P&xlJf8Uc1Q&~5Z2c%m#wuBBN(LmvID#DbtD1THeR;yVQ+f2 z`35T!r|-|t71BWX>O(~OHz!v(Od>(LfV`Bp58!_w?;M!2LiABTpL7jwJMe3!ob zVp~`?%4BHE4>cb>yh zomI0S*AV`oUv^`7FK03;|K6pI!Az@G3Olas?{sULlJK>O` z+?c!=+t}jYOK8D&P{72bU^KICQT;T&1|%3JT2h>cCm1J%klypVVmqg6J)9t530S3o z(V?L#sSd#X9^R>PZtqFqrp(@8zwIIkxS*8mp!?ze+$tKSO;{_&Q>h+f&_5Ydbqp4L zQ&h%^R*x0OL><}c*<7E`6@WcD>*!T4mM;?BoYY&YYdSM z4C$r(Mm6W;D@ghFMuVq1@^g8H`mun8f|zDoY|TsYo)K0Eo1X!p`v3ft6|E#*R7VwQ z@axI#rW(~V5%`4x89&_1off<<@NYw^7-dhW<8?JI8s5~j_q2Aw$xp7cd*ae7izwhgV#qprZa}7^C{svu_t&TQ z?=fii>-{^ge$(jaN*xA(FmTOPYqS5O;%$K9;ZEA_Js>p@g7!AFn`&#jW0eE5?PvwxA%!BDhQm2dNrVhHD|-h2?X>AP4$uN?R5 zVV#*n0B%l5)_)aaMFCk2iT&4@n-xRMi<`o$%PiAVbZI~iwAY$@Hj^YHjUlqh)2}7~o3u%#rrNAnVY|8nJ$fY+Z|R zf!csAQUp!Tc+f|z&I39X4mk{}GHPZs84LMYARP8%j;SOby;P=e>GSQeGd$~@w{vdK zVpKT4xAU_u0W}6{oD%0$c4t&il1U(1V4pkMG7ioW^IWc}W%~qnMT0mN`io8geY-wpIXYwRjQsT*z1*4P8 z{>%7vDtfWXTZz(UIl+|N)E#ph&6orvVr)WD`o+yu(zN?TWIvpXb>uzqF+vKr?k?xq z@tXXx#=aG#6F<+-mY8Kg*z^wP(S{EjMfa+xFZ^%oh0m=Kdf`uq%z#s0_h=}K^W=fyfK&a{xeCP-@fayDhR0CsiIyIGl3DPTuy z?kSG6j=5B3h+ht0xR(G*r>QjM>2ofOzgQ*{!8-SNyx%gsC8vc&dR(nro5Ubt?NFBU z+!*)oDLY_#WZz?>cjWBnn;&V<6}>GA%aDXu|&KObJim zg@=e4BKdHG1I=WDwe{vwRRnsG#9SPI@FDvdB`~j9ruYp~RcG(O*SDJ^1-t=0RDuKJo^B z=2}RW)U(*w-l5IjR>H7-$i(~HjB7V{mrJ1n{2fsqrjD3*gaS)LgE(lSIPh?@B~t#f(-%_FCUa{>T9uZy5=f>$w&8e8Le2xn(c06M zPUDA2W1g+Md_SqZE3$Vgz!~#aVFIiNO^u%=Ce94`Hdd6bJ#i?D5{b92v=x~|9S3o?A9PfqN4UZt{wJhLj$tOuQ(6N#P5qI+&Il(z{%L78A|g++x}x$?;6imeOYKJSmWGd zCmdX8;6MjOAos;<%p?QJNzAj1#tcTTysz7F(S#c`9Gn54O(iL!*6ur^*5l?D7bENN zwI`jc?=ij(#GX{2N(L#+nbEXgQF&=FP-mV?Z^U z_t%ARG0BL7ICOLAq)1+CAgL}U9gVa%om+z$MScVohqln&;~fnR#x9TDuaAsmt_&2b zy?!tV>W;r(LA#SY13Mo&eeztb!U{u|YN?ui4=ZW|FT!9KDleL+xkp#Ls}!F@N=Qf$ z7R2CDs5NilUmBSUmW+NfgM_MjP5%wHvr{x9=A$9%m`3MEWOr<=ndCmw_-xOQ7X<+S zkPIzYGkxf3Jy^jRBqqc8vAw{=(h_n-Y%MY(^{LOeCmQ%I6-)QUIL%54GGlz)VZxFg z0hPUJO^<<{D;bO1*tqXE70UyCdwfPvC6(y){Pg@ncup}w0^BK3!0El-t|b7G&W|f! z6__D{4z(=m(7Z_X8s9oD#Wevl*}t$8_WqiXxy_>uK?XYnXRM$oiX0rJ_vp3cH71SO z^n{38sIPmh$$ivjx4fW+yZZ&il0$4Ab)lf@sGt$i>Wo3ta?Ex>4J%OD(#YL~B9Iu>QR7~PNyEEiU_aR?0f8DM%e}1J zbAU<`@ko%qus3m_m)3SNwr(Q4psGwXJ4NCNhCNes@1rwu^?p|M$eJP#}%Qx*CKKfV+adx%N ztC=hX9i0x|Q;xaasEIC)p-EJ!);`etheqj3;%JE`|Nx|4qG~rBAr>tQYA>Su=7_CR4l5MmUWTcd#KH#_TJUkyt3eQvZhL|V-LGF&6`#Y z$;j(yczaJ(Iz@PlR))pQPo>;~{fs}vSn8Nx@dr8#w(< zNt*dJNJ^MV7GyRSRKd=vkMwgs(9vlsGUwpXz2qw`8XT-Ez!%vu1?h^~Hgqj!KRCtD z&&l-kQUlU?U}&hSf(laH&JMy}n1)d#5%h>^$Z~VkeZXdA%jV`;HusyE=k#GhF7q3< z8OsQUfASNXT^hww)o6uShW6knOg`79EBX3h!CrUApD^(x&NEQc67_+~iL#f!_}1g$ z-3Jxv4GTD2hPNP4NNFr%P;P=rt%CS?2a7xX#P;{~_Hr<(mh^InOk$Fn6>GL%*@3~n zW+rTP_QxhCXHd^GzVz~+{aj%VkQfF5v!mEhh=gY#Xb`j!%)`&$<)^turJ|Q(m;^yO zsgxnKSM29XVHZ*XyilnJM>2kciNtrEdT~E*V1fDt27AN-&i0`QI5i8!4Xvv~QaDg@ zw0)J_E_|(&WHNr)^VoSyX(K=^3V+%i>zVs^wr%g1_j>U+a(5?o8-pm3dwe@2-|A@V zsdXanJNTs?K3>v38+paWs5zDGLBKaS|IhmF$6nIg_r8zcGjnPSBOLzm3@k{EwIzkl zpZ(l^S(*Cqf@SLF8Nk&4bG_6BICDFn_g#8AOv&>H5&F;V|IBxdBmUYa`3H7|U?%TW zSo&8Y-Z6dSnOMS`J3^wmZ;_O7H_f=vQ*qbhLN90tX~pjv`w0;*|JVjIV7xB|-kB5< z!MhT$pjy$yj`J3x>ZNzWIv(GkrC&`x729(W3jd$*Vm6GdoM}mSL{H~?|rYg zXW*eHV(a~nyX`HS(>(lQ*L)xU9cV9VD0<$YpvkC|??JMv<_VGCe%9I+2yE|pAg8O{ zmQVoOgTamz-YIIDk0tO3NEEfL;2o#kPCrqLIDf$;(#>}o&%HhT-S)C>m$w54O>zf> z3=E`=3!OucvDR<&&gw1S)vQU~+TViTHQ&CZ9TN>!(*2*;5n!DnTbT9U^H>7#5+7M+ zxy(|q2x$e2@K?Q7X1`vAdfwa)<2feLVpRH!2>kPpD^Y#R%j{mxrh}6 z-b-lN3w1?DCRmM~y1U)t`;Gl&cMS$Jg5)%j62o-OZUW;Rr_CvhDCR*dznc{dR^&Aii5rw%h6OY`4KtBd^Kqva|2E zTV9@Q0}cl&#=fU})IPuY&!+LI9Ph=#;p}fvrGx>Qqu%vHm8q{2iP|T8vN1lJk*z?6OTl)M_?+PBVqVy7(?RKBPeiy%4uKmq@`2!2tTaBQa z3t>$?&&AXv55u1Li6$EAkmZD#l$UpkY#I(4d1c3yDE{c+awCiC8pu6LgFD=o?~Xk+ zh(^Qx0lY1o$;ioncxC2BLQnR`pzP9X-xyCp8 zPbIGkdtGTLY=Nza20$GJLfOVUNLHoKhb^`{F|q@?0AQ;+Bjft+9!G$ewF6*>?IpA* z^2*ZbL|KEv#J^TtjqbG4fNi=zC%gol@e|>kUR55hKe%R+W+AUQ+Fw?}_!$Z}<6qmVCm-=e<&p$t$ zNfPTF89CI|r4>=zva)iWPuWjNJ9RFC!HDnu@`a06wjkml?_l#tg~JhAjkj#B4tw(l zC^%$t` zvmURlD7|-8hil*CT4jSlH8nLW8yj&UAq9nzlX$J`KlU*w;mi-*2-G&x1umo*#HI?J z*&0*s54h~L2CXSt2x!qTueY~U{?XTR))r>penFEG#_o0;xwAW8wk}CEPF3rrlm-Cf zQ<60{njT(WX3s^=cYXk~&Q7w30ui?FrWA_iHwJRD)icTbv-N{IfvW)r4jgDnzGzM` zMG-%zGSmf^Vv;Na8-!nP^l560dGsGFbwGRC*E_qoKoG49t8|!y!^x?T0HT$pT`Gz> zU&MZ^n@#ec80wweuY$5S*9n+LO0|aI@lou7Ykv^Q!C0E#yR;K+2dGXU72Odky!zCuQjoFI9vWJ`Tr1VIRE71hAW0n2BrN3nTj4P=v+Em6o2P_? zRw)6{7=q;FN|{cQdn?Add%_Erc+Z&J+0wrbVm6Xifmv4)x7$$zxYNBrLIfB3f%^`na z59DgLA{5NBj=sJG~oa zYnFA2q(eR%1(u!GtGISkmj+(JfE8WZpbNsfm$PKssmQbca13h$Pp#r^3J1?_5gjy0 z#@Id;)&P5DecwaLCP*r>a^_>%&G~{5Zp#4M;g2Z2jb*yLABen1u?%XNO7}CpTy6BP zZtuYi{TiEnf35GAqf>AHdwS2U1%!TRWsPucE6ss>HrvhH`#}! z;=~O!ijgo>W~;ZpvC$k8xPB94b;#3F*mOAJR7Ec(-Ao}+xxO$(37X!d&#DIVPKMC28qnI?6=au1)0j%U>mV-^tfk-b;W?(f`AjXbsPK|tjfX8GfH|KF5^jG6b5E6m?VltQFh(e({jeaek)5QU8$1I} z7M8tHhb1JsWV)dtkc}x5V{}5k^$G`9vtl+3cfNN)QgA-FLXyxCdGn1gZ~H->W_Vcl z;IWPMf+!Y(_GYzOJ35N1skc59)(}t$xWJP17Wz#lntBZ^QS=1am1%cR*;B?Oxb}h8 z7!@&?k`j1FC3t7>fOYWB+=qU8i3&Ta1=68_)f#!P#ilrsvpT=hH}i=X(PoFeF}|8z zm(XVJ`eQzmM8c3Y{H+Qm#f71OBsZIKuk#e67-~c>0LA!#*$;Ei4`(hfEyakW`&1qq zfu<9b33FLkqdxa6MoUY}HltK5{pJUfS0H?06-FNa zg`~J#eF@`-8~2%vvQ)o`OvD7NjSn?!Qm?^(CSvwK-Aaahy$Ba6cz$Z_R0zwt4zTRt zSxRf3Y~?)J18V?JKBqRTB)XF3v%&_Z7Ml2Mn*hdJ4y#YHeZ`-(*9f>osEY(-$N1-`%?nyQnfQI$T+$qz~$F|{!1el-GTkq z*40fUI~0XuX?8BEs(f%v-Ai0gYIpJ}4JGQF+-w@(Sbsl1meL(eXcSc8;NaM~GuU;i zt@Qu#^&L=6WnJ5GY%_L75tU{~ML>tM2L)*=(o04eKx(Ad zP?RbqB0}h)Nq_(WLI^GJ?@Q5n-_Q5Y(zRUPFbrVu%y zs}~lPkig6@d3Ou_nx z6sM-CY7h4ZkJQX*TePI_d-5cPEvKNs$KkAI8XDiJFz@>d?Aq0PxskieoKbZs<7G+4du4Xx50j*~^bWj^$TRh`Y(UXXjW3Z3(uXH%<0L!{^AqZ1MiNLjXQQ}Ml= zzq^P|EZj|5*XtL|p9e(frbgQ6G0x=T%n_d5>i7(WUo9|JJ z0)L5(s1MQOhm~MR>I%h{pqAKmsy~q~nA{P$!4E%PX^Lhe_8%4s=(ztu(#tgvNj&I& z`t=?KFp-{DA5tPHx(|_qt1!4a)~d$R!O@9RWplYWK%kc4BFOlX0bkC^h@E& zmv9_t5P-3z6IheOtvfl6?d=9Ig(p#gK_^3)n16hWfC3+c9cPu5FI~d*KF9$C$cw-k zYVfF}RIT3X>Qv`fIWD}@3wL_t+RKA+A)T#lpY=DheF3)YEb0uO4d0`nu^nS|PnNl+ z)eBJ#jj<``mlo@9yBPf|BVU65#K_Q)0u6uX3BsIqP1M1S%vyBhr|hYPL-OE^XjXqQ zIXpjLo&&mH%Q`DFGn_g5`7)fZrR;WDztv5En4cP}D|F#k1A_>#nF63S8Yt#4YhazE z3YZb=Y55^#{_0A+j~~|)>3w}MNdJHiZ|N;@z!czUrG_9qhi3R}b|f#hZyuGn&{4)0 z0f;K1z)gDc$mVFs!0xk4p`@=4sj90W*$goX54_sbVeFamjTync} zfW%hv7Q+wtrYV)F2;xunOwQ-7dnj$8&4YTtE^IeGE-ut3%b%YKt7~Z34Tfr<{*2`I z^R2C|aLC+VY-S7yAbnF~eh8f6!Ok`(G(2a#av8}{+`k`nwqPRT%kQZ1-}#D6*BL3g zHO{Zz+94QWu>JQhjg5`Fg2Q`dm81+wiuFa6k9HB}<~%*_TAC-#Mr!54J3DrJni}7} zE%!6YoRUGyr&b@0gOG2dTmI>NMx0Q|6Zg$(cW4DtD*YdiB^Z&oYieq2Xc5wsHSfd# zg74@Uz}#0+;T-M)t8CuTilBi{jdh2SMCE+N3*)hgdNEBQq;O_1(s8udC4mDn7x&9T z2gFP^Jw6mII@lsCXMmhg-;L!={1L7otG&4Zst7vH4zuHFS?Q~licrGA63Tf|B|RT0n9Xd;!O3aMNJ$BxS}(;|$n1Tg zd82KaL*Z=F`TA0ItB&-0XWEbj#TR6nxo_;fJw`L1BT_6|105GQe(`WFUr(wO3D7dk z>@PPq3EqG!Pds6rA|tSxc^M%|?;JFT)1rA$T zi!$*KJ!Cr_Z1&?p3L#FhdW#IB$;L_Fp`B-N)O#gP5q-FrMp{jo4!u1Zp7G#G&vG{B zw=!^(b53b(&IWVv_VRrDeM!}TOD_+;tQ2g}LQZGfMTbp`>sFK}bP%IK2cUB8I#D-| zi*y<9y`iu$NA7_HsqSZE!v~d(kkvxuAw1v$_@%C{&M-pCd1m5|d=M8P$y>cZqN7gXez+#xv~-*#QOID8v$1l zsIw`iP=$g@PqiuLwaQALUhA)b{2%r)`VYdTSA&l^B2Ga zPslPIvANNCoizzYtJZPh^y_V)SKc$06?M_ar8MeNxosS2vs7!~sz`0WsS}Wr?%JlH)A4)Vj!2nGK8wAy- z$+?5$p*V;`cTn`x4xngPxgc^F;1SdWcfgKm%3-$T4jPQjz+b> zROe&7B+^9%mNOV26j6a7_pY_Iyy-jduUYq)F>9Z0X*G4fr1C`Nu%Cl+j{dX7$YBt_ z$ML68&^Fz1v5|haQm*4%XD2Of*zH*a8?(WXL>&o^q={o=`IyC>C+?<(j~i~n%MT7i z@K1J83yonGjGY0L%i+ODH9edzi8M4wa;8@MUn^D*4|Y57(A{-&@XY)+F7T6%$;r## za&(ldc1>1ZDpcmgh{$uT&COg}l^m^IC!1+0 z_}R?R`}J7`tPFI-b&ZWcqrx@F3idSWS$iWutAH?Hw13XMrEno_a2VFO=9h)qbgTB3 zrVM&6guxC6_IE$tI@utJX`^EQAlU=6tqq8D5RuK$tqMx&i{cX|IEwT{uf$G;#WU2CK216yxl2fAmW}4UO&G7TAUIw5do%MoFu6p)}1g zM}fq^sd^Kd3C_7t4X&8&_m)E|9x$(N`_R0=xi9YTzp`gVvtiye%~um4tCrx|x%+jg zlOLTPv+j_kImVsB{nS6vbLhga z6eEQ7W)d$|?yI_9B+IhZwU#MHvNf0d$3@BiEIAtd6F~6(*qj5jw;(7SQ3_FrU1(2? zDsTM0K_6aC~S355Am)lU2r;{J}Y}Y@OtX{p^baSA(D#G#EUGHJ4 zHe^t7y91DV*5nuCjEoHMvPuNhBKh7rN%%H{Dj_#5%ir0=a|SD90*tme_+JBb>HFA- zU5Y0{eojv2VhU0qEkJ}6U(v~9J2o`5f`hd_hu zY=u<+a)d$#Z1KuwLj#v#U$g#1NX$9cHYSCcjYx23Ctp8ixA_3>W;Ku7kZwJHhZurSK+iEt`RDBD0 zIENr_fT_A$AG3K8zF>*Dja50a8Wioqs%7Mx(v8azZo8b3WE@m%t;AF|+R5@%dKDWRHYIzN?b|DV^P+p<(g$5wW)R zcABeGBqXJ!jfx@+b_pV`djbE6XBjxO??e?udolvSTsaCbb8$W0!tV=)(<}ywtF;BO zkg<6~)TP>#*VwhLulE&*hfo6fqjAEtI|{jZ! z3@z)2kfKeOFhs8nosAYuznu?9B63zR^dA7u}z;QT3x^~yYnf@pal<9CuU;(8+ zaBeF4>d{E2K2s=fdhmklFr5F1`{lX=Ie4ARXeUjQ9TB=S*Y29F?d8ix zN!O17Y^UCE`Fun{8EvfBpWHBHGTf4LEm$Wvq-%2e&yh>wY@Z`L*+|(AKw%O?T4u+q zh?F(vrgC`aBW_b4glhNPDVS{GZz!^cFj$D-YNa-c+#kITj6PxPKM}Lc{@<<>CSm>!#~e zS3!2~%Or3D1z?M#QTeCW9~y9nCxg*6gwc3UAsSyCeVgY%-PYcovHfCL=mymGoH_Hs zrd!#_6`%;4foMIXhr`B#VeRtp(9W_Ne#tJL)*I}lgXHu_)Y8vZc|W(tUBYcrpPxRb zoSvCcQ!sn>HMli*Qb!=*YN(8P{5UqD91Z3c<_HUBzf*?54q3Y~=W&ME{oS?l)}E%3 zPU5#tx=y3fyOx%UMbkUcV*#GqIC0nNXCbSEjN~%|4=I|~S{$u6A+wp5M+uQz6>W{? zSVjx~%w$ZXf#6o9CLT1dc(R!ur7v1K)U33!2FKC7pvHvw@s^^X-ASLd4*Oja-;dGvGXp&F+fCQ6Q!6bhYBTR;PEVCdk9b8!j;u8zFwTjMM=6VMkPbnrr( z9VH0@bsd}n*yIC#3cLIiC;cJ06pRSC#*h{h6ypJ6wX$xlmU%s(JO+0R-AXxSx)rQT zbdZ$~c{~ASfa)Y>UEy&*t%L#| zJzs;2{Lm}DZgCIzU)Hn-1G~vC01jOz&Sntt)7~^oYJo_> z+*kQUXlsX8>EIY3CD{w}Vx^&y5vKWKxTIIxEOvf2aU8#JlCy_Q!=*Vhu^p#B6wus; za9Bc3m~=^$pW6Y@bEUg>$w&(Q1(5Z`gl#zr4pqK(J3Mcp9wEoCsMwC1M_dDcEx=L? z>eJo)xVa!N%?Gnw<4B93mO$E+sHRWg>;h>y1mX7NT`Q}2Hxik~#MP3}Apm_3%@~B< zBVB{T(LImW7wkZB>XF!}C`AGML>QXxMDs8>!*U>rT4i^IW)H;h_K^_KswgyO=rZhs zpiz0R6^m54M;i)Eq zr_V(fc5ZZcZF6PTLIocrLj1&uT?E&09iSDS1(geUbxEK|*qgYxKNJ^GNYRwk;maRX zj{Yqwx&c`TfXj};;LsfW#ujUH^Gj_m32FT;+HNw@8qhLaADpG67fz z$Jn^BHCRhs-JwzM?$5v)x$0!cQIwMwI*~JT@WQWX77+YfQ&PZ_bY#J_p)ws5y||KL z;x84on}%yQk4Cl+-5X4ct*;%Xuvr~|ndR9VXl0orc6K6e4_rcH(1`5N$m;{SxqSqw zZn-c>E-gI#!)iAR&ZSbB%wYr+G4^r-^QeH-GM3(n7Mpzr9EF%sn(w7wfjPd+fr_X& zQY-WJ+bssypM2BiIQD!!^|mj zb6a`sBC{ptU$tC>=o_h{3Z@MZT`Vn&l5W_87l(lwl%M_2Vj4K{TLny@>MY4}7U7&p zeDK`uglf49D{7-NAH+4O#)tcr>i#!L$Wg(~!RFtnjhcDO(Y3mev&0sZD2Y1oMNU9k zNtcv9cSGvJ%e&@Bl|!Y9z6F+;V3B2(iyTKsO86-FsdUs&#n6Nam!e41-CJt=J|C3R z9eAy)w%);s-}KeOu@9}c}(QAkk#4CW|RmlqeY zE8rx{>qWzhL(AlQ`2O-|i9L$aws&J9FR#(MbLcM^6+aA0^YQI*F@0|A`W4wr_`_-3 z;qc2rv82_Qcg~PAh3QX2k|Qt{8M;9?*J5r+Rzz>dE(Co1sc8A;MT6Ilsm|3Zi_#qK zuEJ;%77+yFWZ>y1Y0^(7Vlav8a@tCah%xizm@O4ByPr_LjsO? z!Td{D;8W?Rm9$8Tn#WCYc~+jd@t%e2jKiVO4LNC%8!^AFUOJI-g9A+J-ToiUGMpok7xghEk%mlmxz#`awn~|8W#Ofm(7^pKA2lZ zI<9XWyLGgz?9z8G?2Tq0pP)C_kEtNa%I24p=)+KFKYG!tdfbq)suP-*fYu|e!~ET4 zmoBAY%_i)r{N5IT=k!A7eU`n;rFtFmTFl?YOFJns@@I_tp~ta5y`ZpeI0qk67T7yn-Msw$wLKR9w84h)12fX=E|I@?1V4v$e90`E60Kk?0-YbI69s)5zYqIDLNuJGx5%Cn3`Jq zY6pszIt#*U7+ac}vlhPW*)3dFdF{Y=66N1kYLR<9>r!qhD+9I8)**e75UKg+vJerb zd?w8HJDNpAEZ)i%y_Jxvf7826#m`73Ve@)5zp~CxcN<&3O;2j^>$+VsieoO@8mKSM zbGnaXisI4bH7W#FIxNqB-RvmglJSR@NwapW4DcbhnB)qr$Y!*R&4VK|>s8`ePevwz z6LOio22-?QNelfxn|2t3kkuA(5+I`{>Z-cyTMP}nEvOp)RN=@stjPT})xm3Ju0#dU z7-=H%+3Oc$9+j1aye@KY;+|JIo5L^HETxu`OjR+F5qz2n4VRKvVYC}UH|8|8)pNPe zl`M2g0#%u;z6qVUKZ}-MujrX3BC6Hh8~0*rZt8}&PY{G#&k0io9(THoFqoJn6_Fk( zi4x^dp4^Rws;{4$zSIjOfugKjz*%%o+~re{+6H4T9q1Cjd1Lv$H_ieT)5h8HxLP>h zv&ZG@Zo&6n2_amhr08v7&MgOmE~RxG#$bdmG)^OnhaOx@s+HdXVHvudU{GKpkzwW4 zRX5fz$ma=cXD%){11Ns#qyX24y6Y8Zm4eRg!>06IWgJ_vCdY}la()G`5NO6bAcZX) z*ca|kj;(92yNYMxfQk&}8T9QZyZxB(%K|8C-2e)q1UB}aPM1P>y1$HSZ;BL1TKDL{ ze%PbpQijhw#xApeULMOfE+DbjHFWR|C#mW{CGLj-7KeJXfhesXD}+%;iP9`MCv!u9 zKS{N&u4PA0>D5hsJB=M}T~E%fDDvkKF{iD@H`g++RM1j8wt!ZAytLIDVg2=zs&b(G zg6xj*oFlzB^g&!)z?cU3;*}7jRTe)FzrH$n0gU`WFU$|k^85446Z?kHG}q!O5vPji z%95>t9lxz;MquW9{k{}C499W>cs>?y2-g72SL`*Ai^?1`euLrDSn#cEgY%c9^yVa%p&Oq$Vn?J8c zyLbHb*F?cUWsG$QRj|^^-rn?1tHohHLn5tfdWhy)D~q$g6GVHI#$c|z%**&M(;_(L z8uG?O1d~6@182PQ(T(!`^YEWzuxHv7ikUwNV@&ObZ(3P(Ohc*J@1NhU1^@xbDzek* z5%)vrgZE(N=8IoBAAgmWbzQPJV{}7Ne7t?qie_EBcu*q_?QYZ=O8V(Ol79YYs56+% z`hI8l*9DD1w3<(+lFQo8yDzpu&o~1p!1b@s;s{7e#dtZ>li4PK`7+v|*3b9P-nfeq z)RWTcqY4ocyW3LXY?*@Q!5F1}^cf4?R2{WZ}C{Aa(= z?+>V5?75`&AL6(;gaOtsBlS9!ofW-teSLiqq5t;<`}%%~j7@u4{Nm#^phCz?{^t-8 zbfKziwkuFGe!73y=&GZGHH;(Ye~sf_u*6Y5R2ba<$2a8Uxu9j@71X2s_E{8_==fif z2ZofP<_;a}h6i-ZVAHCY%RYj`6KGBokutFyc~B;hFSy+G*4U9Sdr+(@6TTr zsFRBV)%qiWs!Y^`&cRm1f4|ex^u-@eTa;eXkMvx1t~@4RFTV6y^bbaafEJCW2qluY zU`%xrwc|ktK&QcfeU^2=`gpw9+3xe`E_r`tV~74H35=DdG@22aIFZbuaEq zuz+L#T0j{8$_i=|_@TjW%1{7^`S9o9Z%KRTFd zNN5uH*AOs^+W0eldrNHEy4gQY!teE0e!n#TD^f;JTV3>DUs$})x9ji#-p9r9@jDBD zG}E7Qg)wcr(7td}-2dnKR~!Cnv^_;Rwy*8hFV_HZll`Ce^7QOP^5Kh-%8m5x%|F^p zf6h)6yj;Heef}|+@8-6o;00Xw|KYD6%-WWWDBr(^_80x}KIxqtI4^nlPgs5DAFW4m zhO5@E**3<;R+SCW@cgAN2Pb6$qEI)*@w@dHepPw<&Av36d1v&#fQx63ale?%io#&> z`BpqHr^yrc_!ko5sAcN8SB4nNgWa zX7r@FjYFS5y%Syo$hGGc@L0i#iNP%@VYP4L=`=|w*tcEYjD88fyGSV}xnQ4tqZ3-c z=$FM`AcwO@3|Gmd33KuJEOvB%^-Xg=3`!c-oL)2DbVW}vJlp8xD`cqi2D&5gS^ zCw3kRmgfKK>(RM0Pu^OOX5IeHD&+EE`$nC8e3*x8j=;PT)$bE(LpIf>zu=RSmbRvT zQ)&;9py&v@&CvyGZU}18seo}F{C!10U?kTp4?cxyZk7JF+dEC-3VwgL^+@7Af6sNo z?yE7QSG8c|IZl7l2L4=ZPMz_uH;R~fa=D&r{nL)Cw40!{^1m!uyKHry%V=X_@cO^) zzx*NXy6tzx77CyOz#-!DFsG9b-cR$X@qh2rimo=iMyE;7HA2oEBB@bUg6sk1?jI0I z0<%xd3nqNvXqb7zFj02+mCV=P?H3=YmQI9G=dBf36GNJv9?|f8 zjBWfIGCM_qwGwk$3I`kwBLjX0`;iTOMT30k$qVy_E=iUChkwQtZo>EIVZB2`Ymzdt z<4yjaKVuepGUa9hCxe}USj=n_D*#o%=%-VqVghw^rZ+TGL`Q+f>pq{0m-0k}l1NC_a zDa*N6F>bvq3m=z}e4$KhYKoST!*nY5SX&yov`a-mK;wYQPy+=5=Np25EXPj~0YCfh z^mKuq;pnp5&7y>}W`bpgM>QApN6Q=nXFe~_{|y4W2)}iNHEJEz5|JTJf25Owqt(95 zSAxkpbbaY&Zj=p0b;0QDyamhEpBfFN{$_q%n#~)8OvkS7x6Rk<&0LNJ3}#ZQ)3uL8 zy?(tP8K!SJ9ZVh(h-$kPYF;rur#=BzmRmp z#V`sk(ec7!Vq#OfB~P7F#^dqV2p6N@@de* z{@w`j-qnURl<`C~#3=n9VtlHBx|E>}>e$}DgB9!^WEGBdyLFj&H0C{7Rn1lXRaUP zriEkEZd6P#kZBiqr&BBm-*B#;GQXO&BhO z&2WWcZqs4nv{ENoQ;Ly;-6sB%*)=#ms1h5Idv0kR_J)|5vlDGYFGf#Zgi4^d+WxXh zxiSAGQw>xpWt-Do}4-J)-dPTx$7C&>>T8F-Ags2Gb$6q6lpmBa&1Z$v}kC9 zxpC9zYgslm-|12U!{+O=fVHcOfT>zFm~c*05+5-p^lYuUKml&iZPCPF z45fVK`zmBcf)BK|F>3P|RlFFt_8imFY^dqoHMsPe4-X~~iDIlnwqb~qSgkqurXQa8 zq!^d`+7IdQtzN&`Vgpu1IZ?l0zct3OG?hCkGs%DiwX+?Dnz%CL&C@b{1SH}wQ8of3 zBeJ~i2ErKHCA3j;1{fiiN}yKsgfx@U4pXED?e*z&$1ec)LoC)Z}q-;=4na)l>Q2sMctH)# z(o_@SsQmonhBlpUHiHT3&!T)~j)Q`cpUAar&bGNWH_XT?_rmd%S z?Xu(@T=$dJ`dQEYj7>kAeh|`*Fh-+2SaLYo`>X=eqqlMh;2|S}> zS~oV_-mu!}-P;=GmoFB+m9sQMgXs@JBKW1u5xM$ z^ZkzXytRH_q6%3CjGE%7gdLKSVS1KGZ*gnSyE8H6P|J3QAg9T+Cq*dIDuXPzFcCEM zo(Cxu2ngVGr(U9RYvD(F47U7a-IjecxnPoaEQv9n-Rb6k*w-&Xi9P1X3=)PdI9rxYl z26?bY9DT@zqqq3%za%`Uou`>ntEMIX_(-6WSdmNKkeCR_Q{ZvkUwednt#MTDsz647 zx!EbR>i%FTgsaNwtI^xQ0~w&3vAFkZRi?2qqJ`+sP~1gad< zJ&3kWt%LZq{~UIDK&+>SFn_xCouLww=lC;gJiC0X9NYfu!tAV3375o{d(2>N;e;NN zV77u4XSPtz7N154+m232&qDhsb}Sa#w(F^&{r#uDjAwRq=@R)4=Ibds)ykYL&hB9U z(dI%uGloPH-Gt|-v#=%ev#JAM%z@S@;fAjl?6G9zC)VK2&7{hM3MYphXPRlxVNf$ZRjSN6I?ps;w6&1~zr23@ZwwBfi1B8=id}?VFT6 zSBU*IVs2jb@h5dZYrjc_6MyH7%;$9Qbbx;fAIGCr+%h8WBe}lQ%$@1GF@`y=CSZ-y zoswr}o@k%2cB?llB{{R6rSz2VRETjlv9oB&j*AnNa@F3%ck09pi_ZHM`TF&WmKINn zd}6-UaPF>?w&xqiz{Rj^iEXf>{emGHq=_a7N;=;Tqw0Z$zD`W^1>2SaUp*gvRotTF z-7a}6i%okJ-q!ROJ9s#0u;R6|?ig6Ky%SDv%Tp)pl5)L!IrQXFu&XV0k?2d2%rp|= zo{dQcJW$xn>lyOwS$`|h`f`Yz?7B?mDiWNH^>b(Pl*On@rkF4T-?r=UntU}8zuo_Q zm*O4UP5e^-v|}AW<}``A{0+idrC_SwWM)c%O4|`t?(6#^Dt-jEP;whc<+hnX#)zIq^K-K{W4vM&c~m&s)3ceUP-w*E zhGvi<{cVq$A9bPcNp`25sl$xIuq0CaMuy(zWnAmUl(U-yv(X*Ao$R4!opaPz{xJLF z2Y0j`qD?6+dH9n!!fCa%DQmX&SZHHWwotDdrr*7gKO;$Vkon|9r!IgCu@E?gv=XeJ z72s!k+pX!1mSc?$uJ77~q4@7SoytX>ZPe=i%r^KufZLHOjb&mNzA|j!LR}YSs#(mf z{_7{JqjoehtBR$#6mGOw_kbA%$F09P&9npGS7S*fy~%B9aqNpTP0Q5qiGL=b=-jK= z*R@`-a>J;A-Ov?PWL0DFnRVsyci6`@j~mq;!{py`nlvk@NzzHnY{&$ctqBxxW9AFX zH4n3_TLl(oXoY%feb8+&m$UKK`;sx6{;sEeib~)$Z1+>#?e##xHaq4HE-~JaJB{EZ zdiZkawx{W1qcj%1v7EEuwAaj`@s1@m*Tg*0C`&0&)DYQ&pJn+R@Rd`rK9N&UuulN# zP0`M@b-Jc4PY;!9D0x4t=uvAN!jobO4_k}*9vkdi8Nu!x_LFD?+u)isZ20YdX z1+klvl*@fKS@2JuTe49t<0x!l(0`xAnKaP~dGLt*Bomlawng$At+Nw?pRnewFnZ=l zpgmoV_Lyv^3ftMt;iS`f4Z`thGlnD=?oCHjl-q1( zBb>B$`+8_+-?*Z{nz|-yitaXKewYBoKWm`1255)h+Z@Oo#EI?XHo4J;&CgEXu#lM! zdoG(+>tfvAVkb-6+QGhoHdi*C%F2Pm#3lS$)R2tR(4M0O9!8rRv_q&h zIh+tvf*-HjWWt~20t%cW$5}nOfJ{Pu^XF1Jpb?x_GYyFa^wSnSBs^M)aodgRi6G*J!l#HQwpK2Gh zvSRYp$Ef*!{OD#m;?N*TDMi|xrWZ~`Nlf;c&X)vJv(1JbBZ+HKr_&HYq{B-eu^(xJ8u}z>jS`P|F7ewH zotli|KSAg-Gwn{WU#y2#Rjp}Sd}^`vSDFh?&cN}qL4^dZBwv*~iY4jO@iVIpr}(Po5AY`O<#+HP;xI3kdwt6n8EJSJG{&2@sZRp>uHzb z=?pC+u1hrRZlv&QO!inT6(ZB@L-9eizS8=(h8@NQ(-DHD-G{1lEs=>7A*R4Joo2Cl zj^Bb$xoJC`3Pz~Da7u%gFh(p~5Z_sYSE!YzRp*y;2Bnd^x;D^}YwlXL(`0cBGVU%R zq{>IgFk&J~(kj@Gi~Ke z0SQppQyjsCaEFdSb$vITYM1%0x2?JRGp)4w95{5cIO5v$DSs9_SyDeX8l`SK!#XBB zTPkKXrB;o%()?nrx0|k6>xs;L%@Vg9?ESMG&uqn7Wh8-ya~-;-#qF8|UD;-uuB4rc zbQvsYdS_26%hCDaT(+9_Lku$~gX^yp($8cC+iK0W> zuUqF4nqZ0v=gm|dJDJ|;kiigcBxkU9EL!(xv41qNqRsl>y-w2nSi`jZ;0&*TLl^bnwF&q@oiV(cex(!Toz|jZG)(o4yW1C8=Ky_ zohfF=LM#++Hxgp={z7@VjgSB@QE}G0zdhEWQ3)4`q;vwt`H&AHKFB4s#X6Ym2orj& zH-Y9ofmrz43(i~_wKoDk?M3iW$IqQfinLd-t>~O$`CyM{?-^aaRjJLa^#c?xby#2^ zv%)sx7s|6*5T!d473f#IS8ojtWH;%g2|)j28)KF7-V579=LZ@R_S5EJcitYR%n|ye z=Qggrgf_%+1U6%LfDoU*okR{4L>|i#7WHeLpPbDvH)KZBVA%6q(qaZLy#GqQFY$J=*=@do=+Lx8x0-oC;IE6?zs>RxyK?MNRlIYv)0J4?!M{h zzk{)qWuNkI5#utS%0XI9NUIrvzt!P(Qf`=9tnozC`$x^Ta{Qn~Zd-<7t=$qhjYK_y z9rdk>pTMHpn%&GF$$9rBpysDUkq?Q0MU?;mk~(rTNrx0OK!;wOi6J-*SMU7l8Kk^v%s4I6(k$iln7^N5L-$O4_viuB+m^zND*{Bh;a8e$TT`q=-T)o- zJ9A1orCJeg7dP?A>@{y~vN67O&WkB#l&fHF((NPiXMX)8q48L+p=A8ACw{vkGm^f# zwCe*@)ZO3X3-DV63(xP`U#v50*_?Wafy$D?#pV3FD|tiF^vm}vqQoU)n0kDK#CRQ^ z2Bu;R+PsP}QlM;4fg_9Ci3Y)lS;laPX=GL2!o=e()$(+Z5_6M|z!5T+)JQxUlLQvd z9bn9vVyD%h9ZYXupCKn+t4v-jM}}qru48v#VIS5(6#8j8Bl@GcX}H?M-h#Z=E>(1< zfIQKERcF}36gGvL-X_f1!hcd`ekzZ^gI2AsFl0^6VrO(Z@P+IoF==;i+-@Do{RIod z#NG&mDUUtoC^DP^jv|1RYmMkQEq#Idt#W%AbHPzt#HQrOu3oABX3RbbT#Hey91KFB zX^R;lu(&<`ipH=mm(!qIGtDr(XJ4j>)=sP4=dDheO}tGkaQ+(kl##4|rQM7Q*cT^M zamco{(ejFs5fs!)h}SY5rV@>)iJ#2o8K!2D=2eE4j#Yg_4*@XJOPd*Z%J+&bxy8bU zkUb3@!y7^qn?2&Y>Y%`1IBmB)Vs$w|!(S`8DQyEZ)KyHIBpSXTogR;*%kJHx(Em`T z_ub>3iYPyilpZGa1E2Iw{aS(-xIw8i5%TtZiU3PLS6RlZ89J-7$Fh<%t~LRir5*?U z+21@`JyVXIA8(zaQaQ)b@YPEYH8&Yzh!ScZdY%a45ef5vYJJ~eoAVvbUN}8$jkB^> z>>+9Pr$m*F1&z?9k;^o{Ps65bTB2vz8h=KA@{vPntkV4J?7n#QQqOY1YokrI*^GG| zCsPK(IOOy=r3T-7hC!Bh=`4OvwZ24{FL}DLR!m_bJU^{=%|o&heZsNy(JXhHX?6b# zG-yYH9h4mABe90s1-DG9oooziIfucbS?5f>ks=OsOB+6SaBp-O!T(*;(~8CbI$N=U z4uv3;HkGX%O?~G0PCUc0lBlis@1^C;uxd8EXl!W6*bpjeHukP3PUQ55=}o)k4mwY? z;r#4Sk5TiTLCSHLvq&?zE?*V28Y+ew{*tzA`!d1G&7g-ChzbjP6>w(Y(3$QdN7hIu zqaJ0yGLoq(Q z8%J6{kH!zp)=7p<=CdEK+xjt7ME~89kvWP%%KiEGO}QrO$PK5?zaNQPF5DBh886wT zXm2|qe190!AX(mA;GNaH8<@gj6o5uE3}0V}p;^DY4$$^oEQZnU*a+tbPyG@S61-%^ zYW-pfArTIQ92`%2i+$02{rJeje3g;_Y+F&cp0%=CIuQVn%?5&V)TVEB- zAg{K!*!iA*RM*$lG$}Lmd|)ljU6X83c+EpHxq;H3nw)VnRY&c z;K{{T!pOxe&rmqvV(A5N&QxE{)|V$b5uFcxP_z4u4^RfkfacLTU5EX6@~qh@u=>r z;zy=H+D-hVVmKN}xcY#?H!&G_OSJZA;@}$>VYu-oeScEweRxzcjztgR7+NLA-J6*y zdc4Ks?8coY?g7$PO}o?;CU2LF5ZE8*1H_>z*Dh%{{p%C)9+^94IzA8Bo;r0Z-3ij1 zd;PA`kVWV6t7@T1$YteY8K!T60PzXf)Eydndc5Sq6Vj2+GtG`eW3fGu;qaRks3^Q@ z7RBO~f+gkIckvF&`~oU%h#lKnBE za3_{?mh!#=hf91OP6m?*L8WOi{uu`m;J5v>YPf|_w0it$ZW!XXkw>I9kIHr%tq+zb z;ve-Rb4=g-v z%vIf|Pum7;<@%&HGR`S`hn>hgLyJ6V`9KrEiI>r;t2)<;jCdldcY6v@*I%a`#k-wZ zwQl|Q8Y<#ri0ilR=8L-?f3LK;Awg3Gk3R$DuT0%ruODl8{ToijlA0-!K<3$RB^n`W zz5%16Jk*qO;G@ec)3p)C4!iQ62eKm}vcS1IIXUIeOlXxRt{3#(OxL4U)!sgta<3=G zadMz}Y^XjBF>aemv8nJr6P0+p-OLC8ee33+aeZg}1C(&mx0sS_gVa&3x}~M1!pzh) zoAL;DnPnDrHwvNE)#7WLO-lx1BYw?lcLT@)jhAb(+V)6OADGu?ibtuGjg|BB(`pqC z)G9G2`dhQq>ynQWG#V0^wRf=6LU*u;bnGP>fzuWqgWZ4k(rXP9-V9T_df&U&qYpYC zu5vO(fj{saj)0H3tJYiUPttJ4-LcQ2z%zkmuy3EqpY`EwEf7j(v^ZQ2N{)N=jDs6q zK|>Ny*Tk`+Q#;F^qL>KXfvWY=LC$%vD77oXN5?RgH2w-84{;0Gjhds9mb z?ZSQQw(Qwe6_ixb;?Ujext1)68bQo`)<=yb%@}@J=i8c8?-- zvT5O*GMYw7u-^T1ZS-_}MGYBx8c7JR$v3GA?7!A&I2I@Z_AoF(m_5)cq~^xD08Isu zC))Y_?q>roI=Ch-Xb$R*A5>Y)TCs>|5?7uy4-zlfY@PjB9^W&_o~S|QemC~hu%7NL z5_V>5#14il<7q2Gx@BRSq)Up?BSXP}RA-I6Nnz{qYbjp$TE1jH4yobRUF+C99smsx z?pStV?u#GSP5{eZZ191z%>2isrgY8m&SqA8CqmWM1von26ubh!oztTPNu@D)^qaqLw9vkWcI&N zAuF<<>pt-W{d0X(KTPTldHt4Z&WRp~fXa%W^7EO7vqFQXb3<&}Jj=^^kNUsK&sQ)n zL?AksbT3(jc}PlJPCCntA9jbtwTsKss=q3T4Hd4F^+>IX=@+nr`u(PDbbYp=D7PuK}1;p{xu=J8;xgIlALe~UIp z`j*zud8vrWH7e*Ld4~~;K~O7ggTYrsG}l<^duG=m{o>P%xE*JRhNRR2Hc-j63oM*E zI0To;>BItSs^V+v$NA=)-8o{lH7=34ExFna-K(l0L+9<`5m2R7hMk}Bn*s>ar*MvH z)ct5d;ZwT0j*c97-{5*i2$+J^OW=O87AP2hD?{9dGICwnJ;bZc>*L~e{{ci6DP>is zk;{LH4R0STv)+e-GseD33cd<+@3Om@6#M=r4-YraOj!Vdqpd%lDP1OpaAr{?$G4eW zGccM_2+;dkRLOO{VamB$=*6gp@qy0xC{IirqC_+O68CT&IJb%ZSvI$7ZmriFs9@9i zEZzs&Q=z_Ahf@RM(Z$6jZu34H_zQ!xySZ#SAI;hgOo934amLF1swpzj;qWwfX6`2A zs!LqKl6=1-?g5+}@>jI3V${+puuAId+BdGIP^53OILCyUBdy%vb)56vv%4x#)V!rp zVJPHc^etCjcJ}yD;Y;NJBZdAH2gHDs>}G`X3_R+d7N-&LYITz=T3s7I7yZ8aK)^+l zr1;ji0BUL!WypK;DV_`zYu`SD9~_Il1;wJSbR2MTZx02K{B0>GN8Gsl6kgG!r8ijK zRK4E;+`E(;9e)M~A5h>lMfsWH$zQ*I6~DpWP(+%U@LhB&G&P7&XE!s`84-i5?{!Vh zvPKcTuuN{}UBK)4)IRCX7ZiV(I5JOUmMwTJ^XZ<^#?=j*?>uBzQzG}o77Pa1G`(J5 zUR=M`@@fM0o(AC?<66M3~` z)F4F4a5hv+1zDIcC5>UDi?(N(wj+9cZcW8!@g#f=q(MU8=eZ{urb#g@Ai;G-Gn4-R z`1%g0rm{6$9A}1^u@^+8jTIXpB2Ai(3ZsZz25C~FARy8Nq>~)Ij)GJj6qFVf6%_&L zHHk`z5+G7TkJ2K95JE`;Y41PaT7wMEz4u?gzkQgz@$LZ{_>SNg@PejJ z#<=_9MqHM?vKF9u9uXptGI&G6vJ4l|%{Wd%&%~~7%^YuXE5#=FxoS64riaL1j9R@h z?J5#w)dGNBV2z}CU%a?0C&A!UjvK+l`>`*_TnfTX$+R!)rn5TM!U`s=-TTC1el8oL474I~5HG9N2Y^ z`huBp)V}M`ls`0h``NuHXx<0LM8zmW8=&@d332aABWL3?td$nN(2&h~pMCR~hMZG7 z*8n0z4=e9NQt8VNuZHj3>YR-#ZOFZFd1odVR_&>*COyfgr)+dQobb%@ zjUSB|5v+gsEfmx-kfx{Xgizv>MUXB1d$=W zAIkNN_E(7eMmd#6^}Cg2J1%p*dMYoST!;m z=m3c;o2T3kwze!pbaA*rGtOI6y4|EaT_iR?q(G#)zI|8gJy8gX{xQKRpB3{JfUUaw zv~^Tx;vTtH#OuY&eAjOev@3sL@b>e4Q`fJi%IRD@cjn9)XfUaFwlPK8LeGUC_1OY| z&%nUI95*=IOT5teRbQ0AqP5<;jrXN_TiEOva&P+n%RAfrf4pik{PS{Idpr^AJk|C= z9jtJ(o=cvdgAglG4e9-CqR@P)=aI(BTL?YKq(e{!*)FyYpZcv`CG{IMd`@+g*qk!j zpMjftU_dJ@)KaXHJc{Zw@+`MLg*sAiuS?5RxxvMxzE>Wb?dwQp*YDCY{SnP@L?Gek zAIB1m#8>*eZUE56c91;%CmDJRjt7xCK&m?SV%Z`K%fcO6zFlkWwR~@Z?OOxEF^-Xu z0GBpXKUly;;kQv~h1IC9uUa|d=-2J378|LA-O4CuG+{nYz7F)Hd^x)Ke1BJw z8&bCae1uqPlEf}U^N&!}x@ay8we`j!-oJF-MvH()ot=6dcKXNm9#3G;Z8ulNOgHIj z_z;IX(in3M_b}0kPN5F+GhnDSxf@I&A!u0Im&fbq?NrZn4vNpJp+U$!$G%iXSRTP| z7G7ijv3L0I+yTwYpRR_m8Z?}t>r~y#F)IjNCTr~K`U8v$$j*8C0zC>tte}XgNuf|O zLGM*L&tGdUbf>C1BH>_xYdJ-n_vt7>0dEV<#}tO59)k1QcRv}crjdR+SSL#F^2dj^ zm2Tc0CBJ3Q#cwv)lYtlgmd%>8UOut1b(QX}tp|WG=Da6RM6B+PhBG9|$*#VDLFacy=k<9 zoDr0rCZss+)1e6=iZUjV(z)jM}~JorsfkWwKUtpara(pc7ncJWcNtf`${MI&}6 z9D4wxfl`6A`OkJXrIgUyzy&~~()k|t?eEvzIT<+ayTl|;v1^YM;s9VFTP%{ENdRYe z#fot26%*~*j~fpMPE*F-Yijiedw9%mX+=eey5Iqn?_D3sQ@=R*P-ngqT*x=okW0*3 zmj&a$t0sGwp`eC!_7?Jl%$-#LUftITb?%>T(D65peZF}O733qs;BB4f%gwr5S03U& zMC0Ba$iDO@oO%6JZ$eYxX^;>a-&Ai`on+19mzOvYzg$nQGfSOnvd(b=yooLTbhC_o z%`TK-nxvX=YG>;ejp_H*s~VA9Hhnb;9O*dMZ3*Ssy}s<%Z%1r*CC6@(F(0;j%I896 z4~m%d2XL7*ZNvG`Jcc8(W~PrV_`NrbVuo5lY14KI`ieFY;_fO2OxvVq1efILupgI_ zB_gq`U;PK=q7(zjr@SB9pE|8*58)ius&j4~CFT(`*L9b^f$sVd6Wu!V?>B`mC1+db z-7@V@H~LjL5lnpAhYlk{g%X+^_R2e4pkeg6EOYQZ0xvG-l@L`n8OM%}0@wXCpn&0Z z5M)*1V~fc!d~~Xb$jMQvE7!pEj1gYF=#p2O|03gvV@+7U{2D0f)K&=jc+KzA5$O%R zSvGl2eiJ`1ikK0szB~)IA;I3DCn1&r0RexH$?k^kb zylCiR{jzK{7}*mt0XVPUv`T4RL!r|;F!B6q*36-opg|1}a0s83LGi_nGBV*A`p{9e ziQnie(I$!;m4*zs_g(zy7t#;uA|DY>>;vCes-s`1yuRq_#*ZYVm1~h{T(?AE9v2nG zBk}&KI{y*CwV2(~@-lRBU9n%Cr<2UOx`a3oqP8Uwu0ja9)L79Rl6l4CSjA1Ufs+YK zPd);UPn+*vHmHH0|2<7uKj=I^v()87%dj6CQH(-!VEVJ1O^!v(uS1mLLEBvL)`OH? z=ekF&Xm(UnXhSx&>{nGReFvvMn4t0ua(A&{xvr4Yu4_cZ;SQm*HZG985sG1FDiMp? zOCBBlkdbYakI{{>*W&JA2tl&R27h(luR(PiW6BP*QaO zh10HfpY$sj(DmIN**1AP!snaroGvAtWSf2%v&wdX3=9hleYK}`-iNd0rQl=UT(0m( z3v=(ier%WtkYi;;1{nN6Rije^TMG+h4LH7PJ!s1}r?cD}`pHiCG~#h7opn$vREg$6 zrHFW`DX68S%hmhR8A7R*t-bqUopWP%AO|LJ*Y@#x=@Zi!eqC@a;8QLW0fo-|*N-^O zt1z2sFwRq#=U5zOR>f#Zs0&vWL9w>z%|;M-m$ba&voany?!O5Anf<=Jl^*Uj3~l-I zpJd1Br@lqq+|QJLIn>ZTc5Jzl)}Ne#7fBqi+@rhP$G!$5vw@`&NB}Mz3T&wQamSUZecd*?NyZw z-3v`f1-K|=c9ZOtu`uorPeaTXQm#J@Uz&ZX$q|mrcK7>#jVn2w;kfi?|9>FyEKp>{&Y!6o9*C)k$S`Jy((DHbY@B^_Q>j|TRG|_D5$NLQx-ADI>7ujEPM+xI zP3TmDGkZ&9)niLWZx4R%1jIp+xz@by*~;eL1sf5fmkPv;w*YLA4X3WHRO0|fc;&XNjN6*tUCP+n40jWiG;OyL+2ft3r>9<86d?X@RN(Zx0l8SuYa;7=HpOeXU zq&-~}9k(cIo;2c8>E%)3VytQGCW8Xgysj_l$qw>1IIc@5Bh%QrR-4GZp-M0Y?^`%S zrpIcNM&GHXD-TEtgX!n}lU(Un^E`SAJPz+#^4npHe^mVQ;jUl4Te5Z6hSf61zQ6l; z{hB4at>363TCZi>Y-WyD{Pau9(KSc@@!NM>ZvT1p`xdP(!)Z}|S0i`a$8Fjx!+<&% zLf0eBHR@B-8|#nUFXzVVaQH3*k;#smyS##O@-)*7XWsH^>k_p#w|E+b)O_|EJE6qp z=_*GEzwkf1Ca?4h&Sr^kIzs48xO?a6jdV{*5`i1F6yYM|hk2z1dWUbv(&OL z!om)nq6*HFxB+Q8VY`@Juf!8noqEPr+8S7Yg1lms%1;-t*0rwe4gQ#C`mREpvXBe; z=3-IvlN0La2mXX%J$ERs(j27x`ODmB8hf(h39`&p`&rN_aI`@exSp}HspbDX=pvx` zB1!_q*X$?+zZ#&|3n#+RoHchmdn#n-I*UCY3LJ8ww!}4PNV_s1s@iKGjM_$ zC7fVTXX4LR=^5djbB;K(1)*^6VEu3bhb!Wq2$S1Zf4Xvfy&kK;vZV)j;rE0)`>8u9 z$nJVaqv4+NyRPL`o1j-o`aosL>G_&`PJAg_0aHHI!x0!c^sxiT@i}p;lxB%KbL+^p z+#YYaHEZO2_N$9IrJe(OlOvRK`5*E+LP%!XT{`IZ1|LN##o>kH+R$|xqx%pWuV62S z*A+d{ndn?q>z3+s;2{lWhw<5^1;gN=rPk7IWMmzU3`K$~fr!!*e&FMQC741oWG?sRa z8g5olHrLTJ5U8|WF@kuN&DiETkDi-MiRB-R7yJa`-=oV7FJeW3}#HN zvp#9E*0$n`9q??;O*x;{>y&4Zlb)8A0q}zxA-K=W)DiKtI?Q&rE&6h=^K$hHXNt;B z^3aFW+M!0RTf6Oj6mR@?ej|={od(11%$vdvjZiVGsg3rl;qqc(psl@m`dZ5@E0%(D=6qnXQ%UQp6d~RH# zVPFtmnW-qA7zLkEQZyc}I2y6Y(Z3fabvVEBIw-aLm7VJr*?Tu;C6QK3rS?y)U`y@a zFJA#=)CU|Beok@?&6z4#MpqhklY;ETbA9$ej9z7`2zq`P}_ z06twdxX)nQi2k$}DKGqDT~0n28%d$$ZTLJiM^j45111MJhhhU3_NsXgraKj!@Lei( z)#6bWyylY!j||V5`P)g-AQH4=kugR}NSZ;C zB>@HdlGVV-yuBHfCY)-DD%9I}Mn)j$KZDtrLu$n7IJM+JU*=xSq9xJtaw|SAcIl3* zxHCg5q?StEUVDP-`@#QY01f>>H8X>qk+Wf<+u`u!j&RrmR6yJh8M`Gt(3WUq`20~j zcS}1XW8NlB^uRLn;pep z$Kk3!HtwXT&L8f|3;lNbc zeUMG+uJuWrZf}f?OI_P`!tfd@Z6T-b>cQRjwvKI1$viVFU(UFz8fdHk!gZ@bvzucRO?TD0@MXp?|lL)g5_N!_el(%(E!v|4>bWmojTX zqk~}rujJjePRh`pLG%&5k;QdU?mNi2jC!^E+{VBIYb-2bloT{bJGsLES`K8DQjHl5 zTO_Ar3fn8_?*)8Tr-@X>Vzi}`H#6c@^YX;!Q>7oygG9LfuPa0!)v{-FPQ~uDuM_sW%P)F< zdUDwW`dA!gCtDm}vK}Fb#@1cUOh5~1NgMv_gG({+cSXs41x|UG7=Q`Bt%YZ|Fk5@_ z443G%di&cZ4IjAh?Z-e~ML=GrNv)|ic&T3XO`s>|zMVY$;^DIhY;Ff-w6W{`g$lDD zLF|;kwS8L)2lT-|I-rD}XiB?MfVMLsL5%v_`aOGri`VnIqKG?hxU5L5ffH=}?;Al+ z@c+6s^fta7A^8II1XGbL){T9A#=_R}tzOBRP?YI^{3vmpD!)?9w z6g?)Tu)mv4Ed1i%w>(jpUH$UIr!PtW#xu!LCzh;2@T^0-p(i4x;$Ict=pR0@TAO zf74W+xgR~~yUR1v&aj=C|J=^Mc2l`>FZVzdB=|%^{?@;(g?A3aMhm=1iSO2k%zs!5 zfe~@?wG&G=z*S%mlqFdGe-5%=`MSUsUhC6;e=R&K@BlEv)PG|H%d|qmX_U${{?`#9 z3lxZs(f+o+QJ~|_>oEK#^qU-nUs~WX5aFDZxQ3UKJAtQuG$}>7*=Xp0oJ!_;??)~N zbSliyg7_`}*`~+?xd%em2|r-i!yCHHLyw{2f6xdqP)X(26o2=`1-sL(P!8~IEpYk;-CEtA*(WU%%E|QwRo4H5P>akL4#6&o zX88YJJW8zIsTSkzXalZQg#X;$`oG0Vwz<^A{pAx2yt+skr1|eZMdhxmF4&ic{jV<; zI{WjRHA{6qoJkr!;`;5q|0dZaxP5QZ@3^&gAQ1oCskl37N~H<67wpT@{x5I6KdmW^ zbttow_T)84m_Po9gmH9VFGyLB%J;EF`Cf}HVacZNya{yk;J?xhqvDbjB!Yv2EsprF zqAj2?DBYsr&wUivhJW9blm|*G`?7Q(y1pyvHxT_0Z~V5tihjg0ZQ7gk{?%sdabij9 ze^?h%#z{Bpk}i7r-0E=NeKw{RrWt#ad{lN4G;baO!^c5uU6+?2B@X_*Co}i_<$GlU zP+CX$g2o&jw-I^gh(7euz6|;StxtZV^!#4Ken9;B{x4gv*);} z=kCYF_W6(13%X97vDxsr;(${7y&Hc9{Ur5fUIkPn!7v?Lszhs}4ZYq+IZFAqmk%Bu zDs?RtH*LEY!ayGqh+kJd@bZv=*nQObRHhTVItyV7-P=bm56pYIyd zyNN5@bd;2NJikrrr{1&si~|BZ4{DYMrTyf%Cr9x|MSIIlgLP+&wV2`H5?ou8YO7p;=d7 zH=>y_p6WPj`9b3|U3-yR&pm|MC+kh0Iw3zn6L|G8Ypvsb_0QhBX{bM|*jg9&BK8&a zYJP@Y^GEr-eU4ps3c=;DL1Z3R6x@b!;*v8~=^=w%)f*J zsWaXSR1)n^Tk>f_>0t7rX<4xwsKe{H%RWq3XC}q%fQ7|-80j11pw*+rXD^7bEjWPgg;Q*G!gr0-)jPWuj7PhPL#QMD<~1ZB z=SR3&Li$JNa19-pQ|3lQ&nI8Q*gG^UhaWv7vrwBmd$33In8Zt zEq;GY{snAAEZAK~v#z^87X75OasS1O7h~P==}OZKBc;98uVP{TEqp5~I{G&hytJ}% z^{V0+=g)T7*ZnAW>Qq=IVb8s-aQRy|r=C5en4PIc5^J#G>$5t!#)>!>-APLs?$t}`etTp&W z;3rzV+;a@;640hya_q&K=niLfCp&AUz*#eOk9YUqyQM!%`4L5OA{FO@VOrlZ0vE6l z*q%HknTAeZmzT^@6V-isJ3IZz2y4(PulrIuyVNLepM96QFcs~TbjH~AE&2LxQg=!{ z%1Ac!pq4A}ynS{~O6%&Zl?j^g%57uw+QL)Et{CpnNgNIHLWMrs!z>+Ms)k}}6O=Ze z`r(zLa5gVt@!fA%LB6S`m5hazUDW(d2o-w8M@2nDMmj=1LoSxbzn~M!4!NRa1D^hB4fm$_zF_(et^SbA^F55KydoeVts-oKo5q8UHui8b zTBF`~oUQJ`Z1@78%A zn)fX1EgyWzSiH%r*C-bbs1r-}fGSZ)P_b{`2&8vwBIcT1*<@`QGgpua^TNhy8Jf(| zkWbf;d!h=@si~HG3RxR%Y(}6`<#iqHaJdyIxPq-p$eK0KrWnW3O;#Wp?JZBdKz}Zsekmhn!n3Du|1f4kKp%m$LU} z-u4yfgdMevL3Vy8bz6v9m<2?p6nLZAVd-dB#iP(waii7dRC^b{EWD4N59rV7E*$2o z85HX!BQv+r(y{rDtcv3%ketVO$LKI0MGW&%6uAO@{-;a}n^Naa_PRCsPjVj((uy^2 zA}6eOu2U~TT33fL*yd7F#xK62J>GajU!>tuaS{R!eH*ITAMePf_bOOALN9&QW`nPE zFl^yy7xgka;@GkEF;7E0K1824IG^lP=Xbyv(c_jB(Mr z>||*b<<%iAbHYh0nZKOo^xP~8K>JMb(rLL za@GDsO`P0)+X*`s5B*{6CC@$E@ScL7+)PbTjkJ@n3a^Fo!OLiLho2S!!CZoK+j@BNqY>ui%jnRj$Jx7a)13!UCj0~H*!IV?WJnfuzY zl9*pU82+lFWt0@VuiR_r%RN1(m-qlU>yl`Bb%~TQiY3m>&v3g`Es^M_RtZT9PG^mx z)YWD;567eAJhHW%co9&)T2$|*VPW4l+D4H%y+m>MhJ7Jh?g$J)s#a_LBWn#hMMeRVBw zS{&b^G-t(Lmiyc{dSpYERKoYmWQq6RV^dR72A?K7DJDV1v=$5zFieh1YehC)0}Sed zhBrMG%FKW}w*HOMh_fv*%E>`6tAsgw9dNRZnn_mc@yfvt-ziE~vA5=WYH5`k!-YSpiT*8joEGW-;`v2^*vms@{u;FZ&RoRS zP71t^@fMt?WO#%M=()$P?Ws2H_d<>QzB)X{w|?6q3yL>%-(IuP-|-8nm*<0u6C-JAEnL}fsPpE2f7~L(o9$+ zJ1M5MRTl3jx#ff%d*YV90j&*F+Zr!y#Z!_*^Z!tlx#4i(fH(e(uY?G^bMW^?Y)5Zl zo&yE?W9~m&BpK@V>X6G_{J8zy>ycl|<1xYF&u{;+GAE~YVPvgmgzEMjk;b~5S|Ba} zLet^Zz<*_TkA9DiMiWCLwC0E9Pc_e46F#4{1G8UY@zc&JpcYX6C7nXB>`(4c`qlJg zV4&651YL}~(m{RfW^mgv@ak#7r$ca%M;4HiFxqKES&ID93fysU$c(Qy8NIE1{7G4L zQLenX*fzKR)6Jb(Qp!8Lm%gbT7&|}ZRVTe})7*jVomcJkuxt=kK?@jk*fgMI8qI;f zeTBG;uRj~X;0ydr)nap0DG;Gq;>C{@V=HJ8O_OSipBZai?o~2KJ54;* zvBBOe={Q9&Tpr<9g-A&l-e)#<_pRj;5`BySB7o8LILj_ zQ2~^~_&QhHp|IcUE6Z7^Bzww5cm|HSKGvc~v>uz#3-zC4+m9bSHSsic2$1b$bEB*omxuP2hE7gXZL)W=0o(T1It<>em5H33SGCR9t4h!>-dIE7E zbFU8VKo*f-6hh?v4Nd-D+2q^nz8nyKbiH|=)VNtn@n;A|jaN-GJ4Ovkd;R@Sr4)TW zL{NqwzyG&Q2~f|>^*umij-FZC6Fu~Xuim?H7Iz&a@lTzZ9evy3SppTnTG^-45G<^ha83oTBu`62np3c)zIs5%RXnK{!llK>JF-)Pn;v? zQKtFE8D?EuTTOVs0oIoLJ;=XN)cOIUaNl;w{Cku41rAN$+|TVE0#<3<^_AU_MY*>= zsL?T~YYUey@xIgOMhP;zNsbjLZEj&IMts4z(wD)hTP~On{b?*fMnYZ(Oc0@g;1RGN zzOKUq=*Cy-d7bsDWNF>`uw3*fk`SlW{p(7@5K^Z{7K>70bdx%sm7&x?+E_vbvW~bMlR1m4sWN$~OPp+ht2}EVPwrR=SgHkC%q4 zE${ca#uUw>C7+b>X^vdD=fiuxLb8p)*!{@X$M&dw@hzxvb&cyl&CmICoNwICn{^>0 z4;apG|9K< zYw^TC5I7vv(mL+ydc2DVZ1rN%#2o1V`HeO6@>lT(+h8Jhz?-EcsU$cU$`-rSZ6_#f zv_^L&;`Y>Wdwf%8tT*mdtKyT2!$bkp#u)EXtW_5m7~{oVxV83_fxz~k-w;myLMf=? z{tN3mXMi?PA_+uz=VnUYv12u=dhCsm9HLgx1v+o(#=l?!V^EHhWG1crM+7MQoY_K% z007*c>wU^Bkp8Cs!mn&sK_!?z4m+%L=q9plt77O(ei^qS^|9@~ofXEIfuDdqNXUJuJa5uf)J$I0+zqKX%46S6^JKFkbeO) z=l--W@d|aAtIT$WVnl-qWw$2Ov+57%+ydis*LEo}NgW*>A!9Gxotq!m=3f~tc%E&) zCN9nlriY_3nn(YLdigTC^W61YoD^Es9<9DBf3(=UeP1zgGj;I!Dx_)~yPPq>;kX#B zWrxv6$uEAm5bpT7B=H zOm$d-e;IQ^;QXN_S1F_`G)uv`KFNN2iSnZTan=8eFTb=8e3sgFTJP#eQh3Fdb3Z;s zn-8Im*w~A5*kc&>H29j&o;|yG=~A>SWz2b^Hxv%WnVFMSqZmHE7BXMb*{OHjU9s4- z*{+0~eM%g$mn}3i<>|h`n!uy$`{lNr&}B zhuL5`*u@wj-y;$B;O3Zg6GunK1O`56q}*@vh=2@iMJWLRx3L-M1&u6>n7rHhs-q3a z`L&{8I1f>B#|JdO?jQ8kmgsVO19)%%-Fr5~_$c1XIt*VQ?C{mJZ0#=ba)r zj{_o6GTiSBniY-6G{*mF2GPbB-?~>DKYY7fQj#iaODmhF(o8%(nXf0}X6+sOqRZyT zUK2DXRH17 zpxnZj?+yAuSgrx`@Y**-eOp5caucDK(+%@QL3yLa8sDEnoI*Z7g-=g~R;Br`XpSYX zRC5U>LYk}S@@HAq(_zbw`ZtAQPKANAeeDAqfv{;AJM6p5S5nIoeAZQiM!#(Ew|so_ zQ$fVsRM}Lp&8)6akM&06oX|&K9jOp@xk?<^GdrKwW!{L~%FZi)yL!LlKHJIPdi^Oz zz}YJ)vvQj^+pJiky__<;>A?g^@`z6|a!8-ix;gYL6)NkX;A9~<{5g5S)*djVGoLI5 z19GILuFiH&`1Y!BJF%sjhHR)!pWt*pIU!fuVVU)cQ|xkyygU?Pwm^allVfWZhy-p0 zA&;(&FQKXyQiAiMp?HAXt#pu;p3hX(JAUk#R%%?Z8GZx6k*F*&$j}StwsIJrzOmJG z1A~ID@z?D1J2@|2=uVUk_Ma!2!?nOnSNZ^!ooYDF+Zvjalf&r>P(2kU=Q-R!%}`p^ zA8fz=m$@gUV3AiN$_v15EtW`?g}8b#2E?I333;Nj*1OcHw2q;0P$crB_3;8j$1_ck z{i^zs@$GuT7Y2_P4Kf8HLe7V2WEm!kBoZm9hjY_HKG({+jQ-_nq48{INlL+Sd3|pQ{7JCF zpnm+Z%g(vu^X~sS-oZg$9sZ4WVv6`qK@CoOjD4F)5I# z)NCwQ)9>4_(NCoItDk?zUxLXiHKNkICEf9fKW|WTT1#`1Aj$VNnJ?~ZBS(r#ifV=$ zwPRGY@bc_lHY>lHS*r9A5-H}}&)AT)dQP$42aGht$w~Z88?Zr6`|e93(5%f3spj!7 zEVH1$081%RyXVRq(xPkd#q8)&7btWFfi>9!&fR=G$ptIEd80i`VpRV)l89cW>{wNh$r$#7x zK2Ga%;q?u~wwlKWSBY}eK`#w*?#<4^Z}Xt9RB&i-AP?(Ga7WoE`IOIc`SrE*D8x{B zF*xhK@x=iGzR+x6Kqa}XI|y*ty|Gb zJBE?S2_*tW>L}Gn33t#Cd7CW2YRp4%=Miu~EUI{u!L_@U6_hMXQ(D-X;Q~Sxn-E#6 zhH$TkIFG#IkL{pG8({*DCX3&1TbY1&^6PrY?N8pMp%|OzG|wtyarFd9MANX1aO>8s z{S`bXzqbr(G=bae5=UdPr~#j=l(!~R$#b$e&0Ic5Z9amL7@saF zoe9VH6LG$s-i)%r5;>QC;SYXeSw?b*K%jsnii4`3<{9va8O$m7U6-P zEXu8`3mieii%dw&&F&ZtObbM!otFqN!ULHeQGaDQ8%ZlIbHFI7`wY} zE1t^xa_MEZOZPQFt(YAVE*#1t#Z%L;I6F2%IJXh^w^l}#8P)hjTToLF+rE8<_f!Lg3(&H3@Z~>%hQhH;W?%vaL zZFYWBFWm19Fa1U2;p1~lT4~;`P?_kL=n3$h#o*!L|YjIQf!vbrx;8$ zf81!I80b(H&>cPxA3lzjt%3+v7u-_e#~PNb28tVGBlQM82N@3*jHIfLZdN0Ex1%)=vx z8!`;sb9nFGUzv$a*ws^9l5uFq1c~R1Ktii>4kug%rf@4mDy(?+lL9K@clRj98;m?J za0ElcIPLEgn)fwh2TpFG_;1nxJ8C z6P2E=0GV}*SH<3Tok%}iTvAf^GhScCr))G2KG4HGLk?5UPrZ)oQ&-a4jd~4PzaBQ;AFz zxFq-t)Nqbg?A+Fa24`p(#1zQ-?r@l#*ZwUlb%)Zy+l59PB|)d;!@evzy7@aC804;9 z>$Xwh237~tImwWL?BeV&VqC z3vCxLqv!ywlg)@Xnha9l3b4WN9S8Z{U1r+!&CnQP4u>zCZQE^OZ{OpNu%XXzF|F_5 zbAy$23c>yBmStc%2RSyRuv8p|ch8jA&OSG#N$cNeBjTjs^75Z)*U*D&)H$F5zwmU^ z`@-oWPK#;Gk3!+wipgckHSGwINF_p#S|9@CDc#c{VzhLyJak$*kPhUzVr-5@oMS1~ zKzlmD`xkf4gC;zv!_CjWIj05u#p z<_Xyk%4SEh5rJ?&l}2n9h@_p9(}QDIRZ03d4>V5S3TQGk=*M<$IZEu1hB zl5wk&%{NU$`t7iW5_`J%?QQlf`UpK=(r#n}Ve-npG~Th^h(Y`Ss44brIaH@}QupRT zJ;uUaZ%hY+p$dy947S1S0Q0mEuc}L_FI+3Rsl4vY!HP;&ML<_B<^9Lb&h@2zLFRW) z4$tj#z*Li1b+IpQ9bKg$Ts=A7MXgB>Zi+Gze(o+4&)b9LD4Xm`id`;;_>>)S5Roxt z=$v)%3vFU@o;BFeYHpV;z|Y(obfy{vE6p$s{RZ;=S_5rrpQZX#S@TdIk@8m#o8-QH8B3rSxK|A~BEHeA(r|AF{*8=kRx)m|(r?_v zXgxp{*T0T4esiu5kyN|NiTf^Qt{8ZDoy(e1wDv`>wt8ji2AU&}29~1Y3>NI!%>b2@ zc6t?>In%N9mSL=J2WBq9kQmZjp5K$JM~+O;^?Q>CWtD^BRqpz>u*uT~qX_@L`rz9o zq!Hz0MB6ZADEu3)vY4}WDob)_Ruj!yiR=K}>u3ohqmrzKn->{I0v;viXL*KWg^_fL zG0ArbH`cb!rR7Onn7*NVQ}33Ephnb+TP7QkONG`|V924#*h^R*oPiyF&9Z8v9DXVS z(jbDXfghW`zD`Ew27iP`To2Jxg9_gWfncdHy-4JgJBQdL1%jb5AWNEeOdvan#=Hjt z@CG?l+K_*F*-*ADx4RL`EkDwS%)gbcgL}!O;t!GNL_tk3sa!V@VRXJ+XRfYOS!ccl}Rp1+{fzW`BPJ4ax z1Ymh+I2tRC0?ktHh4cFV*ko? zLlwio`dj(6BZ&fR-~E&nC;B*c{(*Z(7#*uCcx7G-V31%O`nt-`z6Ee6f;*lSt{=pX zl@24+(bPomHY3qtwy2`iV5_~gDN6oF0_?2RMG0bSiQsud1x3mW8v42=(^W^ zzzahnzFcP~T+d>Gykr(>;*`d#T2~TQUNI7ke=@x5Ke7q11Kmgx!!dtus4+|**BGe1 zf^P^H1*jHmfvPtm#mVMWWRV3kJ2ra zxE>|)AZCdSLM4q#&+fX||3uT6PiIzkWmdRbSiqUXx7xS6TkoISk5kt==l_@Csn=#dZrQZ@_c#AMW-Z0KWK*eE z-pV64G@UkIX<%R2&cix#A6SxJ=1OlIJ^O;$Rv6&Ku-bDE>8uL1w4W%y)c(?gv@NZP zjUb-(69AA!-Ya614oxj*+}Mc!DgH%bb*pu`gCQG=L2Zj#PZKC<4E?FktKv)yg^!kr z$HmvK?OOkfWxQlSmZB{ck(|iZXXpl(Ra;obi^gb{!TE%#dP%y!SL?I5>3R0PtpnrX zz25ctM40y4NeDN8g(3MgG1);hjgdh7jj$#>rsz4-r_wvvtMj!XbZu+*7ut}-ja5d2 zioqn$UePNJhJK#yzM5qjlJStay^`GF5DW%0vugPN5%F`nUan?n1cJ@mlm zRpFN-#LF-~y2La+D2+ka!Od}<<PJsE?f@{U1wwOdM(3nqYnm=8oEMpdfB@LAr#O*xz{ ztGu+Yq*8^K)&xD`G#I*a+6}%oeR$FM{BAOwf=qH1M`gMK$H*O3>g2Q7K4~q9KYIgP>(L6@4ilw9`Dj1sYzTimNKN%aNWCG6-lFY zsV)MpcL3sqFcQIkbplMj`|grYc;O6Vnz#sxpL^s(oLgnuuNgd8H_Le=-LD7m;h&l1 zyVg$yIN4{n*CDDKmT{s?^!KZhgcKFBtTQ=YZeS>})a2;_-m^x&7%n>rk$ zjCv1|(j!ZYJZR^oq;y{0H$T(vntkJeGJ=-O`~?`!ISZK0QuW0%k0h2wORM#W+*#jR zD;sPc3p1|Tk)#qJaX(w>Hd|%rN%L-9H7TZRJCuA1G@I$6_iuDh!;Pgea_lSJPVgS& zoz2-`R5sGh@1~Jt=)#WRfqFJh4H|hR4Lg}A1P%$Q22)WU36hDr)DcZYDx%Gz6=Re> z8gyfV$&3+;#i6XNixH^T|ELU75j`!h3}VGg_zBcgy5h-5qy1Vw4n~84bcwjwuP;z9 zDMIogmk?x<7SPn!EiRW2%eHPr-02v}NU2|MegNrts48?BOW{1NNz8e9CMg1ZO`Y*4 zC~)dtW^U|`tS9gM=QdfWZI1)o^z!d*%vt_8!%)e+Z+eLzGzgMIW@&j*=Ez92jD}Fo zMXfYdkTxd@sEHssI6X%nLYXRG)=sA@N%&2?x@L0vS|0KdUss!lJu0Ljh<6tnHHmk6 zBQ?3k#3!B0XZuuzI?;Ul4vA)4A9!@~k!PvaP3%P!@wUp+rPnFkt^n3RWv3&KF_n!G zx!D;eAI)mMSo1WQu+4BrNeRz`HvTP=qTzmwa7t*zh^8XyPP}<-vu@F5DX9ahEHqEG zTJ)y^46*YL2eT-tub&_o_?h9jo-S?*Zgr~PV!0CE0u9IWwHE*cIvL3{uH_iodRm1lDlw{2_xGPdU# zVf}{lbfSop#z4e)eytRigB&wwLR?c+frhd`GA!V{_} zG1B1Tt-bas%sk0){mCr}4+662-aV(I3fZ_)9np;CK%3?1c*_ZYMo6Z|HV zex4Tdx;5sS?%9xSi1TqA9626OK5kCjJ1;Zy|SCU7(14TU%x86bLn7O zAsa?7ofd7CJWCxhnk;WgyZo;0bF<~?@_?$TVI;jitb2IYx6G^iGyUY#wbW2<>%fs! zRhYEU5s&7cR*m5_jAXvlw1UUR1-DjF34S-}>6rQza#Ds35fjmBHFL6t0VnVrn82VTp1FgpT@^Yhl8s=MlBWAY1bY32U&85Erd9l! z2#C^J$y7fQ8-VA#$B5C*b6TK$m!grToN1?8=PCasHHSRxKld&GB`pFIFLtfZhb_|Q z=Vb@dCH!anRug@6+fh+UqA%pgb2li1WiDC7JCgdndGTR{3^%7$}YyUA1? zQCrzWif?UgUTA2qAYlU0Wlj1LoD#Bg#p1svB&@x8(Z-qTqySPtdl5O|&{R~Yql82! zx%D$s$^zakQSKY93B`c%25Wd?s)%ef)ofk|L)fx^K>BGU4$A|q;%Yr|P)d8Y4N5SO z+1=vw-LlD9--z%J)g)>C;m4#XD)O1KtYTy@Mq~`#zV90OQbc&pxNMCKUgB(T2ujrY z$yX(MLjL|w86JPwswS%$LS!MyEXO)VK@Vp*%s0gd-=V`Z+z2Hkk`d9c`ugt3>w5iu zV=JNGi)5}=l0uucaS9C-w#PVak|l9haFR+1d&P7TZkOTQ3#wVAVB!%7I7H;uJ?JZr zq&4c)VBf6DeSnkwa-;0?O-x-fQFssZItf9lru!_Vspw&V>}X;-u|wH{K{!(|FM@Nc zE_J^hSr>2Q$y|A(;mfNClW+l8Z!GAd#hDZ;391(e=#EFjX9D!qyH-s`~vh%_mJ zbm>h%q?ZsB0RbV>OXx@q#Q>osgxq}s&dhi3_pg61U5k~R?E04HefHk(5vtEo^X!Ia zDHpBVS&m)+euzEU?UBT66?DmKb2$M&4BXO|H1BT0R(G=mCk%+n1-%!#V=I4P|#ds(d%cQKWh~g^kZ?8u}HSjOO$9BiuCk&9+lL_myG9_`N!66`N z*=9GB^lHwaTQ9h=f!m?2%iy-ET<2bS=R`ZcS+_ElMH&$$%Y_^KK#s1V$zoQc<^q$7 zcDv0MCC$5oS81L1b_c{T@q+nN&)2~Dqp9HQ(u88=<`bx`>BN+^-Xb6VI#N=8R(qJl z>MQpzQ%q;U&T78PcsSna&6?LQ$ zTuF)^Gu~6ucu~B^U}sVj*WrfZUH050HcF#b4%whKb$N?n`>hS^x1&b@wDv+AA*=9? zI!q3!%VVHMgFswQaLg50!r8U|8gDrOTcXL7(Y0NR65#Rs%0Jjtoj>O9J} z6iCM#wwAnQ_K3@+%m$gU!s8}tp(O=itzjRTfgYmQk0BQ7)eQL&jAmMB6B#fuMw+-J zaks{N{WU@*W^glHkRdFzbtv7WJ-}pYy=H`6f8%xV6xfHgAW90`3|&Nf&ZuH`s{qP1 z2C#-T)=Y#qWcN+5xzJU|s^X~MUa<;>%3N<-qm9}(No}Y`paZYWbk~1E9N{P4hJ~n2 zu}hDfE~?s!+)4o~ZWFq8enw|fa>WOdm^^(lG(9}ti+w^sa>5}zs9)DxZgIFOe|l@S zaO?ICS`!7-n_%iNWWnBC+{|>=he(_xN^d=?-7Z)Ofo;XoENQ!hSM2V!l+l}RBA!E2 zXs-!*lioaa+&I+;#Or86PVDXPr-hN?6f3Wn%g#bSDhbEWOD5M{+(eD}Og=kVY4<^2 z5;ZY{*2DR4wUC&Y(4I}Ilk43|LB^@4q-%BqwgBtR2$F;ack8buN~1V{pb8YBQ|8Jb z@=1qjx1umv>4gc0u8p(l+WCzqA!ofEB9*k*)WbDMUVr^Lj=T@JFPGa6GSViKziy2O zN?!nAg>$=EYB$b(@+{L?%<_Pky>S1pm8cFc@94H^Qyt-Xk%gRs;-~F-12t}tj`XI^ zSao$lim(BDig&i!a@(Yf%lRp0p6wd<#k0wY8!9o2pM*(1>&|Z3NC0pjKfPv=EDsf- zm869b65a5vEd%&oD7Zi=vHS>jUGA;8SmflS`v{gdv_MB#7O9coa^LwAEpojV7v@F+ zX>r;sFttM)T(R=FWw%;UCTO`w_}(TS-xzGLvETvqnc5MEBF5Mlp(1;uW$&&Hk=;s@ ztQ|Xew!?kCM413+1U;Hx3W|tWs2!^YN%9NbSG$wX!V)#b9b4x+YE=bW;x>H;TrC>f zbxILjabhQS#iIC@lu+G+%q$vCZDrQ-UKjpjp1Oj&6e9*RwyoG zjfr+-BmgQ|`1>SbYO5z(in)Def^>bjDHLmhfy$@4^p6DpdP6lP&9pjBL=%anZ|9OX zYrQ09I>YaKfkRF9f9}Ec5@l_(b53BB8v_m~Bia`H(d0F{lDfJ&*j;pp?08LVD~CvX zeZQKGDu>?NSm`RA^qM;aa!YKDM@miMi@*^vqL#81CjP>;6m;`g9l?};MjUcmer-S^ zRPfV~>#&z%WinObgcukvCa&#*kn!t54X+<4GFH0Lp_!@Vy_J%f1@ZZcYOdO3Ix`{m z+w9tLn9c`FX2=jHLj!pTyKz*J7qq7t39Hi3aXHR4+Oy>xUmS!6b`CKDOL+A{5k z^P}2%1R&he(O(b&rRa53-f^D6fT1dJR_*}eTP5(l>jdgeIc&(}GdSJ(SPT%)#~SR( z?#-1u{N&uH@ykT{F^V6w%Q8#boh;q$h# zzz*gz_>t7IOHoOeep6bKQ-{_g9!w^|zTAgcu4O=tjMQ82S(^fz#)|O5e%$FwhQPT2 z{$ciXX$9XBHQNBL*f!c^kQ25Xzp-(Bp0I3DXKzqpyHpF_$3$8_EAH#9uKO#4{kzBV zRp#9vm6IjRLBim@Gtq6CB5NVtlk(*4mP#}d9fz+joa_lS=quFYU#iM2LdH11Et zV!7IVI-HlCR-7hd`^kTeZYEbi&5|o1Ga^OpKRxF4 z=sZ3N)$LSOt}vr_**0Kw>rIH7qSA!8lN~2KK-R4fW>SKqqz++T^U4iB7P-k3^1KZ$ zH=ImNBwx~p$Lpo(!^*TdAj`ca1#O)zDb9f(UEsSUYpr^$?a7!`hZPYr z)A!w;#(k6J@ebq!0I#|Jp`a~B{1kYLiYM5h1mICcmVuG}b$%g1e;9_$*aGqNifs1Q zk!f%WuE1d^*DVMD_YQX(fDH9&TxHV-UkT=G-m|k?xvb|UPFghUZ$|t2-r1QrSs?>B z67SSg?2M2#quX$?LtuJ%2y}bm*Ouf6;Gn!W^Hv&}ZAa)19Xix$Ed zzAi|XEMC7MAi!9&xfrC&Lks56&cl6v3%uwMc*?RwGMH^IiJzZ0nOBOC%j^yfCr}|{ zI~#6~@_S9NeeDkGk7S!9mmMm!R>V8;{p2ehwM3t6M%1*MbSR{ruW>JgG^*zUI3QtE z)lFOA`8eKIgRPMACfJ?1)nMlXdtZPHOrS6(`;r57ra)dl^N)dR&-0pQz0@@jOGon{B(K(42OY8NLA)E^xHYj$OKl9GZKoqV}3sd@_zeIND50IdQ` z99*}Vo1N%=-*to=MEgZf9bsNcP8*+oTY?gowi)+U|Jg>A&#$ZeGzY?I$Wl_R(_NPh zn6JsEz6mes5Cew`r=lx2hEkf^g~?JID=Xm<5fP=a7vv(p#z5Q&lNnLvjhB|~pA5Ab z(MfDSXK(TvCGJ)(H%li)COLO)xNq<$p9zPC(@jRI%Wy%;zC!wh*TEREKXrj2Ru#8lexDXRV*4ymn) z@Md^6aBE|pgRB5Ta&OlGWgfT>B90=oy}?D&W#Q(JX#hEU1LV9{K7O(pt>sL1=!}|5 zXC^u?j+U@r0q=4cyAZzH9VlD;_`a9N2m5?YO%NAe8iy83(62A``w08)L|p>f%noit z=Dj70vr&HodwAIGd=h{s?T*5 zl>=^#FTv@H_lib&VPPQ*bf)Ig!v%JZGj4#qMDJMjpkW8sHIU8N9}d=v&>9Bjk~ch5 z9z#X_6-6MjHDnc82?`ID9`>|qD_+8^3~Ugshbu34h;J5mnhP|A<2TmtDl02vRsf?0 z7lks5?xq|yuFn4ciX7~U{d$Cr!C3_2i4F*BJblUua);{S#|B+num(=|mrHC%hTO-z zMt$!u|E^%=r?_2sJ_O?a=S3I*r8v$>Sb{U7w>%?D!PTsP%16fXluDaN{Ye17l^4N3 zzL4gE5E14ChhzRTY=lULk_0X+xZ0Mu(RhLexKLSn%0M5Fi6Mp)ouBI$+3oWNaMksf zT~@r3kU3b0$(}52OVkFcum*?^;Eeld|C40ouNNIsL~xJ^GB}MQj)bn&%?y}?2h{+s z`cokc1!jyX$*jQTjHB&8D|q%-;nK`_YykHd>%m+xtgYEsEjRJ2OQvwE&sn&YbCh>u z6|4RPTvIe7!Vmh;#@@1p4$V4h2p#}s?n!9V=N0O;pg?eq12Ol<-cq+m#iU22sM{%3 zKLAw34JyQ6ST0AvbRG2qKe;DW5+$Mt zL|hD-dH6u31(o66kLJv&z}sFE(Oz!=9QUJ%+}MfHP44twm&2dG5p+G)Ob9fy7Fn$4 z$8ZFkl84Lt^h*~JN|8@GoQ(9@7Fm|ASAh+YoELNZnjooPm#$n_Z$sEOya@W>eHKz)que!0 zx=i7KYe;iK>QrnmPCnVMDz0CTD}-zfFBn|Jy1%_#IR@3pH>&mDcKsRkWXDV#;Ur={ zazG>wuM4PT7D_egq&aEzOYf+qexY@KSERWtCW4Sq5rpqd!zC$eP-08ZsQAs@%XV|2 z8~5235yJwA??&VGH1%iQijE-OAKHWPrOMh_=gi{I#Q=Wf`vI`JRgf-Et4R%_e<2jd z3%C@x_;oxiBl5O!NDDob!fjG(81n1-M&(6*MAS$Bi`7Qd0q|3Pd`+@%@P!uDm?U|M(rZm<10`7 z2gBZluOmN>mn4G}Rx$7Z^9Bpj#Ss+>NAmNA>W(39Wq)I@dfeN6{`Begr~F3(@-2Ax zPQD{V{y1_(wh7YL9ngAi|~y{Ryu4W`ZN>&XFuFjSHhM?ADns(#PTV z^=kZApS02DnBZH-JgdtXHX1dW&>j`N;|gZ(8DhImZnhU$7-wh$XtTFC^?Vl@^TJkKwXXk6&$e!shhorQ$BI5r~4{2a4bC2?g)-IZ+W zaeh^9J*MW$m9$RtrXL?c)uKlNX=pNw7C7%o6$jHGZkfSeK)pm~2||3xYtsgzcsJj( zI;}_j6-C#GM*@&OAVPr)U)rd7Q{CK#JW#zZ6pemVYbPg2Hz^_UBo*o{5x zSpd1TIWDXgL!eVbZD|c3K)pP|1j%(ES$SoiL-J`aLe;Q01ysPHS|Au;HA`dv09U6d zMy@0wdDv@^f-dn;c zKaIPqM{$2Eh^R%f(B^x|PeG*JU8AwTqh5QapC(cTG!X@nrjRnQg^%|Qe=|@3I<~;< zT*oT!13+(+3V}gv$6lKfKLCtIr4RXi#f`l!<$5Dy_lye_E7DtOW5$<*z%vob5-c)e zKxxt_MpUMR4opUx#gTV+at5s_YdQwiIBH(zawQ)|%o+aMqODRqHMkYFG=Bi`SDM=Q z=05yejtext2Wl$pI0#1q(CYYs13;BL%vK}NKB zh=i;I)fXzjhCW%`bg0y}qSFYR{=tZG@O-kk5-JxNtY}5@0ZBV348!6^%Y!)RZXcF^ z5L_+%1DwYZDqITcMP}kmfVmgI!S)!J5Hmxxs98g>~-0lp0F{N~Z4 zC`~Z*cC2T5KCt~32*d{%Rm|h*mXBY9OwVW)p`QZYt@|2K2cQjVR-thFhwk*^tTVKk zeN2|e@1I+h`?*$i-%$=6__-gc%TkrN*}k_J^#=tKPKU}|1*S_NzTI3%CJ@4g=H7{{ z(!FcvrU|r4Rtne1cn!S8VFArnLM z3{%Z@ zG1p01GTG~tA1jy3`Lr6fSEG)aEJrXR-$DPa2OkDuY?)uBMsymr1CvD^-ji0N8v-py z>V1eqJ>@sHcV{^gXvJNV<`(-Jo`*cELjVXi~p?sPAWu{2e|Duu&rU3d~BNq zXqB;x9p?gGhMHQ_#6E|G^NM0hO%RSo_%xb{hA~E?h11 z3{hB%TupYo3C5cK_`Zr3GdN!I4Cs!UV1r8+yw641GKCYg5B-&*d?iKM>-=8R2u7aj z*V_Y?<-)+0E-o>I!9HTZX}h7_>{0=x?G#0Impgpv|Bpo2pNgN!4m zt2@nMqC}?TG~Scn65muhyBQr^oK?Yi7@ptntb5Z@1@`w{M6c~P2f~I2ul>EPbunkl zw6DUdYhOv)l#=(Y|c-b(_v zqS8yntC?s_$AC*?|0$HIRByMxG;*L)bmXP|vLP=Z zhhzWWK7d`swa!a^PTh)s3ZL8nv+3}^&n7d7Y_bwgX{fuj{44GdXpz!aSo}aOCe=rc z)YW5k|JSaR0jc3JgJbZ23S}OFJ?N#W&#O-Sw_fnT?`k#05%~+?9jpH-zeled1@+N2 zwur|v%>kKD13>EEviA(wR!)XltI?`bIxw`O{~trc9B|KSnXt$M>kR!v1i^K^QKz69 zx(n3 zkwdSYU+YxAemD0TbEfg-$glh#KyY|_<}99IialPy|N5F4A3z9q0YV78MSdtqpb9V< zs0SvLQk)YfEF}Z-@c_>c#a17CG{5{B_=}~?1Bf3-_Z5KFSi4FzfEKLpBsfFzxEdfr z;0H|%KZ+5`4Jh~@)a3UH0IkMf_qjI~(f91Cu5n4~J^IFO!FwFx7q-Vsgn9=Y7_VYt zf{zxUfe*&zmB}n(nO{Fk1t;%j9IH6auTgBO+|Q`tIrR3E#eq48{Z1O1<_Xh3vJ*%L zbBr9lSP(k1g^RG1jOVWvsfB>E11=EspHXt!7{)8b z&K|nr0nfn(hzJ0~n#X@FzCZz71@N^ed0d0{Qclk^Gi50oJ&73_mLg4vee4^`Gr zgnf5cx}0*?E%)L`=I!WeYT$Y(1;p3W#*1;!jKND`!h3+ryYQl+7r-mk4ra!}CV&>f zEW(ac&bWaAY;ADtnPwz=0~nu1PTjMJ0gN;xFop5(YHft^L}6OR>TmArbY@{^Y+#X| zdKj3gjg!=1U&N)=!{^Xdxch?0>6~@v%uldRKQ*H;VE(!N48>L}w?fpg-80jLw?Am9 zhZR2mY_LBghMszj-qw%1&*pnBICzac1pU=sl}V@bf;LXdkbm3+gyfd`J$HvN~ z`-+x>mLtv1fTlH$kzWFJ`gnVBQ2HY1ylNQjF}V-(+_K75?^>(jzQOwM*8s!QY5d!Z z7xS7%>r%lKPH6!srB|`poR_TfK~G)DB?&wi!bi!K{|WS4+-@ahHDKfwK$tiCist1^ z_29}txwQe%I1I9ueO`1*4-nE;0j9sHTR;g=emdqBoQ8#+WeGN-&YwJy&}nF3M0n}f zN_8*TBi^^Vex}8~E^Z%mdL^f~Ks*Vapv4~*{{sx&evb8Y`wKmu+rZ_OfO{Zu>Q?Cn z?|RvMjAB@-25ReI0;H$!w*`4(kePi=s0bU%V&U_vOvCCcv+Jg8!P7r4BK)fMp)~|E zQVCOL^Ls|^2GSFGT6}X|7THOlY6ehTr(Y8UfZ63jl+ghO&?&n5Sh0%_>udi$v-2SM z8?J6vs^7eJYZN$@04tjP!qjcMfB|%K5ou6IK1}abc z&F+dL&|;j|0W1I>?bcmj+4U+;Du~uu=-IIZNsIs1zXEi^!ybmv7!!uR^}Aq0&PMTfN1W!lewsAIC&!ooIuOJ% z(QqFhTTpC#35K0t8BUc);nAvrUn9M^%H0g}4%xa2|JJeA3-n@PRHd!B?sG&=-vT`4 zkl))qo)yrw;2i2K_IBU#lFDIXfZF}cssgg zad)3_KrrqCI%kfneEHz8@VpjK4l%jC--$KQ)VGVW1%l!3z|@x_2yId$wA+dW->UrE zXY&fdw|#nkfdN*J?A+ZifcGfwfqLN-BdYOX#;68>=6pqg{Y`pmn1c^32c9%?`k{xoC%&&JRmKj_b{324@jFwF{60s3~Oj0roezpdk~80T0WH$)*| zUaW`ifgzTFA%c@~!ps=xz}Bsc{FLNnjR4&^zh20g81t42@}4Z%r`r&>T&JUQ(XxOS zqCnQo;SB(VonLDgjCTD_SqMbpZ>f~h^a{Hpflaf1~TL zpHzGuv-lR-SHL~ET2`vwf6c4^Q@@p$Uf)oSX%Tl-A`3<*l2uP{eyG~$jOa5_svBm1 zJU<}nBGO?-{_8-RgHk%fEvk>R#9U*f_vq%jsNJDDR7mn%X zdtv(O-8+%+n^CC;&R(E=bNXzogSB!Sbzg>pk+JdQU?cq1#fOCtl2G>)beoDt`1l9D zMT&kGnF^T|qJh7Jrt^BXbwc>{o2EL}m9({oYRf5uJojTh%t(?xD5sxU9VMMtcS`}e zo0Eo9%gsK5xJ6&lU3gf~mOE#|{O?fNp_x!&?cE6_d2 zQkep?YFJo|v34A=`Gm1?6j=m+IEr3!6kE(p)^5>*=IA?Lq<$pqC>OO84?V(fn;dJ5 z%uJ>SuT@HZ`T9_4PdAA6G-`PQN5=*-QpV~Y zGFw|;q1)5VpM_u^zkW4k6gM?jdUB<^E5?+fSGSl-Prh8o$cn@L5uj(Ar$s!J+KG6% z`*ZRvsihHO&)X2emtf-YN&T@_R`NEv*&3%l+be*7og!}$2N2V&$@eV<-t?INbtSet zm8(d;SHHsA6kJwPmbpquO20%XksqP|vx(CARW?TD1zAn6_4Itn$P9zws{5$bAwFdJ zr@9{1y0zrB4TMq~b@C}?$QE42!Oe$KzP@o>vM$FLJ1$B3TqT= z?JKtRz*%PONwjny@1kx7^y{;BfpyMxeCg_yb3s-DrygC2;|mqNy@nju>CJjNTd(cGIl8oG7mHEY+k-ReXd z&}Ya)SLuw;0R->4ns&CD1~yT)jp}GV>c&aA#>u0N$?Db0S=1+pUskEo^YRNHn)>If zbtk{Im&hFx?Mj85KB(^APlKi6{hSoCw@BFzkB!yW{(vHXrsvMzjPZOx5l6$q%hC}s z<%R`o9#21VJ7wLN3gMS3*`oxYtaNRCg^!>SX!x+oKX1%*{ zP&890*rp6u!aAVb^5mhRp#tfxeDU?Zp@8S@MW+HtMu%_D&pL&-&U8wDz%Zb2j(!lmx z9`1t8ysmaZF@&M597~FRx*IXeEp!(d9FB+or|hn}k|sOu9Zq1TjLQAMTQMlup{dP1 z@mPInslPSFUcU<%lN`(>;{%1AhFnR{xsa$-IlIERqRh2gZK;$zK%&q#G)#PC3cKt4 z!REffFhuvG%$6LD2@jYe#EnT7K|7%?1Ou86TtgCOz=-rnpJ6QW%`rO<<=5JZUfPK4 z0Q(Te9|x`TR;#D+mFGgfo(q*Mh-V05?GeBDu)CH^G|7paxYdv^N$5z?RdxR&DjAiD z*Z1);i5k_$yg$E&)b4$#6)g%9;OYPc@)Us1bk27e`M8?hqOF!Gk(wzY;m+%Mi=;uj z-3-BevXqhjI{4S#`tftCzKe+wLhXs2D4}e{pqp9GU1C~D9*ZP&)R_{RvJPvjVL69} z0hG%I4TCAQTxsK~^#(t*bg8(Y$nhz7~PtI9xN575^ZdYgh^BPA2sou$Gc{4hZ(Bw_@XJW}Bh) z&Pych)k~_jCGUp{R%+{XnXS#c7G%xVlzsXkT)cH=fzJqXJQ*96amVY_um1d>yD z58+!Z&H*CtZXMEtCi|IpR+ZX|oX@*-?8z(*m&@)2ZX3Fajcn1^LLh1Oh4(N~fcWb; z#FAP8&8|ncpxOnQNF^!SMQe~(imxeJB@%#U)6CqV0=pIcw6kMAisTtuAu9`?nY<0y zf`VU_9(i7z)^U?|!dw@5=Nay&0R+b8A*c`k(!hf!`_7tWt)p1721$_m&Y`P+Z@=hN zQEu--lSchHqo7$2J%Y5<usl;7DoCG`T;MY@``1wcTM$ibd5bS|#N1*?QI5 z+$ZjiMJ-&UKJOCte~rj>aQy@0M?SM-{2e0D6h8yS@BbBSN1iYROK&NvG3zqVT#EuX zQcY5Jvo&Kc_}GHCtYdhWA7@ZTiq*mPKAtWgo_VT#3&KeoTqg`?ol#~Hys_&2xuk9W zA?f8^b_Aksp~*Jn(anjbi&vk$x*g#zH!C<;&^uFTlSR6LgiBT|W zqBHY;Iz{vi*9WCdg~aBUg97mHc^KKoKu!4(4PBFr)kwOJRfutSJn>T8g%Nz!hGn}$vpX(NKh zhujsFhTfxyz8}c!7`wv8Gc_QUoc=C`PC-E-F?J7-97nA-YhEW-T+i!7Z68kvmI7vb zrkYI57M|;!Uc260x5nOoP7ca=EtPFAQ23CAM-Jqq%_}H;)7}(%8QgtPSIm^9snLr( z7tB6=Tt=QR+<-KyzJ2wmD*2OV(QX^B&9#<9Fy1!bsrm<`?|o0(ic$D6TXT+cyaez$ zD7S)O2l1{l#Kg<<=?!jf8+{$h=WN@glJIpy4(kQG97hNn?&}fArMnUN9r%W-C)xrv17SF6K!9nnrIT(RMX?l$~4s0s{x^N!0{<*6m&2@%qoavRqT2jt61_j|V ziX?U0z`D()BsD;N{q=&p6PJ7`7tJ=a2xAqX9ZHhXAsSTpe z%FJxHqCmBJ7V`SIUfZrTVfqq)osYwSN3#ItMS6ESDbG<{!Gt^+EaY$8lGe_8F^CiQ zVc}ypNT|4UeW>^Vf`eTtQ13jtBR#G1yRZyYNrDeG{Z{~dt!yg>UvIlF@~Nm^KIRv@7q3^QG? z7jnb1?jG^M_CwE@k6T&p7_Ho#0rNb^kc7-3G%cT|rsE+1j-RG?ftw&3>tqd5YEESC zv5+e2tg44`|rEIDq+hp-(gP;k!k41r>}$v%qCqA1O++?_d578UB|Z zweeyUeO&Zo>q_iAnAjU-2AUxEB-eB3rV1p=-lRz;8ci zJ_|6}(~3bgt%*n$x`5XjhecG4yT&{qFZD-ZfJGABiYsUz8ql>_Ad@>JdZr@o%gyXz zz6bC3fwgoIB9T+|okJ5{%C-olmuN;ihAzV&x}?p11B1e$V`lJg>Vp@Aub*-Hg3ADV zUk`to1g7DD_-Irf_mu!f`B*Je?BYgtJ{_>geM@Fo$kyOth1a31U4y|AwP4G3VS2FW zaikfqd~PD-T~ILxRt_$#DnM$Q=y<1av*-QzO<~tD#m`Lf9OH4}w(n@gd)*TW48)kX zPrwY;e)HXa+ZdznSI|+h{p4c66?7hTO=1}CE-OgZ=EcZTWP}KDDTm(r!KDf7@*?zXEKK0mTN@^E2zM@Z*ssb$>HuBU#p9 z0ox31Kd#_IWrwF-e;4uCcxS~nHvN6`L16cvPFA@r1~B-q;!dmy5|Yp3wI43=%sCuD zKpdLV6*j54EAE&#-VtAt0hR@&p79YFuJI&aSc)bh<~mpGnX_lnTof+Raw3UVT5N2+Qj7X%ZVRY5$TRMQKUk_0~5Y`w49K&JJroetLZX&A8 zV!4WnxTQM&wzVr635aj_-Hc4p=-9^+|P>UOWs|1-ED-f2E5?Ax}e#C#}Zm^OmvGY zWehNCnVI;}=Zq&oJ+JL-ZjLE5EY$8%Ev=7p*D78GwcRLJhLSj~+al%Qh+J6|?hwcw z|LoTHo{F-}EEXVp?-Q-9as}~tokX{_%Wpk*4}VNrKmj!Ja%5wNQ5-j%pzO1olWWJ& zKL>iJee)l&QQa3;2Vzg$7nv9ZV;Cc}?!_D|c&hKg!3_DstZ~P|_@^_9hrFfA#8zhR z@V%uc*Nn&yX`E%$lIa|_Y!d{;ve{bo{RDc;&9)r znFBCe{y!d0^WjhUA1kSRcdQOO9(%$l4|hk5%%;5C=I>0 z^au`G7C?l-<=nuldv6b&@jHNchg6vDW-{2#N3hEwKsYqcXmQ?8^{{Aw`aydWK}xSQ zvaFo*o%YFXzu^JF?X0S=U%ze#Qv}(-BQEchM%ATzDPZQOv&z3%46X#TtomMWa0gS_ zE_2WbP>cS2uF2eLhYj-+oE?Br)GzjW78G^L@_EZr76j3He{Z=&%B@!E|0^D~K`pld zB1SFJopDf2{LL7{L*NM8lPL#lTEMcLKkO&^;txakFKR=YV)>>F9*U5`1kAbL>`Yy; z-Y3N&KVbTy|H7M2`|KWzGtCnCd8e@{{fGS=omZB9PS8**A|u+_V!Jt& z{bhr-FXW{f`4(pdTF}$e_l;mSy9ln!Lp;j<&816kp|<{WH2%#~O<6|@v}%S*N1R#C z9MuzX<1F9>rZ$*XyBC9zX7U0ZS{v0V5%aB^{qw!ELVveVg8m>`TkIw; zP4*qz3LQnoQ0>YbEmtobidKmFP9TkMTwlf0_6G&}B@ZH<*MA+om)40ZR?m;ITB;Vj zmvprss)HvQ_||yQ7&M^WWQzH@OIWb{v{^5S?}{et)Wdaou@yVWOeAWK@}hQAr*VcK1pa3+D4@;6V`#0jc?# zh1k&%A-VuOasByB7A?<#t-sA;2}Fph$t17=_f~&#;p86*MbjSmHOB|hq8>XT)iquU zB<^6^%*LwS@ABJ(S(gLv8OthMT4&d0LFV8Dw z$HJ3RYM3OrJP+RJ|7Q~S6v=K;fw@epG=#rnYq1$t?b<(^&iJMmzf8kDX=3?wTaHcj z0h{V;rMVIeWW8E>X|*zm<&Q(Rj>PilYj`o`F{VqD=~r9E?bMiJvm!M<96@|n;(DtB zk^KlnDrbDF3v#!~%2L1beNQ()iQnRkF0O_Welp{C4CsRm5D^GlXoli@0@! z-+F?51q8q26oDJRd14MvDr%V+mw5v|1I7LHz9qIBj*H>6j)IhY)XJk9QaKr?y>{6JH#RFHbKfz#Rxp;EL5sGcHnxK{JfcfX z>Y@p1Q~EiU{kJ_B1w}7mZczKDJAi*Dh}OzypCN5Ma;T{d>GSgPvyg8}Q&TTa6ov;_+?1`JEz)wq&OEVb zq^M3H-v|A+Um6izGE_ZOD#8?e?M#q@#|by=%q5`q^X-REp zhPcI~xVy_5rvMBON1Vb_Zv_JbloX-mZ=YXyx1SKs{g{w&1t#f&u%IM)H2YImzWMt0 zc5!uep5Yp0#t^rv-kEIc0=D*?c=xAsCxU>{O@Z;YU)7c5`B1zH^S~O2+oz{Ph4obxZES^^zGc|zC)MG*4bYgxrNmjsQ!) zs4_A)f1ItHEQr@sS6?VNWcS^Z>@@Z)@r9{#9VK zzrU!E>SUSqcGs2f=Xk3Dg@#mF;6xx=A7`x?oC$g? z%yPc4^BtcF?81o=j;)<07M0T{?hOf?vjDk^1|SLT@sam4t=yJ{!)YGL-&?F(o;(1- z8u+IlE??HmRF$O0bMTk(eU>w;#GMB$QSrh>N<6XGW}9W$)vOsxoChQ6&<(R|ZTIO` z)!bJ#CfMQ>z&xobW#3WnRd*Ci@)#@vYUcmtnE!1@(WH1yX}dn6LZ%A+B|7!i8*1v1 zR_<##bz6f!J{#Vbt&_0LJ2mfEwZ2TGdQyQ7WiUOr-~w3n4%LayFZbGE%MM(W^ZcY~ zrb=$9jW(}d(xZdF2E0nzrUld&+X5eQWEkFH3CAS$ld@Gf55Ks4@5*Tpq`tbkdh62! z5?S@$m($ya4piy!^!D_9k8_&SJxdJ*oTCX;*P4IZk8N*5Gu3Nq-ndAQYRbJ|J=u^NS7u&b z>vIjk2<-HI*AB+yqVjZ>~scwn3HYpqFuiGtLbgi)+tt=pJ4xI~b>}FEc zn(v)t8 z(SyBmonu^#GJnuq$C8)l&Q_3jx^LsuJQ@u>EwSiKds=|`r~#hp9x7rvae@ZBI-O6? zc#&_(&G!zn+!iBIKysCI&j|~oqQ8XWq*pYsU(EewKHtTvjeMGES)vvy1+4GRZoT_X zm%MnX{i703FQW5`ZNkB4??G5QJKb+EmR{}QB8tALiF4OYVJ0~4h?sz(jrx!wzhPT9 z{jex37W#C%j)(6i^&R%`l+GNqnb>H}3i545%27o0msa(*viDVT%#izy0_h9Exl6t^ z8bw-fU6@so!s3iH1-fOr2|_k+vW*v>yk+RO%XPYa7&UWP(bHp-XIsXn+Iu^m;7L>z z&i>^tp~)m%7%qT~gmaIXr-GtQC~zgx1?U@{=4${FgfzDB{1__F-f_{x4vcQ$mKR$GzO7R%ck zQ;@Lg%7|z@59+MK=XrV(6lO0=dMRrG001(S@S9#Szg&nckXZE0@Y);_5SvuJg4+oQ z7D`wetSis?^hu?{ZbV&2r+Ld=&!#|sj64)gWMZNRzjT8wpgl+8#xCq*a!gY-3ba#a z{Es`v=O_C>kUhTj#9?;ba3wWW)q;E6!KD^!gxWeY<>s9LPg0LEq$j=I$)07k8cfTJ z4JCPX6ZlAlmuLc)$E^CNWR-!8fgK=GMjD?b>`IuO@W@)S(M7SXd0GqUnldX*s}X{r zs#G?6cuj9#Uuwj}qkC88$0{(^LhT8f*=1M_D`;>v(?gyyrKQX+weF!_)c9$?jbDP_C73yIOzA+T-fr`i10G_|;u-&A54UxYd_YL?a3RvW*);$A7 z$>@%JZu7h-lHUAG{sDbw2&RLz_{puLx~YZrOR;VGxvafK=34Dm+K;Q+9f^>=K&rjK zdjK|EdRY!0`UbLt+G^KdEWO`UHpFu#XyI$I>gx7R43WnF3yeKRMv$JH$O?sEds$iU zm>|?tc#5(0_a8q#Dlti$XulEz?>kblvr7T;-_zNbD?B=!P$u?}<6KwgRdz+R$CZW~ z>p$hflO^UKIjtRB@-k8GfYjlc)Wl|9quUf0xsh?zfT_PQw%kn7^8w2lF_+a3o?Zk# z+q0o}UC8sp=36&HBkK?qf7Z?ua=NYERZyJOaTLWh0--Rg%w!q2%#^ zluoYNgOp2R*4jO`C4=jI&xBVsI<>mpN#UI9SYs}rXOG+KFDz#yueGl z&Nz-q;r`QzjC@U71rMI@(@4=cg@s+D>j!cuF~!69cNE5A^DXjp8&q_&Q=8i^%ij;RX)o7g`?lL#CuE7Y5hebJ?#t?Wt(`-GV{(abnP~26BDN|NxQZ>>sDai z3LZUPKkPCw%Prs{FY{^EI6+OFg+ygVa<(;xRymMjfJIJnkcd+VTS0kD97GmFE73vez<)M}B|iM? zRN`u-FLY~He6zw09zq4E>>AByw{9$X3PIf~gl`j5 zSu1zg$RSx?qx{r&cIAqg!Szz5*$(}lbn2q0Vjr55;d8@-!PTz#0Gishti08S)9zyZ zb%)7PEa$rX*9sQQS4xMan8LBRboPb$<=$s*8~Js<`eA7JEG=+gJPG>%4m10Jjqj#| zM-%+&t<^aSzK(f*};?ibbiU}}Shv~NB0 zj|tu|#kd`DEf70M?f!a``{37Icw(EGnd12(%s-8eLQ+2KQ7^07~ z*U1vg9U@YEe0eE5b5WeMHA=2a3n!AK-EPhO3J259GlZ>% z7nHeh+}7@xeRcOr>WdU_DbTSeNJ$^qxY8BHf-cZN4g#}ldC5pLv!tW3cK^5Sa(B64 z%j;b2GyjLGs{m{2ZQuB_0}BC3i;z|tDHRcEk#417!03i!f`Wo{cgL8p(WN3F-HaL& ziAl#8gHiu?>hJr1-?`+{OSW^)ThDVp_jA9`E0`PEqK!#MIB@L5UtO-v1A=)M5N5TY?+j7pBq6$j;__ zKq2JPEM2lN9{$u>u5n_9TWZfdiYyMTs5o;r^lNkl-q4>RJ-IPE~vu^%1#0UvWrd) zX`Flv4pndFE? z>~8haBuge5t_NugBCw9#l`DF@#WXEyGw2mBDaZN50=r!R8H!D+o=I$ikGi|*anb;o zqOGN+*X7Oo%(5UcbGm<0AWWab9@Oz8xR`J+TDgL_n)+OrUMQfKB$9^)6I)m%wadQc zKgiVZ5BT+IjtJ-m;<7Ki)o?DkH{ejzQ1Tc_C3>Ny(g?)JK0@_K(|R`%JZWOY#5c?q z5JZ!oh}3B2vq3W-PPnK(bg1)UH;*W7pNVLhDv>(3?H|A*>C?CFjEA~S&`C%z7M9uo z2Nw$N`>Chi(M7u^MpH9&h}o@gmzo;V6UdU0G@M;G>4cz%y{J_GoYX4d8ysUS0m4OcHKniX-#JBXQ==IJj7OXbG? z+n1A-vlyQl4@(oavs7=&{h9>pcH6qvUQamPEb2bXq9dFTkogi2K84vc-exV;L>Ss? ziCeKRKhkSCu9I0iieUg-0(8pNuD&$)wbvhB z8>2I~yoso(_7IUS;k9}%CRfA_$hJgu*31}y<52~Bb6 zCsiWB(2EEdrHzgn{0^BS=jZKQeeC%u5y0_ttO;b@Vk47v?usTqW0e6Ar2?cIPp0R$ z8(NkYP~Y(e$(*$E@`sTNodEONIhuSN@|+ycE?VgXk&ctoqg=HV5$z=Zo{?-mL(ziL z0zrHgp8*E>%%V*#rI9 zLa_7_FFpiT7&f-qX`A}&Ok>X*LafRTIG707LKDrU*W9oF#E3KK=_Cume94Lx+o>F) zM7Jl0TC!AO`aM_6&n%J^w%hC3N2SYCApab@8r-vaWKqEY%-0jPzw0xn-_#14HU}aV zTjcG=TW<5;7${stuKPH!gxzNYY?ZdkN9=uelJ{b?uOF(tTvUJ^8XTN2tE=hXcOU^8 za3kN<7V`<1G%@)25Wv+gG7~DuI(DwhXYx^vNkvA+#@T!Dy5a(Bd?O|P^Yt8aTblon zRLFSzpL^~GZ1*eByaUV9$nP^gKCVZ>3jjC{pqKiXqtnwznVB;EL`!vbq-|;;rf6W3 z#jwBY6~(wX$?Un_lVZix)i@Y5JabU%zJ{Bh?^sz1FkKc4cM@l|v(?W_7-iJf^0KI) z$JgMxy7=3f+#xi0)@JgUma#Fr^iIm;&o??C7D+BQ=B4W&i`W1a`Es5KgN+1%OhiK zjTx3n&dt`M6pB9W>Ju)x#{EzCFDwNAvk!TNb&>W{$c?j2vZl1g`~CClsY8A9x@DPj z$h^LhI8j!0wn52DkKMBk-3Mt)U8xWIWi#(?gxKnr)AzTsX=4>z=@#3J73>_$Jw+ zmGT?lcTdxcgpoeHe?Q-w$!Qx_F=9V@Fe{_^(`s+mhcf!^tC8KRttk!;Ec!IkOCB}# zYY5~Af!D04XH$2m&z_B^>pcr#+7dX~Vcumyq(1;R+@RZex}PSCn_KG6YF7Y@grAgy z^SoZEI)7_f%Bipke-gr$T@g}kX$%SzG1K_aJ>xP5uMvUaw2#li=LPaE>W1weI91g} zjVfiSjI`}K+eRYbF$+tcI2GTOim@dy=Mi+gHo~1^ktpk~L^60C1X$G1FCvww;)kB)*a*pDHr65VeVcrOIoA%8kdm~*Z!k7 zZ2V17Z_@##ob;~>mHiL7U#q27708tYvHHH&1{&!zNrNrPkfB)6{#AB!h7rnpWyiL1Q3WnOE7oK-bgjZ?~2(O$Irdh3k*^35LPhbeCmbi_fU-~oSua(Pz8I@)=p@-cwFq_Mw?8NapU)cpCcH5PD-P19u!FY%2gfE)y!uVMn#5Z`4R=|a|gPSV(dpBa$uRS zM*11~8frg<+`HQu;Jc4y8%&gA_`B{@SP0sVR^)y)_ugkj1vDD;6KC!oJT=JPXdN_W zZ#C2icTNSlIFY?Y{{RBC11}LzR_pH;z4*>*Jm7ufWKTVYbV(ZYUA=W&(!g^5s)~2< zL=~(iscU0JG^01~t3&`vIP$kaE^W#9XDv>Y2 zLen3iJ2)|3aN*Er`vFXMq6?52Y!ew77*rQdZyiPzzcvFwJxcZfu_hj`l2A~kD(Za? z&9=?K*M>I8k{HaeR4f2axt8pG>ZqJcb&|^+X0X>z@QiueDIeunzW5;{PF<%2a8_${ z7Lh5Z7|6i900Wd9^ZH_lmAVRGjsbuAz1lcEN!C|GRh7D+h}YK>HE3ZN;( z>T>E#kd`91scwq#hqM($@=$gCs;kN|0Mx6kVj2J)78Y96)P!6=`|^3GXh1D|N>lXr z-^=k96%kR}9=4}l*Fl&-={&K>Z1!mtm5&kf_ce@-9fp`Zi@+gEz@^&y-)OvHQ13Sv z6_!}s70Pd1cgh@6034*a?11r5#rC=(fEOm^anRpE$M z$}SCPP6Y;TSoI5sYz| zA5DS^>ywQqj z8+WGJ=w?4RjcgL$a6^JOYGWcX;a>Zwa!>SeiZoZ*RM$$G8q!X3AC<- zY*(KMYNW)^{r}j+wr2y=?a@m2^6=f;M|Tftrusg)*gef;K24se1@vY9sUrA5s>mU) z$xE~|9Lv5g|9pZE$XfpM3HW0NFn|2JQ%zILSKi@Q9*LXXfxm9N0J52aGcuZr1Z%;D z?p;*shm>U#KqvGL;0B-p8~yOAkAXoQimH5kA*C{oYd_@;q$Zn%s;XVK6D+fTAjU*t zg9Wtx6IY&Bby}g~BOtji9|2P(+#{Qpp8jlm?@)UIq4$ySf`olJWl zYl)qrGt?Cic{ioSZ$%NMgnQt{Z8B@MwiRPD9yNWA|Cn74JR1O!-_QXB-)E_e{^b2a zil*2SWo%79Hf>j3HQtdgD(B*Q`+aB}Jf_4;anp4Muo(bnmD{qwL^1VEyE1HJAMO`9 zYU#XPsrx-OsDcYYs0B8t)K6(q0k2@a#KsL{rriL=S>p8t zYGaH7lnf~g2yDR&j7c7&dN(iXN`-4p0cALg)~O?HgQ3Y|r8=I8MdhNt5sJm7+7_KU zdp9Y0GFEB7B879QAg<`qV!uUiPMgS4@cjwGDkrC4T(}ts0r<~enW}gcS`8un9}?C+ zkhL^=qnyW=_)TWOzTj+K6Mw~AwIs!bbI_5O)#E7^jQmE1f{A66$-;EJ=rJY1qI(29dBSK@_r#Mgr8NWz7d=)H_3%=P2@9s8T|QA99fU0VqQJ&{&UN=y(F+XpQiZq7w&tA9FO_7SfRn*wa-ymGEh!Q ze)`pxBaeMRNH;(4leN5Ta&-3vSEN-g3=HRu#@W}c_Ja^5%x*G^=gBr$s%d~em;U1; zN>hkZ>f@;~?Q2!U1O`6K1A$<5>c*q)VkFEChIX4XL+F+8!oFISyyn0@Qj!Ru|FLGF z_K;5)m(|Uu^KNPT))??10nimeZI@4M-j!;<<#AM&wxQF`0J}e1KzIF4D5_HgY)?h6 z_r4}8bcC3iw?0=R?uPovVUz`tF3#yIviY)p%1Ge@cM1D$dX^>{F5=l^1A3Z|ac-fLNIsf&sQLiTHE=G0>C}x}fkkjXKvSADuOvX&d3D4Def??98qrHf@=*9tZrxMyvk)@Sf?bF=rk={~O>>u>l13oNCrfU1% zxUc{bdQ>d#$dvNh{rpn|ZV zR0d2Jo>yJ1`z{^wu3KxPuN}Xs2La*cP|quJd&g*>>8c<#1*P8<-9)A<|yF* zPcR@RUR2;NtEW)%dw|A!k}MuDszogMINP`Ib99ht-H`YC@#il6I9Z!{n4`(9ebPv+ zm;zrp!GP_ky2a&(YKl)ZLZ(OTwReB6jTiS9%}VQpcSU9kV%;v0XZdJYWPP~t(MnTKXqFyR5{P zBcnUxBNSpZyyT&YYgSz#cBYc=0(s0#)JMh>M~K_j3T{(mL~SRG!^g)*)t_3wKK5o= zD^5sH`xjrJJ*IwU)BnWpj{Q7Nk=vR5T>p^l%1#5t$5l$1Q+^?IoAK>;dSQXQIx&~W zv1F)$&6V4_e%PF4p6ok{-DTlJ1c*4;KV{3?E;G^gCRE%!N2N5k(drsQO9e11BO@N1 zk*7gP``RSQ)<4=h4v`z*w|)hwV9`WA2dSi%0>Nz^ef{_t8;d`%iEqT}W0ep@&)tK- zeHzkAr)Vb@GEAqJqO?Woy$Pkd>D0$w#>*NTq+JP z;6?ir_@M=IS)wfx0|F!;kjn-jj_X&+p-Vb|XU`6ap?jCL(+`NzKri)KVp?7&auP5QI|Uzq7wz zUhxCr%=eXZ7Pax;Kw4$6)JsF7urusklNqq**a2K$>8GbH9Uht=ym)s$pt@G-kXTdMlk{-x2c#6= zl_}EkQk_$qUQ)piQaH~8tDi(y!@4`|`sV&Kkdc%~27lD*NMFW|s`gR%snwoUFZ;`Z zUnk#M4vy2mXtykWJp&Pai1R72?z0=)=>0D*u3>@j3fMfZw(;P->QybTjs4^B_BpqL z+zJ7QXRhMRIw05_CH93%NeNNK`F5o?Sj-m|7f1BRo6I@n0PobQMkJs(k5N;HS*TK# zk9w9L`2k2UzzTb_CILV^Fd!DAVkIJw+AU^%(IA1IAL;>t4lP(fb1kXa{;Uf=tB*l! z(wiawM)@scB-geB$d78uEQ7=jg>M9LSdv;0vs&&@k$&`=5dHz^iosELn3l$5@3!k4 za>>G|2?en8HS`-Hvcu`)Vou zYmu>G(_K8-2e3gR!ca%*y0Z}AkpFASNJO-NeX4;7e<`71E9LG>l)WT!zun*+vI1CC z4V*Oxw5<*DF8-?x`DF(U31o%C7pS*8XoU{_kQWqwmX42`;fYa=f4esA>^ZcjX2NTC zIS_CuLNn$W;dvk>4*(1ZkI1V&6GSeU^t+U8M>KaAvZEyBfU!dLEd7YEM#tfuO2P2Rsk6FGf=A zj&KJe4g1kqU=4#?P`d0%2yZ&tt7Bt#P&z7$i;Ilv180M70F{hBO*y+Q;7$x`mghQ^ zK=e_Z1LbTe#ep<&OBgumg+O)7Q$;Nb4aikIR!oTFfH5#V{276oCD^j5%`&In)taCC z(kXpM2uSOW@^bg6Te&-s(@;DMQ+GzM{OXt^P?V`+#kjsb-z8goO_+>S-W70yG0_@# z;JWui9m>11Pddj((gcK-vA|M~9L-!hdd4F9g?gU zB#F5A1H|YC6#)p_F_1&b)n57MIlaCqydhvcGi-2>_+5CGBDN`I&)JW!6*G0LGgDg6 z%SW`%<**!r?t+9MLkrTR%5k&;V;Fw>quUbSiQf zl)9CGd`H|+1<1^+z8eMRrP_aCSvckB^D2vVRh~r;2xy%>o0kMCOti1xCU!EMvL(!Z z$f*ZOK6M$g3Te5V>--7sc$I>RTy-E%OCiqEo7>sJv_!Z@`tbzAiOc34t3976`hp;Yuj(~fnxdj~Dm)8diRoPz+mS4bD*&Rb_6zVrEns$3dkh*? zSua%&9!2U%83HmG&gz8~?zUko0KURN2C`Z&2O}B)J$=|BFtqR$gl-(c4!Dx0fz(HA zZsh4ITNxUvoAp}UmSo<(k>2cfgswY~aroBMDWNKl$jL^XBJnB)CLw^u1uNJfg(qtAnC_b&U;#EZyXWkK zWD)29Vyi;X1`b*^2RT&1T)Pq){knz}kk9wzyZA&d{bMNWZQZ-6Vo3fajti=%8CA!U zBzvS-@lP!Uskh8(9r>ln5F;0-FD})=!?!lp}9t$}zH(6tC90VnnrdtQxq! zyXmo00WWLk(Mp!~&lsARv;OF%;sMt{?gcEj{KHzVq8BqKKFzC%;EJ{w_I_hXkP zrhdr#Z~scQf!cA={rk10F9j|~V;wbBEoXzzP|cQy(4FQ(l>jO1n}#ja(RlTe4)`sB zpF|)p0B>$k<532%!q>@9$BqZ(s9anF{|y>7T5euQCtKK64OBGAGST&w!r_m85#)jZ z0irF2)MPpzik3o=^4~5$I3hBeO7Pr-DU?Z{uNGBP_$8yQ~nUpdXya# zN9A%_#+E$VPX)UIt`Gs-UJ*$2<`QLrDvn**0BvFG!(QL2_zX0yB{e@I<34Mc;R>{r zY|GLxfDGB&AuZ?adLgg3t&NHI2G5~S+f5k5m9e-htUV)-etKHfj9b4+tmBO6nw z2gv_h77{D+e5bW15swxKKz9gCA*)(J#`qxdQP>sFFx`d^53VyZLzhd(R}!pK(>W51 zdNsNWSa9|33ZSv@x;oQAx-pd|!?{7A2TPP`DL1LkcoUMKEplzGMRLx2UjOR^bnqn% zbmcy@xhz@V>asVrC1!g^G2UVBDcs`5_m6zs+!;T=x)0!-Lwu)n#tofaH^f7ILryt< z^%7$2f6h% zG&H#RW&BY0a{Ke6d30ddQ7sY2aXpP*jnbL1sHtqla`?dnzcb0a+OEHukG}zxq?WtC zyCDBvaB<~l^U{U1 zlbYw;=EHEaH~H(|m?3mV?2nGtc&4g%HUw?VW97!iC#>^!#U4++S`nI_oy|w12h9B+ zJa`>C*NbQlYsX;f75aCs{fUj-ktrL_kn{BAmkKDD^`{3aD$L)1>x#A4Pb*pQxa@sa z*Y{4}AD4)p#ra$>ys3@qPmOAv8_i0NG+peiq^2SoPc@f-5%76WKYR*pw$06FTxtZv zWcdgmJbdulx2R;~R8(xD?u81wK0%Xmc3XM7 z^t3FNl_4o-mmO;*UBf`;#ql8`DXc@BlMR|2Jt;J62#w;vbxFyUNR}a^oQ@GVdnNky(5*OCu0jrL5c@ zm0YJQ>AAQ*x;vH&7l4{tYL>T{7#QY=q*^{)4$GLQT_ag_G@%^(XE+G{ zAL8<}${pXUaVi|dUn5xX;%?k9^>T1rWP!AAsgX%0*(LK`-mjYkVjV0G1bo#Y`JW6)6VAp zSOW%Wm|%l(B{wWZ6ZZ@}vkW*my!M=m#jH^JnayX!#ucmTnPgm`yq2JM z?d|QvT*F3iY`ViGP21yN?w;5r{ETD8N-^TVuS9YKC1L;E^*0AtpkB@}IiQ(KY1QS% zaZi!$k))`oypz@`cEd;P*g$tD-|^h=UOs8Az|AGmo4ehaD5eRPh)idh0n^;T8YdS= z^A;%)OtoJ$54U#9B-yyQAPq1?@VJoR(1P*{H93LQSAMST^jh)s%xlApnrlU*Fj^K` zSJIW|t{@zPN<_$0M##dO-bk5ZlZ@x4q%rKjXDd3)D@_xGr?tYFTr zl>spX>z%2h{(*eg<07_wl^GWV!EbMWFmqE0bEItuYi~1xa6)HJ3k5jPu&^MUbCZ5y zx^)%jvAMa`Zc7$%3qy4w z$ET>YkmZcZomSoFlmdf%mq(`-q%b1&2P$i%HTee*Y{t3F%WNhuX0No}8u!+YFf+>- zM0uVobMSqNPrYy>41)`aVO&11rC+gZ3=I^x2k+~bJ(Tp!VOoyKeN}UcBwLO&sIZ;c zE2;9oI~sc~mrOV`w6!IkEHim2JIApnrqj@pRLYb(Vy_choJ{FT?SS*6d!vK?se6`g zORG*ekBO7#&S5@H$_bAlCdFh0Ol=Lz^ZkPwKS)feF%)Ji>)2qr++vZ6Gc9;%g>YxM zJ7f~PmAdTiq6>CB$!KXjzE}qlQD}UQs;m=(!*fI`f=LUEk=;Z_{F5gUQGMJ^c--;m zZ8Aziko$@M&gPTE^8J-#!$=4&0vpmQ)J14Gm#lRyfCC15S1-uX(z47Dyj86tn^S}h zfPJ=`3hWGoy1`m5vxAZ|?!7v$wNvvISlj8mXG-ebTJxhsici5*sV0hO15bH*nbBzE z^Hiv|y?v3W!+6p43S&GE)Uda=b4^h2$>FdCr2OgF%J;d&V`+}q8XYNmgEF<=PZ#9S zc1^OZl6Q3L>t!2sZ)9F~Co|;UVr-o!&L8U)G&5pc0|U!}KpBoh9AubDLGo%AEFbtg<)G-HunGl~ule{rW(L zysJc8dztx;S|d)s47_?;+GBZnd2T)~ZD+-IZ7gSr3#LR>I^c5K&o)O4WCbVpfR_;o z_$ux&k_6>YFNk?#HH?o#pd1B8xwp4hd#I;MnX`%W8>~}yAu2qDVj0iYp9PDd@Q&x4 z*8`j@G!*#e4HsBS9}>TDOGqdp40E^qgbEV;kUT*D!zf}^se?4gB<3?wH;7VvNPk7_ zsHaV#gQ4e^-!f$;IS<(?8CTp(6m^8w$TF`$00gGuK&G`PvcVTdD1(2(ox9E8_ZLSq z);=YHE$=~2_I6T4sH>6X3$ujFnd#dr6Q>XFORnv#G+?&YrVa;~fOW(i&r;)R{Bww} z4oaJ|(X|r5Eca6OWNZ`?4OuHA$o7tzOc*ro>m&1 zOvgz#H`JLuKUM}~j7p$l)_G!-QM6ds*4?h_?Ojzg^w6$1qY7jE5*S6`n|LGVKC8)V z`%?`%R`3940C=djwnf3jPP?Jn`~)#L-RkV{-C>lZvbVQ4Hy2klXr+CTHkgy)B17}K z=C=!mdQ#{iB6fE1KFdJ{9``ZC@k)*(Uzi_#ew&L!QyY(X&-b1p=QGd_)wOTn5j;GG z<-7j?uhME(a#N=MO@b(Fp0M&+7CKPY*AMbEqdtAQ|C=j^*0+%n-!jNF^wgiXXg?C!DyLa+GbDM8O3hX z(#P6(&N|Z4(dF0H8eO<>!EUtZU4p2?*OdY#7gqurf}#ej7V}=D7-x@# z#eNZj3n8k`GxgNzQ{X*w^73wqIE?CjNE9yaU9JTP-n+`XbmWu;iZ%~4fi6V8&P@&x+tCM|2_hOQ@8O+Y?r%tP z|8O>ZEA9&0pS!(})jljz>Kc*;%J<|M`Zkq8^I;( zF1eetm$=hGIxFflRT-ZkcOR1FG01r{ZddYzHJNEVart>cOSj^pK{HRfrQfIa6W-KI z-iN3Z4u>>lWMw_z%HJ%$K##fa?EC`mb1Sh^2_&Rklzs$<1qW-5c{u#zQU7=_OVJ#7 zLh)fsDw`iF9FYl-2t3ECGjY3?Lr}0Um+8@w`?+c?6f7HC0*u;s4U=LI#|ECZwl=iS zAfv-X)U0z#OhE0B{rL1<6g=(qn>X8gA~FdBL%5p}mr~E?ZoU32OoQQ=_`7sZd<083 zobyV?_F?MJ#59`t8!aEDC_%7OiEP6o4~43BXgFpZS0+KiqzxW9Ky>Wusa_wu$(5tt zq^B5fTvcu+Qu6R<*}p}!U-Xt}`XY=Y3;O!{f^UOZqbVfDZX|*>I5aduf>(vTiJhB| zFPhMEJeu1Udq*CaZ^RThcjossP(|)(X$m(#!P-eoKLG}4ladZggYG|bjz1NwWZdkc zR1RB9nY&kbQl#SQ6fJF(W!3u`+Niv&4pwx+pL`^t-n=upQoMlIG|Gqz2+y33A!%sa%SWPL znWlt9Xy3la?rS&~kHEnA``_U1QbBDJ)Ahe^ou1}ArT0OS_@L?AgPk&d2?-5zbw-C_ zDGD18uB+cDc;ZIOc^Lx>mmP)KwXjer?{$$biVpQ7+fpar#_%Dtd$Yo{!>Cs}G@(Xn zt)hHbLTIS!RzvV@g(}S*0u(Zkp{Vj0oY@0FNcF(=;;K_2XK`C?b`F<5xwbTweMF?C zU3VN2y!I4-jOsJJ4(vv<2U(orp@|EkH^s!%&jvMGh62;}z~VKqc{%laKF2pa|3+BP zefR;!oo)?snz+t6X74(!2UDQDHup_#ZQJ;Tpf5vsXg6=;r6uU}7bq^0F8ep;%%Pz# zwB~P`EbT5?>S|@N=ao^q;;!-BU`-G};Tk-6*4y)21`?o%#=ad0JrM@%$`Qb~0ej@4 z6bxp%mzUS4c1m-=b)I*F(}nU>6v@JU3?9j;UOx&7>rgpG@d$Wwb2bcHLiUhif{um% zWpu)MuMk086vDoueYk%2IuaDA`F#o71NIA5I&&HU2rMX{F&EZy-_5^LHCLO zx^a66ZQ=Nwk89F4gTPS)D`5Un4^9i_R)tEmMZp&;N5P>s+U7J+)VA zX6w_fJ4qBhLa14`87Gn_|Cu)UcO3t{rJcrqT9z%O=a~Ez6i-p0qkKr=n&Gqjq^?HjoMckAK?*V8G3-9p zpcd~CJFKy6LI3pMJN)_kKIJ}d-^qy=L!e!R&kdp=QSq5lN9VH!;1{@Y4kR441WL;W z$AnIJOrn?u!+ojP+a%-kzq8`+{qCMP0Xpcm^NE(@9#kH4XGFy#K>Muzv`_P~R*p+W z!yC*>>IJmVd8vg>fBeNUmKkntuG0pf1`p)|C2js(X>^pOEVX^U>&oyUy=ci-)S=U@ zkw|@3@N4n5Y1&IQ-x6IR&389sZHQOBT$DX;);+Cizg$E0zg=|R>?O8AKE>|@zH>tI zjcQ7ABe)Am;P;Tpp9*fDzUjFq>4mL_ztTDP5{?akFvic7+nKq!%8nx_kNU6c{L?SX zxa;aNuL)Kw$zRpFyC|c-6Z?B!UN66o!5UZK1s=bUmIN=fRT?q`GhL&Ly=|yr+cW>a zokVqrZgHP)eOgW&zPWg&_)^Uk;1X9%f42-$8U`K0=UVw5fhD>3%-`E9vBJgjI|Hkn zq-G-Uzc)I6@!!UsTcqL@NdCI4@c*xL5!ej=wTYjqZG2b;w9jKGi=J0E-5=Q=w*$`a z{hv$t@xLuQ4uN4?p$L7>s!(hyGdsl>{9M{5ywW*6e}#kxe(Qg}O7;5fzi3o+@xQ)z zRH>c0RI<&u*@o(&<=A-2xu$FniSZPn|NU~>p;LdSi&bpb(@9yTF@FW>#e=l(+=l0_Ad^nt{*!xcOMm zX#OI+J(V79@EFRT>GXJaI@ku3BKq$u?aS%^nz7Z8=V(pSeRk4y`t?nrzY~wM*FtTlljLgQ4)C&sBb{I()QcCyLIakpUtJX1)l)o zps-g0g(4N8i#jZeEbrHT{rc6;$lBj}BaX(95VQ&7WCCOQNf@&<>6 zowhUneKV@(-M`e?)a!@VW4I-Qq$vxD#6wvEuPY;-1S!|%+8FoP-P?=RMg#rFq2c1V zywx;t&IILpPDXkjOai>KdAY&>VSsX}H$dAgW41-%YMQC$LB8+dSo9NTXTH$9Au>0J z<$Q>e6XsIpEq9uln~!C4Ft4`en$ESs99@;qLntPXPy1L_6<-L6c?mYFN4Q;~fT)pn zZIk7wkq+u8$~S@ic`O94-7YTPZGiG&n65AUNApNlU1U{cEjgxLFP1-f<0~rcD1w9X zY4EBPclA3M3)hTjWs^9^ku3Pz<~^j?ysNLHqa=)e)-^GK<--_weJ5Zh*6OC{^?b9U ztd8Pe-$6J3S&GjCmnM$q%!jB$xYHgCck5!Se8a4|Lk!EZ()Etbyf=D_llQXoDUn3tEKhJ7pyn6Z~HXT^}d0Ahx%;v-mXjUlXE` z`yWS}RPc=r7L>-r%VT(uJSIVj@EeZd%sXxABMP{CXLeW>O{@#}A zA8rb1_w5?9p^@(;9`{o;G&EPde-Gg&LEkFnB+XJ0o3a6VYmWxgWP>xC2?ze|h6XYF z4#`7WxJ6Ij6kzQB{~eW7v1t%VX6wO0{qE1FvHw0pA@)CAO!y%ym^&sbN^+*yxm1ej zy&u(xutj|f&n;cgNE_5NMZ-PpqqhSTb6JSgpO0GV^Ox+n{ymW;FW+}1wZN4_?QtZ> z2iTrLO`j0jhiKq1R&H$AS8h92&T=XYI-%Ro@nNt5GEKf^^?DTT=>7l$HcJ_l`$g|3 z)ZC?f#acav*`p>RA~I@N@E*3tv-hO=L+(4=+*iYFiLx+}1w5|I70+*JwHyutYFvGt zh|ho%abZlEE`mcI*@z) z=h{1-%fH+a{c{5eP+2~$vyV?;OVZ1)*Y{9X$t{&Tq_2-2&N?ED6AKVy9yZ{Nb)~Ut zW6NyIU(&UJwteRz~f3 z#%Rz6^C88~jhC#>B3;x_zb?rKiRozQnD71k) zs4Z~MXWH0`>|R)aTUAbTCd+E{?L`lY^7#^`I!xX6s68*soU7kj|J=zT z={}#PE|XO32zG^aaPjdGwis)aRk1(Z)n>c28b>{sl`xdYROB}3E}4sOF#At`@g1mi zwlDjO<9n!%{>4{`Gj7VD=+tq3ierTCM_C_UT}~T(VtVFL{ICAndx$Os(O_PZ6zE)& zZ2bI>_4tvxjIEw;Zq@aDFMIG4rldTk!-MggkB=Qdb@y;5LOkG2(ptqP(ih;Ba!pO_ zGKi5<%fe75pO=m`gnhe2$o%=IQb16c2s=VlI^cvA4#U{=wSNc_6#_&6QDfUJDSmtJ`;iYNeJ`lf~xN?NX0} zLM^>{B{UmjE2zEthmbqqtN=%&4yj{(nDLqfB)7D}@w2R%P0BIHYajle-&6yKDHELI z?BuY~Qdc&>+#+G1U!I?rKm4iimTTojb7@cATP`YJ;|!3w^{8me>Tk>4oPWOhncj0E zAaim#izL0J_ZdkX8ao)w43pN(EL-tkE#XLl+|%3I3j?k!riv^GyL}UP7)3X&z(B1A zW2atP8L?be!MU%{j>y4_AXbd7DYRnkUO!eLt6-h%`mUP*5<HR?|QJH7$6#fzD*X% zz2fdGD11jhUj@!EvkX{0VV}i05xYRj6ai31njQdHv!CZfJ82JeyYEE4dnfn1!07!m z)SrvV?8*F*VV*~VPr?i6Zadi3<&Zn}w(lSQi`(onZ2LKU7JGN3nj7|(6*?0eZa&3q zJI@MK6VG-pKw3lf#!QV?({i%{dRg#>onF`kD4s=TaztvpvbFTY5@qDM6^BLPJBk2nvyO0^r#_h@qtizV=aK-ba22Pxx zE<*ZmU~=B#&(MF_ayslJy`TaxOFkuGapHEU3r07-yf3rnP^J1$u7J)f0|-OZT zvT9ieiCMFnemhm>)_bLGtiqTlrb9z*Q>Tv91q*Z)a~REFknLDs*cBP9P!~w{T#m2a z8)~h_7aO|GGURGQ)2Bj$-AGYE)EJ6mnC*H^b* z&=XYf6%?H>H!K!Q+S%M7p?Rb;uZO-pfoaQzY}cT#xH7NFmFk(C1*sv*08V2MLOw{3 z56D1YaDmkG6r27YE~^3V#Fs=0p>$MTO~tQl`V?XNVAD#clKSn<;|&de-G$9>M6Sa8 zvP564V(4kue+BHXZ{`{vb}G3cW>a>=P{oTzBt%WLBU%#rAp3MUfBT0)aX|o2d5w(e zxG6Z*{`Xa1s>kaytJuxaL(8MP(BIu4^OJxyB8END6!Ur?#vpwk7eEXTJR{R(89Nv? z%~rQIN~k8KjDco2V2g1FTkYmjva+V63E9C_GVlue-O_t`foB=m3J1ASBSkt~t<{80 zCaBDA#HjIDJ9q?au8&qmwz(B!oWIhrt!G^05i{cVRNxRGH&L8wJ-VsT)5=+-_h~;F zNOfbWUl|1*+;g=)$nu;>$q8buG$c*9CUPXpmY8+HkOwWnR5rf@ml?_n zZ!~JYapT6uO1r=i2?vgRoPsxWuTA#;iSEMreQaRhV$uYH;iCY1peP7U&&OU#^g__ZCq|3 zLHqgKH*bn(xI+6)6@gPoRbQP87bZlIOe7Cjbikq#M zJ0@LD(ti~vcE+_~cQY5`9^KT^GPmywN80SVd;T2O2$bYyk`BFFVt^pewx4siKaerO zF9KCT5UY2ex!5A314zG_j_2IsSVl;6X+{Bl*opL7BXCNhY0jW-$66xE zqtQ?MLt}c^=I38WOL}|Wn5Cs?Cs6QFj?RC`UoB4P2}kU1bp%2jp&G^>Dw~URFM8)adZ|1 z=6zrkSx*p)SGhx46q0Hda~xmn--i86sd3aXG790wcbINfOl}FOOBVs*4L62^?b||3 zVlnY@>e{OX(lt&_T>?GtdYsti>+pFT(lZ+KF{@pm=DX8wtf@b&tDX>=SkS@AUOoWq zu2ge{BX+red(UzJT1`o=Lyo%VzGo_|_xG^{c2wlquDG$^r1u^C;z@2Ep@0?U-yH~8 z(>V6wKj9lAD=DB81RzhNFKY3bjo##_&41=dTs|y$d9h=!#i;_Pqw4dWEi&m2Il&a` zNtN^O8C(hluK3XENpj&vTOqvaz3l!pL?C0>BMTgciB`M$oG|dSQ&*h!=`mdhzQsip z?%_by)!I5399<|q3!vkvMq@iHP&r9&e8w7-+5-X5hf7RMg?g|XBJhch+&eW)i^~iA z>`kaI;)s|8752H|{gjp5YA|))wdjGgy$>i++b?pA#j~h|0;hpU1LCRoI8EF(TNoY5B?5D_KF0{zzG&C;@ySuglXNSJjfGu@ z;QZzksMg*;F#xdlMs>&r1C81s_(4Sfn>DyPpg-+a?MMUC{mhlWou|f(u)R`5AbPDF zIvk|g-q#Sx#y3ICes=iNh=oRX45uB@u^TIWKY8cu=NYNwKiz+x$`k7xIpM!@1MKLJ zT?@M64>riGJwX_I0y&WZN>sb>K)*1W=b$&ENx96npRTdWmsGtRSIzE_I9V&>??d+6 zJI#@d06$CCgU8)$aK)n%d^FHSJGbQoyZ#*QGS?v_?$_-Y04zCEe7@wuEG$<wZWSPzO3n=9S7lcw4+i;uF|e3z^3*+fOlhhP%_ z$Jl#^HI;qe!_4T24Lc%zte^;p^cocr0qIS;f`EW@0@8A=Fmx3VrT1Q>Lnu*EP>>oz z6bPY12oPEbge1J@T0Y<3pYMGhhIxd9+;h*_Wv#XMo-CGZBbSgUF03bN0`>j<9O%_W zc9HQ^Wi+|&F;m)MZ8ylLucr+BO2r@j`v)eTZrLWY?ppkTo3B8#9u%BUT*9uRxO8WH zG3H}S=6>&@%aB)C?NsrlWG-TU%Ey-I=9EM8i;8TO|NM?A|DNoFtnzhI6dpzrgDEZQ zKBpCcz6wN-`a5>T=wlwAMy{67WVhCtB$2IbgDaae5T*)cANSkr@Ko zHSqH`L?O)lNG22*vcH`hjW~YXVg0TNVJ~2kE!-P{ngMO3NCT1iS{JmP7a`tcu2IrJ zPF@wqbz>O%Ldahc-oI~tflmRRIerlYVloV-TK>dD4%H(3T5gSfC_IxN?Sd>#h%^+r z4Eb%u51AtDVifDy;kb-Db`^;}`f zOTu%uHQtwPec)%HmH0Ez>bWPAWMsWq{9j9F?*$R@z0TUm0;rEUY_HUV{7rGp@Nsh~BWsl{|GB&Kpat zC5U-c4*iCj)Xw^STw(`i7aL0~cqv^<5bIQm_c}MO6tsrnxy-m1Ls{V5_6xHPVud~G zzikQ#)9~;JW24(p_LGm-IFBE@prmBUuPAW;lMHC!0{|ffpZliEjRX+F;_Hv+CyR7`C7K9Gw}gdSKY4RYWzS`GaWopkU9U=0R3Yqfh-W0VTGtOK+u z3>rjVDWX^=BBK%`&ys%3Ivb2euL7_Zu!(!QD<9M&Wm8-kdA0;SVIg zv3@EI@B)6s$}xccmbrk%$a4}$lz0lIjlQ&~^tBQ-{dLYCp*epsTe9vdJ$o$uBSCL& zkDt(c;x{*lf|m6Osd!v+ZWrSqOE|(p6)uG$dXGH86j{=Gg=}V{WQo$>0Lr_3LNS;j zmvctQKN17(ouE8*x2&OmNq+b6tXkcxp>R5i;XNF(aKa!%^-NR`*lHL>; z#d`~Y&2DuhP#;h~c-n8PB$ktxmwef`1!>BYI`c82tOpWGLrqb63iQ16hc#-9!{7(IwH<0jA7!;9?kahW?mttQV|#kSWomdKalHtv2c)il zSKAU$K1YAO$06advEy)3DQ!MfY-R{D1`u;?``eT?t5^YGk<%_G#~!p_uRfQI%qT@q zJCw}~$ERk<5(9vyIma~8?Ba2P=T=n6YF^WNO=}dw6sC5Li&+*|lLyFoZ!yk&&$kEs zW5r}Gy(cD%aKh)H)^7EorR2c%w?DJJZMW82)LBU*_+>C4WkupP$Dp!QSd&^D0=}c#3^dER0rTH_;tHUB8 zE^cpv;)yYmF9vH}T;x#g8>?$eS-PaB+rfpp5Mm2Gj(PRUK%-BB&;Wx_0%VY3;oRTf zR0fy}Op!1cK|oXnf|$9sx0u<;Fs}2`$fs@S4AuYHB2lpJ<6k6vVqX6i2mW68vAYhO zrr{-rMRPv>d)!F9a4?4!Q&k)P7E?axz26yGsvso@%}NM395BV#-8D~Bru|1QrW7A8 zZMgL;^etepoD%>=&_vV4C1a+^aKHyZoP)j^e*si6F2P;$+u2WTK#SM!uf62fIcQ{$ zUbyM~V7u9QaP7VJp7n(xO8JmB5PSC5d$(QawlFX#Y}&H)>aq_hJJ)q@r3^0ml(2tt_y%MPTUbMKG z4h}4+q^;H{Qt(yyk%2kRRgqS)`q>~RW0gV&=%TLUc<**Za5&YQTcXB#{F_(Mjh!C(vd!>lin8#=CcynwEy`6g-Eo$H;?nl$cw= z=HP2^MnQ*9u`nd&*Y0Mc8vY`$30YHDgx--r{mVN*B8CB@@l(Zd^1{W7-_F*A2nD3@ zYND&;Mm&b~t#flgvpEu9W$iSt44YQpqqs12^&K8{WOmZU<2;X4aj$Yj)>f)y&uYMV z*oL950lqZlsg=olOT|s!U}oq3mf=83V=nNX`KyVe1QF~=AIP1iFUxGAMW~a|#6ith zpbt`(lfS1~a$hJ&q~#;LT|L%9#<`Fw^%@$8J2fu^m4rY0se9p3>6l^(0Z$KOMS zZ|F*XfbHB4X=k=(&lOw<$9skE8+A^x%bg$2kjD3Q8v-LSw#8oaH(v1qm}@Zmls3|T zHo@BU`_B0YkUIr$jPUL~2q6O8G-VbikFHU<1m}vq#Y&gu1p?PptdLXo)~g`$qhb%* z%*J86mWz5DD!`vEIqyd_pWxYX_S7lx&=jlNtqMgXjp_3pFFv%9MgrZicDhP_*QJ32 z)tbYtzB#S%J1(0`3K#$bUihw+*PnVp8ZCVvukcL7b_D{0o{KQw`s`f9P;|*6M@ojU zd`;3R(Ww32L*Ay`(Y!w_>a5i4{X^e#GsiEizA|zU-*-n1Ub07nebp|GFu;Z?BM;YS zLCxFKb{IVT4*|=YLO$e9{AS~{-qEFhV!PJ20%lSIa{*rW^vIEMru9%y3OE?3#O3;8 zlOh{3_zwtY_7Hqpq;XxY@vn;CB2aM7wrNF-YjDT0Q<_MgcAa6yAk4#1Z;tp15?-_d{vUk&%%-L+*{) z#vRknD@aolMF_xbbY=o&t!oI|k2Vgct-@JTXsEhTVAOwK=4Sdoz3iWaV23wY;aQ)H z*{s-gP~i5IC5S}T1rjr($j7&EyOUleXV+Ikecg!Qg32yFn*|08BJ@i`F71TcLZFew z`}gXnb~iY5Cen=z;}Xj58iRNpel9RX4#)f8P4mHaPs68ycyurheald=-gIH8y1=&? z=Zu5kM>S3DK(12E+^mj%FY&X(2hlOi>SfvDN41UDN)b>U*4RDw%irn~xiO5lwt zYXe;sZ(e%FVg(ie>id3o>P3K@=o|UOy@Fzoz?ommjds{b=W(ZX0HwELU|M_16i!Ck zZ?;EASA~@hQl27{?Mf38i5r%@^y=$t-hZ2}!#`9Myj2s@nRNpY_h&7-x_Fe=QNe-u zhpw);duKrY6Wf)RuQ8+BPp9%$qgu`_i~zYzp5fi&5eilAMZODzg-EFAp4r9MJT{JC zv+yX~djWquKm-qhpyJ~bSj>%_?XgZ#s4*oEoL8}#820Y!ub)Xa%Q7#;tcUX~JP_3Y z3(;RxrUV$hu&_Po%~lsAh%BmIhYr{;j+Cse-O6#icL7LxdL??D!BPOCpxTX4cq6L) z=aRBP|BD~Xr>@*n7(PFL2EYfme@QCdU8>}ZUJ0+$f7rOU{hD`eM>cGNxS`uFE?r)j z?gWcQi+^&q`h_#=)l1EM?#mjs-KbkUzR;W`b*)>&PTf=rxC`JNq`W>Yb1rk)po%(J z!A%{Bufs&iRW~5lp=Q-pi0fjZ?+9=RHvqlW2dXC9#B}5Rh)y6RAD@^oGBUE1I4(G| z>CFRwT%IQyTr3N~4z5jN#pi~~Sb0ZVBiEd)?&`nP;fC%c3?<|><)k?T<-!latC~a0 z$0)8NkeBuD_C;8N@1hNgp%hTF={#1H`vbrXA{PdsdXuu3;Ecsh_Mi~83ZTvfNEM8? z)?J@k{hEHl_M|YC>J1b(dJhVATPi$-edW=g0d@yC48s>Ig1^YHIZnFwRC?>~o0YfO z-g@;YwJhWQaT3}Eu#*|?{a@~idERJU4Bt*$p12q@O$4yf?4qJuX(ioxyaOt0ra6uD z*^5+rPB`4y!ruTo8wc$Df$UONMl00!0#e}1;iJ$| z_DgW$ea-aQ*>7ic{#z7)^*o;%lyy&iY-#LLYtgr~9GAxDXbD9D#_83)YIEf9dlqLs zc$zKtZh)JklE0PVD(r(qO#&z3@HD0zum#1y;KVG8H`7a_3x6U@qwi{oK^i7S)u&YK z#?|Nxv>&+A%G(#|^U#E!$N=bb9;LWo3CH;+^x@4Bl%G9txFwOcZ`h)3vjyu24;68tN?(iZQz|+(|lj)oKQA6ePh3|rkBCz z5srjIZtHw}nMc-vmfN?!V(Xape(Hn(+WdfJq{_X823$jN+ z6hqBrpcLC>MXH$M5(XOwFi_b4##G~9Kzg+t6qkYAxfsNDUo?M1+{=24&uX8Y`>M*L zNh8J+y2?Mw_=}=a%Tg4PM)&SLJ5%s3|0aTQNo%{bKaJ-|h#yIfe?;q4YIq zv0!#q*vgmm+*rnSfGaJS71eedlwkB1%}87jsSK22gVWjZ&mB_td)U&tw!ie}QI~~m z(2)e+4r;*0hrmLsz~L81m0FK~W12Mu1YoYVfK?7yd~QkwTyvo^2Kd=b=q zeZ=YmDUcDd^9|`YegsKi23M^EnI&|pEZ!==w0X`;nYNZ?TnfsAc@%6dKePWhSPuyE zfZ4|l%F{DbQ!wZa!zlj61@j+5)ARtV0@4m8?fNYl5R#Z|orsj@pxVF`zwM_nMHaPUFz@BlGFf!&D8JQ| zKX~R^T+9qHD+N-H=}1qkF6Q1wbt)@`b)}K%8@6dC1e*O=L$O-u~ zOsmPSvZIalr_79JF8Qxay1aoy;A;t>NTKd?wZEha+5*-YCmfnUZpAKyA;m*aiK#L8mD=%Qh*cs{>4G&z|Lcgg^)+;)7 zA!mJI@Zlt4Yh_5Gp!??Cs~Py=AuQ3bR-kPYR^w=oV7FJBcl{F8G)%Te@scGFu4G?V z!gLe#!-zfU3n2+Q>l9)kS^m<#!<1Vl;edctkKO!?4NEVh)si$qN8kjqlv>e0?MJQgeIj@adPau|>;{xBAW|SWRH1;hXAh zOYPm*GXrzD6f!3#7n#nx*b{tE$pl)!(}yUi{@J75J+Ka@`KOYA$mjfbjrl=h+yY3q zNwq{}n}~YF{+&Vh7c$O`PKlV{oI8In_@j_>zf`SmBNzDx3;O-Q09 zk8{`kXbN2a`30h`-*~s>4x=<{ZDm9!IC^wXvlf6h-)L$#ZEkMzc#rSo;PnrW7L?FQ zX*k#;+1->0z&@lUva>T)visf1m2Z3UG}+xFJw9Z6E3IsA&3c2fn*oie=0s)3RJVHO z2u}$CL@m8`x~9%^A>rjm+oENX6=%u{{n%1v-CyEe9t_vjw^u`q&4jUy{|>8KjRT33 z3p8Gzu+hIkb^|gKh4s2#&F(L2E`$hiOer^_YsH@hq(eRf@?0Hb9vfD6#_NlOyz+^z zK0qolthZ?6_VA~69Z8p;g|Y*w$%Y2 zeaAiJBhV#7zZCwvT^Bi$ON!h6DLLK`X-EWHj(_p+WjpW>%woV1^6(FYli}QDCJj+G zH&-Nv2ieg;M7Q9`Uk^tZm};LN?cs93@g79b;}rZ9O%g19qgWfO;_(Ry>?Hk->B?@* z@(J>fEHDyb!SZk#a{A%V938{dXF{QcWKG|7AVeI)G)acD+W8-MIRmD)Pi{TU!-nfB+zQJ&Opyw_17rdPC& z28Vg&>@JG-D;283M?Bt^|KAAt!czd#4&Uv_KB^b{=1sbHmx?NEdq+?cXZf*ElZ%=d z0zo9B%P?;BiMd8tl$05md`JYR9lnrVgvN*i0bpmx2>s{`aBj}4AWjq zUXhKr0NgOp_jO%=9v5D*b@<#s83GNnD+m3~BMOyAf-unocr#cG`1bMo2o0M6{2 zu_K4ihZ6$JX@wjC#3)@!sysF;LpJNjz!>zbA|Jj!2bwZCPs#wiD7MK2jBu`cB7 z*wzi!f##h87Iqv|K3su^Ezf&C)%V~Vd_9`GOJy8K&W%}!`~Ll|{SC+q&XxX33}hP! z=VBBe?yh@@Nw8<8uRHT`GRPoaBw^YTpFP{STxM2_dg|81RFQTX(dV-9Ejcc3ZE(6N zzRj_6=IwOboBd6x-UAO+-R6WOp=!tO5oc0KCW`L=_T&t0OL`)f){h~EUGW*+!a#B*B?8xQy6tLwsS98gc*tV|=zMNB8Sy^jkE@JpREK#st5uuO+oa$HcVduV9Ga%Priy ztKkpWiSNZg8MzFla^+I#KkqB`=7Iu zF>Am?zL}m$O4dPMtL@U%)Vvsud9xi)B4J_>UTIEgp=;zJ3lM$EPJ&@Bh7K4=9X->P zgsXBoicJK83C`5=f%%q8OY2_cwr@|wxtv%}o`*0>WNq^PVs6FNiJv@a4HEh6lWDJO zRAckvwvUmwC{5a6po?sYzml7k=a1*P)q0J-@cy+|l-e1Ty(JJ-Y#G>qRJO+E380>4 zgUzG7xwd+e0#gIvg4jHy$^%eQB-L6}7(626F z-$PIMYFaQle7;GIZaQoS94WeQ3nlWBv+~lIWnBt0r$o1dpMxGyVwm|S>EuiXN|fbL zI^CV(reIn4H17$EOt*;dt1Dq4nI-1y9q!U=7Y+KttgIYBi|sQ0_Ftup6r z+wDcDJd;VT+Z*m3uM@K ztAnjvUJ*hu2V2?1WT2-Myy(hCB{bw3E-bTiSh(<~B{|O`f0&tCBYMb8V1J;OUX7k? zVQxvD)o@JXR=Tt`E>b3PX!q!wP&(Avtoec%${vA@#%GXvy+k@v>=4YLH@kFPVR*dSPg?*J9t`B-)fu1*2-Wt{d z(Dy}8;+x*nRH|tj2}`1o3AHx32yvx?Hi2ecG5pwL*5MX*-gQyy#!ntkynTJ69l8>a z#*w{kbwMT3&Z%&l(;6bCr6%Ts2UJntd#+yf%!}stVPZ;q;Kk2N3%cpv#Iga?;LxWU zM~>KJotc`MNkTz{+{|mleMLBd23i-&ZtK3*9zr@k1Wh-Z>Pmy?f|^!Iey%lmO#7@NnLj zpS=7rr#QJWv+k~uAM+j4SS#?_!f1_pA!>5@s(f1QT8127)A3+t3fTOa>6S49g#H3M zb`1jpI!u9CRi3!=L8$M;<90P0D6cvA!2U3N!O=Vsam>vGn}Em7<{MGg{#0#kNZhyZ z#Tn)X_Og`^NjhLDqfOeqOX}>|vnFJ6z!u?rh-FzSA>IH{|4CUWP3f8}V@pSsl@*gm zM!S^l_K)H0EwBs3GF<(J%fQe@8?I!(Xtb}qHNbFQil557MqB(bv2&A&vcGq4=M;wJ zTdu?7xnV@uwphu!OUaK7DR6~`1_DS^_y{kTfnuBuuS}t5R)|`C*>RNJ_ap;^nX5T3 zds4@%xA8d$*6keP>+Mn-6w?a9Sc*k4oXo=Tj`sFnDYOKC;%m{w1oCDSPwt73w>use zLi(iIDd>b3f>CF5R1j5Rxiu5SdQMW_@%Yh$nm*!MseQ*v(|R2JD}-D5=?CJv9&Gqc zSA7kSiaPI2v7+7TkJV*AxZNyCioZg+}HNnL1M>K+q@RB+K#(sh?&j&>Ku1ClvBcke#_o1M@HODMbeFvS^OH7g>muSRN=e@;wLp1Rv#Psum zIyfNlGH@+(`V5pD;NYk>cZVrg*^_II(BR=+?juHE9XZ-D@=g^~JKj&UM)!4qP!0&A zM)WMoZR1(N9RxMcEnin3;2e15(#v*19P>r_`S}JEKokRN56+{3AnM# z^ZZKh(gsS1hok_?Y=fd!pJPlEXKt+e@7o`!t8DL65X@f@9GD32LYOY4Brx(hMNHyd zY}9ZiE=q&};4yy?@7U;XNlI$3f{!LjWAo7H>+{WbBlNK^#*)uM@nmb{+$ZCLpF^!V z+m?Pq;B4su{jcQ3Oa?AlE~p*-a8`S-VV+LYUL?HQ-w$(-9S9%7$$tjkH?S(4m-E0A^>A)K_Ua(u97VULWIGe7^{m_F z?a(Dg;LYWu*Hss?3M6l>#we{vnpZ6v%t4<+A*9D{?;qkAW0!7wPdUDT&ChxLXg;B7 zRt@7|(|W6-g5Sp+O}FniCc59GchB&!d&Kxmrc+KzMx;zKNRHl5$HDe;#uYxNuaTU- z2Trb5R8&d_Mlbse0yCB{h&_l9!)-`H=klF8CZxxnh^$R#(+XWTOxfArmsI#snw=YH zAyG-~jjioJBg6E2`~OtmvlYhRRxSDqLfr}0Qg>~F`kEi6Dj?_L^Wg-cEqd1WX$q+M zmR|C!EEc?7rZ%tV&ljq@uX^agih7+U;b~R^p4{6hYbByF*H;f^sidqok57K6i52_>| zUkNlZifxTrBV=~N{s2^s&&$J{9V-J$h5W->@K1NGOHRtTj$~H5;JKJ}8%qmyLQ8j_J^}K}ZUfMV?F?y~MNw~Q0wY@kd}OzS3~%4gw{UAPWwJ+I<_9x)1Zo@j zOpSF+OiZc?@GO!m)VmwMhoQ6SHT^l7IurNaeG>{RFwCDJ72JCK%Xo`8 zm!q;bAjga4RpPhvw1>Z^Lvk1TTE4!xyVy14-p5}{xINvy>NL?dhvsz`4^P{s6w&e0 z2|zOA+!md}<2_e@HgzNLChS;#koj^c&f_LK{Yc_I{4_ zr3a0$_!E|5phSmpDg_#mr_;%w6D9qcRZTqPwB@i-L{yYM zrn!lV`{@2;#YU8F0=I7hF&Ouv?1S0&nSwEV68)Eow}6tmz_fcYH&9nV`j%M2X4^`x z#o~aLIL3O;1%wa^85WNG#Db^MuA?jR5(7S?(6daWZ8`0(3#VUz#B^J$X3fuTg)S zpn_GQ%82Vw0PM10xO8EU?LyS(tz81eBA`drnr zosTUg)w!=OV+>#NBYn9y8wBoj*G<8z_2A^f8i?9rA+RcJ(lKK;@ON-s>C8XtZCPA= zw@xAA@0M)1COsa;fJRSD_MQq+J=}Ay)+h3zyw3kq{@o({& zCWL(;-yK}NLBqeM@ID+#fy4m_s+QZl#=3a7Z5te5rx!`hYegEGfL+ zcH{dJpWWZz8gkNFgHDMk<5np>t$sjyUeJ5xzw{=MNUBn_SzkN|@Ba$sJbKi1u%+F& zh@<|)Q+m8SLj?Av$hY`@2dKoN`qHFBXKImlQmt?f%IobGF(9x4wTY}Bx3%Ns=g)cb z=Kk4pXYPaa1J@5r>mKPfkVirzP?j&ph@hdY3s}$Npa1U!x8DP(fr!hAGT#>W%RtcE z17pPRC0eI^zK{U6P=Wcd8bW2VqN;%#8QeswVqLsijA7@HdR;-Px z>c$l%99S6Q@#5y@Hea$Q?I;6Gm}sJ`{d0l=3M2l7M%6jY%kJ`)1y^P_{AV$DSbXIc^@I$%X$*x}juviejwt0&d=dkhaYVM|= zc1R?ztn>YV1yJ#s1p*IM6(HrVC2n5n8TD~O`z+p1#6XiPkW)FMjw6_KIHbG8b z(!MtYh6RF3vD*%a6a`;BuckAq&0yI5QGcG^jVn z)Y8T_n3mdPzit!@`s&*!>bmybbWHItJh?rlj)moB2^$jM>%9|N(pMQMtEJDgS5VHg7A#O%`&?nI3uroVjh6cDrFh!;I${F;}ffmBjXm>raR?5qkyTD@hyS-FN>)M(z zJ3G+eM>fb}^4ZETL?Dg4XkM#=Es!LnpayTNvR3Q&RUygi>BFA zHMHvfU8VAeAjn432O*cO^{PzEyLU4NwyUqo61)=V2Tl|KxycdA=J$ziXAmOB51Jyw zV#@5kC{w>d)SlD2B<6WTj=baByyp^#spP9(XjPqw_G z!o&&Q+R=92O>UhE-#ktDCjSA0r{qkkTmcTPwad!f$OGdP$=M}?Zc>W0w%{8YVbwLyy- zQlVNzb0zwBV>dRrZ*!ZXbNwxKZl}n3Cjvtab51QXnHSsV>Y?s_ke$}?Hza6Qe zWOKMn;WhPHPlRt?zTrpttMy-Y*A9z?+AELEdf_;^cph<>atjKTiYkml>Ur<#|DB}@JjE{6bq6Q z=qqz~50+Wok%AaY-b*Rb0Us#C(>^)i!Sp~<8TJ$VV)0V*bZ3%tS8+^#gDGt<1wL($ z^x8YRE75;^$`z+SM{>R8vF2?!_aMQ!2OBQzfXYAL7naDMCdpuXWK2~B;__HgSLGWz zbH59h*+XCffo+ij=Nkyt)2v_8;V zqZ78ic}jCQu+unUt~(x)K%PPSujU3!K;7if&#N5_q>W)2^t*=$yjE;%)o*^KAD)Ec z%+aC8qhWUeRH;|8<))a&mo|05p*515N4ju4uL=BadVuS2jjXWS8>8m21Ut1G4yC?% zj{i)VEWXXjadNj9IC?Ehm&t34sPNVkJ2{ZIJEo%|)j26;%Nw_rx*5W#ia-|z#@>ds z0zUShRa8_*u&Ru-P#YS}|Lv|HcFXD4HK{Fa6A=@W!i0cwFe=`Lw;DMFa@a;=Fq1qU zKcW9j{2GVBoJbC;f=A}Tzh$&p{y~6X_V?LioE8R=gQ+#D2O6wEAI|gVskjO?Nf3ma zkB?mWH=WQx69ysuOBI{?P)ipm>*L33qGl_xGOQ*IFef=-XzCTBy)0Lor${5V72x-A zp#LRWJAIfn{IXy~mzUT$w#BP!L_UKdrM3?yy(|gd@;;;C*{dQy&#?ZBEnQ)LIH};u zzyFpE6@04u@`8w%&ixTGtmWv_^X7oYN$B{siIQ3&a(K}b;-gZnnP@uX%*uOBHHtN` z@Btn)I(@iJ@Kztlvo4bNuzky(nJoIuwBcF7ij#6tqT`~ZJ#2cF8_l4o@6n(;{4kUQ ze7;b4!LzEijgE+y<}-Et8v9X3()Tah9t<5jR&*OSP~kY( z$R7)f344LPd$66F5BcSsvI+whsy$*gyU=_5S$gu&l-`3ld`0T-xBC6<3P&ZNDHN!e zN{0^W?u2=YAo%d>eR8Nge{z5;&U>(F&SKl4e&OY7>htgjkJbYBcFa>R-`KQ2IpXg( zIy4PTg{?iu1kNe>kOKsA>>qHB{qKJrBt1)?XTFq<3+-wR&cxbfF|9z=&ANFN zj+^zW*6O$PR8$6pLJ8L6D!<?qvm>1KfVBC- zby$CKtHiS2+<$XZt-OO|RAeF=K3)RmC(t9!!2Ih)aaTrQ?B11q{e{NfF!m^v+>>*y zyRaA|>k1kS1#)a=qr-rFPZ&v=7PXM3M2J_zO_T^V+JUtBSnN1Sbc$WVeM}RJv)o;K8?%V08s2K9M|2QAP%DKllXK((Y~Z?7E`C+6XG9?-!l8X zG#B3oof2`WF6l}SyYmk`kKiLrwmo``_*gQZ9ArN=$vHLN)QMBvR0yt|IuBOn2R(1N zP}t8)Ppp0BC4QmmS6&Wm!x?Z$aZit?^(4iPh%6^2Sfi|7`Lx%?B7dBnfzcED5xnaAN_5Ca6uCjWDX5#0k#SlF2YN=7^{>{r>tdmIFDJA^p@_hx3?UzunkmTqiwwFi zbk5(*L`w+}IDFP3NHg0@Ko;%r`J}hPIa3 z$vT00&Gz#i)!~we_`e6{k{_lToNCxP1%ienwx>mbS^9Yif8Dl*ERKrRWf}yEV^(%) z2W@Elb76_X0=Xx8dAb2~aVnb{Sp~_D&kW(H2+mFe%z-M@x9c(jA1h-32H-bXyen$Z z^_^3I6cB5kH-||mPLwtHIUL{r@NUlUX$DpAy|33b zRV5-J^9sVyf89{}z@|&f4XZ$cXpVI(;9L6XpF-36UECWDGiFc#Dm;k?0o^8(b%fTq zwn84P^4EHvYWPYyaNT*Wu2P!<|5Tgl@d~uD-e0Yo8(er^Fvwu8se}G73SsvIWx-Of z4`e!z$(~&|OJo;B89aafdPrLT)&9%Pi7H} zt|&!&zO3L%I<;U%ah48SbTPA$D|SusoQv~t)9V_0Cn6zc;H!wm{JN9;U`+*MSwIQ~ zGd`SgC03Y=KsK2GLc9MXCPK<#?IxBi_-3Qd%galI!H9$CUlReFKbTTutp(lA@8m_{ zpZH70y?JvdfLXa+u<^Cwv%Q186XWd+OnHRB5u8KNN-Aj;Kn^|~uC&CFO1KKZVeG-e zk8*4HFIfSN$l`nq4g^KuF9kDxXi`UJKBdy{E(hgMM)GqI7yG+hU8r+f(=_vPTPPm% z`fD`k{vG@4Y5zaZR4nnBn2J11`scuQ=*nBrzPcs*v%@2tGU;-4iR3_G&A+5)*;@T4 zSyk!DU{n!7ZsO~2Vb~SdcMq43U}GPK9^}oYV76fV@&$k~U)`%6!WEkpj`)-9m6ev= zpq5nlAo;C?at5FPm{ommIS4kwVhNSA@&vR%nfviB8G@waB4e*|Rvo|)tUSg*4e!IS zjA@|Nn86-|H4vl`F4h(T{4sZ6tU8lr%=lwm#Pe3)lRX-&=0FZ1YI#Wua6y;nH(?Is zugN~kpx&ME@09@kVcfzfR~VQV-la5gtZ941B{%T67(Mq|_pgV^_H&nm-d7Xft>-3x zZE((C8=R}QBjefai9;Tt8(5tDvQp8YLM~Oa*#yAC!0#n#hn2tdQuqVATv_mGQ*OmV z0NPK5)|WFs*hrdM`ep<`)Ooir2*ww~_RdZb+NxmSBuY(P{q4Y<5FV?>#b|k9Q|V9w zI=QzqBTxVH_g~x4R~V3cAi(j!Baesv6!W9^ zZteMkXdAbLP1%Wzd&@7~ung94d$1vZi{&0bZp}_A?GyVqE1!f2{@wT&NdItWA&;fi zVnP?DHgg=*Be(|aT?C)9I6M230c~)>mk>OI;n)Nj@qOH!^i%+A^ePi(?sBZXL8hd= z3gSg^ykvL-<*_;yut&FCDiKV*Ha~^ZPfbKI76Qw#iy5{U*IPV^B%hl@yNJt9I>Is^ zWkIi1ZG4>E#geBGvQb=E9vLm84vY&bJSnQG?=F%Cl49iJ-OpO z8=Fz+X++y`2zn})uEerz=#tw0ppGr{A!1k;h-@B}4h8nsM+I%#q-=U=Z#I{*oPbkP z)OIOrUMs$FK+ph;RxY)4{Q}b~00}iN73lMwm+Ex?zEL~ZA12}rImh0xw~jp|XfrJh z-w3!aIsg+d;d!F1EB)&o&LnuKX{q^s`2N!k_}F!mwTGH)>No#U+Z6Vz2$4?A7p%o( zAh((;z+Lv8bE}HhlEc2B)um`gQolM(h|3$tA6w`RcjdlXzi@7c7I+ieZzFoA&kq`k zc2{`+4cc_z7Qg&;r{U?*NBW-dbfZq)ppCB=2z~@QrX6Y3l%0LKEG&G*v;gALfH^Vi zfKBQVavQ&C^U)x`c`3oslDRgQmJkfCAZyd9U0qYN&|+G;T%y-_?svw0h2z~%)lj5e z!vW@&+31~kfa3c6#K$!&hg=ISgbV~~C50*P{C%$V<;=wgMe)_laWBf5Jmk}dH!XII zxI0D*IRTyGW^ud>&~LRV!nkVJW&=9$<5zc!$TZ#9tR~#b#n6fW{<@>Xwu>#@oNx0S zZ!%kC`}cYmzv^K>0(ymmEkRwldBkLJsq75s*Js?`CDUxC;|XH$!r_RwfQ=BwBd0d? zmZ%!Pp24Uv>}TPJ;QQmit{j-thIE>|U~Gxa7)-D=k`*)1SD9G4rwSe9aA&-;9p<=5 zTDYHZs8_Rv7g2~l?8;Gn0%N+TTt$n%*OY&bSNFmuiYZ_}ef*6zAX(aHiliI%*H0K^ z7EYNRXlR-}Hp+PN(b*r!+1k)xx1p^LXa#=g{YoxKmEAvFE1qS(XaQM)*dX+r3gh}) zyniEZby|Ll=4jFp{M#S)8~m|}j`|Y!t2G`!(txRE&O+E2><$A6Mx#KU?_%eE1=miB zX5Uh4%pA=MyS7!TYjj9>%P7JwrDM^s?OA32MTZv|(;naB4^2$)J}CO|Vqg#2E>~iE z3QA1j`B78KDf$2p4A)vqo1Cp0cYLnqR#6g>VtV7o(u)b16kv8|Ze5UGr-_(h*R+kl4Dv$8*`Sed1DTIMBrU0e~P%_4OG#5yQ$?x#JU1bQo3|7m4sBRMu@$l>IgF;;Jbbn*WzYqz>mp1tsDX+cE3#@`HC-q z+80(DUR@-W)r7BRJKt>C!j&w327GO~zV+EpH!d?QIzwtCQg3X0E=>7l$=}rW$+0Qr z8(*td!II^bB8?c@P9R9a@om;if1IeO;^J!pH*hD>rrt|Cie_;1T+?zUAT`pDizbqm z)fZ*^v3;zD7eliqSa5crWgoMqHpXoq4XCnY;kO!EQxZj zJFE%981Pzo|9{#$9fkjfQNPZPgfl-DWa_OB6b*gQFZA5AKMSwK~>A=*6Si*I3Z{mtPkW7g&7m=fh4IEVA{$A0gLyU7uAVQ1hA=p4U zP!=@RpkflRc)TN^#K|-D9K2%G(~3z0{Ju%HnT_FVXqU!XyC3h5PYWGUk)r7Cdh{1t zemeW~o3v4xe0yptPz71XXo2+sTuXcV*NJD>z#;ut9CKy!pXaa6lnpr{73IQVZU-^; zpb0SBS2t&@AF6H3(e{HTxafXnH^i7Z3#jiiswe=jI^)=u7HUV*_iW3F2s_pe!79T- zph4ll+aMP@=X$e}c(VHsw$lK!3*xsvpgn%FB0Kyr6hIv!HrKC*DIYs_Y_>It(g#2| z9%l;~mVTJ&Z+|fgKJ71FbUpK=8Z3Y;gBPt3vWn|23D~2*;@`FQecj4# zUmWkd=X>WzS*kVIK4mpT-7S`YydeJ{U2g&prPn#AM+GH<;A}WMzDNB+qWe+7gW8arYNw(yZHG3sX z_Uy7JWY4~jEo2?r7-r1O|2~60pYQ+s{oR+4nfu&(&pqed^M0T6JOja*;m}B+_ojo4R+%fhVo37PjP`Xe_kIuj4!qj1YR_I|Zz4+&v z6KFN@QQMS0U=x>mR=9a@eKIvTB#5q;YW;05dVEW+N;9Kncz>5TAi4VQt`P-VM+HC0 z1dEL#^DoaqV+Nfc)qqyro|^hSl`%FpTP2aBz?-^)ZWS)7tE(d?lW{YyQM0Y`XgI5e z!KSpz6aptgF1r=yR?mDGg1YN~t)MbnD(5Ri5-75Cs-zOzpL_s!0R4*47=4c0jzyMp z{K!djBTUBe3wZQjxJ%6N9sT1=OEUQhB|6P%g8I?(t6e5->Sb>$)+ZEl=7-RgeW0SJ zz;4RCLTHN(BW#<70$KUlHNJ}9+td}Oc0`DfJFyoy(koqoA7@YIXFkZf4l7;als1E$ z5<0OnTzsR#Ds*V8k1p1fj#=(6h;5pmFtb4gmnRP^;Ibedzt&_5;^}T-ob)C9tw=ZU zC@U3*&vG=(Yo|k1^CvubpGbcA!u&q}7FQJ~x3Y$3iEd83l|(gQiB6VGCru5Oh&KOI zm1ljrCuF5plSNe`Zit{4q%e*-qfmp%gO(pY~$`ku@KXn!wkW-w@1{OjApt@y(eVJd~I) z6D{ZH(dX6l^XHND5jVUi{jaJJ@Kh7EaKPN+(Durv+jOUoW5LV6Kmmo;l8NM2|AG72 zQIG00c11RpX1E&y`6(lK%^pJUVa6l}R?1xI&wa^mD_)m=;C?$rc$hyp013sv_o%2B z^wfGXmyqLPy+*&7{|WZ?cRG#eht@A)(wvRH)K-yk8EeF&hW2IatM*2t9D!?ekdiT> z@(K1V!*LM(_z_IT-4wT6gD#@&MIE|67z+*twQ|U?FsdAb4t`!IhzR05K-^bH%+x)5 zhIzB$aaH@()LNvYLYgmp#|B6XtD7pDn;TwzFZARxCXAaf+>!KpzEC3}tk!lt{(ihJ zpM1Ocn!nj%Ic3fxbtfkk@K6D%7~J^KW4CD^?C3`YUWuIh*j)+Ogy-!M$w3@1A%&PT zDWK$cY94->=j^yG3?O0Ka}-r5Z(Cf>aBZOmxGE8r0znN42U9)5>BZo56C7N-_%)&a ze(+MpfsiH|r>ds+E%4qfj`DbqJYP0Fr8 z${=Fr=S#8X<(we?H!m}*LU#Ei=3LJjxt9B7HrC>i5cFgGVsiQRek0?V$WnlQ86(4@ zax&w@{u7y8Yohi%HdJ4g?ow_vv|RMc{TlwauA5qFwat z5k{8`++FZYrMu*3Dy5wjL#Cb@QJSJXa|O86=m9u36sYK3T;^`<)03~$DneUNLI8JIyf^(yLut(AY zx8A-!Hy>8uvJ!dCdj>L8SJ<{3ddU;f&COV+0|$iv@OT$HJq- zQh^lCo_SAoAWB0?>YE+qjc~R1+2t=EOr104O1*G*%U8>8fNjc2x@mD4YPJdqZ=ktU zOt`IkR>|+lI~wFxdG@EU85@VjmaD(UX3kk`MLKlh8W+RXhc}&8g}1g2AsEZDi8iGY zn&0XQdIf4y5B04-vXpLxHzG66W3fM9zw-qI1+2&|&j3c_KFyJX1)|~#zP^VmA789T zKX&-MWnRo5zoZ;I7U0-qrP?u7U`?vQR~4u7DW<_U)GsIJD?QG_s$IH&&AB~s@< ziC*$T7z-L}d1X-jR)lp#u(N4?7S$un-bgQYcRpaT0XXuD2Tj|D0|A*nB8Cm*%;6AXS%OOMFr(zwz z=}N98xSTW8s3L!Uxs)l!%~k^gO^aHgVy)8JH^GhV=$7u!kkiA8v>3dsDbP=!5h&XA zmUHJrLWymTnYct})@+nRzQ?9UD65!Kove(hvRmZ-eP;TyMWE)+PJ~Il7+64-n&$am zs5c9r#z%i1aSlF7+Al93K!4pMx5tW6P`l9lBdCDT9NE2x$~(z-r`qZ~3lTX!Q5*Od zg>;+qrrz~}5_JHaP3{g>2Y>`D*mXn+e8k-LJ~%k|KKalxTmv&fNKZVU1x#$42KgGQ zz4tI&PK|F#dt$jWN2jv~8;xH7-UnUgtTN|(d;non;6lI$&k@#(FP$XehEIArsL~3) z$q-M?m)RN)TxB}1cjY+adCR7@)?&Dv!5oSJUT#sT{h`$Oi>gsKaiyMsZ1KcBIv8>L z?2Z+@{;KxE+u^qmKPbZVBY$v$&7)fmw`{s=PMZR5$cNM{xjlLNkTRu2=!kJxmswQT z)9v<}f6&*H97FYkvgec4^a)ZKMQEXJtkKMT@= zD>qXVJ)w|0CZ1$<(>JcY0BCKQ?(5cQYga=lSo5o>BC~f8_qk_wL=&OP7xyJagpU3m+)MLAYqZ zGH-xA_GD(>!1Ln9yf9x?QNh5VUr~MQodedy&wLtafePd1O2#Kb7-z+}GFcyO4%2({ z2Qk*nIroZ_>hXsV7tZ9Z9V=XJkB=#~^PA2d{&*E{cfX=iXHrwK^h40xrmkSGp^VIy z7*L_XQcgAB7v6bxtKm`lAAUkdiglGFOb#I4iXS@U+w`*u+|Mbc%FBD@ju(sdKf5dh z;&%TY+cPuHLJ=5Gew6SxGAS>d&+>kG3cW8a^j^r_F5cOcGRY@jQmb?|CLGP^N@KRW zj1`Gy`Rrdnu3s=PScPyt2S~R28t)xFPR@Iv{@FY#Zu<_Qf>S3JYi!Ylva}iw%R=`q z@?wc=ZUWu>sYMyR%y;YNovvI)^Z2cM8Jo}I2_p5T3t$7Y0ZkKTJ z95;oWvhD2Fg6y2i$mDmKi`wqvP(g4JM&65YT9)ew-R;=$J!1#wuZjdVq5J;bLH4piad8M5dp^0N zzo6bGyl?Thv;pF_W)mORBPC=d5b?`Z;7{vt74X^fXgB^qe2?0l%Fx*(2cen0nShBL z<-D1dbV&%)kz_c;#qr(9Q53i=;l!bjWpV}G?Lt`bxz`ZY*8$7G759iZ>f|Hs>A-QBLh9L0i_P5$>zN5#wuWW0LI(hQ=kY%XiVU0@EaYULgC;;2<*IWIf z=MBiyWR7OQo(l_Z>w)=S(9Ge&6HpV%D4JYdGwBUiB3F@l2o*uV;){z`#xI@ky<@MD zGP@?(Szv%sT5N6NZa{*LRY2_su?-gY=A}) zuHrda*YH#GkJ~wH=lWPtbG_!_LsS0%eDUV<_wTzF2&Ivqe@gL4o)&)t_-&^d90jlkzHja7)WNa4X`t3=i(Ko3=t*+!x-~aa z@V3VaBo(iK+b#mZEwOt?0lD+zolN7nPBF{Lz?>@=A!SgNu?m-s?X^PR_Qh+z?N%wT z&K^Q|+k|RRUu!Lk-=HU#T>*U*0E2_v#OOCdwRG-}rY3DB0CM))hoUsv#p}PFp8wYF zq(mUbp98^|Neuk92kZ`LM}z=JLcR;K>1Z_&?_+)Fzaz_3a7|J_lqd7q+eJ(KB#%LM zl*VKQxvzH&%%H=2Q^ScEfN8FCE5^}v8{QgMPrT=!l zZo63zx*q-?U19wLeFILz#L77xMTta?*z%Q~!;^f^CVcxbqsRVh;9fKTJrD)@+_q9} ze@;Ey*E+ky#%bZO5_fq6_8E}p^Ok0Jo%H`#&yG^5Hy5K4!g73}B`EJR3-C@-PI@0D z@NBLB2;s|t+(7&O4p>BH=6D%JBEm8Z4#DYmnFIJ$^B_Vdi0i}1dFC$7sh-~hg{8(hFw>E=ipG3NkfF}m+cF7KSTh1DylD+icSjHRqXLH?OqVxbp+H2h$ zG`xPib3LH?Dpyniy`9?_3Tlaj;d5Of2de7$$2w-L>x25VbqUZtc>l?wCg0A5l%NCY zX2ux!WZP{jL&IVvrR7Rx7fH+Ik`ZD0rXZd~Fj_Ik6xRzt?f#L1yOmG5;r|M16V6@+ zz?3O9nbX<1miJ%^GF(RkqagUZ>xP}9vSLRz>p?}WGPI;Dh&klL-F%N1m)aApzA2tNrp^*nylqm52Ntx-M45cjy$rZ>T2?Q*sgn+}-p;Jha(%5G-uGoj8Eqi1PwrN24%7wY zf-5lxI1#jp2NmG3mHb?A_~mNw#-d#G;Mt$*>zs&Q- zpGTfOkK#V~g62!fwTl54U#Ki!4F6(h8JGU5>G0(F)9JaTj~=M81oHs}(V5#8Mb;r8qtfl1n`H7m{~XyI<+TlBWCNs?q++qy2o zMsNGKoCGbJ6dlsAVPm&Iw5~$8uFRkuFfHvcc8{Yq!WKWs|7Jf;@jot!uAFw9Uzr?T zZ3)2Z6KWY&93hhPgg$}TY~scXA-K9Y^#=p0w!26-z1B5In?G{46!cdDH(y}O#~7o`Prx6z9j8NJau*M^f~E4ij< zzqI=}VsFYxze?hXm8l%v0Ma&XLNHNSbi+adHxRs8pSV5Z0$-*=SwF}c*VQ+9HY1B) zk{i*YW*uHZC(B~-hks3E+kwM0Jo6WL}4L}qQHjiE!S4Bm=s zkAT&X8*QV$$8^9Z2JJ3aPGa%osVor@UYVCzA8y_J1+L~tn&O<~PS6d`aqsGJAw(#N zIeuZv`PTimPY)@Vsw&!*f1uiDb79fT!`7af&+_DiZ?M#MZ2NEk6@=S3K*B+rO!{=A zxW~!~b96wA-a*i3pa^E_&foU+3n<&~SUtjKTx{*P`Su1?CHV9p6UlQdgoS#~Dk8SB zfT;?byvQ%YfC!%&wBsiZI9G|IaC3!uA#l$)?wQXGMlomOW|yiA{UqK*^W_y6L*;vM z18rMGvh4OCM0mS7OI3ae<>FboFbSUjZPq)8*&MfaG4$B3a*tYtPimX;JiN}v#@UfR zwh3KGh%kAU^&|xC**8DwK8pEP z(rp&*374IXiHTB)^LAy9WwHpo3=!~Ce!sD?LG^XVV?&4!$B0efYE`R6sS_Grq^Zrm z#Bv%Ej!N$>pVf(GiF1gS9=nWlXxFYn@@`9RHECQS!po(CZK%T25sUF(>yW+)K5icT z5pGweJln-+(C*U#{?@J>UL=K~m6{o3y`Q8bH}SWVq#lZ{&KT0&pxHO}!U3W$ba_@t z2XA4H>xf%9cGhBLNl5Q1UK3oX+SgvmO*ciWMr)Mdyzt8}kEdN|_YhW*Zx<`2hyO_~ zJL=!WY|-ANSn1rjhD*vU$lq6OJ6Fh_plMcjI-^z7tfyH5_J=BGff+q7{p5t0)zwl$roTJ(963D*(+ipJw<`Oz} zY-W9|_PyC)bKdqQ-M_DbvoyVF$-2?b*Ph;1BIakF?!aFh1iwq=@$N*55gyRV|M%-6 z!OyE`#JbK%td>?(5bmP?b54NFO*&cnzF4y}_~5bVl;wBri;IgaZaYWK?qtX#Ei7`E zD~Aa9On&D0`oFFN{d=L=cg8kx-Rwm`XaDT!EcrU*)#erFEE9j7s7^6!^V~I)ok1Qw z9w1!p%3Kz6IFM@=W1qM?H29(N)K|eCfjFnL^M-QliE7(K3V03`SitqZ5s3HN2eq&_ zD~RrdTwues8dqmcj7<_h0vS#K84e6-xIkzI?@5Uh&)nVd?mz~b=gn>q@KpmW$US*H zQjJuuV)xvj19ik#vUkOTtppa`+7Js5^nBV+!*z+mV0UUCaCw%v=z#$fE)ajDl>k#q z(HbvxK48-#@XAOlL4g8c@U(@vVZGs}v$vSX;Zt4h_dYX!JcQ8XA@AOIkqU+lqE(oY zs}~)@+gDYg>q}he-sc=4G!a`Z{HF@F-6s0>BUGezdbpw~#wv_$7KHweA}|N#9~%2q zkiR!hT*QD0``oc=1R^LIEQCixIJK*F>~so{S<)iBc8r_Vm9l?_IjD7$@J8Bj`hP6F zObCJYY?a~{j&1~&9#V7|tVh5Yr6)>nk{l18RB#*1e8T~j1PRO`5flhbE-*#1qM%<3 zcb|zga^;0rbsfJkD8?5KVsmoyzRwVx|8uRZy@exy0sQft64+U-Y#UU?zRk}mxjfAw zQScn)Pj#60rb^6HH6+LH#f4)9tr83!=H1HM+F+Al-G$eNwSzdOufLm65gnIAQ5T_1CI6v;Wz7kYDl#J(%EX zdBNJwgn>_vyE+Gt-!in2Pu+|p0o~T!Qv<33-dgv`%WuC2s6T_9ZsZ6;0BjRwhMq!Fm-z!vr(vp^ z-Dx6tUoO0lO5`hKP|ZnBjtAksJ$!Bf;gXMh2%P!3zj(6>QtedFeC=V1blTfVZ@I!A zFzW}B?4o!}Q1VQS2L46m37e!;|Yn69)kKJbzrG} z*xuR9>ucvYv?6ETgVni2scWk$q>fTU_V)Q2gYZLT$&I-;E82v~-0YM^a~7;r-iIDK zK?;%Fab5R}v#&(#I-4kV`OF-r6bWFBY?9~qV5x8j61o0Npe;qBth_hihdppAKSciQ z97A~DF*e2V0W)iB(l2)e!rwpHiS1TaeYXizQ6pURt+ummx2PLoBN;2|^M|TIEs+V! z2rnB}VOW*S7HC2A;A@h)dxjXa_b9}t^>uz}e~Z7kcluSk{$gSFEOo7jtdA&Ef<-dM zcxA_CJ>3fEc$!y-!9ltpAIhGc#mBU@Jq^k7$xdd5^Y5uLqlrM<#I!8>=S*L36kD|C zH7102o%*f}l3ERb{37=u#{QA5IH$qKbamfo{~y`NspPml(swLZKC&S=c;$H|&^>&-M>itk~{&qc~Z>&?* zA)S*X8KazdcX!ml7DF-VvbCY~+*JazWy>cD426vx9UQWE(~E&XbkGR&o3q5t>~c)- zV7G~k>W|i7JAj+LF?apzoB%yA$zNDm=?Kr4Z z8a!2aY>Eg8$dOYals%!OoH1T~@@KXrV}k+^gOTfHz)|nCbgR&*mCnU@pd@lm@#<{w zdjpzn5r~o;@=-bxExSPa*doxn1%P@uoU}LYF{~jo=5LX~8 z&_9=zUZppja{3P{ht28*g}{?umaECe?P%im`||3ul*^Vtb^id>b-At4d&|}}>vTR} zTWb(25X?%l&QQlNcMt{{ zU5oos-*%xsY@y#1D0?9$*|gij#Oo&56*!;(u{$c&+4_p0qCN360>P}5q!*;2_aq?M zX|kW-5?U85I^wdWg#Ez+HSKBs50pIx-{@?8aBx^6zoxm+M1+P$IH2cTq=Cu-SefsI zO?e2Qsw7bV@k{cjfELs}bZ2xfI{dD6n1Ye!I-?>i-wv}L-~y#nd;A43c$M8P({ymv zlZJ#*cniCUz8(v+%$%a6u3N-QQy~6b-tnT2CZ5Gd<6fD?q+SODbS%=k0}bk*JDJ24 z$fn=LqO{?q*%xA*cp74DReF{?-q;fR`fC@&B9lPd;5A|zR|meP+b+x%I^-PJ z4N=ecnl{;q#SsXlJ_CV(8r0RQFrF%OU#i(D&^wd2kX2E9{urXVJe+*&ETKSf>Y5Iu zJvI!5w=0QB| zmx0~RnhDO^8fBf%`Br%jIKF44U2nAKgg)(FDc2vI2+i@vx;pxAHJ<1Paa%CK*4uWQ z9DX5DW&2#v+GDJDBBxw|wF@%_s zBz`N)O#nu)2NBhGfMr~2?rFvN7{p9pegH1z9_(g?^>b^^@@da2_vdM5;|u(`#v1s^ zzntq67x>AADc_xAwW@rmbg1-a`BUI$497bT`ECod&tGO9?L!Fj?V2(HDQ{a;z}37u zX#%dz0v1&Wb;o+`SpeYfQ^_7}Bo1};@;REu@y<^mrcC_zbubng_rS~z2#xkuygLQ( z!#jO<2_W!E1Q?G;btv6gTxb)6}KKwwnxf1;fw3GvNqOFd^`JoNv1 zM}@P!X5>^u^S=`SzdZ&Krb1*!tg|%&Wlh0J15oS#dlFE;^+DiwNB7Pz@|DQ24Q7(C z6l3>{V`})jfQO+9c<;88#v`whQt;F^oV70)jQeJ@8I`l`KZ1n4Wkf;%2K_{NF+0U&sRki|87G8jO)VJ2ACgJ6^TPuoS4OApXDeH6RmNdM=gqnC)HMc8p- za59iB-<~TXUuAcLO;J}7XzF@aw@;k^Y&(rPD4e@su@`YfpWDUI1%!35l zceG{D+0x{T3DpS1PBFn~@$T%ZT_Zlre{MwSe`z)Yx|<3#8emh0DjkHxF!fDEdoSR3 z?ms*u^QK@rJPT!TI0|w#=Q@qLn}ky!vG_oGcA^#bet@bT!{@$*x zf#~43E6vtju_)~`G7k8pKO1r#mfZl$yqQv3d(?gu;5Kg9v7Bwga0x6Zu61(&%rT&3 zeMYC^DfC>+Yc$77aJ~cCn-sYe;n^k7DG>0jlW%vry24=z|90Dg$2jGLZvF2Y|=V1y>EV>mj@ z1f3MBvg)G~fqs!2mqrW+2!`tIQt4!9uAg6wd;#HWZGZFg(YLR%E?Hs?QzhRtTPOgW zth5b)gZE)4@Q{3%|B^JN*p1FYfcq@T7xyRHcq~*#a-e?hLDmQIq5bafT-aD|eeGhX zQ+K8wctGPK);KveB>J@*`2%-f)V#2u0C*ys8Zy^=tX&|G@EWSv;cS+VxcS(6%=Wf@ zof;L8pXj_VnowSp{`Wam!(B}e`N3c4qtplAF|S$96Zwx-)U5DvfoK*F$5Sz96XdKB zZx5GrbOT>ivjL*1e~{Lgq#+ijEirjk^;=n*I%Z7x10uVU@SbFshd~acIV)h8A^K(! zWn->?MrL?$q0VObO>;(kXB*I)LwjI7NeIz!VA#|g?5hDe2m}a=)_RdqhxlYkV6xG| z;%lYb_K?e-N-l9KhH2_sHK_He8rNDp_j;Zzm z(=B(f;H(d`oLdu6oCx6NhEL=|fy;{^lp(j;LI?D7QiGA z`gE`(tv23zRDSCYoS$!g$L=M$cOb=80(HPmO=&(cXBrq8Tqp$?$=e;+Gt9$yx>@pX zUT9YW^n@RvC#tW@PVyj;4j~?1n9heF$W#ykZjsz_`+GHpfIRJguf;M{oL9_y2oPuW zArrwD#~_ zoRXlAVajEIGAE6Ill~0WU)m8YmPo9az?pLnwz`?k>>W1!eaK!z&q8qsqm_V;^bQ&j zN&r2zR9!(7 ztaawm&LxyWtSD%)W+!0=r5{9H8?al1L3JU0AwYUx3ibdmgoyjyq|Hf2egKMp^H~X~ zq5!ae$G-rU>ceN361upS=Rm}ALqNnR1{<`ca@D?Kb%n`6oZY{yLrEgoIlw6-22|wt zgus#kZniCY4~$?fj{%z61;AC-iC$yAz`IrA4*&{>a`@zKtsU57x4qZcLG0}0DiV5^ zcJho2P4P|lSqa&H*W{uJLfOc{u69vNODsSl zr=b&I+)ulV#H<6LIFZM8)DOre_g9g7($BToQAU8+qy9_e6p0a9?ncsn9bt%o|J)X^ zCzUR!b!=jj96pixRZTDxCud>I08liHw)SB3?q(yHA15U+mmYE{6LO%uhN%AZ*8r$f zV!neY=oCdepoJ z(?mNhJxx!+&~^IUSXQP}2h-=D<12>%JR~=7b8S)3 z1qtcGR1y~qyWH`|&|UXJM{J&v@$F6*BqR_qLfkts9?4WhLf|YC!Du;OyR|Y8Dlq+29vR}dH?NnhYseZXNzkbv@xA+dqJU%wsB&>&pfgEuuPZ~RtW_Y zh5MqcDB9ZwrgNcPHcOMMcIEk%RQXd`De&E!W~ZfQiQ7{y+X#rPSOBr6?TJSY`Ip4I@gD92O>F=q zM{Xa!-2&yONmLDg$AS&+KRv+l#br#a?m=DwvfF7rg6;=wKvdYc3NQKgQ8KaQyEek$ zt-M3u;^66BkA6T}PFKy5nK%SWoXG9AZ?gO;0PdhU{zC@9->B{SVHh`clQGXaOcxu* z8L5@3uesmZ?e+m@KD*9;DxXjF@V^O~#DspvNTaP4ez?PipGKj;)qe$HlB^!!gaQ*?|VRT*i>oV}%h=mbBAA4~0%jT3CnJedYsQev;|$l!d+%5A%;%HWfKw#bz>IcMB<}WKfZ8OHlTrE5 zIr{^98k2j(yl~cp-HxEYGoPJA!v~lRhvD?Ox`iQ&uI}ciyL0iL%Ya(N*v3I-%3B8B z0T@>K7=wr;_1fN%M}8|AGl491ifYTAD0VLa|JX$|z#u{wd@JCr#@hddNCAmlHg3ZY z0PEKCzrEr3_b+IkmEs3EGqv}BUxk19i}z;XiLL$LU=WK$@B*L;WX`#_HROxz;cX@K z>sm5-8}|QO*AD+Elsc0fz|-8*^1nugfppgwV;j4YJ>KBoxBQ(q2E2jhV)LpP&_G1o zTN0L1XXWDz@<-w@-H+y>+L0Mxq>;=hPXREsvHwM|AfWe& zCi?w>`d%A#n=^?n*Cp&TG&XDzV;{?Nuls|Xwpt<~q-x`f3&u^9I9XhNqjHN|pUxVx z!ZcUQr~*na0F3R^A?)xHQF3qflfTEqAM79_gO-*A(T>Alu>Uh@+pA*;7`k&UK`F5ED%~qGHIRi_9f4! zhSZWPdzl^!skKaBf8*;kGIZ)|A;15Ufk%6eLg;g>Q{5phrF}Ll zzh!8)jusDsj2-|};3I?qJ85W@%+%_Z6>gu90_G0sjEs9KRGEFli;K&9C?6i%Zd@DD znKvl2=6kW1?CXZ~R$7L5bs0#o_V+AM#B?ju0v zRYZa>*$mZ?emqKuUin#x21VN%>&+rOz?tyboBr_ra#R1gEH1< z^Lzc+3$GElGzz_08qy#HO>s}ARuZmuWb41_{6(hFD}Jt)30+JvJEf2%TcE=nPVpfI zP>MU`CjfH}hm(ACUVudDI>ls3QRSIMK*AYWY9fW8q-hyu#G^;~ zszU@XjWaM=BFQKx{e!)E5=6;PI1JqL3#|cI2jVdKbak{RY?6H}z$$<|zlodNRECyD z>*NxuJV$dp7pIiSMJ%Y)oVrA)tA}5N1teIlB_U3U&Eeq9F;K+RCFG9X9weLmI@GGS z-3h9QK-pRQ!kdt1Ag$2aimJ(~lD8{9J~dzp&J3h&+GzmL+ERTkq9RLW}mav+K4gwRe zP9O(DBap7-<}x{xbqYWO1aoyN(qU2unl@b7_H0sS*_=zAsM@B|XMk{LxlNpIB80D^ zJ!+?1W*B%IMsX=Z4JJs;M5-5Fd13~_QgV6`IQ9Aiok^Qj0TAwqK9l}R_gr)WM#{?3 z?`x?&)@jo1YA~>Z&tFJ-$E%;23(a>x=G}&6LjE1XLH_>1i&B6)1Nb`Jv)s_gm01W4 z(wU7XC5HGU_f@mr?_vjuW>8rG(*+=3zLSIk+ryY8o3+3O1G{8V6Hi{PY!#(;h0|J* z8Sn#5$56ySQ%DcOC@J1O5+Zf-EB~-26od6(V@cwGM2D`-HfQtJg%GCrLPiN6o$K+V zxZeT#*t%9Jk6Ovi_)Ta1ezC4KasSr%nnzp30ITE7<+f>#Hc0qwiM3ak$#YfmBxAeXIIS#jED{PRK*d?l$Q(aLhYp<#*7k$xqFlwVvgxm~R@q1YGIzU_gq>D6;DJuSIHG?~!f zrnL^4=WaEuN)c+B7=kt?S0;LwTiTsNfos(nDVxz+5-@c9@^~&9F;=c+F7(W*)N|Re zyT;}e!;lZ2kjL)`O)Bx_iG}$4Ysb{%%th%Pi|O}QS8B)nNRChvpc=us+vn4U$?MIP zf(d))?G_0-q{9(S9H6`qaSI0|u`8Ryi^Q*GIbN;Fo6FcLHWYrnkYAD(5x&@7jua;* zqDh0W#;}w@wif3{ar`WzYxYcVqPN!=LSM+?Egn8~1i@)~)7;i9*B&I%_Y7#K!=igUy0iJYkhLDCWcm{>D% z@xlb0@OX=@C9P6T7E5^I`$w=9c+3h!)X+bjqv>dW0RaWgH$7wng?yfl+ric@lV9=5 z<+*2}MHWf->6u$R&CV=#sN!y8%GGxUX(n?^z zuNJedtmz?2QX`Vp1?I|x_9+8iz-oO7Zvo2=PD}vGWW@6phHrqVv-x(|0A{lwIH!qt zzcJK4`j&(#mT+EJvL^Zp)rELWuE=mAG^IyLGvJtQE*7(2Sc*y@JlqaaE_azW8FY5f zpmnXpkG_lz2HrguF6`kA9YMzi`*>L7mwyKyvSGSy>_X1fVpc_DMLO_}z-mmyntsidiA`*)w=tl7-`p(lc`@GkdhAQV8 zHxo`*$`OB7xh=J{pLVCZN%cC+-#@K&`1ujU@aV%by4Ly;odd=0wGZ2DP0FBUte^Fb zgNP+Q`OuPrVF{N9<{6^GE~@9iAmqx8MmrgMH^|Q3#c2?*B-`*-r4Y8|Bv}$Y%w~Sh zSbO$pZ~wrDREW!BZg^3$gf%r)Rt z39YdHq$66(&vzUH_}jNm`hPmo`aX?hCeBK-AksgmD;RzmdE@U74*v{ME?5o_qB?p9 z%a3@v*{S_!E=z-SN)vLV97zc$Y}Y6e4TeLEecEcYCIo7lGgm~QA>3H%q_MMu@l5}0 zFmOjSG{89}sVlTEB%VM#4rQ0;DWs>Nc?VAC1ly;klfM?Ln&YRViTV3J+#hU}{p{X; z---nX@xw=CF4x}4iI;8?j|GH+q&lFdy~RmuIg*g2$ZQ#ECB~(7O6ju6e(#{)xcmG> zoTxtdOchX$yK;$PO}!;NY{Ob)KZ04Y%(3`d0U&@~>~8vgTtqD|QHs-J(%e5DMu_FH z2WZ|}zY$!^Hvq;&oRbD<4AROrMG=nn{%6pNAqd(QN|0Q2O;rtIachr?05udP{*~DF zN{MV9!M7g7H5P)0hwa+B^@-u7VAghLXspvr@KYqtx(2Z4%X8LJSV zR89o}Ep?wV`v>DxNP9Cs`%Q$g=I3n#FSvvGxnu%QoWvMHUhk!9XY*F%g%Kav547+H(L_ zzxPY-9g*Z@A+EtPR&gXF%5Ng#e2UMtvW;Q+K52l?hN|meHs{eER+oXE2Q8FUZ3wP3 z_4K}Lho-2MiV<;Bbu}ksL5%m1#B?4pozjygCoQdd=KA?~wqvuOVq(t`0)C1LGOhnYJgy#U2>`L!G8B6aZ zx~PPF0YFv;OS*EI&&e8Mc*D`b@-|86yj-zlU_6nl$Q`8eQ3MMRgo6Kl^MOMmKu2Cb zuLyw?_ESHp_EyBkyBX_-jj=yghe;h#`g~Jj2$e&ln^S#n3EO?d<@zrK{#43pB;`SG zSMzR*cMF6!g-}c4#~CBBM#Ipl!=wiYgUS@-K8ZRsfYyj=5dddF-BOG*$ztdczY7OU zgrb0nm;8D?$-@!G!=WXC(MV`VL)dMz80n-)0GH}X?I_QN`mc+w&q(SsNGJZ83-=$L zd=!~&S8`0K5|27gVNrc^0kY&7liY52=3Pj#LogbfykT;A>e9Et>$HHW7R7J0x}#-h zDW-S=&s+{XWq-;rY#}bA8S?-9?OQsVs7g2XfNr6up2vxpr1$EhzA%?agZAY~zxttky^Nomc+2kr`skeY=IeKx8-S|+G8aC|PD7)b zO}DOn@Ggyi2iK3Z@F=_$*D5b{P&axJvNXXD4hFz4|EV~2Jjlk?=e_>wGrKn5QW>gqPrORXr8f6Jef9mB zk`D+b=p(3)2Q44^4&J5dfV)=qrzTc}cHt!7aOIeJ?$L@wj;Q^C-|}_1pYq#%xDNc0 zw(g*6a$2mz6?9o?-m0idYR~V*^I&N#dHwF0C2`3@eUS9Zh&vOi3(UYyIf>?jR>BXq z&`FY{FFYgAdcQtvu>Kmq$WTCdLSb-GhW&aoPk!8!=$#h@uhaYXvB+LKBXy1Ej<#IY zR8r_c=-Pg0*~*w+irPTH^y!U1D$j0Yp8W6;gATrbp_3@9ql&vDEnV=A(ez54P=!5| z_wBNr*M4ud>r(f&nPjD!vh$VyjAQNBr+J4ZUK9w*|C>4jci99()16s#7kXZ6~ajpDC@r$Z~&Q_6+g=H6CvD%UXtfR({ zu=^-&CF)T&rpbLyIrGdBCk1^7Wxq)M<^uJb>hY7+&pjB9Sl*o5I+E9>cxyZG8-2!C zF3*dstb_N=Gbv<7o+s@0o~pUia_%0OCsoXQTE?%@ZuYZQ1}j4(QH?Rmv#hM2%72*( zc%P3@Op)1{t2D!~oB!lQX!D7Z?yRVL&m*-^{}{2tOy?o$Z_x?z*GhF=U*shgJQ$H9=sRJtAXBZgb;K`IG1xG(;JJqUO zt@2zX_x))%Y8o17Dnxy4sZ@kM;zP%>NDO&f{Y~$3J8hq9=CK~jJK5PJnfLtNhNX$< zP`)`QJnv7R!q}@PscIG}oAQb-87?HgUa33yKz#DrMn$7L3nq;6mohJc2|dSNajxcx z;*p}_3%S;(?^qQcEskP8in@ISe7VI_+zg_*WK0nSWpg@N-&1Ws7=Q~GDmX~SJ04aw z;h$dDTs>axK~jJP{T18qFgp3%{L+DIoa+}@S(_63-QC#feWjAF{@|z-44VwW93;So)L%+xKpq7og|=Tol%S zmAhFaDL%=nyFGb{X0X8UsN-;YwJ>8si{I3 zbl>O#^6Su!IPZ{-QK+Yf7mZiwei%F_G$_6ah6#NQCNGh z(CvVV_UZWqC247hJj3}1Unh(E+cr)N5}lqu`2O=LZ|QG4MFm*etXE1*AH5u+ebqpF z$6-oJ)3<)gZ))X23l)XITs)U4Oa8|dil?puh~}hyWBS{#sz0_a#}Dr#b=;J`+BA0V zI(=Q}5LJ{ABBSm|Y+dz>Eb?&w`Suk29_~JW@okU-uh7`TVtTrkOHsPhUh?Gk9GcoV zG`@b&Xkg%(nb^MfiN|YJKd_`Mt-QqYMLmd5y5{(HKVn;Ma7?uD0Flk=p9gLOZqFXQ z>^ki|L@Qm|^D6XUv`;|P#Y+cHLpRhHHm~xQ4p%FTl&x2PeYe4r-(siKL>}c4^~YR) znJB99dyfjAl>L^OWl5;U)vmq7W>L2=)n0Qxe)q=gIC1^Lus*YFw|QvR>EQdC4qM|G zKNVH;7ka6ewIQ>`~*SN>k5EZ^QOV|Sye4_5t3mzcYFHs2KEYVin-xCv znFaPL|F5xFS>4*NNxUK#`o*?_focZ(mXPkqw)wkqGjS}wdZ)l>Ym zmMRVdNnEdV^Lb5L)vw*6Qu>ZbZ7{N;xgIzmLv=-=HTV6x%sd;-6l!6CQTDZLUwLBs z+!f2wua1QaD=xP9Uh#oj_>IN-l-@`|7H*w=5Mpi3NtjW|MO;s72<2J!l)Lb3mi54S zI_BDimIZSy>uX~_JA7mo)vh1f-sj-x)I2v>1RCxFu)3mbJv0Lo`;>2M9izxqKY@^3)&tW(@@BI(}(}q^CFCaSXXpP*U=WsBs|g z+g(4ZYSSB6dOcA+2ddhuw6n9nd@owmIXiE}dMaRS)^JPorF0eDtpulMP8%cA&t!e} zMP=(knq4dQBXX=)nCsRGE{yfB)c!IrtXnvjr8Zj$b<7o9JAXXw%NJSCyG#Nx-<5xI z$)C#B$IGY}TMeDF9ObD5dFmrvFD+@$MFyS%57RsKEwQTl zHi?>D{^66EpL=Yc%&GZV_UeehVNrUFdjL0wtSW9`|ceD5?h}h>teQ;mVLxz|b`d{B%Pg~x!(8Hf^o^ohxI@wUR`u#h|REtU6 z)LKRuNZ`rQ2{;-mOm?HdF{fbM{l=TdqC*1-PNHz^LX#E1C3`*pkLn3xA+g&BCrJ`I zPHYW*>cEU4ZIXPaI=nx%&Qm>g>hLiQr@AQ(t$VrjcKCu>9QA=_YkRjcbp!!lg-`fo zoXG)B(*W6|_ldqlTUxr5AF4%8KqITv^P5% zRi}TaSFVbHqrKW2>%cSPJ!NyV?etia$6)W@R^{Y%@}H$w&O|WEd&Fu6hR?X=ngMVhv>7PrTiU7%eSz^}u5UJyr)Uoe!=r$Fv$; z``IKYh(_Txd5jPGpqE0_E#y%+DR=|n#vuI_nk?2dc0CZ~m~jZi3pcPk@j}yk$@8yA z#?`uG6N5kC61PDFi=#d-JEMx#CtO{Ch};LU0$II5sz>vK^t!`!38n{Xvs77BK|u;GHt2VsDnI{tNeR)mXSC1FX1fJKgsVQB}^0QHbvUMIaKF#NR zhK?2ECeEv0aU@t)t)Q~5sn1nPx}bwjQMOyCdwjJgNZ4&5ch0e5E&9d*k6Y^5t-Pt+ zX2zA4TOQWvp;8niK<_)WShHQu#2g}I7Wwu5?L+V+f@SUV+Jk@2V``B4-t9BZ z1J26Q5KDHyN%@1s5H+pl{NflDu2);GqUES?C!mH=FB9w+=qhYf%p?s3>@qmuCwmn;e~+lXVY$QcJb&>ScZY`gLP_ zVcn3%3YjQkF0P)jDjWPqswUxe-f;S<+gQaBw2)BH;cMaU-ri@a5FUMmtMf}#JRhsF zx_+z+!yq|fAaW38K!#O$m-;fsBK)rj>=iimow^-}@{j-zytg6xYH;xhEn+JMUkI%j z6cqAIUWdaHZn-%vFlvHIQ^tGX-#k{8%e5#Tsh3!)%~e)XYSfpkm*p!|=wYz)><$a$ zZ=h#$`3=1ULEKGOx=27NVnwT-Sa0f+v%Fn zhf}pPW~K8}0fSTso)d)G9cqVz&H(7+WQDG6jaPqQ>x~OuHzn<2N$@8o_>Cub`Ik|L zVd&^@Yu&WT;_FX`%FD_OL0tMk7Z`MjV~!{lgd{#b$1KT8@C^_<3yj44Z zx4TQa5JgEz={NWzQo)27uW74px6!C@PR&5#^=ldR$*xE84!@>4KBD!tA>I211`@Hc zw43OoB6zlXw)6vIG4KExd3F4`bw&rrl6%|wZpO*7#^cuNckb{T_RS;-)tZ^77iFEV zKV0SWIu1mT_x+@!(-ZXEh|b~epViJDHnKOQv}4Jf+djAw!)#Hi?R7Z5IE>=0MaV_I zvXVIBL~oSY&4$p4l;1dp9;@1YzJ2G;`SwUs-!I9+Op5AU$d-=T?j{c42=xWZT`Tz6|bP>WAw+tr8~by27?@BX2QAX zQA_TtitsaZKk{d7ArBvf%o$wcOkYj$!QU=^_X?U+If*`=yzsrJvS6Qxr)!l$&&T4< z`R=xPf}rc^sOw~xIB;)ysQEbzkKkkbRd}Msb-Bw|>%7G!a1R4-iHU`FX>haQ{t%|i z`>16<(DAkypixg(`kT1vZ6N?UBqcTf#?B7AN9-1*6Ccs21Fs6_ZT$fP=}6{hmX;8% zsw&@??CjQ+V%8@cuB~$ow}ex^DurE>Be}X3T5-@tM=Sn<(e%42GfCsIXT&WLzBv0N zL&l&+-)jVf1Zm!<`fC%l*MC&)9^j0p8s?7%1`;J38hJe_v}J3L&nY@My$W zfx-R#Eu3YP@GuH29NTglr4-TTZ=0G;Clz|OqCWd%+m73U9-I#K8kp4tHD6F7F?$fr zd=cahz)$yY*HCEW>2ta@JQAdBM8WGBDc@dL#`Aj_p-9_fnSzAM_r2S}DKs##=~_8H zy~7&unq~LkxY~UC)oxh}i!Xgyc7?#2D;&{v^A))M;-*)w66YEyF-SBoFS~VGb^eA= z4u{Vb4z)jsx!!y}_XQxc^+eYnNVh2Z(e>SiV-FbcID(G5%)kjn=B4oX zF=BF_3JCEo$H&a$Dt&~;u4v-2o%ePdT`T(SJ_2GJL?<)L*|#T2Y>?F_(Mzm0nD}j* zn5M|f6N>r_`6h4Z>()5Y-;nd09E|BGwwsv^-1l-j{78DeIU@@WP9mv^|IpOE!^y2L z92gR^bw}dHAGp^qjA0AT@@gw}e2!D-JO+kV|AwKTeiF$PEN^wK-hpf-EKd{bjW_My z#Y`CV2u z3<$Hc-i~0~8o`mDEi_(xJ*bbqQb;rNrOoxxQIq&65@PAw&o=F9%<1}Wqs)Y#RX6`= z8HM)6R}4qpzzn)=K^526QGvLDYW~pn;z)S)W){JQxWg7@Ru%{TNQB#gI8UVe;YU?x z*v^}z$w)$d7AB8bTHzW4;yIFFDUhWPMfQ}so0vQ%j*bdzUucbzrIYioQU@*-JPQ%K zf3!LQQ8>%xlkmH|qOT2ns$y;xP;{NM*xL|)T&0+EkMSjhsH@FOa2GU4?`QKlM8396 z9RMp)Sx*lf&lj2=l#(}lZ*QC8`LROb)KYahL+UANF5%5O$bJ`=CPNlhorHCdf06)3 z%|l5H%+|Yig(dmyk<33fk}gmxUQzzSqR}@45E>XGF3d12>4`m`z0ULwFVFi_bzpAR ztr+5Stk`YtyODgK#gvU{_qQV^76(6F zDv>=5^-9!7G<^u7Ika6qfLzZN+IxSFmop+B;JzlsJ#8bACYCsLBTZ9gTlWU}!P%9o z)B0xCD1Py>?#LHeTvp8@Oe&fK{mw-rFTG|e5c!E!cxQ&u^0XQvYPLt>>hy~MhHvOd z2_m}2$$%$b|MP)h}ga7c1Hh~s=U#K)}d&xE15DG9fxD-Z1e4K zfu~sRIFc{Nt^FDem3x@U@USblUJJ#E~@oI9Wdi$PpK?x(?E$Z-#d=lYr!ZHwx@RCD~Z>g#6L@7b&Px_5VNtwQ&93#*@hJRoN$uI?ynfIqlNrq7D|Ho zOt=8qQj|khKq}+66MF7QTVev)M|(awsAD&cGIfU8yy*h!zY*gVDiB@H%1~~ z%_98K5%?~4s>N1uFVb1!I8epT*HY?9D?RtF-M_YIN5%>51=l&sMcOZo9Ou;UJx=k) zM~XA=&O-DsN&=7fJ!Zp>T9M37641L5pTA7tNa>%tMTH(~DBe}rLlQIP=h_^Kc%;S`BTOL>aBsf?sFP)Iw>uWLJkjuVH4+2@9 z^UP|x=Avu_o%ZEr6dF3(2LTG(f2-Sey3ZiB5UFR_4pw@BjVBFk?xa@s{Tr%}oOtI? zcKYg`&{~WwKdtfEnnZ!dE{#ki zv#9sh<3gqEQtZsWWU1$muQt8=aa$CEFGu1m1*Hd#=HnK4_Vt#a6T{Ja^v@h5J+EN{W|@P{x7` z6Y-JTI)!vYIV0Zw{(#Uh=R2t#ALT9=9d-4PsLVHACpLZH`5KSgi_A4uATngp9{Fx5 zLJsXVF7Ao-5(L!cAYRRJORmOBd~@X@FNrXj49aDO`%12M6I$V7^gJ?Z=hJ9t;0{ME zx0g|NtQv2bFX|;t19%dfTW)CZYH;O=s6lUc_s!i(=gF%edBZBW)kh(tKs3Of|vzsDq z2k2*|v9K=08GE?eQ(|2U62*7Pq@4n(Ys%X8+6>wYh(r_wEKzhY}b8V!e`16j(~ z(O4y4_8<4PE2HZ5qK1Q2E;`EV2dS|CaFHqz*F*m>KiVjV9;54LPd8}x7jPfu4VSIk z2%hv4kI%^zw}x?~=swMXquj`ysl&}s^(Hn*IKgE?ju8o$qgyU(Q!F%4!`HzT`}rY< zr|N3oM#5z>LVObdpAZ$LS|kiG<4F_M+IY2m?B%cNMd!i%Qt>CM^+%*#Gc^pJFh?JC zDUth1R=XgSd%P$mG}S=oqVq1>hzQ68tP40`?;pzm>_T|AbU4Jj#^>(aqI?*jZjlER z8V%G1$D2H#th5s8{UB0F4chL=$rtx` zwmH6h$x#OCu@uFhAom(8b{)0+EF3Q5-}V{TYxe*mmzL3%i^Rkx_0hepQYO`u+@aTf zbrm=9PjFsx+2mGuE&8Ps0iG|DZaF5r*SrtOvSEh{^W5EN0!hlY%ampWy||iJTh{6$ z@N+T4a|WEy={kCEekh(a1e~;B`|5sLNd&tbiO&i0Gn4-(Mm#~+lakfS2U3W@%5it7 z_2W~s;)`+l`cJ32R%uoNN~dZSZ);~A6ra&fsZ9}8H>=Cf$!W+;G0?hv(zcOW4{!wD9e3@!ndbb z4~{c!LPoq{+Z9S;Bzh8K=AZt={~+j03%p(1h>gwIz(_)%ey4PX zij#||#t>q>8Xq_fUCaY`z8*AJ%u!suYNcyxlyCCe_OE33gk-1aYhyl8AB9iR*JSwC zoGO<2;s$nn!QXH)LxTYzB9j94)iPJFg;fMSi`6oN+--hWa-V2+(9(qCQ|BItqTCW>u;^>{|^p*(K%T~820jI3mWJ5?lk^jX}Sg+_sedk=?uU~Div~+MJ8>nKS z#xKQuj_eZ6lZ*^WmO4i-)i^ICV$3dgpF1&;Mg@3yDaB;ryl=LHvl8!t1>3Lg$Woa; z?2b0>NYiE@3{)#VPx0hhUnsc?`uxVM=f^MQ<2e;>E4mZtYfK&tF<-H}E2g*5hNo7G z#~kCOTG_+%Ln{$vD6qhuAM^LGKu#B-ZHqh9AB3HCRq9JBqSaF^^z?F>s*#t#^2NFk zL$x!{$4c0)zqh!s^VF0m02yl#l@+2+>|#DU zc?>yQsHY5Jivr=>huq1v!@LEM)4W9!!58osz~4R^7XZJF=1&OA+RG;wakbG9HJDhU zFo_>nD6T&La@^#}Q0~~!MEd@Q-o`wR5kSVRt~7YqqJSM5?hmEyX;uEdx&R-B7x!;qAw$Y?b;z8Nh(DEd5G+OhLDvqZfXbhd zT~pj=R`u{%|Dvo^Sm)}^lSQ6_DNnr;ag{^sS#f_&GhcMJ>-cR@VMD^~IB5pQ}F@+>Sx7T zrjl%FhN}(CNs5`@p6WhSqIXXH{P|I=L*ZNC(hP;h&={6;sbt)`Z8007AjKuSLTp3k z5wo_1q=FS!@lWOe{wNa1_faHvU~@32a($fKm`FOJw_-0$Ei1!ybleW{85w%YIzLW+0@W_~57Bn;RFjb#x+ab3}|> z<9vDHM2=j9=kj--$BH#_Rc|JWR{(#&p5mF1NJCEQ0nqp`+6=NT8^bD0}*8;a|ak7eo56rHYEyyMo%P&zF{?M%|zC+W$?7YBfTjzihZa zbI0I$OntVJ#vXEYpH&Lf{fa{)oHqE<+F!7aV=yQa9gr2yV23mw2zHdq>HOFZt&%ssPe~$T`ZSd z68Xjo06e@+&uh1JIGwis?NY!jqFrg!jt%!7pu=>JcNWqwW3w{dWR953_`=tMgKSX> zd$&AYXQ78YJxbWu>aY!MRg z#-i6(?eUZk2a}bRmGw{|B7#N)B(IP)g439Y0J}4`L{U&tfn7eCk>D&&iTAlCFc&or z>2MXO+RT4-1F*@DkvYk}E3F8DgEs0!zxCFSj}hCg``T||cx%}->gB^T@-Ph0#U<93 zGTwSzVYmB=z9tvrbBQO~3P%aWu;AHpV`n}P(vneiT=iT`YeqXPZ=Qs`DUCIsy4AjQ$6wQ_+c<$ls9|-B_-Ah|rbXN=pw2a0 zK@yCilUP_k7Zenvej|DRCMHaw@G*PQunC9OFX%Hlb-0YP{r;u$NA^Q=4fg8C4nlgj z;w?$aXb1wjK71U7JFI0~uYmT_a%L8g>45dUKxE4Q#Vr^35&-o9)PB7>J8jKRzBWrr ztWsF1+c`(-kDR`1&oydR8s=-+E^l7#W~oIsZCk!t#W7G@7N^P8@S(rGOj*^ z7NG`l5s7mHKEVDga-WbyoY)32VyC%D#ELwIbN*gqa{H&{HT4NI`g ztC;1o^j)tk82LSYS7`}gGUAzk7H_}I)4%){oCKrfIOBPze)GHyTQH952jXsWK!|dz zbfQ@z-alahL=~sQqwfzwPc2HhtBzdrvb*~XAq!AVKRlc$IsYU?`rEcAxe8hT@VNiG zAN_ZU@^%l7LWH-4sRVOa=7>HPs(Vb?3RuEPh}^iya@9jQQoO<%TehtdUMY|xe zxWms+R+1ke%EK&o|JIl8r{RmfoB0NpL2y`i7vd-G_aI?7@~^N$Xy^6ZxJgAaeBKE% zy6E>-9e0-`Mow$K_**+4^&mdA3jUGyxGQ(@F7El&y)yg5%I~D5r;D1m z%eQ8byw!JCxF9!r1kXl)>lvUyGn(=6eVljU=xgGmV1sPhok0au4;# z1f15e_LCBra%ph$2Sts}buiV;kw^M58zxs*fNn9QYTDCfKGeY5ukG_|U{xSt1-v2) zs5UL;7>vJVvR&l4e{M8-QeVSo$sV`=Ql$D zk%i2EBV<3GE3YNkh$;%bM=v_I+xH(zRT>``(lm+zwVGF)9?%jt84Wb2F5P2e(uU}# zJaZDxDQ6F-gYx>_yTbrd+*fm6TxI+*doqn6#l?p^3FG-OT0whDx3VASX>nfFN___s z_MQ}+5)Q$Ay8Q2Np37RFo-%wCquq87nIm1 zCa9l|K27^vX6Brpk=JWWutP*%k-55;5fIQCJqh*n^k(YHt{-}UlyqoF-TZrV`Ox{7 z=Nhc}7XWAlEyw{k!otIieR>JYC!_3nF{Os@V?)Z{t+zSurvWKOG@=`j5ukSQG|KYT zgRiUuMelox_6Q=GCCOTA>iE9>8h6d8B?9`_vrF3*ll${_(NyH9%HRUH0d)!e#v9&q z%yNFsTtr2@1bt~or*#-8yPZiQAtE`H2fq=j#nmuMi zi}8!|`zqx2SXg{BxHl9c)o7Qf4G`=ehPtH}50J_51rSv|v$@R1<|5?SChYcwZqn7- zzr&;@s(s55jm#h%8XCzld%=>vr{wCI4<4*|{^($^fYTsjfs0G%(s#Za8U1*<>Kt9m z(CYRfDC0%#P=8=+5Q?2Z4gauDuS>JNEEWrF8fX*%F%+Xl{w2plz#W`?($>&$1<-lq zeMcDO56I+Rj6^tzc}{#<4rRm>I#!%-FM1e>Ef+~5ZudC~Ic`~evsb0s`<$~gQ0|_4 z`6g2js5A_`cZXM<1OWq+m30$}vW;6WM#y+FU}QU(t7L=hw=mmY%ReTrUH3(Y=|&dRD zIWT;H#z_TC=dk1eT(0Z083;V=tJNv>FFC@`byq5X+rAH2npM`gRFDgStTagkw3%7h zV{dQoa!On#?mr|8mq9K!l4{Mhhj_1hk~xp-CN}@T19dgFRaKl7BcV`3UeJ6f%HpWU z0-=5Sw|SqVk3P`()O+2}8+&PytDcRwtEa1ZUyxR=YPPlY259D`q*D?>rZ3&VJ-lGr zc&AcXOU>7DNeQc~Q5aAyH%Hv<5x1Lu3~5~)&CUl9G8VFZCww3neL1UX z13wH9S@@H#HAy)p+p+3HL*MwG$z-TNQ&_sOJz%46Tl2b54jn3gLCViiQ-*1w?f z#p0i;$DM-sOnvNiras;|7aF8eQL`mE_Nm?*ds-KXo1=0<`P%H+@j*aN?~jX&5H$r% zQR?YqOaHe~IAhrUjnR#FVSoq*<&smlB({I2;YV^MHC}Rl{<|MVN3?CG%cO}P3xAiu zuJ22+Pt@=}UWUYi3i};^SDlyclLxBKrP_Qe6mTTBs29hP%yLaViLR=+>p$1Po-X4AgJFccZxPdk@&Jfixw$i;i z31Tsz4lhPf1xsO)CZLyW-2Bc4)&bC+5t&7LwY^vTqz_$q*asEM25`7q zNnpz(&m~E1v@U*P&m}9}Ik!910AS3|264yHfcgQ382w%(CnO}7^DCBRZMs}X-4zs{ zL+;stbRCQcmDeREZKZkET!03EeDvZdVs%Z1InwLJYp;oF*Yb33vP(bEc2El_MT^oy zJRqt9iHGgU3)aP-6dXWR65WF1S*2?`9DG|HXsmv$M47**Olbka0HEhN6Uhe5DBwN& z4maH!vAC1qlwv8FW^}IJE@di)P&@xOD7JqFrE-*#ixHY{{1%!s6i936 zeohl&?eswxSRAJvaiAxwzqep}%LBTCRe4C9_+1r{P?>!;=R35sb*USh*5@mg9L~7N zOHlcN`^f1Slvuy;*xFm@d2?}Ib%(CfsgNOoT8Df*NlHbkeUSTcD^39H-sDKnb12q& z1?6EKg1-x-KBGSSS|~eF5x&4=Thm|3>mp^p#B`9_&jEE-?h@`p$Du@dcL=w%pk+qu*jk^`b>nc-dmNr(5H2vkg@dpQ3wfPj?x{GQYqfvD8CP zBM_KrBxavryTrxB+&u5T@D(SGiU5~ZLugiir-t*<>qktT8}7naNOx#bdH^3kY>^2OM4Ep-H+lLPd5-#6bjv{hmNpD(Jrm~0!NyL6Jw3%45lc{_&JKEn3n&t+5 zal67mkaQ_m9lw4y0>HwLl1!k`ItzKyp^3^eo(qY<07HP9ig>ynhpH4k(IWb(r||TQm$S@t8Ut8KqDx z^(HlyGWf(E=VoS_-xB9fquhTiRgw%i5s`9)dFgt;F_2K`sDG^D*LlQwbrSKf#`Dqpi^sW|DrP))0 z$1I(_9F79Asv_Zx{vhDv9=DjP&@-g8Bnk{>kK1AS!hkd>3q4(SL~~Q!OGcK{T*PO1 zj~cusg}C^I>`vj1_grQG8{R{TlmV0oWSeQsESv4L;LLT}f<272;ri2~C-w}tV@IHp zi0PprSn)VPy@B|}?y+UTwssc7Vy$QVi9l2{r*^Q;jCcNxw-fXFLaUXnt<-}DVxKc- z708(6NNi_o0(n5O-2ZLRCC^QtDFy}^XJ)rz+sGZ9N(NgcLSHRHCmwFQHJpK;Unyd+pV zHQ5&c)JrQVAp;B*P`guQk z;)_{}kDkW!#VcfK?G${Nc5^W!1ZqCD3)PqWUWPKHsG8(z_hF)HR@NiwV^Du5-t0oC z+;zU2g~r1^uVs3kd)FNTO(I_j(|xw~iE9x+x7uqU=-;CgdExu#Dt?hzTKj6T ztj0XyBtoDW=*)tEoJKK_R54Tj?!LwqY}!+{Rp%?j>FfBj|G8fgO zlP&bI+X&K20evIANfqr4bYwEG+rJ|}k|y<4-R2c#!9M{y_>d(~M7b>yr`0xHis4#Z z)}fhqF9yy5HVMGlW|JrSfy26W9+IedAWCVrHE8(RlK85z{sLiH#%Gyi8zK*^xUe8`C< z0jz032pP6o1qKm__dsU@l#P1|W-EdxMdLABWUy0;w?xU_wX<{s{Dx}S!D zZQJkWtl2Y~ZRgw;PE$}20+$az4e#d3FBcWGQ~-I(x)5auBc-B*F*dP^xVP7VXwFT^ zhTuE=cjuy%crx$KIfJ$Zi`jaCjFT~Ib;t{R;10Ed%w(>bp0`a?V`VU?hUxC_=UB2V zqBhnJR6`nDKpG~naQ-#F-3+$;W86kvwq5r^a|E~aoF}I5fs@aQgg95gkI@ile|=E! zKIKG1ra(84bkI<*B8Tn7H7=i5%NVvSv_X%QjMh3Gh*DF-2es>qiq3!f1eKMHlxoXw z9>i%pEBrD$i!IsED!(*vvH`@dLkm*}gIP8##q6exE@izR#J*NYc!=tQ8cOFX367|F z7s!eS`?#}lud*`X-ESLzP1?WWBOQ{kUXH==+iyh^OJ|o~Bm$*Ol zvOVysD*+6-!D$D@SXnJ}88kFx`@RK#1v=i{wdqn13Btg|C^3uD)joc+VyYA$mm3*y z4j7Pe5Q(_hs@hDJdR`!;x9qckG?Q;FbPk7FU6RrZO-Qix+FH4R(Wd0L10p}0$zJ#! zi1Z)ny7g35laQXcNs58RONw6=M`FMJXO_=;CvpDuDZv@#x^Px(uK!;v*ni>M;^ofH zGKQ*DJ$s5=iKlLd4kDbc292)2^hR*v1YRa=MW*kDEr_pkB)I1& zPpa>)mV&<`8M_trdU)+kj-rDy3+QH!d$t1jJL6}bQv7#cT?6tTnC3O(Hajbg<8`vh0 z*Z{3W>esL56nYe%&k`AZ^0Wa}Q9-u?x>-nFvNF>a4&Fe`p$Z-{qNk+WS0As#~#l;JY8B0iLW6p0zGUxl~lO^ays1%QbC zLCBS4T91c}D#L1bSAs4i!ebiWSVW8lbp$AK-WSsP19fcsQU?S7cd z?c3sCJ^DIFi_1sh{<8>KHp=^qlpy9hEZc9%U1gSwG`)rUvWPkUdpOJWx}#N9AjkwN zO2ekGRn59O21s;>uz37K2@xQ09w^vc#;Ec=ELnbd(|7ef1NP7YL>8kv0(~Yr0G$Ch zIlxOpO+)j2U?6(e7jCki=)@OWc(Jrhtd%vLV@$xam1MHakYk!5ap80>>TAoH|W2YygTqG9;4IO(i?R{zv z;TCr;0g;xPTFk{_Y}pKz{o`|ZO_PtMJ8)BhvI0mbasY(xX}Kq zX=+VWmz%<`@d~!&%N{dncXz5Bek&Q@*61m;i++yl0~ZFx(^B3m zlW~n~Q$T6ShY|wd1hj+En)1p928rrz&9le55k-u%7$uC?ifF;nqzR}Qf}Gj+9t=1# z{zP)rWoNAmw{gx(fo=ol%rd z3mO9xfL^Fq&BT=9uWJnA>Q6Uh-KOZZrh}u}BNerWhR4G}xkhXH1j0fWIF9a?yjgis zWoV%Jst@iDD&PSBxx2GJ>Uvb%*~<~aq^n3FO3wrS0gWyg8BC5ok#jNSRDujtc0oA{ z%!NAQV8ski(e#Wbu05iczNh6*1@NF@;YW%!T{bU`1g#I;MR zK`;I^DLQls8wx#ixT^_Tnzed=ZEBlvF@5kpI=Jc?T%7m1widktB<*HWX*--AYvWZc&Pd>xUO`|1Gl|R2UH( z%Mz^-O;NG*7xhRz)%=}shU<(N9$fu7`d3VVT10O}{^xP9=8=IWrd|F%%WE6ysKAiE zealO)e`skXwNpH*5dY&(Ku0PAbvP~sPm+Hs@5L&%5CHY!jX7Voo$O34Z%W7=?_kohee|Ok}@*4iXSHaG+Afl7I1l{)}DwRu4z8^mG z;Xl9bM`ILo8OA7c1N%Pldx9z>*YLBcVlxL4{U6(CjV{nr*}DrWZa5L6)!KR4**)WR zK%6rG6q9qH3>MPS!Ctcg4;)LJ{y$2tV9>!HAK}$Q zwfIlMh_s*T{FbPn)#8_%=fd$}Wf+N1-S{4O#UraVY4|o0p_vP!(uo*)Bpj zQYbE&)`Rzrw*)C8NUdS_BAG!~`a{@bmg_qn-i6g*|DoR(BqjX^{4A7N0q{fK6<);K z09qowFaPeFXMo+NmcB*yZdhw$55S+2ljteW8yslAAFdHfe}6=3XNDO2oO&WTe_~7{ z=Dxo#hN^%1X{>A9yzl>OIdiD4;?o3=HYm;cAY_C=8`?2;SvI51HkCVn)M!6ogBj!H zQ*%UbGc#A0=Q)W|4V175A3?RBe^4qL9yjQrB@>XsiCgf~8LE&~cx==iBSjjn647#b zC@5GiY+mTgg}n;g#fQ3DQdi$4QJHys9$nS$We^)29M%)-cGB1zJw|yOjOrqwqnV}b zEZOzKD)ZF?eX#2g=F-HCOa`0glP#^y+_HHBHoGMRo83OF|Iu$Lzj64(IT+P6Fnm01 zrM>n2q4NmXoB7Z6a*=7}fJ;l!u2)eJSIM@sXsQxy*tDXaEnrkLVlfV{nm=qge73TB zq7R2{T9jT@kl+V<2K>1ic;j}CVmUJf%;P$li#RjEAq)4a!qu#}Dv!E!nD~T~H6=Lp zDs8IM?crsywS~xuoKdX5--UHa4s7cbeVF;6cQfi+(T85lZTb22?K(bL*~;fo#MTWA z=Nd2!UikK(XJt8iR>-cGJ4Vh#OA#ED^wKF&yg|sjf%J2NIHS1tOWJ?GuW5TWAUnUF zv%++8M|$&Mu($ds89qx?n@MljXogenIYTpnW4LjScIan@|8MVWNG0##(`BiEnD97n zZ#E$f_V&fRmxqGHaru6t2njp@TD(^7&9>!gZ8x6%X4I?}vxD33OLO(lJx54iCiV+o zoBF_iJ0~yC=cO~4i~JR=hQ(|<1@LYW1H*%g=jiiUNAUlC6?V%&uFvjkc4qkuxUUra z)n=HQp5Ac-*gpEL{;)QD&TNGmt6{2q>uxTD)u4ve@b8NSVK>C;KjkIQc)09_=BmSw zG%z>Q&h3xH7nqLHDz29pUsP%S#EmyQJG(EN5C&tv;|OyzO*RwZk+ln}*pDG565?G^ygI$( zi`34&4KMvSd<`TRBd+pz1Roz~4FubXK^Uvj?q`L$KH;W8?(qaIbFof$q<7Aa3*Qny zhF|=1b}skAf&B8UtMa;`0w*d>mYLu^Qs1rL%`8#>ru@Ct0@-uztOo>V4PZp~Z{) z`novOx`yJTCqrf~mE^}lSlGHTFD@!ff!5 zv3+5MQx^fSoS$-ZwU_&lL&)O9$x+@y1gW1Yi)wD^&(A3-|9-?U{*i}|eC%Liaa8-c z_6<4o`xh@(k};Ftj+y+y9p9c6tfcPwUf*#mj%BjNZcTVY1?kIwi`=jh^L;(BTGUz# zV#D}}rk*nGb7I@rDTNnU&p%XHJ$PR6WM z4P1hWK>0sjR_n~m4u~#d&#hpL)Rh@bXs1bW?kt>NJ^+m7h@uF~JcnI`+q#yVYteE- zjFEiu$z9CGqQ5WB>tIAXUOd`vf!TMN6bxIgL(7-I`Woe2jIw=p&}n`>+4)fm+Tgtt zYiQPO8w=3|+(&=E3p=w;)6&mQN&C?*W_!p6_3YAO4ltTe`J;l{k{P(Kr)zObnK_B} zCzA;9(<6V$n{Di=GrgI*g8XtpN_6w>ZiM%@cf>qiPAxZP4L14X{LCtyA=ucthX3Cp zj4MEhJNs?`96Vq#)w_89Yc)$u&d#WVVc^dKcn9m2Y@#o{(*fT1`f!lJ>_nYQD~dP; z{j8-h@jAEHN=qNXVA9?^6To(7@M-71iR+{xnAx(JhSFcsNi#R-U^p6-YFmB zouZTY3xtlPGC$WrF0HcX~m=J-x!^}C*;}{|8sLw&Oi3Imkj$5FHA+t#~M65JiMe1 zPA?+sT;%1dEGv{K)Q^n`oaLF%AvMc4aBntpiF!XFnXUbTI}t>xzwZGvO#V9_426(6 zZv{~KiqxKm-Fvj?n2VJ-ctKd>ntPVVd1g_;anD>^3pcO z@X@ZFe9YFlzb`{7txJx&>Qi%gGV?Uni6Zo~%jRmV zuKmAb7QnD7of&kVn)yd>**6OpK{o#Q{XZhr#f-e=lYJ5}d+z_f3c{Gr zu)(~C58_vH$J}SmuB1-jfs9)3=b6IX*2a2N4iMzGU`H1yZcH~8@w=@3iq+*5{CChc zcwesV;G!BsArWIZ zLDqoG{MFS}$1E_vA&W)h-B~f59hnr+UUm)Q7U)-oz?|FhYoOetE=pJ<~jm= zAhuq>#8%y}W5NwWE;$&y=Y6l{XA3y=?a!q-1MYQ(n#EZIj1PZeT=Y4N-&lOqI&w~t z6;{kMc%dbe=SO57J(NVwxlK?PuYpC4FrdTu;ivCi&TnD~$YxYWW1w&8Wp9k8CxIWX2w{~JUZu=z{m`8}@N53z;vFcbf66cL? znfMn_V8YkHz-B{tTdjQ9?>sC0>;le8BTvoN4f1U~G@o_-NLDtK_6DIG9HuJwD( zR1qQvKZwF-W@e<}j{G|1wxO&0Ze25N{`^w>z$Jhc{0IMQj)1W%(pIhcWlq5HCvo7o z=URCM%ReK^eeJ!1%H(&3gX#+;>!F{Ft-Bgk45r0E;VI}5dy0ip0gsY6dK@{J?K6X1 zqMLHCYEN-2^xmtM2#c%Ta^~`6O}6(snyWq)U}Ab5C_BHhBnq`H`0UqqExft_Nm%qB zS}%Q0^r2{%`1y`+7qNeQSKdevvyuDR75nKUW{I{6P4W`c4zgg5oi_m9g`6?2O9t3N zx6sj-vr+Eb%qT1Q`RMDF_{U}=@N3UqXWU%}xHvg7jE&{W3k)nvwFkKV{^q?yFl{%w z*n7vzps2<{4a`aahGH17e3JqsRmKeO0n!$0&ZHlVtnO-U@%YcAvHe{Q{ZnF}1SkD5 zE?6J9VDj|rAz_#<7^RGMhFD-QbPqBaXu>xJOnS}uRJa%S4*u_U4C8+Xl2(+L3B;S* z95NV4@$Yw-5__aRJq>zSi0r7<>vPkLhTP@Tz2DU&^@&#AP?F%Hj!loE_qcC8Q}bLg z;Q1Zg;e?-fK5qNNmHk{776;Xg&D0prByJt~p{K2-#w5_~;>z zDR+2j@ksT}n2L>64vNx$k%LhZ`VH|al2d4(SPQUE6=h{-GuVR#sQ&iFZHCtS+*u2# zj@qQ9547+ZS1m9QACi_zl23Hl$(d5RSVo9CDCwz!mulxskv(?az`$04!gceYPoXOJ zP4=**LnDX&sLTFdiKt5ESqTo6K&E|L+U7z}mLq~DZR;~k^Ru4>XS@-f7dL?anw=)`_kY0UsY7qS6E+$I z1yRyux1s85(@gX0>v;&pOtww(z=Kb&ySC)%kv4b9()w8J?CfxQ#a0oRXXOh`FYIk`)k47G2{8L_7wVWJJ5{$<0_A!?hcSHih%RT4FkSLZ>fA+0$hQ|rOgEV`dAAC&N_?<$|vtn*dHPu z4cPAQt=oA&5Jg^$PyjOf%>{R^+--oJ^lmx8GFpYht!# zwr1(rVI{6^>WKuRa;Zg{0sTFFPgt!~m_Frj$9zEyacnr{*f-*>KRGx^x+J#u!EM?~ zztG@8hoeJ(Yf7*{&4JRyi1&Df(rSo z{AApl@Ki>MfRM0FngW7Y6g|76=8N)mXBrh*y;dN|bmYgZK<$s=*MAR2gK3WcnJw!s z6Z^-BWU;>w^;1s;-tIsbtjWE)t&72^=J~{vde_SL5k}&1zyamO+&Q8l#@z7vlna^; zcvk2%V;(WHO%c4~WUw(^cRksC10U#LGja`%4-*8}Z!3k&p6s?^`K-;&8GblDifavE zsQhAl?1ex}gizEh$Jki$xc6_*>miO7-qd2Yz(2b<<$psk$1+oZDikpLgx3QE#xb-y z^GH5#29ZkXG39`Hx^eg34iH9Wi^{V`SL!)hAJLo~mqSqf9r3+<0}CDWPAi3stLt9+ zUWtUyj)BBXev~tXPOW~#=+O@yBYS&${l4uoiIdR%;r#q~R|$#J*8KSnC2z&a3BD8u zm!sy{Qw5VLY=Fnlu9qy;McEJ( zS+X~Taqw?dRzO5WS!s=k$`X)0g0fTuitN4j3@boL^4%wZ?fZV;_x!5<3du9?bzS%U zoRbJg?{qiN4b# zpJL1zMX4wfi8`VzIawHRZEuQqsu*>yt5lR29^OD80oT=800jJoL`;EbhGEJv9O&&< zqfVo+x;tm03#OGDM?}g?mcv6E+5O~3oAiIB7Ozsy$i`Hcz2i<~rv4;kzmx-^!B$b! zzP;^0jf{dRI=5ZaXg+?Zuk1irI2)tXrw`Qjk(*GuZF8zuC6Ruky$#gwN-VX*)o^id ztFKex!kM%X*IIAG*v039)iRPxR!U5Z)%irF5FIV=mQ7TbW)o^zeXX}?dt{)t|I&qi zqS74Y0IOmG#F6i9H7W#vpi#|m3)n}VlwCRq?i8eC(-1{ zVSRhR3vtCsyL`WT7T>q;j876?D1tI~bu5dE;rHFZsw{6<{!D7oqVz7t%6M~HNS1B0 z@Y49@1q`b@> zj!zL^?4FaJjy=07*LYR!*uE&=6%yr}D^85GNN}VNZ(>8HJMx6${cGm>UdK4TxZ0jE z_+0oJ=hETfxSJauh1;W|mz@$!^CtyHkQ zB8TpJyW$QSw5U2Pfv-xZAF}!|@pNb2hzR@s@u2cK5bbOWupxc3X?{W?%(k4vDG!DG zmk3_}I9H0)*qS(7tXBJUb!RV*hKPm|xTJ+I@ysn$I{K78KEfabE`8M_E1IVzCJLIa zD%Fx}D;0Y~>&@pr#`I;kPg}P#XZ4CbeoMR(9)^aMyArA2SxR-a-FN17?t}(0q%lcv zk~+7srjp=CYY`=iXs>OmGCU7tJ@?+oCh?qR@)Sn)4)k`%~vf z{}u$|_ZG9k8gQ4{1;uQ-BYFvrowYSev*ipvf5~@cR#{1-xa&n~MAM@(yMq1|u z$Vx|%#}+7bp4H~iwv~l(*s@hMyEdn)jM9Vk9I5Rjs4TM4}CuV2f3=TWyq z=1#dFalT`9R~hBbb@Vu#U>nz5&RlGy`NZ9aA0`&4Pxy$n0!;@(#+QecTW7D_#3NX^bB9;` zblVis>C?SMnrw~Iw1G3jyB3YE9|tbh(Yu{knSfhyXvHx2wUg8>9Dw4J9&k$Y~W{;@-vIcA6hQLy}NO(M(l zYNTr-VCCl0@i)-#XD+uD`}wrfFG%qeo=jslPcvw_BYm|WQc`f_nwcLw2fUYX&Pdlb zxYeW9+x+EAEj#+Wup%eLmgHt1tcBzY?Uoj*6m<b^mpqyFVWJUuS|6OdG?o<`li9ujyXZF!S|cXAm9N^B|DZH{f`=1D8pFkOt! z&dMbE>Ke~HW*5e5+vuFmQIagwO*?}Zoiui%Sh3W0RBGb{&1}|~(DH>&LBz_Ecu-eQ zkLUwoE^2-C)S;J&*X&xk6c@JUZVx{`W&WhXS-cC5OieH`fTTz=K)N zUMMh?XEpwk`eQ#dOfl$-V)$B6@PF-Edvgo`giy)gLBG9!m$U!A@AzLMHLlu0A2YQs zCJQchFGk5rJ>V`%ut>Z9O%3NsJ0Nf1{axax)lwe1OxK(z&zcLbXv?xazk=VgWed%{ zvzkovgO7^9qwJ)N`Qfk3e(0Cg8_*Cv3n#ytXXsBv`$-`I8X*hPh)tPaY z*CR>E$Z()bD>*9ln%x___}7gMM!-rb4_@};ZG|9a4=xMbqQ6W1Y+>XWn@K+rPWW4# z`-wiTBM0RFy!jP5Vr@nK4HIk!pFB9;gPE7DqIiq;wwUgvXc;vuq zZ8>6WM zXh2N80K6G=>LPggwy%R3>HhAXx6h??%XQOc#cwS&nC~ACX`MVz`#T*hlF_0|tDT*G z=dspM;@#&q*~fdZZLBL^Y##4gT3qvD+W3(jAp8DRg+ykLCRh7Zj!*U5)S{^sZ}Q?@ z!%$P6`M=DqCQRnPX!M22O{4j>m0@9F|3;1yVHqV1n9Ch8WUb&btiVzS00f-Ib49uQ$pt3g18rG+_QQyP zkK)>a$3(r{s!V|^UPvn7i>elAV%NYGpvQZv$cz+apEe#MJqisMHN_jWw%woC*7u_lk;)h($Viz#=WkFr|J*yl$hGARAW;?_pl&KSuvwxle?4?evhj zJ=z>fw|De)*&U}iCvov`ca5u77}#37DpP?2*hw9neSqdU`aB3AE{A6Jk81n4$iv_2 z`3Zjcy$@pgZlw9^w6|3%t=yFvd&75r_I!*qPlpHd9?y!kUAu>4dm9;Lw6phr7xl~I zOGAG>OlnSyr@v|eH++P~?mzI-i$*N8ZMxf@X38LV4HtBEW-qqX^JL-D=#LJBI~FiM zBr?Kfn1xo=EzHpyO5s!no!OT5Z@f4U*-uvbM#Eyi!85o^057_~e(KOIO`JsqqX>1f zobW}5z68ye{po{S{*%M2=B@Z*bIMrQt>aM_wS~3Sc>Kt@1NA%vl<}>y|DOv|f}J&r ze$G4>k{t0>#EOaw+259%0mE3%<^`AkAGW5NT^z~m8}DAyvg^!0gZX=* z)ZBBX%iA4UgwU=I-k?oJXH6hA+=3`SZrREoSzUcxcy+oy(s(FGx0*GmBPZ zoV(^k0*7O%kF&$QJ8f}CI!(kK#hm}@qQ#T#WIy7=$^O*tO6}CbJ6*LuSh*_9uw}&d z#o}1W=&t}qCZeV;ogE`s?%o}iJ;5eVZFrM57Tic&sVzhCMsKr=7--qd+sbb(xO%-H zm$Sr++K)bb{P@vZ!Qbols}tn@NylJEbl68cwP12lt}oV#>|~nOXcJO5zKh80SXyZ& zAHx-`a*5y3Gj_JXrcYatPmIG~DjbhPJ0jwBQ^vx>(Sa>%(WJ-6DjXM>Ij*|S&d!Kt zbmL|20TviHg8`PQJ@o=WqEGz>`n0Hr^E{c#SiWF1#fl`G($XRRK}Hfw$h^fS_deC-I5zI( z*9$&l>HT|y|lFZ>vEELg~gH zx0a-dN;8`j7u%$+6G)7{cJW0fO0D8PoOm?-bVR&1(Qd0k7`*fh(biUl_K^Hq2>kA!Bf3=DTHE!UZ`u5sy z(Wu&E^sqmIXQ?if&O;u&nm+hftD~+MJJ8ALuGYf5yt-6(6_Ig)M=0|Cm+U>e)iPT{ zf$tmF^YmO@rmiZOrauZVo?4XNxfvO<`d}FHu{VhLcXQg5N95IjL!X8PAeT{GB~l<9 zzxW~1ebt-Bn5x&f6A!lT$(+wUNNcVF5&!K*`lFCNw)npI$$M8FB?PH43BDb)cY+lo zJJiae!~GS`nP(}ZG~*i1qNgn@4+JZL_4)Q@aIUrG{W~A6M9>d_joYcIpE7C!R(AR1K&JCQZCx!=Vn@vz zn||-^)d>$9yUKN|(?>MqQ%d{(apyeFb{8i*AGBZRWmmT(N%zzscpJUj=Uyn|H{<~p z8Nv$u=Tot`pWO|}%ORnt>aquoodA4&PG zr{K(Q?^f(x%3iop^mJtMv{1=H%r=&l7tEffi(b2wawXtW44$L$iTEqkfl z*N%%LOqJAnt$jK4VdX!h?6R?1U(wS_%l5YvMBFcgqgN(mm>;a?buAmPxY?-j(0yN# zh^`+41Prdxh z>9Q5$JMYvS0w>w!Mcz@nTe3|zw#7ee1C1icUS&{yU0ZxJO=eTeova#1*q8HX*7rr` z8sV-9sm?mve_8?G@wap3cHGg~isQSQByDLdzWV0OS@=`8&_7O^-lY`u>5S2V zQTMag!@D@P3@h@gYRmXG+3s96P99BCPJd+7@Sn5zuvWwI!jlaVCG-cTG|i_VNXe~} zhvw34OdQdPqnsgkKh|Y8?}k#=mAgB35fnr zRD|m*jk~|NEU@BpsjmHoVFTmeWB*{pN&~MntzNVK1R4S7F8msZ54WgY>9$_N+teyZ zt+C5~-hgbbDp=~+k$WiURd^dEiAHNy9sJ6*f7CNI`o3{!tS^%T|1F&+KM9O}%ok;C zy|eg&OA*zUhf~ykjAnLXL+>10zfH&rU=%)-$(hv+y0l{FSv)mc_Unw3B&YqhyL`N= zTE!^V@8>B_LMn4b(+!=DKFL_DK~<)`Q3AK8^=>6gjon0FrnPP`txzhe8U{UuF9-&* zN&TfIZJK;!k}R?*fZjayKs22ua1udiL&Gkt$&7@akgA1j(%0o@O1C3OGz+_NDU$v)Nucr~otG@GU?sELe z4v*=VR3-nV{5Ra`$6>d58u^+kmwLxv*4=&# z$%hXe4hzD0+J%3LljB7z!#;P)$qaYh8K+@MqXwyzU?7Li7TYWgOtZ}^nI}96pK>|- zHDNWDcC*)Rsw}A9lg1XAt#72q>clqfMs`__`QW7r#Ma)|xIgpNP~L4>1zGZSfd~uPIN;s% zFP%>K1Grvmi5O5`6NEEKu%3S=IOqE`WO?M>K~mC_@X&t$s1Nt>RpQ$Ntd8h!Miy}e)cSk0VWyw1 zoR0Q!39+A$UFKsx6Mw`VeqLn($&~ZYe?r`Jt27nX3hIP@V@0Q3vBVDJTajPTjM!j^ zX@u2VFALyLmyf(XNHTRS`)9;!cet*3Vbk;aIZ3=w-AIbEy-uZ3+~4}2RrKF0W=nb_9e`t#Y+M5Zya1{ zD(;2x){bBY&k{p!9p_2tE4wq|>D|^M=laVid(QNwSM12eNL;qJQfIE&mJ%PO4_N(; zK1YbNVNb(wigYw1bt`hXB%bOvoe87Af6U6iVs&n4iI2cNAmprokTWy*GMG{Kv`SSk zPb^Pb$~4?Cg*yvR8q^ci_N%fKkEpevGQJMKd{m{H{%E|#_EGYIy`v!-sdk;TR(m<~ z_A8Q29_*2Kb|KHQA}Dy@;T3!FMQ!<4=ZaZwmPEu8~??dHC?i zG^+BN;ir*e8g48_{xxk2B6I^H5j<(%z5~*-SguevFhQ&mik_U}mZFk}rr6G4<)>+2 zKr?ht54>y`+LB1H6u*k)%K~*Hu9ocCwGuseipQ8+9MtTX zq&r8Bv2jcNW@=%gbd2VO66BxXtB1O%^BKKZu%mx-W0YG+?&N@z>tfI?$n?|Ul#$<* zW8EjdZR#;W&9jz1v!PKJm5}$bek+wZ6($80mJ>NXgY*kR=d(w6wLLVE5kwUC8v4E#1SOH7IxZ)Z~ zYyhE#Sx$~(FGGA$wPKv|ky&^u!XGh{U4iwo8$Em{zKHW&K_luif94UHNUE`6(QYhnz1BaxDxqedT0^S|CdIpE2*`^KK#n@Wr&W2!m0V`TiK!Dw{z#xV*i z-*pw0s$bx97~2Gc8fp%KF@^Q+fBb*1SFAjbt@U7~{a9Q&+5EP=sneI*Tel12FXE8* z4MjbViRCQO;>ph6pXN1iGo-7w;qKq)$KJE(30Td0TWjIyf^KD6zD9(>K#XwI&SlWm zef!RuCRJKzWxq*dLu{_3N#F8v>r>^#oCW*x`aIV6-5n~d4tOuB-vk+#ZN?5iT052r z^>>!>*SxAt?ol3yn#Nt!M&3Uu8q{bmL%Z`c?I-)uVI{9RT2LU2RcCSv-d&s06=+gQ z3Yy=9R5i|6OTNnriZOe-b9rR)lBK@2ChkN=f%d7RN4Y~N(Oj;ZN*H&fV$O<5oL}}X zlcYcWyz=cJY)$fIpf{oV{X;SBr=CuB&A4A2zF=ivsh}ez60ko6?QiFj=gFwIo;*6N zqgS4KHgWH!k`XUHk)(_M@9zFt4*-$}vS+c;pfb9T&lgT|3R+xgX~A=m`i&L!*vi zw;$XDpsMI#l|)mQx1k^@Qt|lJ-zm?;r<$`Di@2r;;!KL5bA5KN$~5?rU^$Plas!@a zXWzlGg7zj+nT7XWU8Pc@cwBu7uJKr2N10L%=Bw>GH02R9+?@s02~KXfqH|f`z_^~f zW_(G^lWS*rl6-{V1#r*hzr2584M)(hXK#49R|+@0yY}g|<10R2)pLG=N%F5zKsH@| zn`i7IOYL>xD7PeGyC%$-P*IqD~uytN?|lm^Zb+ z=Z!tRflsfJR_opKlG>;x74yRRPS5A(k>D%h#=I1^ZBr9qo^rQGPXJi>Zm$CGZiV1F zU#J}3?A*+iZr*I&z(sh~zB%ATVryuNtOO^iF^J0yFtL6+PCXwhp!(J3KZhGs=y}fT z5|+!rYUYr|UY%N{v)p)Vw7o4g-B2Do+ax8XP~xU7?|D12%_X|LMjI(l!cC5}KWt~K zbC7)_h$>S19*W={Y1f1YZgsvZx=?a~udzi^en>F_5i6e=@dA7j=Zj82C2GR;i}@*s zZC6fT6&ZpOx31?Lo4Z^yjw8Roo3hN!ocQ1MAD9luL?LY~EVNb~Lt6it>T{_h!c{Jn z=isLk7d%g~GpUVk~H`GWFhCcfirJo}Ogo;AI{qKwsQ-D{dx7LlW*iJ3PV0>h|G>YWbWq~97{ zpuOWLcZ$|j3IJrk&IDyzboEMOXI;Bwoe=~X0J=Di*rKTUenej#l6WoYw)`MHWm7RX z?TzaXEE`LWHo;^A5-=cYpk))E>uxU~KIpYxu7j8z7)nkR!WvCO6aD zZ{$>xP27Esf|1eoEy?%ld*)7Qp{1ELm~Q$@$KR>Hh*CYCT_K&?&M9qIG#xpGcF*LJ z`b@MHEwAEZl5QPm-<~oVl+yl?WSFD|reLx_6^j*I(#5>{brJnj74Nb*xKmX9sC&-3 zv|diebshucKiaftbHh$ps8+p!4F~)eP_6Yg6YQx!})i?U5g%mjKZao)oU-5pABBOgdfTvj$RWHloEmh<)w!I;nK#Hpi{z$2BhS!^$t@)3_7dxkeDnDLZswO^ z;xD!5o$LR%(5#+kCnc3U8sy`-w-TgE0*pN8+ltREsF&N*5D=(HhkeLlWA{St3#7(3 z(~8H%Ji1Ss)89>fwv4Jgb{0Iu=VAP<@vy(&NJmE|av$D><>~pXe&GmsVha`!paq|K z{~1~mz6vn$rDQC`Hrv4h-a4^!KGIQ5Sb)uoY4WD?u2m~bqeeW(P{z~oK6H-hSLv@X zw0Jk@?z_OdTc_EO!}U60?Z2RN4QHIo+6LXr z-g(8dKN|}Vkgk7LsUYt`w>;uKFzucNF}|jMjTrCC>)$HJx?B#<=JB^XWbV@s_ma*+-@ki(7X+ZW1cHQr|OV{atY zbIysH4F2KvbQi|@dF&;qV9~XC-%km>b(GH*;#Y;y0TN&uK+1Lk<6VytVJ=t)(2$|c zV^@!*sdcbaUV(?Cv9lceKn5?}Hy)VF`)qlx zYDGyD5vqzO>WmXA27HWM+pOX-l4|S>WT)p2dda4Jfx$eo({_{wN=z*hIA=u3sm6t(gYEm?_C-Sh9#3JyY9E~tFP z%*fKf!?)uE%g|6l<>!{AfvgvoD|&uGG;~R=@cs;0b200DsMdlI=j1@WYn$J3V#uDP z0`uE;sJzGCFqJG_Vlsr9XBAIWPJQgP6XnaPhZo+RV?_@LKYXyu%H(6t-o!L_5A+Pxl4U}<#bMXS#xThV6pS00;RLNi;J&+ zf$k-N2-}A%S(?Z@S7DZ6!FhfKoqE-7AeLt*06rG-LMI@y<2aU7ZtX5#VVjb8LMo>E zjdV=i&@U>8euhh)-Syz*lTovvFFFeIhJYikomMWY3x%MO<497ue%4`v&4oGwoFJo) zBf#SI^;j>_G*(gJV~6dqxvV=@ST(ppw_&WJtZ>zAA&MDfw}1Xl5~5_(?+uBH^UzmT zULAQo>D(SxmuuUs-;rr6Jk@rCP_Vu7mR&~~Y^lasB4JNadCNaK!F!4lTK+K#t)>sk zjJ{{QIjGyUJ-Dhs>B_OIVF30T4HZCD8n~*z=sX{zI`2P#@E-@o5Rr4f<_B=lSPG0R z>Y=jtXDB`xNd@e4Ei^C?oFrJ`Dj)Bny1>^tZpgFe-=-qRTw8;vvvv-BRH#VJP@Kk` z^|$-W$_A$In6GTLzUFO?KeY67635y ziu2x#UF7KivhCl-`Yu*tMTKx@qS6U2n6FIypscaa1+aKQ6I7vm!HrFmiH@_ty{ z_;35Zb|>#(GxP#u#C5NYv5GEEDOO}J6tk^3ret+n4Sma_c1U-(jE3~*2T?Tk*Xbv0 zzGc1Z_@iv)Q*XaN`QLAEp6`F99Qf-`Kfm3-|IN>btWQa3UZ{Vk{+E4EHhL-g!&P;z zdt(hjX+izj9(^s;F4x+s!YL};O`MPw&!oo7I%ZlmeQP6zyUl;|^rLoo$BtOn#u|_p z)+c&J?*>**CTUuKvg&?FhHx5OANfyfxX}pdK;!;c)yLo1ptij*|3?l9K7}HzuYYkN zxZ=+p@tyx)edH%sgS2KPSGNE3vG$?S1<9%U$S*zj*+n(?jxVfOP5mFcHTG_7`Aku9 zgDPxgBedq)@*OIo2kCz?c;j77Zm{(vmy%V@xHD1jQIbL zjvhAo_fp^QPj8xg`R2}#6W4pKpR0C@a(oOy8jRQ16My+9;@MM269peE;OXL2h`R~p zIMXwVorl+l`73PJm%$w*kzxn^T>pD*c67LtBLkN!og2p&YMZt|{zdA0`KF$Z9VP4E z`i(w_0ZM&G*j3hw=L8>yo5G9sh~({vnfsM4@l~XqY7u%#NUNz)$^T&-F{VgGai1fKFFqCZqOvfPA8I6xaFG27xPd4sgVgKV5}G3q1eo8%?!<>!!B4fGCDg$_ zrcNFUJKesau_f;&MLTxY*+}zh9{USc^9&}62@dH%KvkfO0w!#iFk!PH$uUvo_R?M% zf%?J>`o_@7UvEcO_Bx&Ow9g!$$H7V60Kpb+mVtZavBHAl{VarD}1~ggs7mX^+grwi`(d_T=*7C{t@Yq zW)eXZequp(k&`1hH`_OB+No6=zZiZuIFQZQoONdrc2svB{N$_B;Y~l$HH!jMPJVr+!!~pkw@#+w3CFV zJ*hp|k}t^)RM41@)dj(IWl6o)>l1%EsG1!J#Xe`BBrb#VOocvr=kKA3-WEO^_QmTl z`b8p~RzT0QHF#DrnWBaLswa9~V~I6SHEd&DO~3${VBOe6m&HwXb!24-_ji?+p4{0j zx6x0tw&@efRB36#xTrmqSM%|u#h;K8_v@^a?^aYG!<&BCu~O~Vop;Jo2#XzAg(v$v z;|6h0emsBS`ef(BhY_OkExtaP2U09`TjSyQ!r=Ha495#zUllQaV&Ux$2@NgT@hG!? zb#AIB?djx>_1!S5qj&mWe!bk0<>9*AJB%P#mRS;;7yYuy zJ6cZfWK8_6$?69F(n}V$5@b#t3mZyJwAn98e!tIVtV*c$O(O>%2O}`YccN4I1F8*j|l9)-cUT=+us9|;TV~Cuc zbk;nArzUYV>T+5$E_pkG24pUrul8ELPq_H__7wi=6H1M&b|dhItfv2z;k18RUMBG6 zbMmyLIov9QG5|=Oz;v^)B+NmZsvew_B%yPI36ZMh5gfEA~+oy-eHz7S=46B7r zy`9A~Bn-wD_o`7A>GwFoUO%1Kv)dkzKr(u#7A5QI~1gVc0fUz_eEmn-_^>wWc`2G8^!!F)$=uN^*( zeie*U)Cz?^9J*Fc>Neyz z6F8_7RSVzL!mSLSWA|O|gXqUs>!uw`>ue2PJd(IcO?kIky%&w~dq?-A+`f&wbu#r{ zk1LDf{0seT1orh^XK4BX~|aD3am#$NIXeddhU%4kRFhe+8ds`SQ1Q8|(Yw}e+wth7VPgA&U!$}Y>>SIc- zk62P4jSi^{sOo@OwRXLtLg6PUDc`2cJE3-Yg+Ck_X6{7z4E-cfkFlUD> zabD)Fa#4WGxXIvsoxxnSbH$CYRXWSWmRZaDO$-mH9Py4&Q}(x@VK516sSiO{x#BGC z+>CBOu|~l80^K>|3}d1^7lOveU>+s`wn|r6ofrIC%Sbk_XmI}lwDQ1(4Sjw;1zG@# z2YdbbS|WWj;umh$MYqx3D|2VhGmKNnIQE2d13macn3z zxrsB?rtGcy&7{Wsl|$m#7a&{!B~bYWq_YD>wm=3dBghNQ86vGJEX76UaJ*1JoAu^WJZv}o!7 zz?&Nw%p_b3i64x_?iA|5ox=Y#7CJIWwNX63X=&sW1&a=Zsy5<}wa>8z5pI@%Kx@_d z9E7o{zW><>1YxZsxhXnTO%PFv-VHY)guto(r?JLJ%6dIsx1%J}_uK}m`1cdPnXt@& zWHt1_VGXeSUP*y-}gSu>X$`HdC5zH|C+kQ+K22#og zyKo2e?%(#~*Q3sX^^qR|KEe}0{?mS7Uv6AzrojD3csCUL$p0}*^apC?q~xmio}0(h zw?b_DZ-Y6mO;L#pF^$G__5WwTDvaSd5*Q>ak-T!y;__?n%dauhqGF(W^~u#|`&34` z^wxXLP5sUv#2<9Ap8q>P8YHYqYQ0Em{miQwnYbhh4C#raH7wJXivU4)!0+N$vR=MF0p?*Q`LH)JtK$#{&&2YwBmF z^7UMwnOGQ|adK90H$w_@YL;&81nV66@^v?iB4c+X;<@*%Xw~>VT9Od$``GoX2b-F6 zk~G&(S{=iHI^VH;v1AQl`P{RI><~fBK?L!BGrgDJWAS0QpNnHsgi4M$*NVMV2Fnk! z=6!|WVY}!w({2>^{PG+}=<7O&*3VT(nZ^vO$anCRnW6`Cq~$PFh_-@2OX{#9<^E#l zYa&`ZMN>ghUVsqh20(=HkXFh;NVHmn*t1Dh4t&6E8~h+`L&{UbE%`#=KO?Tm&vU#h zB=rfNFkaEGdCh~~`yfPi7PBtfWz=ac)!_<)wRIiZJI4N5>6ZcEAe9@=Kfb=J_oN5g z11k>*$WjO%b_;EK#UO{Q*0Ta3RW^RIWg@%ZOe`16XIs)S z^$g#8<5M5SAoevre+uH6_)E|w&{iGKV|ItJ!YffQs69t^t44agmkWGp%(&kM5(>We zqE7cZr-&f60-BFox+cmj(~kLUFO}g49bT!s?ZG({l9OL&FD=v#_(}T8TF0?9n%gQz z(H*^N7{dWf6{2lJHRGUqtZ0;y0S(!DO7-7QN$tgLY{efL5- z?7Vl=0*<3++d8x-ifC_RonRiEpw~_~gmh0C!~8BA$-XRhY0&f2ts4>G73~yD^e`4v zPU@P!ZD%10{}VJoU_UyGmpv65D=CXv;5>NBLgmS-b5n})p$w;t2K$9J%Iq#KE&9fm zil{^jU~zYPqpherh-a6d7snvU#{zauo)xPCdpCzYo~GCd9w6cR#G(u!7kZXcdpK24 z9gv-AN7vZ(Z0Yson)$*1Vn5~I1$Uw<>q*CZ-g#_8N(dMb0X85}@W97#tWMw50PC%z zT{aX0&`qDedo7e#kGMxaodm*z)%2B$w8XKvoYUaEr=P@^{;nF>Gi;e}@F*lAY-8*D z)g+H;1GNy61Y()Z4XA0x%=4Gh`;qYQRnHxEf61G3* z*;|p`&2u9gL_alsgLZhqaw-CFN&XaoPC)E=wxA_dqISxCJ{Q-Q*TZ=+>_I@i8^iQL z9Q`I3Xx7@IF?qn2CN2oqn@lxfllWAwRusiyAi29M(5{yqOZctDAAt8IOpA-s-RO*( zn+NaHZf`GlKbGbr)KKvH32T){JT zi;nh5J&Y$v{Tmhmfm7OO2a7?Q1gpCbR#<5*A6JmwXsec144vDAV_Wl}vqfnlemm3D?) z&Nq|xP9As(Qw2s{8Lbzft@bZ3)!5)W)4Cvbe_Q{JCP`9)H@Lw{?9n8{~Pse5Dwrgzy zKGk|s#?%CzNw#OnkXAp zg=U0)w7!Osb#E}c3_%7B0#A^6Z3`d@S23b+*hwtDs?$UKG5=dTrHutA!5bCb*tr9{ zc*0m`Cb>Z~!h^5W5`cMw*gE-XhOoIze2t0Gss;P{7k@kE);5=ju&LHZUPuDlfbzhx zV%d-LN=J?!ubSNn?%38sq9!WUo!!56!?a%6Zl!S0PvS-VvLS-pNnYRCVZnQRw+&1! zKoa7F;~DKh4Zr5zyWyG}w4c2Ow%D~<)qG0{oJS(-TmLsXh(?wtww$MLOz%x*xewoA z7Nvb2C~b{r<1zKE{4;N_JsWJafa6oW`s{4{fNL{=^MAK8*Di#r3bEmnNf zv>4s%CPnfZ>-+vMRBHh7 zPC3}nrjHV$LoP`+@Y;#B_J&;U!~eRzucLYMzv!vH63qZ;)B;gczWz}}t9}6c^;&CC z$#x1a>r;RNsRk1`Xud>y*a)XFR-M&KZhXmDe)wwmzK``Lq-i~Ph=oP?xLt+K16$kld)`bzQp1jtjc;)3 z`(8xxHjth%+p|uOjQV=x39hMN8WJ(dWgq6UFP=5wqabtYeM_F^dofq%T_^D@h z{!gcjM_9PMk>_0NjRlfTakc({#D`uvE&r*0Yd!Ju?`W*CAc^&XxCc@4z>+1qKzaUc zYm0qm8_ku8vV{r!FH)^?Jv{)xWFn>LYDcHiimO;y0gc3=75pw|E8^M)gkjg6a-o<> zFZZNlX?9tC3zJ%n?fFu`eiWYM6Ak`6cP{v4=u2UeJmdae#F)({8sj_?)L&I5b%!WE zX16$~;=EdHI*>_qLvpnq^UM0Pq4UM@sD({qJEkKJg|-rKi$d}%kQ9yDz%coNB|_jG zc_+h(s}ph*J#=((iHlfZwBUjC{K2@-R(z1mB&C&m`YvVVHriY-iW8E2F$6f{rBZB} z1a)RF;*bi^ve`yCr#{$2JP9wS_fD8^8|h0O@$ExT#EFz;L>S46LF*q?MWV8gAs4M>ni;F*#4yztN&$MSGyDU_pZz9OVFx9md^Cz9ETt3pHqO1URm?&;s} z(?|6i$Qo&K^RkX+cb4JcTG{%S?(9ooWn~s={hz-}_&2wB<6Sh zRuo!+)&shsIHA8x>hejQ&%D{wpl}5SEve7li#<_sPjf5clqYr^%XVVyQpwiUL3E~Z z>44J0{iUq!_ujz|qsAQl7^bT!wcR1iSpts0T=GOsR_nsaX=7(nE}I?%wm-P^1b`AX-1c+`Lxo2=H7;Ic{ZF--uj6HC%u zj^Y`J5Kx!k9Q{J`K2K|bBG2YJ5_N8Mgf0&UudVO~Zeuv%#X^m^FrZYFh?%f(J#hMK zjM3_6%5A4_T08uoY>4wrY?s%Z!>S%ShwAmaI`UjEI)vn2bDSjf(fs?Wm!{FF5DJm5 z!4s%7Q%AjClrXIO#A4!DC}3H`mEi%vd%BtXCM^#Kq1xMewh2`QesSZ3yjj1xzc23; zWU^r1z&3WYO(^pfVFSQ)sOBKr1Ygs5sq@=bEO0CeS`qMpf%7T(VO%z zdXw2z@UHfW0P095zjA~Mo;|AhQrN2WBU@P40bG7(i0}e877NCb!0Q$jThb?_oq*UA zO~Ifw_%p<78+o?ocV8+>WV)?J`p^^cbm<~bImR+uA;)w+Z>c>pD`=O|N9@(;;WimDSSZaJf7@Oh@MQk_K}~x?GJs)bw;> z;U(lNK=|ZqFv7Jy)S53*{UO@mLv$yIJt!+LDr$MJgl%yfoDStvibJE3?`iL= zWknC^9NOAibl?<#4&Ke!e8mS~hic*>2!mEiTYq&rsxZ<&N!w2O?jhQi60`7^2rQ}R zvB~hVND*TjH50urRQuwnsUgT4Rv3ZI9Q2=!>JCDwqReaamCNQhYMO7U5XGJckDe%A z*y7n&9)Fw{aR{T58$#fZTunDKsGHNL)Mgbj$>Gw9p3;mqQL^jQu)l>B2Xg|YQv0<1 znw1X03^_X`sR6!jbefc&tifwf#4tnm~Sj)Q_0gyk^E8xDOjh# zqDaI8pXN;My=mv@(buF}Fm?vBp3N$(;8By->e#^D={h?ybO0zIcuEh_vx5;yW(ZLf z&|Y>PxmDUE5B>y$fzHeIqx1_rK`2Tmr2#GR*I@^DPRcPJe@VtSo>eE`mF@m|zEo*4 zqoo<0P4ksvEQOvd9K>FUjp9wt`=p%`m(eZAHFm z^e@fG-LJjcpcKrcO#6>^Fb?qK9zbbIOJ1v@-Smj1GoJY2VzBf1n6L_>OzE;(w0k<# zk@i5Z#;=nN9h2@;S`Cs;b92{&l3X^X@MeH#3F$?RMNNWSn@et7LLc*IOBdAL zsd-=>@-o!ZbLH%dc;>Ikr;qNgV2LhQr!Lrmr&BwS)JU)#K>74) zZmgV$(%=wymP>g;Ovfi87a6OfzOw!!?8Ux=K614n8Ut#jXC6=Xv0XJ&I5?C8hocc(I2w0uU*;xfoUR5*ViQk zsvy_}@3HC-IutPc9orj4&Sz&f;a0!B=u9%2TzabnPdSiNTpfD~1@NgM-Sm%9eTmGL zoH8Fr&zcGHv|v{#nOXi&uQ*Kw=p8U?AoLoMxmk6JiaT~7`WUv(JnQpWEuP)kF>ys_ zOQQE#PkgUxj=TJu-H0$GnLFC#m%aUfCcRgOzWT0!xr;+UkwTS>4eGXertW?MmQECn zg)RD3T}K(Z74~1)WT} zKn%m7GBTM3JGaxF=O1Qr#YXZ68O0ncC4(8jpsI$|^b4@}+!Hsb{-)?Ni$dDW%o2Z} zM`rH;4j3!YJxI|z7n9|{tt@vJ!XyGDG4#EbnecU^%)eSMZ9v}lY-fZsMT_(0jPr{- z?JICAeBB(LQie|_VB<)WT6~N?s=u&lx2fU|FDtPiZAOcgP-`==ti6mc@4wqUI+cRn z7Db%ug%xG`0jT$S8GbSKU{gI?9TF(M?FH~%a`c{1C^uj@xU;dsKvp#gOoSMVtd3w% zpc?kh>8n+720N2x)pb6T7BRg%@}g7|c|Yag39lRKrlpTaL~XZ2r*={Mr+s@FPp56D zJp(tnL9ivbTA!j2<~w9yDKpP=b_JQ_)xVOfp0TSyu5#bLh}Y^JZ8PGshK} zR|zThB*96$oG_1PRj;@SRJ6A_C%)y=Pxc zca8~bnJf8G(tT{c^H~Yw9gt*K=ZSGS7`ynyW(2 zJs{b@`{yLMu%VOSWjyoeGaup)S{%7Yq5{rG%rw`i|7yrCjZ3}|uFCohKXn=)NKeOm z)0OB7IL|?!O#v}e+ZCM`Pn9_OPEAnTZ{XdwxI+0;L_!o}0Wmwquf9KJ$nIy)bJYM6 zH0b!!x-XBM6B~0I(zYVwul&$4KXFXX zeHYT~Z)ETwxnKON;!Iavan!!=3*S{*-abe**{TrtZohCSrFyIBI#gl)Z24(Wg4D=B-F}= zG<=+-M5W0l8A4R;5JBzt#&&~!E5ISf{0rX`64wX z(I|@}rRm4bpig}^7HhUJX~k@NChYqdvOm?pLpFScawrMWTaVe%h+&n>v+@9)PV#*{ zNfNe_{_w=&C~-Htns%Y~d$hX zgR|neZWfPXos(fL&E=q)au>Jywd;G9UQQdOSA$b)bAbCyo331OZ`S|A*IS20*+u=r zgQQ3*B~qe>a(d=^(nrgn&Ofd)cJv#1yv}mEY-4nPI#NMCIhprVH;6Z~}rm?zxWHvS>2;jCn^WROu!G$- zM<%dWgk3zUi|yBnaJ*hWdVF7V`7-nYW_|sq3aT)JzOL{IsK}q*N;kdg!tFMF2fTFw z4xoO}=3oKErro%w(eqj_L1HoXX+fHXs15MGQfDCoNi@Gm^;cOo(D{+f`n*3;a@;4;jaA5~j>;(26Fj1#j}x}bPv2UQQV zzO#Vi72J89%5^6xiTVuNOWy9tql{HvLKckBgUP=%YN*|X@Zt=LNAiG$h8hIYkhcDe zvjj+gL~eGGo_RBC@^+oz#yvPgnNTnOEWqF z+n7IT+I5DFFkFS{#Py?=r1fN=v5h)3h4znX7Rc)a-H(QOz{5w0&?vq*wS0(tqqFYI{X%U&beKw_d721+7j_{H2tPX(|Oc)NzEg}~^|Kd=9 zQUNOdT?TSKr|!K138C$y&iGt5!KE6)-H+?CLna0NNFtrmKf$G|CbaOpcA=6^DOo@SdC%e5chf#X^aLJtNZQk z0uD)w=c5X<=T-47&+6janu`~C*#>)VdG3J^;RfybwwbR5Lc39nb*Iogk9ZM0=}-vZ z=g*0r|72zJ-jXNME_>(6)Rw$BUROlGfNuGrFgUx91z|dXdIqV7;9~m{+%vuN47ge9 z6bWJaN7};R`IKt^MpwYMiCg^_#C5W2SdHo>f|}0`CQ>^C1EB(e8%L)rPEdaZL>S;n zzqqE{l6-1Q4efQ3=9k|(D^(9V*i-K~=v~-4pEA{J@vW5v6K+&I{JzVw^MCGDgf%Sx z6?G*XE^RDr+5g*{>aRe0=@!uJ{A0rEWMtg*gt$JbC7*Da8|!!wywe$Yr=w0%`U!}2 zF6{g(W8K>P{5d9YE&;w{M1rPuPmP5?5$~T&26!lR!hCso5o7{}DLUp*GalM1i?KIsjGD0AfdFR3UKAC*}oemzlb;4PY z>xqol0z)|y_qW;9K5S^+j|07ZN<(Xvz418Yfv{-0U z;^H|{KRAdRzweRrSJE8L@-Lf`_gh;7blB!a+oLn2(A#?{mvZ!##5pp*frS| zT;m>}j>v1;&ZYma!`#I;7WSXItqQvwDasvCR~v(&?*{BlextAA*Gfu2*Sf$!6F8R7 z)vpT)%FXrXj;aCM&vp)mo8#F|Zdi)LPO>p*Im8F&Boxflk4lAVW0UL{S+laSul?U| zaq&}Y)Y1vX_?y=@+PH??_%#UxL$O84r>oC$lhN-I__KRy)5uj%1S&cD!92ZeM|y7i z0GIfFF3igxwjr_ed!v|=ajF6fUJr3UUE9RwDf0N&RqlWNUE*ylT;J-s_u8iZOqWpu zmXTmvg|7nINis4%xuF@&{d(I32Y%0U8d{>Z}pTsD|!_+em zD4D%8wzTSFvbmI;w@^g9oK&`ft1FK0=_5A1XP|{8Xq8$x;V7(I;k2Ln;u9wBo}s)^ za}bgZt`|m0(aD~pc0)%oCM|!dL7a??;^mw1=iGu^Axl|H^JR@DEroLd_p1~>{n~Zz zn;J@uE%#{W2d#5kJaXAPP24uGdM4|0L-k)uu-x|6wJceV5?|Y%FM3K!jb@f-5Ze`R z7gAouqS|qdwS9_i6{)GYq-87!B|9-l@At)yC|AHjR^sioWAy!O5Q|bs==w{Fh zW`W?LEGbldpew1&XHs(V`OLg5AH@vqh_x#$ojjJ4C(7Jbi`^C@g?1va>Gd_-jU#YT z=Xklmi{bS|^QzFAJ*JBxXJi~R;7LTzM)tEOEyE3^C3_ze6{Dv->+h5^l05Bs%QbTA-RTh(@F20wY0m_ zS&Cnl5X*#~L%K0z+U~Nnxrpo3o-`qJ{&QhyFYVF&6Sou>NQO=A8fjmL-@}_4?8PQl zD-D$OhdBKz_diYD22-5&xK?&)IrNY5Gj`f%%0 zB3Z@J9?w0N;Xgeh*?6q>4H{>ZyR1sDRP?2_%i}_B`7Mbq81ztip!3Re&oH2rb}zi0 zobMbdBPC_(0A1!&AlCkP$rV+rXA(!Q$MEeN<(7@0Yc@}jf|OLGXQ~q3{vxJ zZMFsq$#dOmSI?!SMso@>mHLPdAj}Qd+7HG;%jQ+pQ!gwX>0NLU5ipIKvgL@zJ7eR8c=3JwSos5OXKbD+-+r+(_RPovRzf z)lw6m7Ex=18(~$_qGfM4>eq?xEL4kn`aR_72)=H{*uhN6ksv8)*cddVtg7SJBYrMu zF&=q$#Yce;^}F!VNL4QPt?@@I%_k?9=p@_`amg_;!JX0=;`{zlveAu9J>4T8?_rg zk`4~Xs^5zUVmb+fjVaVZVXAi@rjk%BP;vNKC0GmJ{G$=IPc$ zml73Y3N5abYaL^gDwo}#k5$rD@i!mNpFVi^Ij()TjB*)&eOu>Oexu7MLMp?gQS+C@wcY}f)#3((Z}a?J}n+sX+Li+sn|798%A=4u@9=@kvP zZ|3|O(+)l#F#t0ha9Uhi=kpWYvBY_O?_4}pUGGH;^nz*mEy{-wRH3I#)2-( zRC#*U1S;>VexiPVqnhAwk}2a%e5v_%&OObr_{9D#KN?`BT_q-DJWtj67DA%7r&p4STnunG&g77yJY`+ z+1*9NYlI;xV|dje-y}FYka+d$$E^hzj4))MS9Q zAK?#i$5k$bIf6?}%y%luQ!p`a9%E>+Cs_tkwoz^xkIj6*;Dxd}&7}U8+rMPJc0^7U z+E!BYEbSQjGC0AR_R;t{F-pR_%Tm1-SxU^Au_khpvBS?|{D!h7+&jO%CMy=Tf82)@ z@S+tdZ`YO0F)C&a8Y!zKJ>EwR5-j+wxKDxKGE{Y^rkufo#+oH^y(dWs9xMt2`dK0zVu*N_;4@pmP4n6Uhog>C`OXi5n z!{RkG+k9Zj>E>5+*Bkh2-`a_ej|qm>#>-!T`Z6vm0y!%cUU1f!n3}3|S-pAF;Jt8a z>PF9~r43T8H4EC9Fr3jD1pw&VlI#)cH+nBMn72`{7EHow@eRcq}(dQUIm1KP-ghBh<1E0*xU zNzf&}2ysa^jPBukA(qx>Pye2}CEYLoCBS+g@fIRg6#GRklCdq#H0TH z`>{z$jRxl=96G{Rl*x?phSwbD))ND`*~q>Zg}i%r=jqd@sR+c?MUI5`)l*Dh*i77@ zO`c`f#aD|qi|xmPuB%EDy((N(EufD&w;10whwI710bpP6?CyO&G`P06K2GZ}s@a+F zLaCs0zAd7?hg+EEtJYBR!V@)(6E_d1l`=D>Y6iRt_xVd(+uJ|)^xmzX%d5H72hPu& zvcx7NJnym+A8Fa(BsKQ0snOxJob;K23b?Mo>}ys-TsWTo8ex~adgO}RJ1pX5F-~oB z@~bbiQ|r|$@_I?|Nx67=eWG7;rm0Eq9J+(cB7NU&%DG#w@ettDF4%rt)Cg$yj$Y*C z66B%**S|R8CW)DP8@Kt)v7}k;hlBqr>T)7##wVp2ZCLoD>BXnk?3l!ZjiV@tk2nYG zlH^3y?k#sc;|H=NSP8-&qUjDYXOoP>v`cI8dNs?xLo}CuuG!A*W^>p()HRN7XDF$t zB>pV(*VZVQJ*$;P?DJ6*+C0*bD)B58b@NV5{aDc+38Ku-F46SFVSi@Up!ip?Pn;^0 zSp8l<)8Y~q&Ku?I=jMlm-#-e7N5W-@Me5#u8HxHOqVM!Mds|_^Q!YGuSRY*6 ze}%HAtwv(Ww$cXGjR^u*ENaDCaK?E&_^b{iq23w?cfKp|hq8!?@(=o>BeSMyj_&XF58`Tz!Nm^0E0w5vQ zG(Uk1Xi1gX!{|ic3B!aE`e$04$}KZaPZNn)EYGbuUmXa9xAFvo2%C<$N@MxPo<<*X zVSDv~_2#_5Rn2DLFOvU1hhRpJph^!V*!dei~SB1dYR`j{LAw(>H&BoLAmgaW+$iV{o`wT0{>P*6`FH69!+jN6_#eC3V!D% zRf0w#8AE?ih>d2BC6-TzWLte~?@ax&mP@OM7IZxZ>*P$H6sZx3xm0_`@Tftmgi$Tq z;_w^UKKq~(mvOhTvSTh>YwARibqwqFL^)cXkXYYye#S#r*ZIz?P+%ZQd-_P zig>!QR`znP2nk;1LMwt=LO=itdmob+=P_q=jf!S~=vr`EU_t^-mxUgFPK&GH6XD6T z&7@Zb$G?{5OtT7ZJZtY9*3c+0+q>)otJSM^-TrBA1eXtK1xdlNb~*ewLNTKmq$kY@ z=8C4ZQjwZg$Q{JpVNPx;f^S`XvSNAV^}inNU;vd3r(7tU+tfd%E%3!Ra!RRpVs+v&SM@wVjl`1EId_9p|;4e%OHAUejwx z3u3^%9=*)FG!9O+tx2`js+j89$>pXv@8XD7o59@&F}PBkKR7`@Y6>{sOWPOt_xmZ( z9Mj>@6d{e6(@aR(&&l|8x|(Gr9JdLM@&#esBitEBH&rAWOZVCvK*%joaMrgICnJ1H zCv~j~osjF97+)XzFr*-=uKN4?gQe=v0F##Xzg){ts+(xVB`S)DtGCcLYRjI;oA)HO zOo8wc^Q+<8+2#oAt)0y;61b#&GD;d6Uf*2p9OG%>@Tedc@CjPP_&bY2Dl1(?T@O^@ zHjd6FShz&1k06l6HI1vOsDyrQC%!4LKWUCeg(n+#bVz4d1DfBBj#hp_jPlct1n5>f zH5hO)kl`De*-}5FlTgQ&IX=d*-cX8|6$k-@n#G}P36?n<&2Apa$z6$%97X0R##$Xxyga~lhJ=i#X*$cb8JZhaTa zxjSl(EUlw|4)}=RnC_eH37G6>B9%`2H`(tO2hD?MWxX>pLoT)fI+9*|vCjRsl`{UH zt&|p5?l!%72UBC866=JU?K}^Xhft+~F+}qY?>pxLy0UaneFKNe}P*txS$m>Df$v&HI& z8qK0=$O0$V5qdJCSfdI3A0oWt)UpYUjIIT_fbI2jejB9r>dJ&r7T{m$J=_Vgu@4bz zzftPA@+IQqEXk8f*uEg&%+);PvMoT|mNT((OV?U&YAp_G%!7eZY>LXJR94o^(`p|V zsI@64hdmWycHdfZ(5Y~y2q2;u(H!re(0-uRpZ zOQ*(O(GGbtEfkF{U0I_>6MO-ak=boL$Oi{Wd5szEty@Ny>yc0LYm+5ZK$YLUdr)KO zGjScF^B0>`6|YeoI<<~>W-Q!}epQ-HLtF7 zDa#Yl`X9nRw-aU4{VH`Br$`WWcv{;1oi*yiu+I?cddB@in6)t++w({yd3I+s!bG@$ zSj5q?9enWYf~Y3|u2|%9!ngM!fwk7kE3c!Q>osb6tk+ML<^!tyZ}d4AsI#LFj@{D_ zCqC{v^)?PdC&8@{OH96wS6^lh4|^vMjq+W?f5L|a)qezSa3amCc#AUi0p^R7MS-ZC zm?O+~+C1P<1JbQ)1LZm&?Ip2H!ac2~hZ@lphbn5lGxKky?aD~TET0`+ zYDi->Bbva5f&2PqXBk^-lvuwYUc}&o40`v7Oj7@IUm&25)9MyBKKdeD_~Ui^*88YV zH1+jwl$vET;0fk)Q#rVrF|WUNrrhc?-;*ZNXniqqd!psw%W`#2e!eu^fhkSMZtn{M zs#19NOn<@x+pBm{kqLg2TXP6Id*S2(Ly9K3^S#`8&%&3EjznQ};_xm`)^F`#)nC&i z1_5663u&y4VB}(BQu*?>`UT-2=(Zkdb~Z91^{`%H$JJv1DJq;u^tvZWwM#!%|1m48 z795_1u&ilGFmFq3UdDI*7tQsvAt{PvwJ1}&Z``~A$a z>##D^2;#8%HQ(d#FRm&0ummx;yJk^!V`FAr9%j7nP)k6MKp<^k)<>(~GmqIwEeP)4 zrvTQ0iZ(Oh0*Phrbg;dpNr%7bJ$pg?OTN9dTn&3qB_m8W*GucUme0{!sH$Qd+~Qz1 z`IRPO;n4g$`h*>hDUKGBPT%>qoCh-iJyW~1i_!}vcPGbbKV5kN8XONgf%=Rzj(RCF z=>!o-i`-W43dsBsO4WDT$+mSoe*L~V*!%=^R}#HE<@RKL%qbTYkT8__pyuWAdkcii z$Njj!kus1!;VA?-^H(ClceGAnig9+XuX`ky|*%W`sXO_)MR`aF9el=Cq$UApA z^3qEuI18xu>bB=R2E{G-<89WCqB6ZNF{ZsS?9Jq$*TmpTH?ory2grl$rV@a`rDIBJ zYShqnsoQ?5csrWcDJr@ICU4MDO*K;1gBC_3e$}nI95oUIFa?=+!iEZR5te>EvbStpg$UXh?JL#E9j6N?jfQyIhvE-QN$kJ!wp)h}n~#UGi?Q z#Xd5@zp`a`r8+v|_T^M1)^)3sC_Oh$F*5cozC-LoZsh*AkG@nlXu~Q)hDw*pEJAJa z-IiC(;lw+DuWizpis{96EyU)_?~Xa$Lj?q;1&03& z&pe$cH-1oVo22sj(til(ZTLSde9rNuf=ulfni3NJqtE#(J#Nc^3w%NSiGb4S-$KQpOU(2-M*h7|fErc-j_DojFy7h0cg2{!z z>o5u|41cgphIO^H(lne74#!tE5#2WclmwuoP3QIF=jY6JBZJ7(Cr=d=p}E6iwZW61 zAlt5>AK9jcdbDPU+}wA^RaI5g1O8&p%*veO`lf35mH>bOs*<@@oKXvjC8^{OO>zjZ zM{EAjTHunXhXpieX*x_T?zV~rz9TA;!6A=&oURtt6L>FRD5Bks}~ zfR8r!#DmBv^I39}gap!zw%H!1N0a_<@9k#hA^h&FYVl7w>}dt(e2xFsoPht?FMimk z3*o6Dqw8^EH~;Z7uFbFCjbEnBnTG4kT_kQ#`93V6Q!S(3ul*NRhE#$4kzgCw+P_ck zb+g`WnG5J2iFJSUk2^ocCO$muXcU4LqXL%>AmXkJhnIjE46BwpnQz?pCB|$dL4z4` z(DAG26#(hS%4S|do z=wsFgk8OQ})Xnbg2cvlk%c-H0>i8}p^F0)}8ohtj(cz%Q#1$gY`Ch1*{UT-Pm}#r( zu@;<+mMCDMNdBr=+2Z`-rTZN&@{1_!Y+>j5?Zf9sy3_VwIbo~z6&urMMqPD9TO-~p zgDK=nY^))=hdgjJqw?V>9NG#hg1bCp?5OcS#107wF|@U%Rt&iR%7kB&t#+@BBNH=X z6LHP~AneBRXXMVHR(UH=wkC#H(#CQQ%zE}0w`fQOKgfY1uBpT(#9pGv&%c6yrMFip zAXmG*h44)txl@bpmk-mmu!uXZR1T%1w>-;Du*dri)BjAK8YD;sds?H&@&|^dy@~wi zn#lhx)zSnT0rW+F${+nadNe`r;G|<2`#eWBz>)=$u#zGMSu}mK@JV?nitSoOEygdZ z({K0fVAuLw)pd10DKRjq_`$`&(doBWrcOmerL{S2RzChY?zJ8ZW1Jx}RW@mtTI^&jjvsq%cn(JCT6uSTDzkL(+pIj_SB#(0| z$8L#P@OZT6Yye!)55DkV)7!X)PIqt@-38dDB@~x=$`nd$CFp;qwlcFWbd8JQVSQFl zy3N>80&tjB{TUJFsjp3Qz07Bf`T4@^TvKf8le%5)F+Hn5dZ{OoiZO?Te5eE~AD~pT9>@dXcG*^5V-M&K+`z@*vkGv;4h7|95 zmj?D@_t%iV&!8<*vlX+e_+J1O=6*g&3x-^A+%f%ynVA+}K6|&vyQjf5Jt^>1r+Y2c zdtGJ6H~-lKRun-@0+t1e{rY?u&AmH6&}!hW=O6yX2Y7Ib?_^Vkx?rEo3DDe*AUvy( zZ|RzojPwhAlu%l!tWxI57JRjDVeeq(eiy!18f#ik4H+=10EF~N(`9LkVMhOKH~;fn z|6Nxx5S(}1ermv(CvENQ$R%${l57+sPYE94e^1<1^0ox47J;t-RQ7goLzU_YqyXgG zQ@5~<#zA@WBHd48oVMGx%F23gXJ-25T>yy$^oxTX7W(uZCuYVmJZ6@!yqNUxK@?^K zn-IS_e2$Idy}tj@yuIn$j3yzPl9vHAsf#RGa4o429YoYu=bn{bz&$6Am?z+~YvJTRV^e+F>6!Zm4{=Hz z_{_B|Jl`Qvvic}5GfxYPT}18cngBDblTG?BQRe(?>-T{JL@r!yH%apDaNVe*gx}x2 zV>0>O-ZS`gwP)5->{p;-+2|_~4~vVK<}<3;SvbDL&rU6XhOI1Wtg06>9!fA0I- zV$dP*RQ+}t514dw%==!JyX$G#!41tE$`mEkTJo!d-VYn7)Fa}*>@4hb|l zbvZlnH`4 z=ePEB`Na>_&LQth3Ji38?*XgMQxa)q<-Wl+TO(WBy9?ZcS`9)8Lz{zUrKwe4&9Jp| zK)MB(c)$pmYF>WQ2~A0eb{IOPl$X<^xkvLeVD14xPIav8mNKW-7<`-&@1a(G#5Y6s zBKAiB8w|(4Q+4m={HDJ4xwzOa6M+ahqK27Rn6_{9e%mU|&m5j>`Tm)ejV<)BN;Ti3 zc+C^UdC@GEfF=E+EVo%z>q3)e#q%-vIW~ z;Si|NLn72o?s0HD@4E4uKIFIx;D`+%VT_IIrB<)xE-)|?nq26^au}^M(!PIIN)Fl+$s|bH5-wcbr;TIW@=cI=;X4`Fb;&j?Jb2 zC@CjNV!b<-o;jlrpqH+aM6Y4)o5?b1J_t1$p;j?z*)JGoE73Q$em?!H>P%gzIwh4|<59k$xD%Jo z@=0|E=1u30)G>wG{X%P_jjwMLJ$s)sad8Uonr#w!4!g((%o-bNK;yHw|BE~oHnO|9Gy7|f zl{PC2VR7&Xpv-OG+hcyeX z5kmav`)>k>lMGChPPJ!tmgX))(Z~CAhSmleeCL4L0SUAgdu(pdIR5I*I%b-Y=LE3^o| z(x9CpxpDOP{$Rg)Th&$hqqPL!;5K|X_@ddARzF$HLOM)_VG!6;pmkaY>>V`4`iSxF z-A;I?sM{E|!+6Q1PJkIMTR@CozeXN60jvw&yUF)BY_m(fd;>`82E}IT&f>N^47PT2 z5@ffpYhg?`df)uf)y1}e4Myl})AJ$m2Q*0*5Cm%g+mjc zCuK^Fd%fLu!{D0CTUqkPNC0uFo#+?@hC{%X4ot(#9>gi{1lJoVX7uNzRM3%=lcxd8 z4v;<7e$dlif8^nDZ}~=K)B)ooL)gaJF!Ck~3odg6=`duaqp*B>zg8cdvlIgLr;?lH zNeKx}-!?MMrtbq;n-N4xNjUMKW5Nd}FTAa1YwEjp=Td1*ips=qEh__C99jUrD zp2AqWE^yv`Say0d9vlPw@(=YiHri=6g$k)gjt4oRE1&zkfTa%bltxV`U3GQL;!%Py z*+Y`pnN-pcg0M8;E_+pcT`}Vt#1V>A1cFpc77#}CzZ@ND4GgFnfu8QZ4_|7w)rx%8 z*4+AMCLrEidL}-*%il*WKks^kcH06+eu0LjXwlY5Z8dQrP(eWMz<65@aF4N6$w8W_ zXTTklnaSSnAN*S7fb6@e_y|@^XRffm)GfSAQpzFPl@(B39R)ZdKzfao1qUV|yFhM4 zh=1kEN26}<{uw{MCy)0w`h0`-&~h<41$Yh4Az)yY^^_EU@+8QRf3X3zZ{*sMCR~R3 zz`+6jF!?^|nnnI|S6w5c<}L9EMLs?_xb-xsK9s$);<>XP zy!3CHtXn+ZZXh4{2k&2h!!L5;S--psDiMz3_r9J~Uj4gM{%({Z9T2%MyuFjvAupVH zV$p79?F%=vNkma)O^_t-9>WGFj>f6e{R7l3gsA*;Jfd<}B}!6dW-sm}fbWdMH0fHP0cI!W z)@M;QGs!2>&z-R;+$s>z9gCZD1HCHo5dL(wwJVA_;Wr#EFB8Z*{{e9hnv zPP+DIG;*fLAfE-^;y3)&uMU6A9gF;_O)mzzN*wiNe1p*>2-*0KWC=qvAoZ4o{V$%v0$nl2KR!A-1T1-<$kZSOv_p&q`3FlJj!cS6 zyM4Pgo&OabKMn;x3!fMf+m6jDf23uVD|Tg|22fNT21|9-^{(gTMPT0r@>m93$Ch0xD5 z6zv!irodVkvC$K=>Y2E7I@^?PcK|J9YX|L@YFbd;h=1VWVKFg$jWoARs%O!M;Xy`! zBk&yqle>chUuJf`{DC_O2QVhwY4>Xmh%Zd%J~Z9Bj`EUH?0ij)#&Ny_yNBt zV|zlxhAVcW7f}CGvbPCAc@`hk1K`ooTVb@lb-nT-0M=FRbl0vyD$f186yPjSj=9Hi zr>)N@fHxZ_K*VN?3LhW8cX*umnbhFnM!i!}Jw52?shA)d1jZIzTxY*;fT|PgJbvi$ zh_+i_)c5_~Fe0dX29^B7WiZmH>6zydH?S%KUO=r_cshKniW*q5Zkwgti$Z<_W&|+E zVIXI1J;{KcX>E)y3cRR`4tySwx3cujd;+j_X$6_EXLMpJw6|jLd&^q3D0bq4hRn=0q9Rwi2D83L+=r!R*e;%~uE9h+DdyN{IG)Oj@ z(k=}Q4W*=}a?AuMr*D-Lflh-QkTnMI%5Lr{-%LERxKO7CQU1OnXK)g zB1Q$EG)W-53>*{qFo4&c1nvjUmYfH~yc9$<9WTJ4u>e zb?}S;Ftk&$cK!<`BUG5a9?V(S@H*KedT$r~YkeIdisNK!ZxO#S6YxBNj}0mw|6tCytizhnfo~BA-wF9-C^Nr@;NBDia*~HRJ6F){f(cr z&rLiZB90yv5?mz$C1-$uPR+^THH(^7V#Nw;zar_Zp2a!@8!+I)193e;k>!#%1ArAz zo&+mvX@&1uzY+fNRNJ6@d}jL)SP1a(x0J!^JMlUB;?qhtE;G(KRDGr?(0!_-+jX#% zoX|dnh*JNE|Ju&g(5dzcPbAsG!(S;DX;2O+0S?-dy<~lp1P>5_pVQI^&3Y@P>@E%r<*`rO;1V3r_O26Ph=N=)dJ+N;d(!|=2VOI_1zJ&i z7$`b@@>>jA;}?0gxG>{b2`U$CZEclwbilG}ibQNb3CF7LBFgB;&gl0C6H==e1`>TT zieIv|XGnISX>$p2V<#$>yLUe;d1x&f{Yg`h=6&li>!qNeV5R5J{U#<_n!3&X_aCVR z4AcABZF(1yGr4@@Wk9Of^*B~Xa_I-o6D&tHc!LI@EeylZz13O*!fCIdIwa? z%E2EDF4=#RFSr|~moKYev5Q}3X#rP*gAxkH{`il({9~ZVw&eQnUBJXbs+fG)`{-&X zpe4v3yE+Kd0)azGJEktQ=R0?*%}R7hE~hpc&17bBfqF!#8wtReb?2U>oT*$>KKG}m zm&G11(gMczJs8{88W5Zq{2z``+vMS4T|x^`Kw=qmMTA!jv9r5U?kP|zlSQ1p7l;@< z3cUm)kDAYfGM_$+b>`drk0({8MwfK(k84g0)t{>~+jZQ@FipPLt`>A)%4hc27EV__ z4j>5o+7`pTAc4GQsQ;i2zo2>E2p0P{M-DXc1<>F|l`yga1wlylXk$?bbmF+T25J^l zu1O!%h##DKwl?34;pK$}QY*eVhn6S&`_;gqDc5f{HXWvW3J$0nfjq_%z)R!!};+oxfk2_DDXL2E|BWrUbPAHtok>@nFhx^4OomxZ|%jg#M?l=B2$mW9I_d z=a#Nz3>&ESsAKQ`E*RIpx9XEo23FG>$?ky@I(E|i*o16cpbfALJ;;$dE zT>pF>DhY3TQ{3g~I(G5zqdm|f@k9LDbHddt7@!p+j0*$e&TB?mIqTz$(0?F_eApX2 zA#pJ@tZtD}F->cm?B&~_w4`i(Yl}xvH*ek%4mTbfLYJhXJ(TW85jVg=+AzLOH}b|2 zSe7(oNU*3BWPqb|8VKp8VwC>^FQ5cJp!sm<&Fj~0+%R@2_Le&t31447xkxsJfR-zL zypRJcCv&hFllto3U>EOoO?qofv|PZeNmNCqJowK;CB_l+ryd&gBXW*s=k2nK^uUn4 z92_1_1F#Op(8;5tNcj>_fXq|`Z=YI$cGrKuj0gVBF+|z9#!lEYkM@a3Tue!aXI>y| zBR@lPGHU8L-gF)_T!#*7EA#(vfvAD1uV0kEKBq7w&*=Zrt-+sKxQF)?g}SAS zy(^l2dg=U+3Y50Gu!+skiK6#1BED3JI{ZF$|tp3$Zm&xFe$<@|i4$*w0pknG@*j)zcaBVa|8A(FGbfDc z%p?+?&UU;BSwgIu%L zq2XRbhbT+yMjKND`IYGF#Qra_(v_G6-d&6*q;~fYpY^khXeK(M5xwWe#xGu6vyD>u zbiXpO-uq77x4RAEY8d}Nvmad=g)u$<@?!G${!D)KI|57bavs>zO|dWnm@L-!ixK#5 zbzXd9!sGjQ8RVRDz-l51^r(G1(O@qB0?b9GUy?MoF7AvfR7fTK(w|kM5i}9@=ehq3 z9aujlxwuW?jq(`ivHPoKg0b_DlyI%S<&y};Gs&wwdBIG4g@qN9u->70HW<2Dz@+{F znNis*eOLvUPRSK_lldDpiiDL>YblYn$x;9JGopVoQTg^~wU*>QsxXl=+=D>f0UPSV z4bs8*5w4x#etkTW@BVZ+_phHs2g}&glo<+_a~Hv%;C>F>JtegO2*aQy`(z{aL&%4m z)7t;S%fFotqBaiN69$5~@o5Lly5tKN+R+fTe_>rU{`d`%`zWbv6PAF4Rzt^}pxh@d zXAgA;JYj-5Y0Z_k+($?B7CyK6ycz>f{o!8!A46UA;Q#RTCg4!6{R8lnmeaeZ{mV32R=>PrqCB^8nCbWH znSb~{-+y$*{$3kp(BGNwTz-K&jK*PN(20uRT3eH7Zc_x<#BCRJSBhoh5uob%|G7O z-GX_wc6;I9F@M8d*c}}J&8v)_>IIoEUw@enX{Gg6RUs1%xOW}d_4l@(`onK*jsF&N z{!8GWH|KAUXc!+H(LotWL6Ki1#m=|cT3mE~c3nC14VOkgI(!&hPw`pt#5sw94kJ-& zbo$iP^mO`EQo&qD;OZJJU|D{lrZp#5?`2U{_Kc5d@P7N7>W+ixU#vyorcf6~IlCF* zg2!s5Fuz+!8`hxdL1nRf^O5vHFYO^L#<7_i8)T0tWwb6RD|)8volUyiYl} zQ2he&jZ0*U-yu0z$h|SH- z6VhOuLWJGTeGUabIv}5F%eUN&B_wSvab6tD8!ehCOig(*C4^|@d<8BCV=izfX~M(O z1*7qC?ld9xX1gy#c9_b_75Q-l;`zTFACoO3OQniEYesw9%5Tj$KCx#P$9OxwMwh;g zyt$?@vcr7yHQ@HWg7y}dq!b&Ubmh@^Cm&P%0w=&dgP+rl3(8P}c0{YGBQDA{(@#D2 zQEG>uX5OaKu7vk567K%FlfCXjj5oNJwADFdmM$Sx35Foc^|2r>H{N7(SmM0X_ciuc zK}Iyr=~FYtbRi|J*|$~PKD<0T%U-9bOe=t~<2N8pdcEKpX2s0F3qAEO!a;Mo4GhO= zq4Jj5VVCGRFM3|!H@&dA00$BkTsXb;eGzRYHuqE2E~a$Ee(=N8T7r8Dt$r-lSYx$= zPY4Xp7)_U?Zx85mm8dN$tDW>W46BOkf>gKH{r+&_&8#$Vft*CY5PPNF7juj$p^^`Q zC_aGY_Ef7MQ^U)`yxaz0y?8jG09dyKw9(+xE6GR0Pv-v(dwYd=J|2(rqVY3 z-_xK0m2&`<{Q{q?SzX|km;EtAIR=KS{F4d&QfqHV31^ibPI&E=Wv!l}6~OZ6maL{b zOk92nY){x96)5-=W-&#W#m%C{Tgf$S_~RYv(5dBZ~*jwYnG7DaNk~-n|lle*zb0S zmZQSQJ$18Bn+NhS|I7I>t?o*GDg$Wza@1ezU`k2~$sf#f=N{W(K0Y!zXRU4~GOGQ1 zTmu4ej&1Yxgr+@p)pP{to8n*Q1(IeD`5~6S7mVlOKi+-nS+=xN56{-!T!oH+pckZD z=L5vSK33<;fnYpr1z7v^?rAUyPn-ecAB&zqZ2l#c?W?5hTYvvAd4vIZDjz(V2cA<3UHPoii+3?=^9}T&K~}iL;QpNm)U@1 zxye7Ps2ssMI%#HLG|hftu6?4k9G1C9pK8;jh*Y&oK`^yqYc=Tta_Ka?Y8W2;a9;E{ z%o5;6*UL{d*qk-lyg%OLEAul%_!>S3JKtRTkO~l6pn>L$v=C8td%y*qN?5?P7xMH! zt2%#ec9HUuv@|)>DOyyo@E%3+&$2ikD(J>?a_f0;1M%kbaolkqI*>4ingNDJ-eqhL zSUqd@mqfL8cG^J`_f_%VkBGQz5<|=S<}OGJH9kJRTMA|>VXb|xnryxw?`CU&I}643 zAi%|M8>_B(i=#q0f>WC9;EO~FF)*CYe!&ZS9C&hwAzAry{N&GeLduEZD+XX@_SRym zHzwm3+o{2GVxkrSbGeOKD8^c~9)Mg|_pxWAeo@X5(<=%jc}+hH-To|;1IE&9t;yg` z!TD$!_mR0nI@qE4&Pg#YOIKgVVrcr`$mL#)rgv7SHXgm}lmFSQA4}Uk$}DkF-REU4 zjyMkVmfaTNv`!^PJN1?0zPF@FwB#x%wBhk`B)mQ(HdnDwP%&4XdaY}u zLXX(ZQtsvb;}FIk{nGn_r;pzGGFqK++TyDY%cg{Ui55C#fbln%iSJ;I*$A}0FN24$ z-sNMRikUtP9Yh6EnkHyRn;P_Le?|HZ^4Gq-Pkbnpam0-AbwWVEVxr}z?{p;>T49dI zj24g@(7q?UTx$z3^RNwmO)d>Nys7{7w|&jJG8(5~#zGxE!B_IG5|1k^mcJk9aJ1&` zH`U`AZ=rJjm&l(#V+?HgYZre#P+~M=Ywvf>i*u-`sCEp(*Z(qCp)}a@;wn(j>H;$F zPR@bL=GTE**FRoWeM6L{jhCY*Dx~{8?|{Cf!+3L>aYDDw$kInRGUmF2wqAm`vteOe zGfD*?XUeKe0<{Fa0(vR$?+%tUn*t{lEyXfo;eU?P_KjaK9V~TO2B@cFqa1oI;&p4U zqXY6Re-Dg7T)zfH&0}GI>psy?a~&NyBft_Nrw=ax=DCd|fxA`TJmw(}8pYkEURzBM zyza1!Ha@GYNTwb1Utbo&H#ngO&XXo`bp4^>Qf>aDE9=7pfkTh^>H0OJ*C5}^(U_$* zrLYXfdg3uchdU^1C%@N4iaM~c(BiOShxWOBZhUOnw{%Pt5Bk%t^_|$-;5m&A`4x5VmC*A7) z%46s%Pn+aP79e(Q13EW7)J4uCbq|!LEnnj2k#?T!_Gs?Jp_WI3l&k}4I2rU0(PE$f zkdsqqiw5~j8W_T2`DM(#t9N1&Hu}gX9`ftHwCyzqDTf8p{jWP9YEap!y+QiP zQv9`NoL9!8AxmFh-@#U$vx#roJ3C_niP3C@13IF;5`#0|Sv z*Vcv$ud*f0Lccm@MyACBz*n2|-6oFtT&sN^{Zt-Wen_s44zf!1{OOp~xmEoiCVTkh z`;#!@&egQ2gtECCC!^%u7ZmyZ7f>#tA3nTJD6@=~^~2KPOYt|>!VBO(=tvmv6Ww!f ziyd=xZxjXEUQDi@yX1B2%rH04QMZ+}D|N!n9;|lC)EBd6ieIilT3Ii~6ZGHQ$g+5G zqls!YDQZ;Sh_9vR`+g&(D^B2yy;mSlPc}mJ(o=FT9(%lYiQ>}i*K9Pn)S{1ec1rb` ziyOHHEv|P5EWg7jPKct{PiY3$bBj8($}m!W30S)J`maQ3+&;!~E4Vs)RkLqIk&>YY zG+dcsBo#yDhel>gT5PMWbG4wQ1+uER--D*!$NZk|0b^LDYCP_ma?Nl&#HSZX-zVze z61c!Kyt9>o2~_0V+V|x14V?qV0O^=~1{Wy{-;5o7V|b<^DlIe4L0qwhI}upga(yck zwfY5CCj}ZBKZX7Fs>iX>r*>hWf&!KIP0)-x?IroB-KwfZ70cP!pxIx-6TFDQ+CWuf zI$6tm)N6*~S2NejI5kMtA|-WDjLID&eXtWW^3Ui1`GVEOG4d;I&0Z9qhac4-NuUME zucU@AJ$OVO8Zwt3`8d&-GPu0zOXkO#V@+)oy>I>*p^eZthk#xKt_&Epo?G?&Fp!Z~ zgXvv}`PU}R6;_rf6g{i8gZ09=_y?cWp5gu`D9yhA=~S%`k!^%*qmXaeN=1?APb(%r zE?im)kT3xBaO^2AyHEU-Xv*jEV8KjPORH6ppV5OXNMBf((*W(!6WIBz-G@%`@$yEf zDvZxo3`3Uu&q`VX`cwIRS{0~`CF!(Bflr|9RRU@SDYN)Il3ePMUP|~qU3w!}06t0b z&HoPhJUtA|k1cF|PG<-@-D}n3>v`t&D?|8W%s}&UrUo&aG4Adh`$EzPO_zeroGinG zgrSxx;8rOPnTGk^j#?>@)Un>8iR9*mAVw@VUWvLQ4lWCYO+k5?s?s#O+w6H&5?)bp zC8u=`Tw4hA9`zEmy0bMjV|{T|7CWw2yBb+RT$1bUA_3z`U9FI&6OA(4Y-cGTOx;-K zNjK!MS-IQ=aGYeVd{dzk3}tQwGlqi?=c0O{!&gs?v^i?_AITQtC--JfliOz&>|7#u zE{$6nUJY6iN zvxmZNi;1t3$}*$m1%f6@pW>vkl(Ynjx_GrfdeERYb+y~brCOo(SEoy9zL`6DC;1`7 z7U@AS@Wsi zO<=To1Q7=`p;0?>ITo_y_4w8n(==w`=_yjMK58@k09uYMcW|lr`EL1}jvh`s-LoqQ z3oOCLDy-j%R5&2+hJkwxQ$HK5U#6tATEfQSF02;HkoSpaW>VaGgHdrMvr{}r$**d= z7>&r)vzmZ^-1-R1#GwoSi;E>`65KUhYldsy*b> z{{U~wPYo4TQW#m~XjQbtnleln>n;-M^=rutnhiuw(lX%`%J94bOc_Ys#)rA}=CFmM zf~InPdu6qf-L$0pT|0s>^o0y+>hia2v2e?13}ZBdtRqMH!pVk#?nIYpyLu=SJ9219WLj9c zX6}7g2UL9{9EV8~WqIb9CQR**L(|4RIJv_d>SjGVw&z>`D7gJgH@-fd(JG0LGZYVE`^4?miH z*->a^RqvXj(gGtf16Uik`f&|1GR4KtfH5ZSlHRfK+gomm2zXPu@~C-VT)6gAZGTX3 zX92h6*X>1Dp$_^ClnB|D=ODSEs!Dd3YFS9l%gl2S8Evm@c26qTggkOLgvIiQzV;o*dSIBXL za7V5K-lyK#@yuQmdjtP3KO<#|&`G`NlQp;kyT+Y7hFT2b%o$Zh@kz|Vn#Bh32q7pf za6F>KMqz=QoT_fkw#>SJ5m)8qAXgj>5U$GaWu=<#ASPBdR8w9CtDK6UC(l7H2KXda zeZAm!Ba5o(d}4gX=%QO z5<3_;ys0g4KKGkJBDF zdaSUBmmH1jH0s(LBDm`J6|iYTyr5dmnu$wf2SkNR|C85}p;!3M7!6k7anAC-SJ$U) zl%838&8K9ym3!{9RSd#XoAo*!>=m z#&Qa#lH8b4mhaS4EIGL7S=vX*$TgwK9LDq_`Rbg=_P>HIDXX@vq`13+|3DE;q1}ysx~z^-NtXNTr5CB-tB4 z1S}+IO3O{Wrih(jV>&P8uUwVucecv-V9k7HTx?k9>CJ>%FKmWGu90)4B%klE(6ySm zSC6|$3sCYydhLThLASnh!ku)Gh0-+BKdWYiQA`0@pugE~iyeN0%I58Rsv?BfJZ9Ud z&gxPx7nJt4N}9Ew(2r%uEtUq6N`QDZJTj-=@cc-|HDGJjh~!6HbT#AEpVY<}Rp-G8 z%cGGh#va05;uSpjak zIgRpenDkXp!P&<-z(UV(F%qi{%s^!%reqhmK#kXSOB;4oRfn}{pUEm0YNvkNm%*oc ztVouRKL7OF)T%>4rBr&*2aiijtBmy)bp1&#v+qR{eTf`VN@ALT*_OX(p z{X!I#zAyOYUFBh#V|4Ob2#*Ukc_&$2A|NqF{5<0(IAa#61vyBVca9ES2o0B{!kA zd(n@ICB#5(pAJZu<>??heZPd8x?XNY_c3H<$P0b}LY*^_vc`woY+HzzwxBoPwgvst z`Wc7Z++H&9IB&)aR_aT9=kOs&$W(UeJ*!w8^-J}4Qgr4fdoAAaF)rfi78BreTtMwI&#lpSTT9?+o0VkWd z4Ko;{%GXxz{c#Vj0cl1lX7Q`dvh6E(@~D~{H)B|Tp#F}Nzct+X?3QD{WPgFYJCEDn z-r3Lvm_95pedly4Uq(N)*K6ucwy3|)mWTT{>qmJ5FT{J>u2EGpSM{WwiP?Z&=oQ5z z;=Si~JW_elz%4ZHTg~Ff2+Y+i%vG%JGqX=oSV)@SpPzA3TrVsybAi^9L7G;=6#E01 z|MD`kfdKW3DgF%qc$LgH?}Ok%{f+fJfvKo_Qn^lby%T(#q5+aOIUsrS^0tc>B-?0D z>6X2qSn2I5JDdsNdO&E!VMhD|WzKZd2sS!JUKk*G111eUe7pQRZ7&WhDbXq`*5*VP zf(n2+^_|vkjhefWb;7@opUccMD1gqOgFWhGFs|@Y)7Q`@M)|rUd!nIl+pt}?Rm(CE zyzJyk##)1KdymcB0+|5Omn7YKaHt5N1|~_Qa5|knNt%h2$e8a2A@}YY6btMJNEEmL z9oU63lb#uIt{~g&s}SDWoO#PA2W55V%svk8hBLpjzArnI>2tOhpIBJsNmZ7w{nxVq zJ&%4p_Tc6HQ_bF2JhZY7(K<9ep3uk;h`nXfDXB`c-3yVC(G4DAmG3QErS)vmS1JGi z=VfHNi|GkyObM|!JmW!-r&m1NavALQ{g3%CNyJL=t-VwwN+L`^qvjYYAaH%?sgiTb z06Arb%~xx|ZTa02N8|~Cg5`RsksmY9W*yj{LZ5R2+t|u~gUe605_t;HS8s7JS*>LW z%wuuvVqH|OeCc8!SI`^5mU=h3_KJO2t=O zNT;rI;anj9)`)0ir#*Q%vDUqDp44Qv^k$MsOvBf*{y6^BG1ZO6KS-W4V4#hcinQwE zGuFRtC;d)-zN`jJ<`*cnX2PF6NIMP=P|KNZLj?DXy0g#dQtC~p`x|_nT4S(ma}JF{ znmITL=w);@?hZ6C9Omtt#hsXD9DSgJRai7}Z;|&axqPRX<1=_vI4Nii+cBu33V`<* z!I0Lzo1$bb7T)v2HTce2@*QT-vQXuD1n;$DWV!4NZpJbj zLx|7wtJ>|;hlZcG7_%=%V6h3;|xlxG!Zg_am%V;yUwN<|&g;%{1(W%DK5AB4`bM0Hv7XtY|C%&b^ z-8h(7fE1Qp4(SWCHY#G$42IIo^jVw|qr+%;ic3D*NlHfMh&VJhGrn%jjKqfy>~8kg zS|BIuVe&)~yx^-7>5$r4|KG}J3HQIsC^uK^F34>!oy-`upyj5Y9*s+&JZ^&6_0sP| zbL7_6n%<1o?~I66avh&1t?DQo+jH(p7Z_;OO2dRx{hB*k{cqq*NqG|dTzaPDpAQsp zJdD*c@}micDQ?O06>O~PIa++b1u4zF+1G0HoVI}^@Xs|k6Q65cGPi0)nPZy+N_zz; z?QhqPXVkBDc0#8)e~Hc@!`S)#%@s6x{@!l7-zLwg@u^m>s?QAcKxO_iyqc#Y4pz>77IU9F0K06$kTmBJTg{%?;<;Ce#XH5ps^GUayu8cFmo*_nu?{S zxpgH)rz}wTeF@cYrmy_fAM}i$1%N>SvP;|ab+~E(+C1X5+~Loi<}&KY9#~rqIO4ama-$9aDG2WrcWQ-fahc~n3!lj(DHLtCc-A@~3JS8?d=h*ofU77h0{$X2K&zIh;g+!0&SrQX6Dre zHI2C!1$jx94@w{Ulv$S0Geg2ZBN%i>Bn~`}K2~Os@rYJhaERQB!;gFjY%Vv@%7PBT zCVh5ayEjN9&QdMu3t!dQCd(A5Nzwe@M+5|_gySpbA9;+xkp+*-xV9db=|U1u47*6go&I|!ig*sa3fnFIZQ)Q`7j;cec#(CP_4 zUIX_WuF1_Nma!VsZ0~W?7HfIH zbkRBsE|%})ePtOXdnrnGe6kdMUR*7!>>9!KMSe#&7z{5>s2+O0^DnpTKXWrs*m(Y2U`J7oy~>q7S}#C zM}6(cxdQH}9luMC2-~;~q8lkGq@{RUP))2We>#+Iuh*BCs=VIA9=ZJM(=>TV(JZ`m^c$FXhI-mL%*L7~dm59AI_R)k zePY5|Web~#x`!YY4d|Db@fSk;pv~Rp~T^X@7 z!-i_$0ff9~B0OTP0Mn3&>m1?9?ix1Wv0-J*vEE`^^xnhxt&$OG8zm5ZGg|}wD_^WI zkfH~Oa0>sq(GUPr{6m^$k&~<7(T-Y9aUpgt7svVro)h$iIpdm{1VLxsucnif7q!+k zw%RB7s;!qu*M6yq?eY@_se9uenBQ!S5Wc*@$24Vx3>Uiw;678Zfos}Cv1_0hHOIpn z`ub-PH|oLHRci$%Tqam{p1J_I5^iu-Z4q;U!1t3ZUZOw}GY5 zKUlhKBO1b+m}_0Axg*#IQqkAxY|#Uw_1XZ-=u&mwpsL|$&C=Ft+>@k+X_m=BbE9N) z*$D$u?7QfT34(LS%oasS=*Q3vb}&<$UCR(3!QoG(N2&r*O22X5ueu3Ta>C11w+Id@ z3u??XVt&ZWT+!pH4hmA;{rv$9&?j;EEQrQ+sd{g)XkNJ|jTWxHBFWm=pp4<;v}WJy zkOckLq{_Ols#vX?nOJR*i&$;7C|73WHG*HtTtGdP!_w?Knrkg@VNMXDH5UBiS#~FE zaL!#Yl%&zFEB1}ImM>rYA;BC`_${)_I!K9_JVrx%cr)&wLwvWZX0QsOFDtn;1DkJZ zNq}(M5xlR?D8-T4&jPsh?mWzPdh5TVE9qs^#q!pD3`S{;eyPla)Sz&pR%O~=hBY$)SDk0pz@kBXZpuAIHj;FPu+^{~^LK%WybF(x&tG!Y`eMK26 z;--Z>J1_?RXU$uKWc`-PF|fuc7vvfMiB+G&nZ}obh0JgBR+h^JReISp^_s|8vx;m( zc=+I#mZ%-I1tBZRw)TJJ{M_{%2-LeL?hE@o(UAd)p@x{BG+qSf_aD^7M{>46OzOTC z9&$I%P5y9+44rv701@8h+E0LpqVVnAuOR)nuc!)jfqMrZUp`S{e@!2V*ODzHqEIUK zX3IiqVrQ$bU`?)In?61nbT>kD@2NwagM5g#kdi_L%HdyAhw0F3n)`PIhqURxx9(=J5l3L%iwS9C%Dg}EB?MfmMATqgu9JZm^JEh$HiAwj+% zu;t-U1Hkm{vtyY^{b%kue`i@J5=DzLx~K_#U8$hyV8Lf%KPj7MwU6K}jz$MW}AVVs;k z?Ux>${O?MT)?YcgMm4Ad+sseqXsoOyhV0#cQu|Q@#qUJyBdpK1V9h>SdhIP~kb43R zFt0#>kel50yHX@#1bP6VuMO)~|HydnRIsNs7F>1(|5EwE)BMa@St7a3QRQL^hu3tD ztC|>BrLnTJ{Q%`*$CV(wQiuZfls})RKGfIi0_Hx0yRE|3P$aecT8KiJ-u(JZXv>fF@U8}Drq#fcq{ZftssW@1UPJbryruRhu88W zK0iVR`B5WgCQ?i9eK0M#BUbP0H2nD6NLdxz1(wUZJ9(;|OUq{zd|rFT?~MWSV=H9| zsI3s+4n4wfBJz|i%X&vq!ebV>%nCQ>ZDt+WRzo1!U-N7;(XbP=3rz#Y{pSq|`FFIU zpGM!R4&F)az7pd3PCXMmA3|~Jd2RQ1J<~#bo+oi-=+_*_-fh7xFZ~RMt~?E?^4=N2 z6KVZ}Cvs-P8=Ebp))H9)_Gu0^Y}jbDmVi4)=urQhRpF*vf#68@T>sa}L8&Ux ze|^53m@~T@kx*jhIKXX2Yfx~S(Yh2wdsOS3^E^7>0$DpD=lDs4IsIKN+FNvJPaQk^ zfT%QOKAjbjb_Xf_rtRhO_q*s02y9_PkK=97THXxq@Nua0?fhIg(2H>E93uD`NDUIV zfxaHRnODaf(oRG|wX`X1fg7LU`SBYGo%UluC+yiXm69{(b|8-3ak*$wBSo(5)j6vi zYt+qO?j66hBSKXL$F*37Fh9x7jntr5wVz}*=m_5cDD_x~Xc5|8CvhqyTMy34C$oV5 zr_0K`{d(!=Uo57X5x5v$9bI>qb|9MCs4fG1FopY8b5isg$h)ax%QJe_>Ty`UqkKm5 zc$VOJ^NIQNzvq5XdqZNI#!i`K589Uh7mo;L(RR5g;4A?EgK5TqVh_zGPgHiZK!B(_gpysD}7wp&;LhHzdGY;o|)jlJsE@ z>1LU=nQND5KInwHTbVrvje%8iw#wrKGOVl&6!dAXh49r?jKbJ;?}1LsiO>2!W+JZz z1|mL(9g|ZPf)u{bfVsawgkv^c#JJE?ceDh67dHzdJvowQLLOFiNq1XPo@@EwOTVv_?6#EmltvlGjxFTq_TlQ#~iFDiPsgk6StzLq}y=^*Y-(ujFE%TzSx}W+< z*l8`^4frpZyJmHdDh_a1i%j+MV?wkGZF=w;Xg3nkQG!e0^CW!ZXWzBZ0M!Cw6d1nM zeRnB-)V-(*>tCF)`p^bpPD*aJ20$dut|3isi-^okVXG2jJP_O}^p|L-Rv2@6r8IeNuPAvuS?w0G(I&qGKb_}}j`TS#(QGlsI(;nGxmX}-0O9@d3@&2%nJaTk!fwo%p zF#R*hPYL8G5W30CWRmxqpoN}*?*(RQ33SpS>b^-W`8340Lf7wxNo2S#hH07bL%%|2 zI0MZPg?DRyPG{iwjaM@bCK45>|GNF?oimsS&q8POD#YIbv%ilvcc0p^AK_nSIbj=t zpJs>43Xp{cv`U%)1_orQlw(ttkCR$rijHs}-o7ii=f`wpx8lVMJ*X*CRJ#a-KL9|> z+rccZ%r2>odJDnrU%mj~V2liXXmFXT&L=aoUhLo!t%@BnBA1!J2DqPGu@ zH`+HlQsTZ?xk?zueRKkM-3DMMz~2|4zE+qcoG99cas-H zuZGtuA@oJCl|C}*)HeQx9#ZY8Aa`7p0m>i0Q>bwzo44k@e@Zw7>G$SN`f{B|W?RJC zE>+;XBrKI9%+)}Hr5hpY=X+w+zbe2sP>}utY6)FzI_eDpc^U2p=RfOB*O4yYVU{i&H?AO3h__ly*GEogTkx3E+I3O-%)5MY0}r|p zTAyzL(=>9ckMR4?Js$a)0`2B>g4RwXHZ}Ag7IS8VbOwgSY^}6kdaA#&VvUGI2 zCZg~NkTJlr(LdYBU&?M&9&y;6(DDV_5w9L1W2?bTw~Umj0G@IqMg5$dJ9|wp=lRkS z;-AAnXYD@_tugq`l1i-`cpSsioMn^i}=?BJt!2&cd-qs!|v5tMevb}mD3FyqFn0=O<9m; z>x=?HBBGlOSsm_1;m93_V*Dm zYiQIGl+$lCjB%ub5DkV2fH(}Y1E47jggh2~L)W1fVJk4fj*BnvxGW`kwD}0%F__8; z6cFDm>NUkIXuxyP&%v#3ptIKtbVrL>!4l6h|3=j*YC%g@#*{Y2GaN=D#4LFOiresG z73uWU-Sx*=)EPerNx+rPGwS5{lsN);Bj!DxCoX$8>zGO== zuJ_I7%p9Q{;X$dER8DAq0V)Zku0Y1<&cH~(;@um!r_MH(gTzL^EN7AMsJxUSFKCX* z0%Nl^ckVK;L`ok$FJ&4HlmXDE2?mvSpLJpmXM=gw2!sTj&H(*4Azcl2dwxCxw+Lt8 zKsO+Q_4~h=F=!cWlg^8Urtgv4g@cYN^<8+elz=e5?P#bIiq7x}ke_>5X6KT1;w%Wk z;=@2Yn_xLxq{{4S&qQ~@^SiT`4xd+Z2M(?1VMIc*N(pylV*%t%^Q+O#Aol`IlsBDk zHLM`|Wz0gyD!`hT z&-~77+`OLwKxLjyfIHefw&Etl%WPHN%1gCtVI3o1`3JepD(Nd?&cIvBv44UDt?pjO;p&=5ur@0(8vNhIh(S^K zCT$~2bym;`+v)`JFMk&FTnE^5_~ZlJ4L`9I!z%^kqYsvk-|HXbMk2&F zeO8ir&I1PU&$5Db14i*vU@`tJ2%a*`{-i0vkC^X=JEu8>5V#i&Ich%#W;Q$S;a9-> zhu7y^uot*xN-Gt?tNlbf?qf9`oc3V04{!Ve{^$Pz7IbyAFeB^Ve{Zmn$92v4_HsWM z4xcs!c<|3EhU*=s89#%DcMNr>{ROhynTLOWA3kz0HN=Yuj^9$(0FG*o54pMCrC{j2 zg`nCD9xC%YQN|1|;FpRd_+?5W6`6YpyBARx7L&46f}B$7-%7N8e&d%(kvJH-E)J4C%vy(hBer+QMTJR-3?nX*J zdCEmsE|cp~5Zy>&Y6xgAJq*j`-XO^$1lg&%ByAH>^KXq~zcrp>u|I6ybT zSPXh&e6}?2Ky*}gIsYb{!68z#6815RdtDCO5TD=wpRLLNK1(Egqq5s?cVA4Ap*=Ha z0Y9v7`zbR&Bl2a?0ua!xus59~yUn+JgSz1Gj{fbcceKA99BcR}DksWlTl|j@c>z=d zaF?14D_>+#`~W|~>T{Ky9VgU9TBdu;@& zZZsI6c7o$Y8-e3o9B7|%`T`$yNdicYf1BOD`bp#uQyO$Qg7`O&BEjBy<4hS1NM|_{ zSD*wAD#FZG1W@k)&)pGIi7g%6Z*A)<0{?7ddG@x%fPO~^1k+VtLw+oQb3(n$@Ak~b zg_dnRUIf!NCmTtLD(`!u^5;O+rGr#$KSl1cCY@fbMDV96Fow z)DWcNcKKY|xz+QgPxqeXjr7B`73&hkV3I?K--pGlES`ri^`_n**vzZvU0e~gt1cmy zzmBn$8W7y7L+RJT@n*))MMA)^2go4_8v)t(Sa59d*%_QI_#cRfTz7)(%k+#Lro;&Z z2gfwGZ9SS$M7#=`gG+-{yjN`m0l$R8=Pz^Yr5rAhXSSL*=t}-Rd?)Pu2v2F$S}#2_ zk2$qD`@|-PFNe?E;S!w=yB=D)eI;yU2j{EHt_ZnM7QtNyyC24|JP8)u`)0=zmYsKo z1*P^2{+p*?bn?aviyLpOgon%I6Y#Os>h95%YwxS40~b`Oi=H}Ot!>%^E>LS<2HUxS z@wFgiHNV(XBkci-KR;sVN3L$Wt)#s+erfIa7VhdEn-{k>xArv~-W9gH2kOW}J5Kur zsVAtXb`S}qr2Pr^AGmQNg0-ETDrMsrM%#jsu7fNdN-`1y&!27jH4OTNvTw%;vQdO67?f1{aiHFpdNR=H>Ld}_0r z?(ON+6%3_*-HteioLmt#5YtQNMx-kg-Ax#4xQ{?+BE3sE^HrRt4be(r@ctFHEKvWK zRb3^&$8A5#XoI`Kf9wlOC&Z4qk3nhMh8~{^vC+erLL>zQLOIpU;ab^+K(=?ZpzB+F z<9cv$*MhV(O1E7G-Fwzi3xPNix zT&Fv8<7Kc?N;?8pRD@2&;a#iv!`Vs(yY67%l`=Oun9!+ z>*1?Cc56ybcgkS9#O%S@7Ws3VZ}Ob>yC88!WP?e*`A*K>xj5ZfIm46oFTiMIz*4sT zCOC+Fo(tAvJZT?{@$dCUhPgjs5s3cBZzj-Il~xb@5WY*zV;e}WivWarU7`-P+5Z@? z8Z$-2(_4D=UcHl!{Ay*t>(Eb&Wm zO$FdnAJ?BZC_i?T=jCP9ad1 zb%n&4TZ|pIS62R38)Lk|#})e~bd3PEh8wM2?7O9#7W4_zI9-<`4(gGCyF<2kdQK%< zI)ak_@6F;Rc;ms}4>Crng%ni``l8WV_ zXpz2^crBC<@{XEi*}$_bUD1Oiz(nRh0bjPyH1)agvy_oW3p?#GB+!e(DWVpu?~J#s zG>QJ;%9}<%4OHqes4(&V1FIO-n^8{4%~xOkxBX(MZYHOCvmubwH)!Bp^rZbKD~2rl zZ)OQunL^?~8|H_bZ9_mq&%h7T_}k0CX0N%Ni=vw!iu12%65o8$E!Oypq1Kr|sf!vO zxC*41HxqD4URP{^opR93+jgsoT#=@IUx7uFH;gn)HF9dO|Zfjp!kD z-{|Hmi%5E-G>YYc$P~+iyN6G-E`0ta|4Uw=6^!NDgi|wFP)$Hhpj|K&{97aLdYoWx z{KfVkYLdWK9Ae7jgM}qxT5OuTee;P}tBe^SlLa8@Ei7~Vtlh!*(mRV%n{NXDI-L?H zPsqY6)de0c@^Et=m=M&4%~Rs7y6uM#lxm&$MGPHEa{!9$LgK$zmP307Q&qn4asc(X zJ@I@Y3+Dl}CZYvc0-qAVeF2I8V7DKF#)vLy2;SW{;RDcXlUo{u`N^-jK7#RecsX=QF*iuyN=P&Zkh8jJy7;?KrD;lm3L~17NUPn>wcqXgTi5=3u^{Xr zRD%5h;D0UI)z4ai&xZfjsLYpdeKxx~?t?DUi!A)-lb|ib0Ju2!%MyGwe1sn7>&^_r znZMsFxEMeLWR+ayvE8+HqP{%|REJ<8`k(be2k?YnV5sxjqHcH6{;2<-pR9TM-RZV3 z6Y~UN<)3vL)@XTM2T@atZ-E4vOv0&}-|Lnx;0vITOnsQ-dhFx=%?gm&1tv2mgc>{x zfc^-8mU&n#5-mcY$J;z;>)WCn>+`p2Z@;vle)xk#kIX|Lti^`vHM;0e$6yaY5%vHc zjXvN5dPZeLL}f%R;#8l5^$^$Q$NBW_l9hqZHk6DsyzifnFDD!Xb~|L#olHYGmO*@D z09c%0>%!!L#`8xaEoGAHT`!*TQ{Q|;-J|;ke2;(1?D{k{Loqx#U3TN5eW$HtZj3KK zpaL!nuoSYa-oeXR|Mmtq$XEba%Kbh~E~&;$Xi_)v6x=a6-uw}5aYQXvx!NE+-dn-G z^G2HysEfXuWg5nVHbMxaeAP-|2-v3}*^Y&=YRN}>%%P7uU!d@K@#R4M% ztbmFL4``P&Z)2)X^?tc+-S!G!VXbLZBKNGh<)2eMAEcAjVg-{a_N7Mwwj5$s<<4v( z^o2@Utjb*hZ~6%V0o}x-P|W=Yi@P!b@_}_e(KPsYvVouEqn@akjYW4;tCL?0Pmo{2p|@inD`&xx2%|}46xuy z@z!~zGev{kz&NK)qpLn0VHI+t-;~RZFD(STIUjsxGnxw&dVC);Fue(6xcVHg#&9Ik z$m0_hyy5CZ!brb;)BM(J3;&M4aTM&C>6_XNMxWz#!9KkwlZ<@`+^N}(0Le`=`xLDH zEcAe9_?Yg>n^@o@(3H)f>m%Qh=PSo-f1C{=!i7b6okpo(jsg!cT@E4wud~7v!$JF5 zQ3zW5<`DooSYIY%X-Xgvt2X#nv~Js28<6fAa#Ng68&Jh@quTzRZrnd3UD)6%FU4m_F$eh`xruMz-`* z795B&CG8?sS{r)=A&a+l7B@hf2OiZw+2|^N2L3B~#MY~JYq7Q#K!6$3fqi~?{-_Nc zaji-A@Nu<@0Tvd9Ba@9)1l)K4kv9I9d~_3D?tHpc2yq`Gm?MvAQ0oKz=0`Uo!%7et zDu5peOJ9n)-_e1!(KQ5q$iBWUp{dho_LFSMyO>>Yzh~)hS4DpuGw_yHyEmeJU6 zRhTnh91hZ#2sPz@?*jAN1gfaGPRd~afGfxc0JaJt?%4#&ybG|jdj1quB0|W(xNq`s zIgkd;_dpt~D(htuw9xGF&vL=S`J7rpXtBkNbnyy1+(#*+D5*$L?a&6(o>2z-gw z_K+WN_?f#v*N7y_WDDItXpo?u1l};gT7j3&CIuViymbRX?VmSP!~x=gJOF=~2T)lf zYP#L&K(6lr49AWgobX(I+ujqWe&3)L1q7NMP`sL^*KiCpMK?&O$GoGrfD9+Z1SQoN zaD7OLdW;}?aOC;K10c1WRe<|7pKom^CGNv{W@JdS0sk4J2_0gl30BH1X0Ahf&;2?Ojg_j==2uQ$w16a6K!+IMFP&O!w!IJE{IU2At`@td~dTMGcx{@ z1OYx~X-Wslr=qAQT)uT*AMligV1@=>!kQ7dBuH~tD{RA;LE=o?sYEV9B!%w(v)8@k zPb!4BYr1{WpYN0bU&_F}du!VeL;r2k83MJNXH%i~3=&96ED*xg9>9^3_TfiamaYP< zBYtNAcy;rWTfn6jJ;!7~Vr{4tL>+Jz2zKz?xP+3v76)j-c_0VyeaG?L#z2vM1nIqv z<%;b}$ky7{QY>HY2Pej4IyZ@umYE%vp`0-G%NpR3CmZ_RGkpJU{@bF99((6iaA)ce zh(mDRXzZIDNl`oq@Ig}wa6g>DyBJ%Z&sRII4DDb!%x&i81ercXQ&PticLT_?0N?U8 zQ1O~snl3W&Y4m-YP`$WT7Tb6Sspys8!Oyqsi$L6fVB>(Ptq;7Ukm>uKsUhyNA?k7@ zj%rz4Y2u;L-k#M>QDdke%-jmv4z{aOQ=z z^k+RO?*O+XgYN+^(?cWM=1|=8`w#vfy50jUs%4299TCAJNdyH2K|v*pdMP&qt887!?dyHR>>?0MKB_@AcVS-tAf5eP;yv{c=9Q z86UCCTvp;eIf!?K;6HrLw&kzv$a@2X3%h~1i^@rVt$z|6kdR$$P3r)*eIemsdMvp< z9^Tf-)?~8*i{#HoHdhF|J6x(#2!loAP>vT|2m`2@1g4mtJjZ%hV6JFD4rEG03xO|l z-<}o8ovlB=Z7aSE`*3mU>o8y^NoVe{b2M{+Ow_^&r1+R#aKBNH57Nmh2x{vglK+S$ z^L*ZT4zcrR-Vi)x>KW5G-@$Xfo=}Ojv&aVvW{8_6A`|j>o~;2qJmtS0o;jaa4!|u% zT^<-Qu>Vj0{Y8PvWu+D1kvG9WO?f{lW;mtKq5}Rt;lsn{{mbYlT~kswVSWSO&g_Qv za!*DVSd^D>mpB7BY1OwwR>t6WwVcOAn@kjx7}gC zk3TK9AXWnARs&3XkxtRt6IP(yU-)=3`uy&m)4#^gj2KP$x=7jwe(~i+)Dw`Rz4RM} z==Gkn{D@VWgjX688Q%8clY1Vzi=0RqdH=A@pu2IoDo<8f50_a33zDnrT_Ous3c$JH+j2q zyp+`a&g~z#ZLPGCGZt4)W&~T#5Qkh@Z8(!AKrMdo=d70M{dWMOxBP_5=Zp2iymHlc zhb~1edb$wKQHR~D?wyYk>s^I8^naDRVtF@M-fPvfRx4MkS~ZkctXAR{d`n)y_hcu( zRbkl6(bJmR-i8#K?O(Wc-q9D0z36qjGZiK2? zUjYtim9JK96OZTz&j2WWke%4l$K4t4UCcCexa3Eu5^FD!vWS^zNR^Y|w%HaR+_f6|&r4bNN2g!3V1n zN9rZ3^WMt15=q##cWNd7su z`LI$*kT>20hnfKq+I>B>{Z1%N!U+zn*k*y$%&Tv_)?PEV)hm-;dvZo6E<+Ar=WoNT zA_Ch_Cbh5l5w_gvWbDL+2`*|SqatWAd zofMV|)R$IZC=YyR%IoM5+p_sh(D4`Z+5F=yrjV&CV459_{$OACNoTyx{Zeg;A4Tj) zci;g09#a#yIvQuw<1#0&Gz}onUD>m0W<+=moW!4a=Sn^U#40U zx`kvWfw_OUBcM{2-=tPdH+lNtNCY6#tvmOTOE}H}z=PCsuVFxwfD4LAZ$1LNOjByX zZxygX0t=VFs|2O~A&9|}Pdar#S2|=1yaQvW>M2Q6g&geGw)COn<^vIW%$OLwi;*qN z!zTB7L@wWKaB;51Fq>?d1WfQ<-<=3l4th>x^~A%qmY!38b#ky3zGEfedrI$n|Fkbt zFAO_xj-*i_>2(CJs$S_YW0*|gm#YDtu|Tj21g41zDC+mngJ^r2^A1`z$ceP8 zza@-w^_u{Zj@i3w&hoU3Pe-tU5` zbWjiLwv&LiMU4Rav^rciI~(uz>pPQkff)e(fC!n?0jX)#FVU^XoiGP=z^d?C0Y?CM zCI*H)`+Xz95qcl)Da^r2AwZ?!9cZz_ zYe;mH)^Rr(;;x=9suhWyvv1{uwqvNFcg1je?4Ux@!8C+vKM2GQVP;jtT=z%NxCoxe zd!~xauMY%?G6aw4?%-HLR2p!0e&aM@#U68GLmQj+pK!9K=>ZkYO_@xzcw+44=Oo1< zk2x)KcfX}On#dIu5-dN^y^8y}kBRED;_i@VD|A~3*e4y0FOxuX+hNLIFk`*eH2w#X z`bUl9q*&k0W#_Fz#Qw>a#A*5>F&6KsJTSRAd-y^8!5m`i@s=|Zn{l4rJy#?o;0OVN8Jy##B z3ITNImR{<;Vqdp&EYz;tBVbs4q6*}!YEM8P#ki&Y6gyWhH()np5j&`phc$;b ztM#oX6A}kDKI_}<)rGit;gA@T3<1!%y#UZvuQEsaG$Z3**u&WZ(^zg-IIHt$o3U(~t zmzDo$&KOC98=u-)4nN<$EEf;JlNta|Fu{62y%E11w-1sZxT6u5c;zC@y{O+#D*c1Z z8jpwe8xRdTy$K=#ZU=7v5gH%HqzllGe060)el8kVI%O5;o913ej@Un5#kfgepxTI5 zrqdI$Chhwr5uniAL5+QoZA$_>k8a{T9d(x}j_ujw)Ln1sJ5b{}-#n z4Cnz{TUIsBM0;1RX-tjhLlco4tRm`;Tt>10c%4AD`?2rrnntBr1{Y}a%Du8~R$EXD ztM@m-K%T{A386Jvt#Qba5bUe~qRJlq0$K__XqLeA7=w)hiRuy6i47LMSs2hanx7$cIxd@xk{B#ej4_)Y43?zY8kp! zwB~^-I;PRDqD(n%DXm(xcBMa)r&@9#Z2E2W^! zI-?xym4PPV&biTDj3Xs8ae~}_+m7f^d6^1};)fu&Y`xuB*z~JGyCFLgV#qbz-M|8n zsawB?NW@rUc1P;?VbOp_?z6K){$d2;FlskqZxx%XkKG1Sa>yx0#TK?wxN!kS$BWoq zObL_KxZw=0M{%|aJtadRunzr* zQ?ZDaYI!%A6o--q892%hf1JMAq7r0J~QNk%wkN3d!0-&pn zED?kAF_fY}?Ta+nDMIJbEn^FzcPDeF9^8vcqo*EQBXzf50vzwe&-1Wr29~`feEi|d zl+*ghNmPq@eAbr7OcIA(g+6c?vp-@pS$5WYszliRL_oiSHU-lobNh_rx`bODdit~C zNeRT^C;uTOU?Y7r@7y79RvW`s6*=r$YVBgi4eu0tC_)~j&Lcu6!{EscxPa85?hba| zNW5L#kvLk|tLVSpql+c;UCZ+DNO%0LPY>((jXK^PN7tUN>U+$MoHgg6#8FK+I>T%F zE6}mfDFBifw00YQ2@3Mc)mqYneO6p4?btw}#gTLY?43Yuv4JM7=EEZhVH?m?_i%@1 zvMl6L^0*$cm9F4CJhmr)JV@`g{RD9z7Tt$I)?Aa=DkE|p#*R`grr3jf`+YbQ+(2p2 zc_yF-)nRcOAaw9KX}|Ed!E0ay|DsM|`^{)Oon>0JIn`<6<_!#gcliztq#fxbmgeoA+>KZtH+F zg#`rxby%}b?48NWi?D0hOYfq7?XTb$dFX{a>@RVD z1#ook;ikv}XhR)zz?71LSjJ(~r;nt2Ay8;@cjN#66*C@17|h?&PMCb*d4d_~#LLm8R-)QIoGG+LIS2rK^R4ejn1p!ds>mN7B5Mp}iJ^ zjj?BodaYy4RxzDE%L^vC#$i1=U}wQi3C+iOBx zKP_Lu99--G#CWgJsFbCfKDHCHKDJB?Xo)UGDUf-IweHhPg;P+=5E1hNH z2sn$W}J@xMg@Xk#yt-+I%OhU1zIpC;-=_Ms71?D4l zz8;eVtLY660QtSp(&6qPJlXrq&T*m%xETVDx4HIpbK-IuU^oC%2&lri^_vg3waCF4 zA4Q9v{35Th+=A$B5I`~9Kon`56Fj7bf9aPCtc*?xOFVDisk92JCS$D+o$*#`gy~wOc!75 z4WZ6mTMiSr-z=c-vs@?9dq}i6muv6cX*V^t(gdO4vr*3?Jkiz2>nfs$3z$=_z(LgB z-1a=1<6MiEOPTPq$?B<-o|l@sEH?ImTiy0GwDvWpEp~Z>t6QfixcwJzRyD+MM6d6{ zVV1QDVm`}bX(rVDcto^!jwj_*hnTQ2Yt_6r3AD_a%dI}N!^Tq`E+SKiKEJEmAIxtZ zgxH4du%GV)Yn6iiK8$qmwMaqebixsIM0Z&q+dEhRJ+EBXy{FL07Q8gh5hoMo67;op z_Q275h$nllYA?{abGFPm9=Fp&UMpjgkom!{6rX!j9&_7vcE47)DCkcMF-J$CQ;bg& zD~AWUx(zyEp2+tWR`WW z=#F~Le0(N27lHzdqL+dmjI1a79<_U{jwcHZiFpAP2rw}?K@TUHX@!~eV%teSQR2ub zTq_U4Ap_p<28S#DGal~KXwVQH=^6Y0BWzfNn#+y>NufONN(^N2>$_^c=d;@m9{GrU z8J|^cWF@M1V0|xxzz=hBI`MveFngHjI;>|$G#NWVHEXR8=i2tcqS{4wH=7CVU`D+XE=}zB~YgLt{d}#B-u2CL$KIWZvB$jGx%sRhU7h2nr&D@?m<>B1!MMzLR zybhmhjx#bghIaDku|MMK0F%{nxU)FBB_MW9#dkOXtS|ayx=QajPThF#9^d^*)Py_i zpgAAnxfi9KA68vE1&C-g#=kNj;bvxwMDXZTI@zuW)lwu?w$cW8kAew5(NjUJ>Y_ZR z^|YNtH})```X?R3j3Cp{)D3Q>hj^2Z^O%evQ`5sI=!)T%qZai#$2pBUuf4HfJ3DNg z5N3qXuNG7*!eActAp6FV{rNI!TTM~!nb6F zYQ9vO9^Yl+f(R98rFbjsLZXwR5PV^v7bS9x*;q{G*ln_cZK%YWIv#GvKovfR@}k&E z&L%?W;QZDmBiU83G19L(7F6=(*f+Ht$<%D7=QrV&fXBWrirMQ-6?8y#F=^$>mTA~4 z;kO?D-mJs9fK`y+3HA{*I=URCE$zvUXYM9H1@RoPZBqucoy{2m#p<6I9J_iDM)H04s}(UL{i}1AbBy^Dq;^sVw#xdl6vdJrcNe`rR@n}(@*OT z0;p!U)7iEf=no&Nv(}+-_E&%YZ_-f$2q(Yk zK^)(Q^(GJZwA2Oe%W~7%VQ;MG%r!t8s2wfFZ7Votcmrh}IsA!B&zrf$oIZH#u+`XQ zqmViU&bzHO7mjHIQc_hT$OF@~l#H`9Bht+{K#nSY+78QX@89khLqzT#AMQM>)X0^| z9!#t%tC`SiJKbnr#U!q2WvS09+53u4?Pjzx$dw~xo%h#90kCR5>T!qkLUFF6a&?h2 zF%*S;g+>l9inBnc=Q?a$ZCzO--li>~F_FlH1tm_OWj4pXj?#lZdh9gU+I#Mo+S*}# z4iyQ{8Z}_-KiAOu_oC!>y-&c&*Mz=Z=?ZakDW^xRvzg*Y6nz#Ghu+PB&+~^fx0^%D z>rexBi=1o9NL2o((7 z%k>2nfN6u@nmg1OZ-8xd8`FWn)(VTNob*#5Li~_(F^`j@bgtF+I1q)|Nr{%gf@&-{ zOj@F8OYrN50s-24gPtufuZFMa;E??H#m)azf3W zoVDD;WCZ@8>vD=j(P9>;Fzr3AOc5`@wxyhIM*8UDW=9^Ubps964J1rn(IBCDTA>V4 zCL~F|YavYe?(pnnk1Fl3yH|QHeKBn-ms6UXZfeW;T5gdm2dnmQ>S6y*;l4MPdE1NU zNTo)E0J)dEB(axFt?M%j)kmz8$bgJI70A#K8-yI5j;azcletyQ@Z4eWPL}tvmdVyi9 z!Ac6uwJ+dn!L4O#>wfm8m})NhV^ai+N*)=f#r?57HuuPs?6b5cPEMbS~L$WsWBYRIJWLqG9HRW zBU@U`hyxof_-_=}6!{=iI6I3*#wJ1<9H{rSIAUMKQl08R<=+RbbSfOg@9PNCgJ9-z z+(3V z#Kw;I*-4CG6L6ISYn?u+gI*@9XPo63W%>Cs;DkZdG7!2I?~U5hk9*9A_W904fj?vn z>vpu`bSMq(HQCiw=t^!rR!&MvQKLr|JxU+GQ7l0THOeBZP_4u=QPdMlKuc*^QDX%4 z)y7kN4mZHl9VA6SMpn}cm5a$qG-abGNBYC1KnA6O1JHbrRv$YS%0(NVA)Ya5*F0zM z#Xhw&wYU#Izh#|YOP6x`3!G$^%93kZlp z(HWMw=%4Jf66~=}7Z_BxJ)hqU4h^sZ?!U!?_XG*LxOwaX3$R6bSc9LONfrm4p-Z!e z=ZaI{;(2(JOj2 z+g*_F2ra(V4)&Rkb)z7xH#8S1OCK&URY9qbSqUvH9Sm+a!MvrVKb|IQ8H+Eio|>Bk z?S!|skVlh~`OeQiWo&&(Io|pJzDaR)e`6|r-)C(8`@!c7E z?GXtIKL*jg-KedfjZ||fCld4tRpPXyb0CH@PHlG$xF6G&W85LaKC|zOXW8|;m%@1 zEeRH3ly{LUej5Z;k38S9_Su3cuLxxZ7qrb{oT zJygt*dlwq-x2i4T&E}2#?eI~~@6N@`x9}pJNyB<7r|9t?s=si>tLihD!w8uxch{Ex zuys*-{-XP2Qh!s-ZM=-*Wwjk20pZ)tf-nCJ3~ZZgKFjz=yWBQ>S>PR5f{p$%ii(Oq z%!(B@oL}F%B_Tm(J(Sz>{rS8c5rLbKZiUx8fsZ5_@`~yUnq!J+szFSnlrjfqx^|cv z?Tiaw_U#s2k9uY%xJEjP{*)XU?z%c;(AeVYNHRflovyjoyR_(NFq^Hwc(JVFW?)ck zZ0GVLU0boYfwHFP+g&=(Iy&SFEC=2ey!ssMv9HlTJRVV2Myi;=v3cm@y!ZN6*P1n9 z|G+?BKQs{%9-ddZpVOsCD|Tu#0#{K|{!&?a^%?l;o67Bb&vP}>zLrpfR^F1Tj)v;+ z<}Qr?5n)(CuQy#%uL*bR*Ao2kGW+mVK9OscoP<&ivv}vrSo=g1M55z*z61RS= zI5ci--nz^Sa~Iczh={udBBxwPtT4MD_8kj<4gK@+JB0UaPi4B7-4Bl85-h(NkoiQs zU~-YnpntZhr2B$#6{*bQ8|tj$*_Ty)JVfooBFsewhV!$laXc{#E?Hi7nDJd(@EbOt4KKylv_X;K>Bg4hb9g-JrM=Rne zXykS)u<=#)3%d^S9iLQYBL@d+fB!~iR@SCSo^Wj0CafcaLf=E`lKvlaO?-xNF#%Z*r2S zzj^o0B}cFLlGx5`P1xsCN#hZ3L*8LC1Ttd3Ou3}o)o6WeaKzofzRk5&ru8mD@*Y#> z&&kP9Z}*K(JSp?aNxKr>a>&TR;37Cm{EbF-B8m6`opq^}BWeTg;=2E4En?89IqADM zHOCOn&&yG)1hR$;;(Yx4;e~~cyrLFOJLW1Jp7kNatBnCf^ljXCF1_~i z58UUlNNGT7Z`S#XSy?`Q3^#5=QSu<9>G^rTWEEZrjG&W}liPZI1o0z(MPDDzpZsuB zfJ2Ff>tbk7Y(5xaT6ML+EMIzV>G^frBtfU$%kuIu`7B^9C39ZBIITP=w!25dTo#%d zbXs?A7foU?ypcprpYmQu|2+9UOBY1+p>E*@tHSx@ht_tv%w?{IGUK{w_v+w5xW6hCo z5M+*m4k$a0D&gv@!(iVy^%8y4=Ff}DV(zp;LZhm_@(c{P!?Hn`GJUrd%wC*WP-JzV z!DAm$R#|je-ArVBl+Ib?>@ZA@>!FijUmS^Y+}zuyk?)Qam=80NQZw$@iy77S;;s#d zhF`HQ*%KKPx#|y5%&*MT6tEF*fc`JO zzvmb4Yf8L6GvcX9t>$w-6Zq{fig?5aEkTyW=Jx6A_05Yr4Obbyncf~=$jhVCe5x$S zpK#MX+xiEAYj@Gh9FN6ZGy?%k_sZH5Db2Bn{tI(5aSyCjTfJTv{^!XW)vInvhdTGE zraUpPjTUC4{=vudz|NXBKTKzACA}>n!TF^XjXCka{xJO|;Xys<9uhB(tZ<{rjTnQ# z`4$P?;hk}L?cv#d77qIXi-KPW`<|^RyOLB@d8O861f>Si4BMyiNIm@W!9&a&<0D?P zGj#YKOgY^zJ}Gzv@aTfr4b0gD5=YD)d&fNz=e&S-PN&X=Zw13@mbddFeo3O(1~%(m%q(3AYvt*SjNnkyga*{8I7A!bMMpuEXOGkT~vY27BGHtFm~uJo+# z7<>G9YnebKKR1sbL6otQlDcb+2$?9aBkfjSGWeDm?^Z(S2}zvNL?6%D*T3|ZbWHMN zHUchnDf(vJMNNUApeyY*zTD^hZ(aPky7zP0C1iEX){U4{p3w2T`u7X;<6u~`0i7YQ zYF^)}H~7iO!J)(z1sXp*QgF_m^%bKd`)-FM5%K_?*#oe{E~~1aXm@=6Eb<)vKwSKGHd3?l=KNJt zg`o(8c0o=vKE5($QbE1iD!ghpl+LDaa8N8G$lv>mu4ta@miY8D3b-Q@d_gA$hkrv3}uvAuvs?!-Uv<0o#mvVUH~!eoTJch<^gitfIhbF1Du z4d^V|kxN&@r4NQr1lTPQQqejQT4N^htLB!aT3<719_bCQZVb!9*LBy5(K#SuOuMkE zd`^cnvad2R1o2asmMuuO-7?M9AWBls^q?=&%BgUB?#bO$J;)bwauxsF^7ZAm2WD@M zF;jJ}=ItA{@?|!WD!)t$rF_fuIu=n+?IymxZe_%Vy^cq~zac7_Ln?gthF)Vg3dJ$^ zn=$VXvFqm^YJIv!;4itQb4{9jkBm;H6dd*bum9l~-O{!(_r6qa{eXs?mR0TJx{W#J z$N1Ul(9DJ)Nhs+i$$l)97S&<+YI#HZ!IU=sUDz&ytdT;)#B3=t{)^~RM34mwE>vOmQSn4euEL2G9y8n%cFUzu?P?nr^-Z+Ry&LOi^-@9uZT%Vja^KL1EepI zpISu_hSLe{=iC|4Rd8m5Zmgug5+kjC?3j{tQx_zxMTmwW+k`@R>rka|TxZz0K(^_t z(r%@Q0@Kxu_vaKF@FgFrI^O2y;failB$b2}6>+DH@!wDi;{fL(MGfZbRtqm{+Qn_x ze9SLSqX{ERFx_juD=p|?q2HC_AGBooKHlUal+V@P%>yhzIyM7toCg!TQK z+J%k-UKXWV_;}}t$-;2ygl4^ktTz*@yKUU@TXJb~^u|=&`hZ1OeWY-C2qclf0lX3H;9brtW6fy(m!-*FOZP17SEF+TxWt2( zEkoB1ojg3G%6j)`hKxW)@Bw4s{(^I3GUoLDrdKVvSN#G9P1+IhR&2~&M42{6p9%x? zMI&2PON$sl2d`RE*5^zAJetj_u72T|8s6V;v^MtapER!XA3b}YI_F>WKi@AW4E)*( zJ+BcudE{Pp$lj=X7BbMp)O7YBnDHmgZhaTTG@LipG_q7-QoE6-w+1&ur{1dpdwtG6 z@>M3S_Jv97EE9RJEs-F?pmi5levBSQq zeOYT3^Hn*mZ~EuV`2qwaeZ}F*MSM`R7e4zTwNkj)^Tx@E|A%$(dbcQKOdG*9`Kp!R@b&vlOf-vnUUc+2Rd1mzIZFd;UEA|Lq7e6YIK70Y)RpNRwXCOF z8n3DJz35Q2n7TU#ij>kISC)UR{V9R2oqI2yTS+kU^0z9tNvq#rfAfz+vO9Z)1V5U- z@1LG0#)q533T!dgY$i&?Z?_U_=(?(0>xzv_2?goAoUi+Lbyge-s5us$0FkcDXmlGAsyS`wC~d$|Bvv!)Xd(cwvRSytp1V_JmxCx$)=$SAr9NWRBNEE zkgs*+1J_nWG!Q_Pf9|9|A4vjle`n~3KGg~qznz~au8pD|BD&4ohYHJMyt!O z;7isg*G4e)U+jtYLS&F;D$_$LY#^f0&3RI)VNvmv5=^Y-fl^c8EM;A9WaU1E4 zP3nvIkcsBnwMUfF6*_k9x8_Sqcr`asJ`Lw1&b7Vv)6yO@S&fd1drLe9B9H7vh&luegbCESy{$HCFnpLS=JW8{uYs{Ky25;z!$Dian+u?7 zi}(iGabdohMAm z;j@x?Aa8c=t&4(mW<^0cYwS6iY$ubyfx8_ar!Pbh_4QA%uJXWgv=K5}?kWri(21|+ zJ}6!EIWTCGGnZEgz1o{qM}4aNf)n}vB>cSJ<3O?|UapJe91>}1#!s^cKbYsNicU(DoWnS2F7Sn=26@g(qGkBwHsE+Ip;PN7}*G!LZ+rLU-=x4y;n5^ow!v*}IOG zKH*a?0^M;au&V~i zb>Z6kYqegzQ@TGbzM}Xi>;w{3>%6tvicx9^GNG^UUwI5w?OB_;HlRNJOFASAw}&H* zM8=<0z!z+-zCAIF)im>TG(9u45GqwlF0S=A1M4xRS?kcVHealMo3*7t0SCXui*L5<^8Wrf8#f6sRCHqET7kcsv$L}Szly?&jmCH? z&li9khoOy_$|58x&eWOcn&_mCNK6k|Mc!-GMar6jUm5?&v4qJ50d1yuLcd{)JiP{t&_!>S5DyP4Tn{|_;st@ zT$>h?am(!uo!QRr1RSI`?`?U+#m{9ofB&dU1=IW3?vp=|E}1>}R_s&_XR{dhTeng! z^1SqwOlJS=mZiv|*j4JhxF0m0s|i)#s1>Vyn$72omX8~_;D7rVvm5|Y=6TFzaL!BO zMB@AP!wa4di%WVk-oHxtYhR!oEpfK;rJ0ax2ai4USo%_N7k6hUCj}0w_ZfM@ecvVA z4AF#?+>ug4gV+lV6uJwcF+DGL?)N9y|2Uq=udmxF`P#j(S--voF-nNsyus)HCWzUQ zyEvL~vWNR?C!x0t&orM#!}%{Kz7l}7c_7aJYHRBs#e~eOJnMqG{odh|8}FkB`b$Dm zZjS)=rFp_Uy`gIdY-MVPtv~$f_cHxlzL;1o$Vg)bdlxSqbrp|B?|JFA*`^-S-1z{Y zf!85{p3k9;S~voVUJMvmZo=R=r-y+2NfdJzwmjbeAk~L%tEj>B3m3NVRo;=WmsWl) zc^P|Qh}$-d8m2>gFKyx&PDlvT&d4=9?{`7+p_ztR6MS)D;mN)j_H^B;$^=c4IS>F~ z&W{bA&zm}SrES>#P%cs4*VXP;CVLky9EMzvr?9kAgXn&#YiV6^tS&0L65XBPaZihE zih5R{WgDWoICCh8}0r`99Kt8;PtbQ~5fk8co zRn}1zy6v))Y|1ER&RIHbQ`M)q5PhAY!jnZYVLr+KBQraEk>hQibXd&*4;Rl++THHL%<9Y2Eze+!d5mvA4pcAjGqqU zduDdf6-P8UILJt(mJ$Q$zmI!wd_{Fz3Gm+K<@ApqGZtvt8v2_VmyVd*??j6laI5Vj zHMMfD(WxvcX31mdXlPz^`O&o>ujRlBu=P9@*LQ80Lm1u?1ak2T5_gH}CvYo$`^Mb( zi7%Uhz~=r{*`HEsLEE~1%2dMCe0}Va2<>RR@j1i7-a3Ut@jE(@!vomTL87wMpHEiM zUmi~8Mw%cZ@_(4>YoYz-lebFOP|Otmg~JKvhJ{+QSLv=nwH~03e+8OS6=<)qYf?ZtQIK3Q78*it4g?nV zXMAP^KO_Kv1DP#_lMO@a{2jpqLdoGN@Sb=mx$m%ESn6WB_(=Ww2oL2w(|>vx=oK?V z?^{T*Y+Ab^x4Onwome1b;5CL{Vk9uFPui+_s&7GTtGLN|CE?LSJDE3rRRNc-9uvWa z^QV4T=OZYegKoECH)Uj702lk@CQe!$ZsvEpcOR3(ShruSQ^$?R*GwS*AV z<9{P~Yzz)6bva#%dme$kdyrmx*{I#EtXOQ{?QGR)1#uPYavclX$lljR48tAj+EA z*gVpBp{_27Muk@LS6?0CVaC7E%M@ayE~#c0Fg^N2^SDM&zv+ZQ3SrLEzsz8g5h|U^ zWFL<@8q`)LOlkJ-_nf;#@imcIJcSG@x1ZG9p1Y!IqnUT$@db8Q&`SBIi^`NX8J`M>( zuYVjn?|8G`4pVqCaomC5**DnC?tXWVVlK)8{wrK5L4aKj8GBUobJix1e^?h{*D$hf)(`FFFJJF~C^nUp;^RJ>I|(O|g7%6Z`UVZbHUJC3 zH9kRgza1a>;TM2+0Tg2BQeiZ62#C%gp>6B#l(d_QYER3##x^!4{ByLA!+XKr&g)I1 zENM$FeP0!nuRKI0d3p9o;2*jch7blRRpP^%>q;%=Y3mFeWg^C6;RaMHqiCyM3e!DoDYoS+xPXsH^t@`}^IFT6&4ij_p_7$A(wnKl; zJLmr0`ss^tzl99h5dW`nQ6bOgne&;W28Sg)E-Fx-|2SvJ(n|!CfMQNjLO`TTUUoP> zFdP*I3??-VjsA4zZ3eAmz+8N{N5xMCQ-kCQ+~IblKy* z0A&95Mel1bZUJxnn*Ovk;_QE*l;b6i=97=yN+XyqJ5ltpoMu9^QP@a?$EpSDQOXZg zSV#!>=$m_?k#-N-R@Myb@-32Y#}wTa5PeTrMYxJu4Md^>Tj#(K-V7QA^nE0EOK29w zH!Nd3F2kQ7X@3Tg^ z)p7Y~{{G-p@Yi4bmiJgAdLs&1LS~-9N?szRXt|c<>^zyDSKoW6-oWI9(USJ;X6PtAKO7mF;c3U;JZCbSL9}$w7V)&_dZ~NCT zfGK?qxIP>3ReYC5sT35_N1+=p2u%w~@bSJ?zM$Fu2&^A4FAw#RFktgwSzL52C7~wW zxxVPix-AUb^%7G~62G4X!XzUQ9`3sOBIpJ3kl|J-p@!Vo4T&$&k^##68`%j>pHZQa z#nU6Y$CvTdb3UjjbL)FbUoS(Aux5$)?0#l{Iu1Ai1!rsG6zFwOY}B+I8}MQM{r!*f z^j~O`rEnhqCJruvV>C3ATIU+7?e%e`6E^%J$G#Gvpuut8f0djG@zJz{_ckN*$beBH ztMWT8Yb&QqKxvQ#^&n&8!Z>mtr*UnG#$RSo%8r@PKL6_B2%Pmoz){>LYP~?jVdj`H zL^J9FBw631yDj(N8Y9n=?H%}MP|=`V;V*g=I|9e)A7F+7S7B{h_#aSe!6Q9T`c9Oi+{r`{Ha}% z@??DR3s=MwXhlq1qNTgzx_HpiG8d?6nE4X<@$~x5>k4k=R7#dlUEPC-AIDk}O(7gK zxt{(a=M^mZR&jZGxu0DaOg^f{RWf$69r%j{y_*Dt^HJJ>Si85nJCIhPv{?o2sF7_e*{c72=TW*E z3qi>GSnXpC6euOZEF@7&{6pT?PlS(Ggk+f1t^Jmr+d9}OunE-T#z8g#lUIx%D`Qhc zJ=Gl%g*piUg>=(AU)uP9)ev;C(EpV(e^jcyw6YdCh|JA9%Nl$GAC+m}O@)|e*9Cez zkJk6R9D#CBz-q!dQR;2}v#_jv0}ih}`Bn#iagBEljd5IGQPRBp2@D&ohC8nE2y#$M zW8x~${cibbmU_{VaVuHpz6c;H!reR<#M9>jiJHQ{It`O*>aM2oHzO%P2(R#2{?1+? z!p8ROS{scb%S8?j4ibovvZp+dL`kmwshkv%cd}bI(Gf|{!U`I5HKiHMUgO()&E6Lt zDLTYl6s{%JF0=bENQigt*Wl0`(8{M}?T?9p-tvxBdksX&VUa;Ti{}@gxC+u%cu6Op z6B7|p;0B$P4C`!?z(3u_WKb3)MkP=@$EIePzx~fdJ*uaL{q47 zC%HD}iAsbh%MVhtobiluzqxyLa`RUv`{5^C`i~%38yT z_qLyTdb{?5_F6GY-i!Xx-_RK?`j>|+);)r*-NMfWJP|u*p5oa*N4|@{xd|P8Js;dp zK=)-6!d}N$SsF#NY=Ke^O5eqZ2m4zHKLJ!bj6JS3FxZlCyJ%Jf78Vq%9QNa3=MzBX z%lgjjz1cO-`n}LjxTVFRQM0pu!Dga@4$yDPnSdCGGW3@M8Nw7CgU9NQk{VTX8`7oig4McP5$Y?=YH;RgQX3&RRVz#QZ54F{Gf+hq>xk)pNoJ735kM6u;(aWa- z1q=_ps?KF7Qv9;w>sqiBT-%nTS7(heB50mxW@DoeVJlAqGOipPEdGv81y#M<-Az=q zpy3Ou)|uR^mQGmrMo+T${fs##OpT!L@q-?OyWF-e83{>RIh3iwzZoB7Aq0pSPz9v* zvkXYY&x!5guP%=zCP$JYdI=M{?-R}9`xR}gnJk*fPSUGV;wqGY2}ty~;DiL*kf?WG z(=7|ly1#!zi;deS=>@v@pQFpC0;+By@@{%F5avDzCn*PRhj8y+Fjd`HUvI6i|EaUD z9oHEE1#ihUpV)moB;nI{kdf^&5wWxM#Rt@1RAxluw*qCsw=U=R#fug8Man=RrHrGz zZLBvPaeK+x=$-)zXMUEJT5BVfBp?=tAB~ur-hDt#>>!*DHVRaE_l*w_MzvoAr+FlF z6IB1OXOg^JfSu-1rRRL<>B$0=T`t~T$RzbLc%bzTrJCavBH~93T1G^k$y1oF`#H!0 z(vR)zbcvp)V}l7Vfh+?u3-V2jA-{^TgMpyU+oRQCyDy&~(6@%u>(yt1#)BQ}1>-l1 zFw)GgZ#~S_knPgZ(bKzBt49{s$@hXOgaMSRe6Gy85FZ~8CIpZy4+1ZKn1pJ})zqe{ zY3UIA1O$|nT%>#HP7z7zkX*XE7IxX? zpCvr!`@i$eb?F8Bvh&V7^YnAi3<*J(|JMB-2P)OUWR=wlv3CPE{=6T3<8;qt4BTI& z9M+;hroa@RF=Ba;*8-(NV2W;Bz$waiH5KOcFJ>!fPd5Q9$zS07ja!S*L8QN>>+cB& zB=URo>bFnK<``eyNqv#bH%pN>Yrs^t*09O~>O16T%K)fNEjge$SA*RcUtQDH&B~|* zzW;Nju!OAGln2)I9AReS;T}P5y1uOUKt#Vj-6+-C{r(O*XiblG#Cl>;3i7>Y7=u3vDy@CHHs?KZ!`T=W3+a zjTqbCwscu-7p=o2KuoaADl6E;OEMn}J1fVptl{-VKPLtz#HwTY8$q2_8A8GfhQsKB z+;ci~XMc`-?M{8dI%_M~zYXk*Qt|~7nZ>r;Hn_+~e6vs2kJ$D-`dR6L@PP9l$iMHe)xke3dwP2Bn@mEw2czi}1}TN{ z3R;U--wY>HNe$grw*YwEhMJNeDNk6V zgxwVG1+CjSEdDa+*B=KMPd4!r5@x*_51k=tSFRzT7XKEy`QBL-0ocZYlU!z(FR}Bz zzplSj+T*w-!5Me=mn2Ee6&nkV+qZv%JX``LL7HTy#>?8@TdD}mP&gUOZFYZC?9dR+ zE2D@wtv-ODkViyGIhU?u6+uSJdD*cWD$`_StmAhd|NJ6yBsPHZbA^gbfCyWe7zC0> z+}(U~^AAr8a|SCRYD=!Rv7EW$b%XF>OaCW{j@R6d+p8cnGM4EJJOjJjF-`$O<8U{Z zIQJ`R={@}J>yH$u#>ospq~khU%L#^L*U;1yb>YL4^qxm;kLnATw5ONrb*8ORmBL=FsP1cpy*LG%@630gU=jkbikOKySp<;)q*Jl{y{AAuTR0s>_d}DKsAr zZl3_Pblofbv`wLzk#Qu`94rk1yCR-IesU(fD45NB)$`jb+5VH@x^zhd%g@emnC@a1 zNUtR>QxhDl8W8pSx#D)ow9H2OtQ^Om?z`u4*k*_l`%CYk0#{3q_M#=&j-IeE6)yPs zwbP>~`l)h^^em}8O^DMSSO4H8BYP+{ze&JH3aKSKy+ zhM%e1l2m?vejI=dRbK4h0nRu+>kDGS5441|u8WV5Z!?1ZGkc^_KHBL$<3LGS^RSHe zndZcS7|*Ovx{r!zPXI;FlwI3%0*8lxvao4oTCWdI4pvQhS z##7SJNXvKK1VH>x&-sLysa@dxiQjn~E3s!|-Zj2@=%NjsjS|m{0r%G z0@}*XYe#4UMKWFT7EeQ&05M;5saNio){OxAW;gZZzOf$Ciq8Nj%FQS8xP^p2JwJm0 z_zmZ%+6%uT8$h-s<(axa&?mBPc0D5H>jNd(gO@vg{#tMn+@W$9M)NeZ-2XA(OWV(5 z1BG5EeA^cYmUVJ!>L)#6ETTwnEhZ$z*s5&!L~_@;fWcE?gMJ>!01=m3<=pE&ako70 z!CrlA{E*ePu-arc19C4PL0rkemG*KPUFp)ML`n4N>jJDAq<>UYo_YNC`a^k*hQtY8 z-}3e^;9h{$LQA>LkR@SDtm@lRb$Sqeux5>GeuT!jk#fS3N zRrvwkpEWF$1E40GwkWBJmG|#m@sbvwSV94i(F{l~5UJvkHURa;uu|dex~;g4xhOs+ z1P;eJYUiaI_6GQ3%D2eh=Mo%LDp|GNQEH!y_>it-5TbltZU`lh_eg!a_-+tuWwM+X zi8V>waKuuE=gZC$1dvG~cZKs`R>&?~m8#dtp@@g?u*pVWCuC{mdPsI7s9x?W;b%(9 zJQ!?Kkp0W2+54YBnDVA{xa(epy;`bCh;epg;T^i}iysdum_rK<#E)=6=1PN@KO z{aYHUH^}QB-9pDcPW>7b={GbKReZMockOHg<((@RhAc@5#622cN!r_A`NH&4;awg1 zNSD2?up$iyCrws;Pz(7?cx=xvR8b??1>lRdzAm9;B-l-puNZva6?Fdlw?W>(*p~B; zj@S6Y`C`;!%E~)DL_a5oIs93VDUbW|O$hNP1mwf+@|b)A05kxQr20)ne)Xz!$l5CK z?i4OhMgrtcS6ej9$UPFk>#ASm{G76>(Z5>__Ffbxysi;f0GkYM*4_ljL6Dn!Brh*v zuXH6hFV7JXVeCBcKJ_-&BCimTXQH_?lhdzigH6V*lBFWP+dm+en(g9dX@D9(V{m!6 zQ4!5yKFFF`G(V4Jx&DR^zyf_wZlR=(^ypiV0;6IIItRdu42TJk8`DLQ3hHS6L^Q8d zzP-eozNxeP!x-fiou2~gcovzofu&74LfKBuzf=58!VC3XUtA_BI|V`l;D`73hc~n| zJy)^UtwNFl2qJ)3L*O6CG+pyM1HAkDiod_M?X%VG>=1x@+K$R04}%0$3P;g5$(V!Ph_vorT?3Z)OW}rqw`b zQWRkm(*R5nAo-Zes3kXp!KN30Zfj`#Fy6D^s;l|L-r8?s`6o~)mlFRz3#u`5j)vLhCW z@uWRy`F9uiGNjaAUJ#~hJE(|g>v&>N^ZIvZe>_efvo9H2bG+`e9^T2u+VnL#sN$Ch z^RZUAaYK$c?Ue)MahOHXz$3*i1C$?!;Z|Ai&vPV%mPOj2CZ~UQbTkhWmQwWZuR+aBhOzMi&0eK0 z>@Obam~@DAgjFv=Yc($%qZU!O-hdEDBv#AxtU5F^F@tlzy|=yT)rIU8*lmCU`nD5 z6s%d0#*yydH*t%Dc2op18=wiqz4dhHW-2}0KK52yaK8JI^H5N}_nbefwImm0HjCV5 zW@c)PirPYaea=r5S^+kHP3cGFxZCq~c7^^|{Imu>z(L6~p8#kvlTz-<>1lmbOjGg5 zg#+fs)A@CYy#3yl!Ty-irE4u&H+_^fpeye+@EbiUR}TuCaTKlQZ)@nk;vTiSZJ4zy z5QB9f7c-HtXsFz@x+{iaduu1E2h%8{P9oBIjFCPdO#TxPXVnA$^ISg)AZIV<0!Url zvyiYbVD8DkhwpS)=1CBMT10G*Y0$99e@K;tXF>>|Q3tY4hRWQ!4~CU{NG7)LeKTHv z#=dn^tyFn!hHA?$kk!Fc(ah}*BVpZ&gTt$sQ{bbca^j^+jQ-aNLCAPF{0k9|@worE z$wR2?KvrPzhgc1K(cs%bAQu;6(K#L*+!Ja&S&s6fNZ9ha%)DX@ovqoJ!~kG=kcRPJ zi!cVpQ)JMr$q}$(I9HC23ZFWuM;xS1@@@K~=p4)4Wp%*Kwn|zMOU@IL3%Lka<;OEN zm{D7opx*yt^Wy>Ckjp=my7^G`@9AXl{2b8Z8r#7%G9SG2Ak6DwOzqm@u5Q0n{l+Vgej zHp4O7`(gRG_RdBp4E-&`Dlu4kZBRb$;y?2J`$6?Rey^Nis9JtTpycgOkPrC*XH*|@ zMhNr8iv}0Y@3fR}o#CGTmayd=>Yr6bMMa8uG@n7jmk0aLg8b_-F#$j2=%v)bEPRju zzYgoi-^e$yhS35sf20Myo-=e?rIi%`Z+UzF!re!<&tHk6&MTYq0xP(?yV-RNjU+u83u;)q3>(*!VWnbM5 zdu~Hj#fbmAj;0p{Weh&bkUP-@x~pFtkP4=77J>U#xCf87&z@{Kd6+%>rxWl$1l!Hz3Wl>=#D7obSlQxJ8ksz0P=9#zOTTUF(90L}1{dH3PSKMkE7?}ferr7_{&*3k@ zgm@(q4o!8lw>87Q#1bCB2iK0cw|0K@QQkgU_^$dscdA?5WK-!HePC`Iy~l9fo$CM5 zTk1`)wF2zzDxGqo@;IOv=OM*NA|)b*dmQ(LpO64;FVUDBP9y2u%q|=Krv|1Ec7_Nlmjb?r+y%QO!t4t;~&O_)QqjmHO(pV#TF_uWpl(V{2x=>%s=kNhUru`A))xCpMgM)v~GVaI20=)drjEtR>IcDQ26LZ&GP20%>UI5 zx$?2nc4IoVx+v#(nc>duylA#1bG>H=+uu~@-G9y7b_bEK zU}Aj#Yhv8^i5=)^E-H^pH*B669H37=9g1Q%lh2K)Hb@?qI)=TEf!`tCR)h|?D-EF>;M+3i)=XF)nw@$7XXRzDqCFbo8J&bws`3h8Y z>atBZ55j;x`2SWD!ubAxnkdrW_6$4*3}iUbK<9+30_8bMz6=K9jSWj(iRVfFttB4W zg$wLftYO5ZF401xy|$6@9eso-=<>DOMOQpGC?UU^b>IEi|LF@u2ItbOeD>UONHhxeUdrY zI}6<2FHARc^X}(ZEEqjm9`dhnu{Rhlwf%gb|}Opz`)$xRebOY`Q*!|Q}*S1 z(72}X{@(2j%?j4EC6MhLji<*@Xu3%(DQ4)DIg7iUn}SzibzJ9~^}cmSyNn5xuhApD z7pz0c04i&LXDnb1rMJ&S$II)bgR0mFo5o>R^Ukg{>R}jNXA8mrVmCB4`Iusoo; z9zcM8Y)-2WA@s>N4mS*iCLS~48Gm>!v)ESn=b9?HL0l7r zKeur6m=2fft{nn*`dx@76&K{QO^}DhIG7_?|A$- zv{L@r(q_iXVD4&p3X%|@PH^dvct2!UK@6Bqgq8q)*2L2yQ1HL3Q^)1Jesf3cjF^Ac z^2jR(L#bUa2z^C#H?{4T9UP9%Y#aBo+Pjs7`Dbq9o*h}mq70|Ugg)dN8OHdHv1*5! z;rs=Xq3$hS#!Sx5O{jf~=cih!b=D$aaDzvtVR$LPx7pkI_J3H($tT$gorHDs9c*ii z@;(l^o14?Xcczfle(5W$g~@ZaENtxGdeV93r8b?X($Y$O+xFMsAI`um?Q0IjVRTG1tnoC9ZME*0gZ#nGH4g_h-2R{r^VEE$Kk7i{)9S8*Ab zx02Zd^QL-!0}Yr1br1IaM%NZ^jq~bOiOs6he>lsJ6Sp?AnxnT@lDz<4<+$HTvA3(Y z$5&@wWk-7L%@UfOM$GK%b0B}c7M!*O@gtSU*PIoOx6|J^;WLbr#vNmEZ~?$ zs|n@GRe{&s5!sj&7S7s_4$zl2Xsm5D(+YapJ2EojZM7Ew)vRD!lgE33|9#Ya9v^Oo zg~%<9&*%e{GI^-~q)r=K^e6-X-jMx4B1Xx+jZK{>t1?uu_!h$kB25pLhjqp*$DPPs z^pp04&|Zia$RAw*E)teMT%s0V>^Hb1u3hHZS(~ZND^6R75iT0^Oz*RdL$`_$5fK^K z*qjF&kpQf{ZceQpdb88->ANFo14OjgbxIJ8K695__+(hu$Bab<^TARoMET}PUd!k7 zeG^j6Q#KQ3dizN)2KBI0@NoxGY-0*4u`6+Gr4mgs`O0|AsuFFdi9uqqe5-TFJ)S!K zahZUD(XHL-CM~}+k$hHBY^0DQn_HySD;vqBWU=9VGUzWYx|g9*VBsASO7 zQu{XJGBwzAowu&8K^SN!5o`?412$x$&wavSZAxr^;WTYC*e1_LkERq|V}qXuyVuhb z6DgpzFv#<%E=Ef8%A}+-X83~77PS7cO&rk&&P~wN4Br_thO~2*WW?OL=CNP={l`9r ziN*n#>muj=eELq09>xNMrQgwV$0N$WaZ3m~JZK};hqAokzaS8|<*vYJ$lGPf{f$f? zJ>K306FUBuw{c!S#e$;rL>y{q3%xoPfV*rtoaJv)R)rl98<*F^$teti-0gTv3F*Xq zLFB#d%f)X|qDo@>*8~MiUySf-fWqH6=IH^Te`g1R&>y9iFyLZ?FoP#MBbFm+KBg{_ ze?GOj;gnTTu?+JsE7u_RYa0$y$M46F`oJ|BvsY}8<|vu8Sv&MZ$tj|8)L-fvP7w<-W#w=!^8t`&^2?BPbNK3aO~u zIdovWfA4QR)svE!H*2tu?;!LPr@!B2_0)m0H41Y#f;#PL)JMK+Iyxdg;a|np;Lr&{ zoq@P*i~HfL8}#lJ$X)opwsXs}u7Z*h10NsrxM*?-;n>pobALX7^bYtBXY?eA|d3kjy#EKKZJX)#r++&cH2;Nhi<1gCS_Pg4+F zDj|e)Pf(OyeG-wv>65#x<3o7m&ga;;zVpviR3syA#64X(O+j9EL&{X;+^yhzr+wH- z<7tKa;elKNu3}~-_S<=FPOT(FW{lSMF_jhZBSK*jaaZ*=_b2q#p$=nWP6 zfzLb?cd@_UDc09uL$?CkO%onT{Qj7Q!FG0cJT?%QvNtTL?vo!~IJ!pbb7Eq%Xy;e6 zPvO0m-6R?>Btj)qi-)*;@p7j2M(Uh*0U48MhUeLh=3$9q`<2#v zI&EosoJ<%#a}}g5wyo;t{>KpGe2YwVIF$0X%TNnw#Y$x! z(MZKG@U|-RXZurOTdb_Cfz4B_#`OnN2J5LQQYEEiIWfd8R&P$`ZS4y_ z_fWJx`G)e$2vZ^fJWX{x8Ice$k^wdNU;cD+--CgahUJJsn(kYm6%->yxyCVwvgz}~ zZ?NjBs2mpu|GBxUr9pV26767!Gop5^{d))B0)4Ht*H#9jeAwAcaJs;-sF7qiDrPX# zx72p|A~#XRtGV@JVwjhpcabi(<@=%@Lif`gI!46hXK58?S4V>6HAH_e7DC3J(3c&k ze3?9#+H^R9YHROZ$s6}9JKSDB%E@4mp6^bTd4eCGc^bd|i>~mhwp`uIkA3qJ{oNk+ zp_W37_VlFegH`xX9Nh@7AuBK6lYrSzl|Q@b*XT~oXThseh3y?P7)Dkh>#n`Uh&28A z!@e;v1<_{`X)V0%IKA#1^wT-CAGV69!WlL6A&{|Qy5VGNZHvE=ZeBx{4yk>==4ak@ zEO!CMHq<3EZE%=rU5p*r;4Dw`qvn(9ZWhoHoZs6hmA1v7k_(!?K>AEkidvENFzq_i zjc=50_}d=*$^74YY7~9tPtyp?s^YXA2Dj_b(KAp`XuNuQuC4|E+7H^Dz~~D3W-+bQ zjn<{O{QT||)L`+P1Mqw^m5CQ{ldlj;CLId<+FOR*Ge4_XBZi2m|92Og`DJLASQ&>Ci%J!yf* zte0p37o=qRWSZyp?E=NVKkf+vyEXL+%AO=%eG7)LBf5r!^=xQM#`(o-`@h6}Yvi=C zS*M%^L-ru1z?@Rr7ipNQI&+ggOgJ&B_?|;rzS~Q%DsN6I!#Jk#7f<5blh~(56os-}dA~bF!*S6!X9O1nqv(bF?<4=}p7ljEHW)YjNw%=Dn|bCLYVcOw}S2bDz$4aPja@?E5YDT+XKyCNTbc_ThJiCLo?#T zcS)wp7F77Nh=tBm_S%x$psl|B(Kti>9*SfSl-Ljyp|+dX5Dw?m6Ev@Mdl5S zf}IqVT4QWbSF#i%i+&lx_`AN%h-6}a+4Ar;--YA+C zL4ZTJOP+mfD7(9NDbwMmLBq|Un0?J zZsTO>qdR@tP;W&Ml4IS7c(jD9s+xQm#oz;X%e$5F6mmm@;_HK zzI{?8!Mb@MIYmStv$AH)wq6btYuqv7Wk!nPCkbv4x~?>2S%ltPP7NMlPLV;3z8mAL zLJOvy82#;cjUdyazf|$`>5uD<@4Y<#n2+qag!d&Rbo1(1b)lbZRc6aPYde>y-h73T z9)%f{8u*(jFNrCB&QUuvbUnS&RaCG2TuYu_WV*|8rH*>~6Yt`g;j*`zz2&FH7ZfA7 zHI@b-X326ZZd{&?b%|G1K#FdKbIb9ibgW;Fczw|J{&!$Ccn_@xu+#4Q9SA4v@-2b$ z8|+JskBfwDUK8>M^U;Udo2LPN3Id0@`U%amaj$t!aEwZ+naox!kKi1?|q-?NZHV+>PEgI7CZpuM$ZCZ&iM zS_{K$rCnbSDFKtL2Cj#V4fTwd5=`_ymBOvdFCl9Dvq&47U3N9EU6IB>n>$O5m%|kk zeB}fZU#wWp^;=W)t0rEwJ^5x-62AbTT|7%QHz#g3SSTX^doI>xi~ZpRZ=dqy2pL@B z*uq`ajiBAmi+~StzqS~QO9YNd~^G-Fp>$|Sv$y?LY)AKp?$qUP6mTZ0Q?p1nZ%wnboQa;?aa!tMJa1^i``iG8% z<1B$bZ4439W$&CrUrOMlk~y(($5!#^_M_Tl8Z^7M(VqL9_oc_y)>00kt0(n1X^yGv z1AUFq5_)aXHO;QNG`F$aoo478yM^R6?_BJg4t2KD)s0C~a$#CD))C!VNm_6SfU8Vb z3>K|)|Eaa=`;xq$d6r2m4Y*WK`ADmDz**$Bf7=2+^hGAzi?`y<6uG;rI(&beWNENU zETaOPADqsHpi4`J?-rT3bvHy#+6un^qfyN|VIP|B&83mxR%C<#*lYqp}&HWJ1vOBf_ z@`w=>IOux5^WD?P-rrv;85d_{Oea@=n06-Qm@L(W884JCyA`-&KRrf01Hv+ItEBt~ zGX7ywp}3&NGwJj0-rVto1n@3UbgAEhv^d?9n5jMDwlo-FpyWCj2G^+1V<9x5MUp ziRrQxZ>8S8owOhz;PND0CGk8nEfG> z#LCCVHyfkDuAKrLCg2b|F*3Vsb$5H&)_km~Z59+Ba?u)WEsd=&Da|%^=t1ZK2XQA~ z$T+|qV-bI)yyzL5*ltF*vGD%l6Q>GUYxLnNf$J%K4*e^LR`@^;uN;WsdU5mswE9~2 zd!UJ-5JkF11h@XHxxUG%N1iK$P}|9l(@XzD#AT|-P~(2KbRb5RB^v+K2$^uV&a=DK%WmfNdq`oepWF+~ro+I;_T5}7;6y&bk5Box_f=#CwTC_v7B`eC@Y zxK61o%&X~t9z8WpE0o{W%-PZo!jX^VMva|QTDi7PC8(IK^*qzw4B24XBah(o_d{iV zlNm{pxoY_16cQE2(>V}wsYpGXfaJ^BN^mzXzI~-! z-(KpXkg)6qt3ufej~w6`5wao1`>LX>`K)87_ND zN=(OHy=gm=`@9pOTyo~azJPm1U|^u_{;7aqjHb*TNSFVqF}#O&9COoJwo24_ti+^r z8m;{z7Y<^ng*cmdiha+)jBx@)H}o!H>)ApJRNaQ^-6VmWL>|Mt~LTg1bucLC^UTo}-2# zq{ubvX0ax0dD-ugG;gxsVVFuL#cO73KTGDjb972p{65N`-BZ+qcD)CR#Msi@@b+5y zX?ff6h1*{VkM)O_5jpLR%ih+X!Qg=6h=xTy2F|+5F1b2iWk=w#Rb>5yTZIoQc>yKNfQ19L5Bh~zEb_pGlJJG z2^^}dX=v;vy2J}y%_|&QX&-$<&-5gT;$pKZ&^EH29=NON%77{swM?}<;Z$?hv%2WD zGIfLJ6fr}?RbF;F8dzroJ?hyg4%!0qjzPTn(?HT}G! z>?OEvNF!NtFQe41i`#ip@tS~Zibf{-aU_I{TN1KoZJhXqC{^~O=2fZvMEs=4GJ?kc z*RIsGQnK1`sl5isZ-fNp$sjW@N@l(8@p^q$?IRT~Q;LGz9y-ZNY4g3Q@uBRI>BIfT z(!%<5b7l==ZzT5|j-qlJzC(V2XolD6T~tyf)-jA;6RWG^-=YNV<}V#Oz#GNUtSrLL z_oWS%zD&G?6_3XD&^|FeeLMV9)Cqk&v0)xN=+Rn=Ya-KGu?EBI;8@A|_T`qqa&Zke zcFoN~j#)cz10;r7u_K-oNpII?|1JDmR!ij?l@AFpemz;k;iiy73sTKcHP49HZn;}G zTBx9?l;WUg80?$A=r_Tw;-2B(RCOuE84s?h;k}AP5%te{ zy>jub1*N`n>Dj!est>FYN!4WMqyUCl}IFp_v;<7#OMGtiXRYITx zg+)fDa}C0ii$)wZuWs^h=H+aXEzDz4BTvFCE98|Z+(Dv<2zErZ>b2j%gPQNQcB@P67P; z-RI)o-d6o&29C3v*wj2^S{UqdAW*B_se{GK-QT?RyBZCG9s#FebpgE8!_Vo|89o%; zw$!j9cKt7MQbA%_(MG%X!oiR{XelTtOm-Te{jNoUx5Nt-&M^p1T-o!sR>$X=%4Up3 zgL^aJ$bD^*QirZwDJwIaHiDJw=CDeY+oB`;v*O}g$YPVcAC<Cyo!DO^QbO9qy(lGB^m(+LS?2p<9Q<)tBi?YU^gp z)8)$`uG*EZ;9YQvcD3oUS+c`9>1;Lnpn7s7glf^T&4|7>vHdg$q;^7TSIliqE8v-Q zDrZnn86Qjx{Fm|s&)dvJ*2}!DEOg;SOw7yyvLxWa->ANc-gkRH1NR=p_pW0L{&dDb zUyDh&OMO00neL~u+MAR`*)+wl z8Cl|eBxP$_0yO@yc1N%F@H@);?5*At>Q%lG6g0?(&zdYYM^5rizB?6DopVx;{v86O z_3=$|W&}D%dTm`Ez2$AXgCYc3E6%FB5qPJ^<;&r;jNKh! zf6=n9Y-}(Gp}*T{Vi=zhjB?tiLOlfVU3O^8Q6A$#%ii7w!g+0~pRoj(vtTc#U*`MW z-Q*%%6Zg8b(nHy~_n}P9G_6FrmKgjn@hwH+=q<|%!T5J*AH3s_lL&`^|88gBimZnF zbfZS$2LcL5G-7ZnxVaIfc=*knT>Y^Z61dR>=r%h$Pg2_~P||jDLp9mG-Q*J(oK=KqlwLW((WF`1sB=yVOHgijfJfH zQcqaAR!^F>lSWu8EjS`uZoO^4Opv4PSOlLKfqAGVTLw6PJ~5iB#F3~J?L3KRh-%$5 zM-dyr0QY#!sONra9tK|>26jIUP1rY0*lYHJQxib*fQHS73x~hLt$)v1yMzMsQ1n(X zWD=iR8jAV1@EKr9;*^Hz?2^~C{v%lR-mz*PgKy5?^=}fHcqpOEF3^~ZzaI;q|;Xtlh30K80PcIZjWSKvAlj|5CDVq6lebh1-iWeOwFJ7tVU$ z6pK$iZ)Qx{o2Ie$p&VQlgKtwsZFN@E-&R3Uid`{IMu5T^y u{n~O8+uI3ZKsgRsyB&=fEXCUF{t0UO-B?%)9sVY2n5>kNWY$Cd_x~T|S}A1! diff --git a/screenshots/de/customization-desktop-2560x1600.png b/screenshots/de/customization-desktop-2560x1600.png index 957c5fe210c7974a78f932e527e56ed8482cf7ba..ea761d87101e015936b509cff665ae48f83d5b57 100644 GIT binary patch delta 102364 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�?F*$`6zP{v;@nxVhQ9 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�eE;LU~XR+{-z zx{`_}?}7Xt3H(&T5P9+-a^I8UbJQE%Ix~~z9~Kdu6D7kn{c>vbpNSA(4H^wDW?0c4)i+`PBIo|D7zxuvcjjWjE#*&2oj#Yf#aWK2F39!32I|`kc?bd za1gsCPQOi0R#p#rn}5qmSbDL3u{X+y*J~K0g692J&GF3O0;(Kp8I5|e`)XOGTOl@uL-l_mb8{eew2I}b3ZWbA>5LZkcd$?4=lTLCZsRCuu>Lxvf;z(8ueX^n5(H*0S<)BAs%;PQ_J+IpLAa>Y*dOcE&4PI z>Syh<&WDDS?t@xf7eFnpYw^qv`MgNmXyj3p&s-#z{Cvtv{?9{6>W+a1o0dhTy2%|#-1RZZoW0J&P;?lOsp=FQKVF|Z`w z$;##aTO+D;cZfx3VzJ7P?#{F!jg1H=#_tG)q!T~cK(wg6Djww0b_VF@BnsZNy}5wN zj{uuGi8r@`e>`5*U-wlmQQK{~T@lr}5R_?i={GibLH`#%?ek}h@Ho`O07bMdMsumj zcj1MNx1asUta$+K%t^nobW}$Hdq_M(gI(jhD8-9>aqeML6tb>n((hd8_Gs5Ci0eCm zVTK~tj_RqtWWC8@MdF zW78MT52H!vO6Zz~W9=CvtJ7kq9SZlBah0rs3$4%tC9nC^(X&Gga*CU7U{sXS{&e4T z3H09G3YfY|+Ttkh_IA=QH49K}Z-NwczCunWQ)!=>5#L&OMnr3e#0mv(t)q@x8VoTf zNh-P2%V|_SO|)6j>MDVEWdv)I(?J``(VwXy6cr*3Wi9)E<}q`S1ow2F)i9IF9>cMv z^a4kl6F){~#;Bj}Gqb-u7I;B1Fy#74pN~F_p6-rvmEhJwWCR%k6s(zwkPr4?x?bo| zo1Y8GtW>JmZkBgvV7SL@}TppEBA!ycX>nmelxIQ{7k#%m$>h)5e0XJhyz?MB_#5%!(|*yZ5TS zmJWLCUB|LZN=`URcAR`t>rNOK8@ON{`n@K_Zp)+Q#R7H(aY z&yyE8p_0MslK#sjFUb~eC4So_PF4R35$j9$YdFO{Q##})`c+4+zSM#uE4=k2Gu(NX zJrKdOeJa>|qmwgByVQmbuPmW)qLg%2yz+Rt=UBgfkes0E^5iphZ+{N8g4n7_Fjl~S zGLPjgFtnQc?~iEmmXT0&g#3#60Hxr5i2Y24F9#5c1We#J!r1Q)3WixiqHDpQsl-6+ z*O?C(D{%#R?4K)Wkxq;|NqMX|BqAE(2_TxGH75Ro-N2(q2L;utUm~`{%+l|ZQV3WK zD3i<=FHXAEb44$dH414Q$;->D<(R9@o;b`{uAu~FP4>U~Dd4Gk$I_5UB8^I=lEd?H zW?q4VPs3z-D4*t_FU@MPpf($Utgmjhq!R2;O$#F+8I0o=Bx`(=+dE{<)KaMpMITxN zuRbgMdV}brb_~fL27Lw#*yJU(;GKxIxryb8D)&bzZbyUD1_zV-omyj>OSGi+Ah9$p z##_&rmWMyV1;z1ewB}Nb=LL`c7tL5t_#TWHXbqB)41B%(@c7Q10+Pl0@0mL+kSpv( zskP-CNz3t46QD5y^wW&IICll4!n7ohj=lliEh;nU&P6IGD&5g>ceSJfPECAVL61eb zA5K{IFM-u|>6tJwiE`4(nuAp&1CFArzxM=L@YL`;ob$?%}{xpTI|-mLlygiyhK;!^wS9nFZh z-}u=RN(kbk$@zJCW3}#w67w8m(##WM?=bW)%OEg8mt!i;FbI) zmZ8>z=IDa5_UC&Qo#IL*u}nQ%o%U50J;T&ouaxbkmKYS&+NhM#e~hvGQ3h|&#{~TZ z=!`No`o+}aRy`J;ZFj@Q2XoSc52yQ0;9LC*W$@OPucIIJJLXhgm}SaU|CZgMd@Ndh z;=VG&Gl#Ix9!e7>K&wynkc2;?hn0(P)A?a#cs$3+j9C3Lsn%q^?OZUUHDD|{Lj)TB zBeMU9CT?-hp$^3D&-=p=b~Q^Dh$bGFq-JN;eaNQ%loI!yQVCfu?#3W4wCRgh&|y85 z#Ti)a%TiZH;*CDkQ;0&pt!-CyV~urmAB`i3N?@UdQjneGGpe#eZT`SnlgaAQwJfS# zwO}j_@un75Iy6~SznsIt(n z{N+_Q`HPmMJbR-w-yM<5gWTh0?YE2cT(*d+Itr$wq$DChvDoeYWA6tH3=Jhf`^2KJ zy!o2IuO3~=>;>9xDek-1drKG(FHoF8ReOjR;HJK~P{zRXSbC?GPM?<@EO~v|Vc9%m z#=7FWt{U+#;MVN17`5wxJV5`06kkphV&b=1y*|T?<>iDDaL&@RvFbrB2B=nDMAOsv zyFaKBGh;ONNv8$=G3Ek9zipJ_mZw2h@% zID9Z@tjQLsH#>)plqhqBCHv$pLG42|FV1Zt^q*`-cunTk=jcW6);qRVr#Al#9KS)P z(o`357z!g3nr+tRtMsH0w>~OKv=eAJ9kWA~X+D=my_Jsx4WP&IMb3TBM3J~cgk=r1 z%*t>}ON%n^<=3|}xjBJKdHF-LUYrNrdKWq1bzG2R6Fn5XH;BD(bj6&K0N6k|@oIGLNhYNiF@tNPi1qn@72G9Sv9PTD)E1E*Y!Hn$I z&Kd?dUkMq}@)C1YY`e^8uTKmL+mg6O9aAC{@kV39B@wP4ngn^Wm;#87zoN8HLP^$r zf|gkeQ{8H-i&PV@z_I%%R9AB%dX;14GkAcp{3Idy>dt(sAGLO zYDCgrEWOe&bo2e$)wj9Q2^=Pp{MdG^^ISHe#zs{G1)*z9%e$$f9rZ`t>S>fPCcszA ztHy~wQ_1OEI>mPI=~sy@*s)i;qxFX$_)NqTTZU_RVKO)$)WYmYep>-RAvhLSiXdWg zh`v?D?+U{W(%vFuo%40(QRA&9d3vq%ESC30i9i8H4DR+s4T|e+lDN2ELy_AM6uz|~ z3ljHnplmK`2G!lkRH9`fCs|-d0<@EG8=zdgGEF7qxtX4=k^Ob-A)R+b6Y`iRGRF^r zCMi2Zr7Y*Ocj>5&&4uXf!TR55xYKL9dYAo_V_s2yPDrI#3sV6^Hz*;G@BL!?P;g(W z>3=K-1#PRS3l&>-n9C>)+&rI%L7C-2xw+AX`YSG}J}osD%D95+vPH=&@k-cC`6WD$ z4WYiCl>RMPe?Qn+Wo~&KP-?(JQ|7(JfNgNEQdwKxtxtGWFZd`0@;JABU!7YQ(+y7+ z4I8IFdV~pF88$_aR1Ar;&xfU?r~0oZ-spL)dvSJRxWE6I>15;u#1~UDNa7Uv&dVQe zUs*x?I(CQ4nq3GK=;%k{d}k9Q-0DyxXq=Q{Z!c;#Q7;CViF-8Y=68~v5x zoWvDYI4m=Ogc<|Nl{SY0XyK_ZCsS&lNXV8#;{{4p{rjKPHp{!(1@Ypq0EtUU^)?r0 zO~pmrB4HWQ3<#pvi4lXSA6{NrPy;_^sB@Nm7fPhD3;wX?9V0O0p%n}9+nqa6i^eul z*QuiPiaPBUTkphM zYG%YZ8Xj(ur>7e~VR|oZW5*X$_Jbw(Oe}rZR4x#Z zl`C3m$Is5-hT0FI%Z6QvX{tdq{-un{x3jefATtb1OiYYEKl7%CFn~G&j85OhPu$z- z&&||w-Nl|&$kGB)dq4{PnL;vVmsc6ORV^{@wTdm#19Cnic2KCPeOd)*P^bAw)P@tl zS;5G+0EOc1yOsiRM)uaZdF=C{RYYuC*trwd)75BF?n$r7&;71M3EPiLBSSm9B4S+k z1Vj!UlJuSHdO08j1?s3PvIm|OQ)WwmX%kVq#szKJ)^-Ase*6%6cGz}Uu4JS#W3sP8 z7W9j5h7d(K^~%v(#FsIP$B|sKOXA3)g11Kcv=ctq(s0nllzl11a>sB) z+OF2L8ll-DF$IjlRKHcqE@U)mc>+x~VGWCgiU(ecl&sK((H!VhSA*j5$9Vbfjv(*4 zIMMp{>CrUNI|MrPq>kzhTJUn0()JUBC~OH$r~{RSZi|lRa7{kk1;WUt#_QIYTmyQI zGrLT4hop8Nj*RHaREh$I#&V++PZ&+o$o~rAy(W4(G9E9Z0zbdeA|Fg~m&#CM7?up& z%CueHLM347IH?Z&9JYF5ke<4HAhqoGkgG!bBpeL>@@J775BX6^u z-n%gAjD17yc-{9BFJ!WSi&2pMbs-ijA+KaNf8W%(P_b2$ zp5l%(zMG$!uOyB;1HC`X0;ZS5y8F^LL;!=e+|~g5`i9)f)@_eNQe`wH3&Oi6V)A9q zFx#meuaA)^vl`QjvFgG@yuE6-u!8tov(=4DY3VsOBwSj$eU()rPxtJHE>JeRnwx`Y zX{s0eGZj4^@PSY@`s=MrB+OUN{SI+aU>^rUV{KNTCxwOkO@ruGyuZQ1w6TR(oj!dO z)%-Dn{5&KExDiHJ!$Xcgc{vg!J$;Q#OcJ@vBD$`wy5fGzZ$N*Y;HpM~g#WvR(vFo} za!fdEkd>rzVNX(oe3IExP4Ha3drPvjpe&oAQ9_u-`Y6L#B?etQ#JsNo+E*3x)xir? zrEZ^IP`%p6vN_t@3;GO~;eRFsPkV+jO{}^0p}hJ|V|YhWy<3i=rtC}(wPV&=yzMfm zh6E`Qpx`~5i(Kt4TXio{2MVi3_K^v6>vA1W{R*DBH4)=$@B9stynY5C$yMiv!~}^u z2Vay|FQ7ajPv&eJs0YrkH0a>V`SL(|Y@w_@Vu-$cVK6byVe&CpA%LsEeO+zz_(I&_ znXWJL3-pskWY+thqr25)`Os*@!1(xEW{0*cpS%t{^GqpAQTx;t8wOWu*yxF;Bzk5i zYSmHNd->TW{;M(kOQe9LU`ausD~A!(_Pr1iMQYl0yJohU7FyD>pZ}P@D{KgJfa~mn z6diWg_SkDm;p>>$;UdvGNx`3SX?yMnrI$d7?JAVxn?IihFhr)Pn$wEvf0CiczH(7@ zAx^;Clur}JtSV+}ozcFYA-RT!y-b%zQG{ssEhk*3UzHZw0^RNXwSj*r zT0qkOH@B6kj#|zz5SzOo9$Ut0b%3rz2|VD>nw6l~_&O%qxR=<*Xv)gr7w(C8*e}^R zF1*$q`f4+(A=5H@`T$sL&g;V5us}^I;Ee{t1bWHE9!_i(q0LwvIWG+Q$O5x#Vq(I< z!6g#bhcH%km8_b&SQocZFInd92CN-|+Xf`a@bTSjdVa>a86>2NAx1A-{%}lqtLvJm z4tJM_t)XoX-bMOJ)cHKd> z$m2k!-Ci#4_a*O83tUSNnAsz073eqSf)C31gFagC9~jm8>0x8&`opBt11CI2vT9*o zZ6nG@l-O2Ac(&KSZj?BsR?1x(YWmnJ7k*r`(#$LdKgTH}Bk+DNw8n?qw_Bsrs@?n2 zV1kJrfXXtcpFE}Y_KJ!Eacg(=MD@J0D1j@aer2H~7yu!%1u;lok28a6{pu|`G?STW z3ozUm42s6;ii+fxhCQp~(wM+{G@6{A%nMo?mC@4}FH1|P?Jn&of6u5fY@fM}E08!H zgcsb_(4GC%q>}ovNR57ZKA;O;$YbaYHNiVQ4ZYvOgVGLcvamPQqV7zpWuMRRb#^r? zU2SaARzDIpF?2f8PWhb;qz)$8jRamt{j^-(jqe{9GwbQ?ZLTn}xq5YqQRmqasf*ZW z=3(-weWsKti0Y2Pi2=GD@m~wSNiEdebMOxrVOS}QaX#;31E9dgg7(>?^#RR7?i`;~ zulaq9xD#324<&dzV*<+s`>=BBP zeFx<=YWiKaTwHXoT=822p$oZ{#TQrF)v6Xcgue-`PFvuhD(KseS$SFdQnod|6_`<5 z-;H||Vug)OOtiecy#ct;0`ho))-By<9dKFPw?PxdEBJ&pfW`9iQiVwq&>jS*{KXjS zdZ*0F%EL}hc@`aJz_+#%2n9co<;hWFXYOpuYE`cfV1)xDkgPle>U^c82eckniU0wK zi>bOJ&SwXR{h;UfOIv3_anpH5(CUI5dpJ$y8n2!#4+S1>SE2U6;vjNwi2*ng5e>H} z#lF}5&T{La1Spv26}TA7gab4mfjgv=&F2WNTEV#fzL-XG_;TR`=`V_jybSyBBM z*xlbvKrfO@`#*aV!vt=P?2FM{$S?INAMuE2BNt_m#H)A<0%-{lHb8ghPUpgkTf=iB z`Md4y(>%|7OhMucm zb;$n0J4-oH(R4_!Zf-b}0jn@8pV0%b$rM<$DW5gDKW;R1=g$1XtF?2m+vz0vITv__ zg@&cK2+DF5T^D;zWKea^Jf!9+|8C#8(G0?CgB0PmY~3W&k~Cb^pi@L_8N=$xf@{6E z0A(Q4d7N{FlmpDzL5i;l0J#u$IfI0hs2cV<7b(%b(oP_=hL7LkPA^rDXN%P?FkTlH zhB@Pc%{VJD9ZjNo8Yda-iBDj1;=qt`;?VRvyd4SM`vhpB@;usu>aSzG@ExH-GE@~d zO-)fU_;b;6uRLTv-{FBq(!0HuUnpE`7fkA^Ps;!uT!A0aY9EA$*1}4W(L`%cKhD|% zX|>}RxqKE%>(I!E&q!`JML)URevAR`8PWBVO}=XBDL5=@WhG$}OdG4F6VYC)i?(Gk z(b4V@Gkp0yU^o6P1(M#}-N8O`J*GrV{Wxrrr){Qg|A)nEQr?kKp zv$GKJCIIZ@q8u1v>R$gMslN+*#d?`WC&NGrqySjl!ocApRM%!o6NpS+@LtSgp+%(H z-5&{2>_;gF#b-xfa8k|TWRHoSF!#vkr|K8QR8eWXe|cWf%xYB%5Gf|?qYTjCy< zh83u5N(Ack^w_wl&E++LJCa9)w=%vOc0f(Qk)dU1Xt=KX<<7q-o`eh@0R+%T*t7Kk z=;<`>@uan4c&g@@P4B7?Fq8r{MOOkfSC?pF*qPGCW88Z4O?%g8{=EN`3||H`v@zkU zIU~PUnk&=;j{xkCRGyxmeu=~37W*d+QeOG%^8FrBhWEYx5lTVG|N1K&!BC&?k8{P@ z%lmv@>%Ka5b|;_FS@1XsbiXDIh(Dj)7kZvs@ z9XuQPOpQfT20){PRbKxIC(HNCuQ*;v%C2pATF{aLK`xQH;hp2VcIdGW)H)2QH+rh^ zSroQq;A z_ULGwbQ2L%cl!HeK|J|FEO>%b+nkfYwR~?g;QoUhfFL~71{6k6i6XJDr)di$wmo8} znEPG@!9jW0oAQ;D_N|aLxLD`=a-%KFowu}>T9&L=PL&C>Aq80sCVrn(!-vDPwFFsv zWr~Grc*OoUPqvvQ$UOVL&h@KGk8NC$csc~kxf$4(8w1XNy;E>;V^#74x#gXeM`c?* zIzWNVzsK)afkP*Dd^;sjM+=o3QYvdA$ItiJuf}q4{Z79-u5C1ayp{xRb*Ob;`$|Ie z*r&G7J_EzUb!LGG3RdPB_fr$rMu61v9FD1PAERM!JhAKMhvZA$rX z=Vlkz)cCOgPuv{+gg;-qAfE`kmL5lExqnJ90aOnU(@G#4lTz$`aW@4%H)ptB(7o>I z$#m=3#P_alI`5DgA7W^oHh=MMdoc0H2XbGpcm-Ol!RIop-pB-(Kw3rQ!zHqKu6~*B z0)7R1yMeay7cMg!Mt z@qnIn5)@LI2Bk++sjswM+}uW|#QE+RpQUF7CwYCjg1-q`Jn=QmS6sW^+BPu1V%cLf zv*hJGb;NemJ|w5n~mX$Ev|u5GTM{SZO9k3??Vo9I-0C{B3J@ zw1NJHE>57Oyk@=ACmdW65G>31Pq1B{OqX_1kvoY_{{i0btr)PsTles;I07NM1^dx~nXnkO&V%=D{1hKweqov-G_-(bFXWh2r zJWV3r9rF$vA1?UDaMx-8Z+|0QM8e;5K6VvD9a&upWr}8hqul)PvoC&@`shBuMP#%# zJ8}K9g0$CH&6oepyjCJ!*!+1(Edg|0{7?v1eatB@|0T#-ee?+4D3G|+z22(h&c~Fh z=Levz4-%jhDhXrqmFd>AZT&{Yf$Q$mvKqN#eDZy3QfD`oV_du-*RaSG{ll|NtP#Fa zRt8WK*=e6IjZs-?mTRmU8K+@UNrnYr&@xRh)yq^ug)ZRKt`dyKjtL@bVj*dg5O5S>_!b z4pu}U=&LYgf&$=B#2Nn83!0>PDVuG3lv?0z4l;x1kYs>#KLeNp^x^Y1*6iEgiJ)z? zCVqS)@K>?epX?Tx#tgV=(a2Mhr#7{ z;*A0IvZg77x-7R+C5NbB1FLxYoZtGr_++KmBk8t&UHJQzc(KxNwo1W=)up1aP27O0 ziIr_)dmR8%BDYV?kn2T{5^Biw@P`|jWjEDYn9vcApku|HtwvLwJm zL%gw?joVGHvS=b9eUqX!maR~v;%TL3aEFNO?1^%DxW(?Z2gJ@!VR}zTO!hh^+&>AVEqc4sHKCSE;K zUh`SiFUct*=V6KayuKxS!k5>$nK3KC%)IQd!j2nE&ND?{vjUQ2WrK?z#I1{=g#01# zBjxNYPawe(fdm`xHL9A?V=iH(TJAlF+PU+j`x)Dh7M**c`T%3C4C@Mmc=W-2@ceuG z`g_Ddk+aCnJ9J&6SyZdt{3i62LGN!{(isN452dLk!&ms)D~1kj9KGp9&5Vc&;-n~y zs?f-1Qc+QD;1LjbgiYsO#om?Ig+*v8I%t+K;fHlc~v`IC~m_065DNkTl`#!)ymP2tmEjOoDn> z7o#=ng*Ot@t~#vKP-YDc|8&B`wdyB1Cpc=3b_6&lZIYOyw7QrZ1=F+81fmISWMSFF z#96S9ofC{2%k##@n)6RQ>FfKL^(5la#Mu`PXwpl<_^CUDdtlG$(-#aq z4*=LETKK@h$xUvR4)iY|ND(VdQGnqxk7dB<(l}yt*4R16W__l2;s?V!0RUF0uH@)U zkJ*S}Y~p*K;!$I{u(YlC+j`)C3*G@S19JMTn6BpGHLqZq1p|-2$2XYcmOkQ# z)73dyauimOTu9~b3xME*aSljaomH38LAE$mTnz@O@bB?1Z{2_T2QdN2#WWp&q&n8| z&-W|711YaIE#blMTIl__SRI0^{*FX5YBc26#ot4{WNg_>Ktve#l=l z1xX~dc z1`~Wq)pr3l4P=?LZq$6gV1otVbhLfqG*~&Ur=xxU7+}!v$64hFb|Jf1wpC-pJlwbj zra2e~TlnxrX9*rI1h(u5+)e54v3?6r=JpP72^1}uzAgy*nhJ-Y2N)+eRTmbPB*st^Q@E%&>J^AnuVMz4H~EXARLzBqn}uzk z9f-n8U=No5We;M`mf!EYb-UboD@+Xm|3VFkZh}=dFiriV`CQkT3xp_{QXz>r{D90*S!{h z)jt8id-EswF^IMbwQDdi`bSaLU+221x^s5Z10R8pfRB;?s2ftMgzrTBJ10809pw{U z2S=uW1i#ZCnA8RdcBQ&2ysJn#th5eD760WCu)U@sQ=$UP?!teWYZhPK^0R+a#*sxJ zdfcoFUC-||UlIB5?O7M?e*wu0TAu41i}*)6!ZHI>5^h}Y>N>lwklX%oCIC$q#%TA~ zln1SA3D}bUYe4@K(Dk%u(NdaV37GLu5-_rzxs$do?1BI7zs81AbZgftcZVH?HUA_# zuztW-1u*OQe`D6~&#$=YsMw_7He**oU5s=*qItpx#K$Y zKj7YTQ(Hq%SqF#k>|1!3Ei%~Vaqf}xrxg*ft@e)MVPFv#GdP|1fB5#f2=49 zSSU(e6;VJyQ9!ziqIBuKi6GK@4-a(#1qJESQ97Y_2oMzMQUpQ|y+a7n0)+CvFS@$> zJ?H;>y9Yc8@4b8P%$@R?nL9MrRfVSWMBeA4&oPkbIuRJW(>jbkK*EHh>lM3@_IGS zn{_Wb=ERS&m-Qb;I>I(m0D|@lKm7mLy{B%VKXOcSo5>ORyu+?pn)y@H-;%n!&r0UK z{|t02N#a~31dZH`T9Z5TC^zgeM8iR$%CvC|Rli=>S@KXrhA? zj_2y@i+Ua27Y-jhp7FQpz4@KJzpR?0qS(%|pTze%xruqU&BV^c3f*+g7I8?pGP(&0 zKoh(G0Hs0ZEJp>9ePZH&G#VMxEJL(*cjJ6Q&4JuH}{^Fv{7t6ff0y`qG!SJGCWQ*H;z9zeM_wpM#dFJ>0fBqQ! zYt-AM@C`=%!0qQ|=1Q_$61RZKdB=MhwET(|_O@_xxAZ!d? zh>|qWfm+f_$Z}dkGOUbypI+zZFSarN&x>kaq!(jS>!;NrgQMPFnJJjmRJuK8FhcJ; zqxc;mdGh8@TJh8_>X1QCr)p;D?6__-YZq13DrrN_Z2e1E1PHEd2l7mIg-J zqppk~6Sc6OG9u}}zVP9kGKR?)TH$=~Xi6OQR z43+j>c?C}VMhF9If7IKq0na+{Y)05^m`Of{&n_X3dbd^*a@BTnLdBJ^N_eE2w%zXJ z?VXgx@2u_@StFp5t_>qCNyoXmnXRc`F-P!tcYjemrIlprd`pp)%7WhEny_OfYY`T0K+(Mzcizp=204FvN%oD<;I1l2-4Qk!E|;)ok}rs z>{{16+P`;pX7=>7>D$`c=IYBP+U+p8R`kLHaQ_VUpHw{=3-|8W#dGHmIfEJ1958PB z6jW>?TivkB;9)%_(l3*dRoeV5=FF19uSqdEGJO?9(^Y2s$sQtyNpN zy;BM1(iN>{A#xAOHc2rNi{~QFSWa0EJuT(FdiBw&Ld;;co0nEX_E4;@pWC-+mw`$a zgBUKSVyEr-)m#zt(5B?jnRW+8zTL%%_U_Kk0i~dX+xk(j_)Ze`e-NiQIe6yMC&nin zyWd{AENy_;NWuEIr}5lQ(a62hk)>TNb7b&@$o%t%@@h|%p-%?6Fk2nd1eCnNcXZhd zeK3#d48i`iX|iHMH38m)OxHm+LpsP^b|13&UMfp@s3tAWK7{XP=l1CQuL*)*hYM0u z+rky(*}KG#@5?ApkIGp!4QA@mqLNE!Ej%(Uu9rCI1jzWyhKDU8Y#luIHdqWKUG76t z51OCyIsKhrB@olx;>>yB#_-f$aj}y^Zhl#MpA}izr%zvU6cnVFHVfY+T&=(iG*iM} z{l@uU+#=3Jc9U;o3O)f~@zVOb$C|^2)YObkZ_f^Hpuj1{KR}k2g(VdV>neZDK6T^K~ zD1F&#;$38Kj)t9dhKx+})588+hIg{~I#u}b$rJp}->xQ9rN++&5Qf6%=NS-N>w?;) z;yOosL{!z(l0KY69;JqwJKoMcG++7pgMyMWm<>Sk8MY7eTinJcj&gExc0NaapSi|y zawN8?fdfX@bNca3H|kI=VUq^lMW}F_~f^unIqYuMjWt5RG1yqGUQXnC+0QU8n%L zE(#$wzo+TrB<4p?3lqO}IbvwhPHs6-g^Fs!5uQPy`CvEa!e6~et`S=tH03_sL{1sB z>->Y@J{p|1h8xFY<0mQ@@!d)f<$7$|qH}N3#g1dD&WjjTn46o&mE`Jfgi|pJO36m- zrN>y8>wwjF8JKwmL0RN1UNY(yVL4UvXRuIvb`{k@4K=j|(4(Tqfwy|v84Ze&=Jq_S zG398j4xGcJ_3$UZJ!tvuu=|XGH33C<(ZK)2HKJ{|bxwHUtqQ+qUx#%9GHrWB44;|h znYQGye7tI7Mv#)=HaeCT_Tf}+8VlM0Eo4!>Qc7z!Ih(;lKoDCsoHnA;gscR&V|S;s zw%iwNa?7gf-=VELjY0$M`iVqF-twK3o2w30xl2Du2m2o{8haGIa(n1|mDIIUdwSHP zT1|t9)6J9OM=1;9DLE>HJ^*DPhKDV61Sk;N^6T^q>}oB=&Zuo_gshZIE|k+7KwU;>pP5h1 zCsYcjrkCAcolZ!T?h0HL2FGjmGuk`i4+Smcy}4Oz-YT3MwCdxp7cOk_`H1lJ<`&DV zL|nwRT_p_z2t^fhTZIwAZBZX$U|;}El32~^vs83_*-)7o8JHwR(cG@~>OPa%P96A> zo8A2^wPjaPcdB!&TvK=j&DTPyINuQ+ymc)s1< zkl^MdXS3KsfR6$HzN{3AJ*qYs9udCqG9VX2+dK4W+H^$B4c*ro^ssUahrT(mzCKeS zF$9}Mq^m=s-%`M;ePjt!{lG_Ld&j*(MqaTHX<@Mdos{edM{(*|^YUTnP7p z6<^J7Yl<$a;#wi@15JcHD1gF0fR*>`B?z&qr{{*t789>d%zG3XbX$LabD>3eX0eNs zU}0v~tu>>Ynj&!xk11!D7g4~YS1S}GtgM4(eyD>T5a-w|)ZAZG{;+|b2BLf3tmLpZ z_YiMBK-0@bjamg8z^PX($Z_GrzSm01^fxit5yYxNlpNOM!(*>KXJ(I`9cyx7iQPqu zIMIDk#7cq-?cB8V7|Nx0VP{0YD|@*#Y3tdZI6HEJ8TeWBV{_2ls(a^LF z3K1x{x1o?LiQ4OqOjtMst;hd^(vHevcLOtW*Dy|#R>Pm}N**o8rnx@M*Vfh+YXh1( zlRIWr_+^EWkx}!xu(6E~A>(J%G}K(WkH0zY&wL7*p8iPd8XZ6pWUY**{Nrdr!@NQf zFBj}mAR;ygm99A#HK#D>5~0zD$#~AeVxZ%oQV5ihDx|FY3H&u*l$^{Xna5J5zDG|o zjs9>g_W1yKUQJ2=V`g*J$EoGl$1bzgTg>Ktq@bW!F^`XkP!A7}Fn{Le!|AM^UR|yK z@#9DTxBlIEV_KMxxz7LO5`b|nU_?DO7QgpYW@qN)DCt?nMKi?EJUylxeG*+r88 zotjynX)`U%$SRV%T$jSh%cY^B5_}*zaD{x>@05=^`0|0|#TLkZ9j3R;|;pK3&YC zwVkwt7_}4I{d&lksOvuUu8Ly61hwJflI}U9fOY6?t%^q?5nJ(*_^b|}NZsBE2hZ*P z-m0>D`}4^5^%tIs|JZWggiKCkcVA!n`}e165dt&r5FxK`I+cC5a)};g)s)dhK}97X zYFbwi?tEZaTIGt;muJ49%^aj0`pXB|1tLzDIrvx4V~JV_H*-k&tqA03Hh@xSFcBc z2A4iav$VGW`6RM>e~Fx*U!dP=M6Xl_#p#@3sPp1t(nY7u^y zWa_HuC1tzm&@wP&UP@!VU{Qp@@q_J+SVh~YscB6)%KIGg@eh2{^ZjN}NZk`V5t4aJ z-*|IAm{HmBBsarbcrWXNy$q2p=VxY`$GO-0SQGNKlN^C9E{u=8>G-uz-D{c)>Kt%SjSf#GuXZ&s0@Z7VH8qr7CpZ7nF#<-BCu=b@)Tj(iQu6 z=x657pDVdVIlS))@5p=npyB?Y)nIff#&#c=e~Z-;d@-%yT;Qd2W{qiXZVrd&q~yLm zVp-0GF0pmUBept$lY=uKH2$s~IvRHQ`Itt)kXLEBlWcWQw$@C6hJisYulUv%lg&~t zKuGSGQnR^nJSCz3!!EK~udI(_XCXbOL?M8lTdA&%B68P6HZsG|<6{F}5f~Un%g6`L zT(?jKD-CK2V#)J$0b9K_4dOeq zH%oUPvQ)|*ag&%U3>wD7KyFF_^j^s!FD>Jo>N9*BM2TNmi>*99c5SF3AwJQ1^LL&5 z;`RBC7`6z;ypi&+1XUB@`e|Secpx)c65Z$*Pw;XhO4nc zj*Wkzb}RNAh}>~peqLxxpJ4=k#CL`TSU7Zu^^eZsmdf8t5{fy94>9VNm|en8hp_9b;A?MZNfl51{XczkDE>nOL*CAja*p%(h7cUe)!3?k@w1a_-=tFnQ86%J> z)ta<*LfbnNkonhT=vrxm7;(o!VGwK$rxs=cN~|}*03k)me`FxfI)hWz0VFO+;`b)_ zON~aaB)FBw@1#>(Ej06P@Owc4ZF zd%IOB-$A1x;nmA;47YA~<%~ETF_PwVcJ;RTR9j`6lAo^>LPJNFnLNo>S4ZhsL9Vk> zl9|yY^Z{kxFN5nhMvv$9TSo8?WHvTFN^@(LX(_Vb;!JY`GN|Z=M^e{DM+fw{?rZ(+ z>>P{2{-Vhkyeb+sZ0+%R<6e090C@&CT|h`kXjpW_C!k%@+#L7VD%XZ}&vh-}+|k|!93+Fb*$y&J6`y#DUmSStdJ!l#i8PRqw?jU#yt zxTTxFJyPlE_{_Zjw~tT7ki@lX-PY)weaGFGeR_G0&B@2NpHB%2Z#Qx{8z}hs`OSf& z%zGjeDs5aB0R{rvW{{x)vE0|jQ2efsedX9g?@232{tq==Z_(okDmPI@W0|08~^ISUxPJ=YA<19*iS zmc*{dvxnIQxV7F0aR{4FD@6-g_+l4|`YjcZ%#jgc=4rK@mFHjaf$|PF;f*rm zTg1P$gy$yD#;MEm^rlWY1-Oxe0ADvI_rG2$Gmj(_2)0U_(7*c zdOxBO)D9RtF;qcFNhK)u6VPVQdt$Ys`K$`C;wTrq`c#fgDFM17bXn_4oc*W3Sg*fR znfcYOe2Yt3er=0F*b7+Oi@-Pv89mHVsZ^r_*J7ALKEn)!Br()LN!4T7lkwV?#Zq(i z3%S=td!F*mjgjN|7H7&`KdrY**jyiizRfE6R^{bAMuodEBk&h3hjbp)T?Q?h+9`=P zJ6lJf2e&=#1~K4lk!+ZRCcMwOOc84a6XkkQ9-VeDnRq;2k(g+&$sD{;R z+2tM6n0v~|X4#AF(JFL>*xoMGpX*LsVI8?XL`a!o!5uq~3JHl#j!b~QOf}m6!I} z8lzX(pH*~{@Injx23s9vKb>ccSWz%sPIy zVbH4Zu#V%m#V7@8r?x#I)I|H`y33hP$IMtAhUDt%>-(%)8s&Oj{kB|a7V~tX%9<}U zii{_oR=7Zz?0$Ng{qlg7LuIet5pr^il_F`N_?&Ys7C#!}HjqfK7ql@ zucn~)BtTIQ#(*~;TgnxILxU2w(S+fSkr7wv+{)#$c-J+3*qwCW4Qe0A4w-8nn`k({ zAuuHjMa4}nn>^Q$;4zrm&{bh)%@Jx~O**nVGY85MJ3&d*ClTu^eQGS^7byJ1f6&n|&^r>mIqpTc?o3Hnk zswIWE&iw=8%Qo1#jF%nw{%4^Pfc6f4LC2~y>ya* zUK!9a;fr!?>rX@JnmB3pK&KEZV#zgL1)aKX8Uid~SzR%b@3 zHKN2)AVx!?@_GU9$f}d|-qN{UW?P!GXS2J2M1r6NL@qcx3|g6*iT3y%rmh5iM>1Z& zejWJU+`*v`tXX)6NgZ~Fd&{}uq{}f%#y0^$Dz=aEq8SJ|qNp^lAae_I+{^L@J{w%k zrj(5H_BoR@M9kkvWG0|ke&MHycAy`DV-&`A`SO+iY+YS-hjw&y1THvS7Q3m3)X14jXJizqEx@R$DG)0{Kg6cv z^zQZYW8#qH)aP#B0k*nRw@&G#MQ@G_<#}PvH`0K_LyXq~flt_XAm6&Zi-(B<0liYebj!kiRV}TQc!`R*+R(oi9F2PL3L~K3;N;MWwt&yoiyGWqO0jv{38rUDM(s zM_-eem}ryZCFv#gUM3*oJnx*7ewFBKXXVBbqNfN5mPbnDsHq*0Kpj;7~Eb?QWPmkNlTf1{X7(MYOWND_87PG zxAfSyH{j&vxVdOz)2OuJ8>`=%P<7#9c6K(9;w%KG(o9Pc8+Ab(mCdWj{2Mt5+uYJ_ zIx8T~a4n#2Tp*T%`m?^xlnvLc8kws>^^6D#m{LlnzAh4FeW+YwS}ft&e@NzCdX&1D znk*8ciFEV~3LU&$$t4X0O$9$8@3fZlfl=Jx3E_h^I!rA7B7L>5q(ehO7Xvwlm6G#p ziFm~jl@O6V(d*WUa_lM%{)Hfd0Q@hUCQj4pZtv3JXq1H_qDs$-=HgPbCDr^fGFfFw z$ye7t)1eXz2fp+z-4^#O$t%$u=fz9L3Gb%c?&rmZ*77{uUYqm4!WPQ*Bg8HX3{HkeIeiHH z;1#k|zJDXZ7o4pcHqpDkDOV~P4FGp{yaDTc?1>z3n%iSN&n-&*+;f8}5I}Mf!e}hs@w(Xz4*udJ35<~M;Ii8|rsGV^?!xT;c% z*e##_4Ih!&z)II}s3vd#7=X4OAK9GV;(RGtd$P-GYimt#1(`M~#wrg-9UmG6W2+?# ze9Pjv__-lW4i5*9nw=6jlq9T(1|=-aUNO;*T5v`JgFa^@67)+3@~a5ReCTtIqaJPf z0#o3N;R<0Q?F(iM23LY)*3bxi{kG$+ahgSaei#2Oi`Rp+o~2VZy`6QkV)`OralFOH ze?=+<@vT>*yM+dr%)!bL%3xez4SHeVAh3{lL&a%*y_Dc~jE|fDK}-SEU4=%cG&odl z1rcu9uc=n;E|H5@mE?$ui4D*LxL|vSNo;KM2x?|m=cEUn?EA^_maXc?T3Q(71Yyc! z$@;-SHue~wO@Bq}m0sFoWq%B6br+Vra*1XJf$p5)*qF4CaYz|#PcMQ=u~a$b8;0}q zw+X4DYD*x`m!*xtO3lnHeb8T9}KtYcCA=Ui`B30XD?kYuo#son*`l zwv~Iy3ILj!v& zyQZHHfc)EVe#`W0bOBf|S`jYQd}Wu4 zS{+#Ipa#{vG-&QW`AtQAQ3nW{Hy+(=`b{UBkmt=Zb zIo!-7`e>mi2Y;+&>FUsh2GRA$)X4oz?!T?xl{g>P0T-sPukSm)!r!i8K}J@ot-cME z|DjvtWd*&`GkJk;*aTu~l^YQ-Xf`xf6m5s1L|YaiFI^ImMEA^^h0{bjcbCW5^IP7B zB3j&{W1;~lW?sted?$-713<1lIr>Ndc@>wGTou2d51bcHX$lHH*xd!%l|jt9sCs+H z0=HBUVhckqg!6zhcUV_{r8NXt4(Rk*!Zr~L$tFT=Z4gC|x+;nqMVK->6j6ydX4MA@ zY3AREQM97A$ADdPzRj;yR5i|0foIKzCX)TI8rx@UP4lKKoLS8PbSmCiv zV_Ie_+;{$S=clJn5T-_;jN^Xq*5|giV>$~~0+(|{Or}IAJudk^aed!Z)_G-myD?ehlLBEUhej*K0snma$o46z7Ylr0x3XI=-+??8cD zfN$BRzRh|jzjJOs*qNzTM@I8r+v57WI=*vpb960LU=;{op7J%B7Y`iqj)@`S581;; zj<=L}aBzORlmqna;)mei?=zPG4M!zgB62%>_lZ4uP^%g}^3&~ytouZ6c=HbE{p9Y6MkavLFydoV4Lu?%(pvmKgpWSlM`XiHhMP0FzNxKvA1NpBsdjn8lyp zOQ@>&NP!cuU``q!M{ z!nC^vp4%xDC!Es(uC$I?D0b^I8t#c!Eq`MjVnKT$N_uD9S6T6M zgO^8;si_LZPEMHs1<7fa0THZOyiH{mu>K1NK}gQ*+w3cT)3whP8=0~Iyf~trZ=T&! z?yy?oieO$@;b@g4r{-Hk{J;nbL;FKF#oCk%&=2v@GOJd0u>YGt0GL&{6iIOku-8wR zC-1F&RpFfrbGza?grA!+;9q=qPM~O_{T2Cna_{|8+x(5i=Z`ft(;HS{+sfS1QdzF3 zc*3jx>-`o6+6)kQ4{AUa0t+_z>)|-}l{c{QrPsDfB<>}`uF5PVNoC(}P;LK?#dVV- z*FZ<({9H!!@cW6Ps?=0<5K}_!>gH&gFl}xKLVu`!Fu32crzk0Hj#xK>%+I$=NEms_ z_k3v6u0V>=N>O93!!3C0mMSGBrGl8t0eu@b_RGyr^3%)9`!fWKS_o$G_Z#kWU2R;X z38bQesMIwzKeQMFlS;K5+4z`94Mdlm2dU2Alv#kb%U9hQVu}`ttSKe!(Ma0RS1(`Q zvK=KWC51>6gWfA9r!Ex^bOs-@-XH9NlwwHcfC~yX2R1vVE3x&&nN0vb&V#77W539gc{XnS&ESTGkXU$9>t*shC#&absY8*& z`jNeAuXdZtF^bwebAa;HGmA^I?yT|(yDh~AUa1ij6kK4n*_VyfcS~yMHGBGX*@)** zO~@La8rny$wh7gm*tGOm`9glg6AelXuB(Zpy zl6P2t0DUOFOSS~E2`$5DoSEjj((t6ztL2ZG^X9es&$Y@2jSV2rDJSk-qjDq2<1-bA zB1H}Cxh#G??#Ix+zOq0H1Z{5G`4TPdRu4Z*!kBb*sT8*vhL7h~?@1LtYrP(Olao_f z5Nn$<=ARg;ZiU(=*Tqa2|(eD223=9?8o z2|}hql*`MmD&SXR)&;Sc1qTBEZz_ZQgM(2`Pdgi5Jv5vAe5q1A6$En(5PMD!#XKjM zt(oy$z=I4TKBa6|wr(>;ol2jW&ldwdj&0QzvmUFNs5O*Kh9w8$A6JD(M~u^uDJaMb z3`qcN50EcAI}Ul&&&S98q^e6*){?F<@s$SiyYqrlz=&zyb9;pqn{^L_4jdvkTj`dj zpgh4JD{+zUUPIh%9klhPn$Bv8aJFw&32pGhcjB7BT{zcv(`(!n;26)1H>4t|k65Eq z0nGT0MMOJTDcD)8uzxT9@Ojbq1DIGqezJ-;o);0@h#tJ|fxchp0)b=>H9u11U&QWr zgu+fI!!)#f6NQkX3a``qWMA?_M;A#usz6x}hj?4B~s?aiSV9NS1I~$10$lws( zOdJbI2Dnk<^^?(s&kKE-MWx#%c3)33LD1Wy)Xk5OF0&atDxSHDbvP8mMH94yWNUj>&f~+gXIMb|t z*d3xIpr^M7oiJ1M92T>N544hQxsAIvQRBC`c*Qc_s61n2>1~^hU;lezWG<&CyS=Aq z?#g`KGgi!p8%e4ss(j zmDpT8*ZXDHs4jemvc|Nq(Mh`>mRMW>+OH3s|F$6^eH=XtOO6UXNc^dmh8+V1<=rKB z(2D&z@T_0HdkNws zP6aV)Oiy~OwFO6!p3i)G_ABp> z@azpQY|(?Ac?R@hLK&5VUrt?=8go%I22SNRK>qNc<{@@HXN)|9h-sLzN~oHO9@0tT z8HzGmrt_omL)1__zhmCu1j}}9m%^ZR*@nH?>g21CTZi`xCD}9CfcpDI#nCJ3ZC?M2Sm0Aq%tey-)tQVu_Fui*{ z*$XH+Xee_NVi0;9FZwbf;8N`5~V0uwj^?_35Ff9&*FReZx!J`Nu7 zoL<5WU{HVn6Zs+$UiUSR$+IAUUs$ch6Z+Xc9fA5tZvVnffc&*h`mcVM~YD9C*2U-vC{P3HzP z{^O{74JP%;SrLm|GBPp{8gPKU`t<43ITF=tPjjbTCqJVc2U~mHi)}3B-qP*kF9G~* zZ9WzU@l?+;VO5oXo|8dJG~Vu4u@A3*^ov ze*Jrsg_#&rIK5DTO)WW2w1@6oc7C2i~rb z6p4-H%oHH49|0Mi*KlW;Uqe4j50$yLoYcOysSA_>NG%XDp=8c_X0Vymp!S9tn1kE9 z%!2dNBYGHoEjr|uXWuET6A`4yoTujm_(g6IYHXlo{c92d*ukzt1pgKuRbX1d>26T2 zxL_a;YSL3|qY>->&W?G{iU1gE_H7|=56B)s@uR`g9mu~?F_RPHgu_J6Lnr7hRIK9# zrlvE}%T$4{#{hB^*cEQ8Hnhfnw+nI*m^$A^&v+J>N}mL01E|pJCORz?R#jAMH7N9Y z*z8M3>Ut$<5DDbO6_^D9|AEW)FMq{Hj~Bf)F{-_es{||dBYuY$-hWTpUY_5%#K)-& zc3ucuXn%4?$K#aL6!X5!6F6vVn7D+$Zy&tuJ}(JEL-egkEjaO0>wSybqDH-qH=B5w!KL-rAM~GRwgo*KXr3 zY5)))@QH*ru!(oKc=tONY$~TPPQX~In5suQHQBVQ$=HWzGyvRt;f04y*8}?4Y>B-& zn}H9Z$k^CcfMM93pMM*`IBL%Va8}|{^#j;S+uQ3Q0XrV+br>1q83_*w!-+ zKE5v##r5}fP|UY*oMPN{6Z}r$!SR^@x>6Xd{qn`JqtQsaWb&ri?hw*_Y)S%El`~=5 z-VHKAGMmmexGcE03s0!Vc@60961sTTC%bqp`d8Fgg38xZEgZ4@k(}HZlv*-5b#q6^ zgMEy_h^IyZRQwod2xxf0W2hJJrnRM@rmC7*kSPPA2AO?o8O;FiQ|p}tvKt9Pif)zl z;mBSF16k#lgT~}0sTOmB;0R|C){a5Em!YcxNweT{I`KIuU7!Les5Y3Em&`#dfA?Se zr{nOEDE^7QxxMPQUM3(W%D>T(zXw&55=Z;c!9U$1n%z+etyG%XOBg~tZdFKPZ_~In zPNa8c74VATzAErjNA~mJ^leTa4mA^#@S`VRt7)4Tbar*Y<^u508CXUJ1~Qo+Tn0xn zs+*a;9v?qyekY5lrp?G0Q$kafmEM=9Du&ChF z(a}+HR}8jyXebLHv&h86#~^<@6C_yznAP`WTleVaCVHx@!6rcswAQ3nZ=I~ zyqdOlPGjRSljOAL%cFA4H=I6cAcYC!yK}!G@llI+t=R)zeT#Tt*Rvig`9RB30C_e5 z$liN*uz?lI3RQ%}`)5|ABsLWj+K(INmh5Zaa?)Zc`&GL`%7aR@@d246ea3-HKYjqK z8d!!himTQ>>e9fH=^4Fy9;`-E!wj|;K)4`gtnBxeVGb`l=KwOsqrKK{$xFCvC&WLS zeSa6oiN^`?NrIlc@dnO6wknqDMf5hTp{j`kb(Bo$U_Xx1T(!2g?jf@7JcN^a$A(rF z;|8-6Gl4ev8^mM37!e6wv&637YQCoT+m7c+@5pcLdvMCE_nnS}RlT)2JQ|@+c69sH z&t`0Q4AZkRm30e<*X`W3{ij>S^a0Qdq9xx!fq?c3mJb3Lu#3k~vx&i6o}IC$XWcF< z;n%^NWTzUntpqSVf?GsBvPJSQlH3$jd_?eXAg@5VsG;G$alS!%H(S3YNXe+qgzW;d z0~Z9?r64z)ke+=V{v?3|RLvlBce8a?_oj+xsQMB)|Ml>1?4d8eLF~mv1yU!-2-i%% zpuq$B+J9{X%LJvxfn-o?rH;wG*m825a=H7-8c{{>+U|FTe^#ujo)ht{+*6ZcCZcs4n_e=6Vg?;Pz{>N z(@t9R^YhA`iFfZy>n%Z#|K_2CYI#1O(2H>I<*Q%iVL`COP4F_@7~C7VtjHA(XUxrz zinZ<}UXPN4a}!}}GY2)@3D{&%GIP+rcXmT3M@3W9EJ1%^@8$1s^D$LZC{+5w-`)q# zU5}BcFio)qGd+CrC-VQTx~}?`(4w5YJQhW2sB-ExC`yv?+c{4 zOAlUpAVXrZ93*9=IUgevVTaZCPZI_d1p?>vLXy-xsL|L(a2$B`=Rs@$=N-F1hY=JY z5|zo;E?tQDOY7IuntmDsnOnSYaPnW5xA+;$8(d-G;s=WI4@c3`eSy$tNngjGCi`!d zBH64Y7$`-_a;W_19r~vN92dLC!8V4k#Vd>ZBW$6PkwDYA{BOk}Ez1)n*JGb0M(@y` zVM=byGXy1p;GT}spGib{1AF_@1wxB=$-Y?d}VB>E9PbRwHhDoUi4~Q*~r3IK@dF+}>;&YFW@E#eS|Y_k&!B zG<%es^85awl7Z5ukw{XKP+z;&M$U<$4b~6rekL#FJBRn_-@v>*4_jP+u2J9qr^;rw z@4@(Y5I@Tu*6v8OyL?YWvl3dJIUY1zsVDDegM)FY!QW}ly=eaFc$M0yH;C(1u=_E? zhW)B|=*I(RX%BP$WXq1dVKQ5ZM;E)&So09@H)oHj{w#t^L=-ykeIU^U{`?H-4!~2T z0wPylkvJ;yj^jZZn#2`Sq{P;uP`IRD*aH?G$WWyNXV3lh7%qd9XHHxPukhe2L(~B@ z*n9*7KaK8G`p=c`7_f{~zV)+2(vLI%x_<^xhA7mN`Ti4aU;&OIxa;R5;c{3|QDYf- z67=<6!yY3|h%{TN`Woi{{f6fEH>fPKtdij0Gy1s(@QjuU;3BavVCYr3@O#ewGxRd2 zNLp_=J6+;ns0#|4rAC zl7o3CLuz@X0LfjF{_n47|8rOCh4VlV;bJ0#B@WQg9tEU#L z9viHT~ztb9p36{bUP3DOX2O zJ1EMw3?rS@U|2r~3?mtMuOo(Tk4Ar1pOPL$T0&AD$1bVdvx@N#AHe~UBqE8AJOqF8 z5$!KN@_tw-r?(f<1dgyaXC*D-?~MV{BXuH8N=)DqXKD-hB@k)6N-E^GR!ee6V}wIL z2VNp^P{XfE^e*wh{b@Prn8%?V!8`{k=uYJYP+UCt=_Li7`h(sA3xk%Ns?p3W1O|)H zqh;jmbW~IQO7ZFHv6qf>?>j=IW1gB0OWeD6kG-iowyBBWprlSP~pjZcSf&1IsDyOBp(V25OzAzOL=7BB>R;sLGq+~ z&XDdAD)(`?WcKVjc)z9nf8QU8Bhwu|FUNMqm_#kwn#^xYBNxwbGqpIA_3X77UJO1r zND?mRNKXnj8`CT~Wc!zAS544J>YI3xrw3-bS5 z784ONE=|Ad!H?d;mEQk*{aija?b{JJvMlh(`xkG_lZHb5&rlkvYVJP~C2=e@i759! z`CJkqJNxFxThge6;8C4^Ll?M6CdXEP^Z$AWgPI2o^>BHSXqrNt`+X;PksuP0(p5@r zu}Z}ce~iY-9{L2nq;dN1K)nx7QXih={?Rl;Xu+RooS|;SQ#Z~KRu3m1>9-8QUVnN{ zpr2Bw4j&rp+;3^=4qI_oKm6hgsv{fw?|4pK4KN|6nk0V+=;^2bTNeJ( zTiO|A)a(xIf{vPh22FG!8-{eJ;yzDKPTu%mlR<8Dl{{>LBP6XuC)@O#z-1wvy)YBs zNu7RP#&$6Qy1hGYH}ecGr+B$lrL5p>sHhJgZ023#M0X(9y4m=pWkZaXv0&VHxMvmF zpesQ-OX&kin&poa6j+?#gDmb}ICU(&?CX^TiNDYzXo(1{H*zB7+n2ZN-Lmr75tbM7YEYM3&fm6$y1>|vZW={ zM9Rn@I62lc`W8al@sVs(5G_rM%B)&w5nD=H#nU8d_~eGq@FFN!k9qE+b)!b!$SGK3 z;g65$fn@_p*qkd7%{t>ZJ^q}T;+@iOsT|Vvagxn1M2|{{*|{+C@coqJ?zBa*t(7fm z$2~v>WxZC0jTE{2BcfcArAWacxgTgB}vSue-W9GUMMDBXECDbW9wy#{>s^SXnz4B4S* z#Pbr>wEp^w)=gGzk~^I3ys!Lo4jy>nKPyC<8TwbIH23Q~wj1fs>korM7FA_Jx)xJD zzL0hn3ZHaTzjcuO;DPY%oq_zpq;ICr?S8g}0|Tx-v!FP1ci^ zGSmyY1G#P0!OS7XFFlvR(_g0Ocl0lGBN9ub;IdDv&2ePtKYb)dUPjuUvuW zsMx>)1Mu;$>q+}{OTMR2Xsz|trm6RAZnA(ceq{9Na6*ZeX`_hvi*6MDn6GiyT>M)W zO)e>H;99y;<#oam3=+qmO73ixJfp1}{AKo~ER+M^%Y}QLr5>Btj$wAwmkMb&+Go0Q(K$T>#f)JwF&Z;lprvY@aIr>$xY(3)8m5H- zk_^`v%{JRB?oS4rvpkkxl;!08&vDUge%SYE9bD1_F&b1!SQcXSSy~~0- z718t=Drqck%;1Z6Y9JJ5zd_T8hI$QRaCath-_88XUhE3T);fR$jEpaz;GsSWsk|%> zQ_ytvmJqb)+uw5k?}IPAdvbR5B=#%iz~K`Y3})8di_I~@AeG{-n1^%M>4!|9*~<>I zb3kPZ7}18qIf0nyvd}HBi#ec)eZe5*)HFTEsjGv>`;1&#rix;!Zo$jT1k^8(>{8ft z_Z)dxj(vmShFyvP*&+uQuLrBSwMOZXo4dbqh}j;=KOrscnRiBo9Ncv&fNTZ$k@eE< znchGw3t(7NUh30VuU_qb$lBUfI>JMN+$!ZmkK`IadMW2`iud$ni#(~Ww+#b3r?@on zqN1Ygr!D&RFLQZZV*KS7+lOO#6B1e-z$+N||1k@II)V;e1bW;EmV1wyTX@wKQW$fa zq^bBF(i*SN?)+<1QMK0T&)xk24`aD^_q?4KH&ho-zV$V#^_7q2UobX#hWBrBeemGH z_8PzuYpG=?S22)enZ&8b8}WyD6P?p4IIENHAZ&$jGO`?lM+Skoe5P34FAIUa?H%<~ z+}O4utKlX1E0Drprl?m%H8?Gey(uo_>HMDqR>=Nt%j@s%j?3zP`m8QLw(7{@;h{U0 zgC&v%h~mfkHj6PO(5_QB9rw1-^hA$|fj+!prIlquB%64i#r2ZqM}$nOhO}IeUWwQ) z%Iz#XP11kfeThF0;~)R3Gv1YhFcH}Y2ZDe#P#xO&qt83?lG#z+Z0j{GUWJ6|mQwWb zvu`*Ady{ypHx*v&icHnlW~wa|nPUdZ-a&cF2?p`^a@m@|9(hOqxc2^17@H8YNl?-Z zkoPk|BM|8$sdz`wx(+v)69J){9@tL1|M2XLx+fHzZc$NEj%^w znx0Y-MUYNuxamt$;-I?k^71tHBwR* z-;!RIe~)w~JlR)GYp;Bnjgbx+d!ew9$y*-M|GW;Y|C2^|yH_oq{sxN@nmQ;_>+iOi z)rAJu$ex8*MgdD@=Z&1QwtPYSokBPJkV`oZ2gcHObie95AAk`G?++h;67LBxh`4eS zHA5yH&&ept^Zj`V8QFNEw06PUU6H)bS?o-6U*pW)MA)Zb)u9*n zgBOLDtFB!$)o=upsjpkyb7n3f9Xsk>9B^^f_}@d0dXpr~YsBW0F-ZWDjbFf=sb zNs|oRB^+^B4Va={9@V_qS7PPIvFcuRxw&naHZs43k&`kedt8K^?F^VyO!lIXHUpd! z&%g-e0Myu&9n-tQOXjqDiRK?4qsD(@npS-$UhrS1rM;7svG1?Ci~ zJ^a={{-kc|c1L0xiMy|(fm^cfYap2ENHNF;{2a|`KmxOC%`wnrjyKppXC-<|T^7p7 z;nd-=+4oTvMjq^L z&g*|VvM;tCvHeXS-W2oifMYi~+0zP~pPXVy<%6)(d~h#p{GQv~J>VwWY^|$Solh$M zCOtaQE|0OqfBM@>BzY|p2S-yxw8W{~%c7r*k`A1E)1DVDmbJ9H)v6Dd;*cH8?E{ye_F@9&@A^>|Rux$pa0ukn06U)Ocr#5{TH zK{T|RMNucy%Zs$dvg<;$-bARNLSD4Ccz&*Jdciv`FIVP8K`|G6dti#o9}YJ zFlOZQ1P@%CRI?@DwP7V7+(_dfd}^@2V42i2_Ki91NuKY&t^7O{*Nqv~rO|$zX-+Ep z;HYsa_A0MhnazU;lGc>d%jHG`%te8OWdoD~HDKRxB4%jc9re+8&k``e4V{OsC2vA- z8|{SOH~JJ^>)*!+SZ5j&IzKofU0Gh#f>F%7*D>S+#jC3IP`ld`6o9j<3P4P_8MmS* zYiZjCm}hn7bo{gF3Bza9PaDjK|CDIj)pk!>I(gpFX?93;!g~82cPS32i|G_-n1{rO zWZ#XTXYa%AS6ickue>h!iw<3=4sXU^Zq%xY<7qp-<&N6r!#iT0q*!N}cB$gj^uYq6 zO@Dt3diO<^m}eVxPcizoGL6;0PkQ2NolTV7Ftq5kn1+wX1ICXp8E(J!WPV)ZLwL9% zk2M5aEY>yjl&dIfjbUfqfF@>m#DwP8#jx)X_S&JxPALx3oyajX*P+oyFIz94<#{g> zd6S%Z=qdGj>4puTSFi3rGj2^8cZmz;H)aC90?NrNC<_5YCiL~C@JmmLXQQX#( zbEdYxbF6ir85M(<9rJsq(6_nHPIZdlIHF7aho6nz1& z;6tgw%U}d=|4&ANmjzkDusDtSUNLPMYlwtZGa|Py1@Y?XoEAIEwQ}mq$WiL#KWn#k+yBDE#L(Fzg^I{6Ip;qb- z%5JUTG}Etr8BxS(9-7HSuWft2fqQYnUps|f!Qk5bdqNocJ%;_oHB;5$Q0uyu>HZ?a z)&$#&7cT5sRE1*?ZXYmA5p%&N+?Kxim$sL z-9vagv_N&G7W@hFNY*HN8ujKa{@y*SpUxWaIJZppyKIcU2H$fKnqSi|8Nils0UF(u z|MmI|1ObLySi6ulb_yphsA8^LAx>ZDn+aF zaY(XOzS$1iVz}o<7{gbew|6tN`Kp9oJh>e^`P~;f_q!DplYh#|ss8@{;nsL_B|ccz zSbyKOu||chYGOVl?;7TOwpIT{yby&O-l9l;U#InL(mifKZNbHWkfN4-Gey?rKCF}X zFhUpne15t?rHvqM9os(MeW#CxD@@-^yX*~`W4J9NVkhWbK79D|W?3ZlG9>0Rj3~hu z%dxDT8nK$5cfCmxoB{%Jk4Yb6;0=6F5^>78_r!{{2Hy$Yx63DfphW(jS#(xS z*TY*`%^8pi)g46^FJ78MLp8nh%3+&}*E^z-qujxXQa;H>M4{%ic&gmuZ`P~Bs$v} zQ{?Tk2xkzIGB?&)<`S;#V7|m92jpG(;Z zuj8UG&T0Q0{q5UbG;}j=GkJLO;7VlPjgu!+2%IT|#BOyT0I%%%#N@g#VWVO)_iKB^wp6p2xI9b!L9}XOL#wTORxg0{;WYX-65y=|!RX83z%p za}{siT90sF9xK#)(sEPl3>4Uf;!uifBMSJZNywh_p#vnVL_$*Y?7V*U;LJ~3Q-gMq zaA%o_)tjZYMFES>V%*A;QF=8C5unajRM?opxz)0VS83MF=C1y@+Fv=CX*Y&V4?=t1 zLbtAqKsX7+s?;IGZTilWt*OgI_<m$!US zURz5s7^rFYdHecz_%iDir#>b!=THW+!Ghnk zQ$f_&;agOiM!p@VuyAbWR87tPOp}f;ZN|L3s$l;HvlkB=!tB{_sT~vt=u%nixNk5CH|E743N|72aPM@ zIX>ah6#^&gwp_UsEXhWI`_4y=7N0ibJLaf;WnS?!1xm4n(ZG~~p&6N7TKle0;VTH=>9 zpUqwUlBQQHgkK@W>%j}bsV)%O6oM%i@O;nsIfel_TtBni@DXqA4=pY+!bOG zaz8a8-ZpCw`0yvewuYELZvY0XGsn`uExGG+XsE_LIr~J%89gQu12=EM0{eFJui_42 zuaVk^R#uNn#g**rybEEG^fmL21k*0Nir?Q7!35j>O=UrV!oZJZP{>aoM}kgQ!k}O-t$4B9~8#wQ!_FYdi)sTU)NtfO75Gn6$*XQ zQ-(L!N*+KcxNGJ;U(gErtrBEL6pavg@wTjp<+n$VAKeP)Y>&|Ot3I1g)bw2|wDd1r zTa_~HEO^qMT%%}rW?N{K1zx%YU_dNExO4Rd3Tf0Ec{SnfTF4YTe@3n2I4(~<7+3~U%9g@cDj z&Yn8P*`Dh>Z|Rdt5TvaBejX5SL2Ji@3p*!BqJ`%CXujx{Hq zA%`NaGgYYjZ)?x{^J)p2&Ldy>{9DhcWiHZ6WBcpA&x2~(dtG^-1wQ5=9LK@cA z5c6GY$JyiMCQ4?DUF?Tvn`M)&O=*^Gf0|?eG$KRP?!u2^KA!2A!44?6Q_^RlX&tQfH@|zCM`&7F_O%^t5V?lDSj7CJBqbx3J z+SdjIuS|+oRdz%#vpOj76irLwbkwi@-cGa~tTiHJ$%M`9T26N!@mez|os3jXv-vdc z^h@65s=X#ooCHfxTO-zNY?Zyr(eZ-fRu&x>r)*v@d5nL2Tu^A<*E`74!&}PJAQs~$A8=kSFHZ? znvU(!gmskb%JQ1#V>>(9nsSzgwev)qzDzhm^w5XEU{%Y4&)*(uxh~?uu>-qYC=~lE zVas;|JwvpoK8J-pVs72uo+GKllf$-tvox&>B;gw@eM>(ugq=^=aa* z$16lHW}kzD=~@@=pEGQj(r@WFkwDF#ScOJ3r@oYH&Y!4#XAt%~Tt0k;gBq= zrtwS)JGWZlt-(-%n>^H!qEq!Ms;UWH69sZRcGDv9>5EE!N4b>0c9|7P?bsa=qouT> zIJn5_6Wf^zMEB}4IYel@^l9+w>gdJVqSWVQgKDD`qba%jtw_UrAqenMFg852E%t9d zt#9Jh4CbCa4kH>Y_PyU!Ly*k1L8l>K4!(uIBX6>0ZAA+=pg#4l0102V-9ijkx%J`n z)0LWL(!5PEFX%e4lCzs1y2ca{Umm^_-G*BC2)DjnIB{)j2 z5#gWS^NL^9u@;g{U*fK4xEk=a<-=iGW+4e{Jve%l&E@2PwYg_W zJ!;O__isdB7Q{FT@*Et1#=1dEm4P$LW^)hS5-Wm<8`Kh%hj8dvqjQjkD~>f>G&g~M${WWWH)GX;QUH28ksgX6f0erTeGOjgw8L*WX!>sw0L^00`; zeC$FYt~05Aex4*?w9uhbvQ!|#>T@Z7rSp9-;zl?3eNC+KYohsIBM{HE84gX(WLWhl zd>cfYiWX&3p-b*fp9s-s$`!Rm{bZxLA-t?422Yr?QZxk+AF*!POmfVn>4zTbe$* ze15Rjl#X)V*=jk`5Y;}G{9|7oEjAejY>hfkVJcTGTD2Dy>+krS2}WARb%E98@`x$7 z>SS(A(M+&e?r+T6O zPBbrCQjQI`dRD5_4IL0lBhk}qbfxRliB2~V>FY%yIC7b9<=|Tbn^L^A0qB0%x^Fj0 zmtimCMh%UJC(U^N<3aD^@mZ#-G%hpqBj$yNX7ldz6h4F(4XfDY<9n5Xoq=;iDme_g z+pjQPU)qi%eM_z4XLIFK5~mjM^@bEj3Yk_&V}~Q;E^>0F_bLz8xetNMQw*vLdoiA{ z91#>tUNYv`#WFFz%(@5bJh~VK6Y1WP)bSsIakjQ}_c}r9VGY4?b+4k?i#YY%gera# zk7|;mmUHxDS+P?|5g>WUHPp)qnN6lv)zrM_mPB~&eW;&*El!o6@1X`=Bz8OY~Sq~)tPO~Jmt>&(Q#w-Ujqu&;_c_D?8EW#Odohz_)(fhMk5Got7t5bIa z1{$h_?8$Lbtc4r~rr?frzD)<`63wWC(fSE|Yl?OwwFFLH-l)zgu&I@UGf#w9YqR%J zR^MH3g_korD<>5t)pn2SOM>5fjKq06fZ{uIX{=Oi(I<#Y512$-KbYYO! z4rz_BIpCe?@=>n)-_EXa48Lb=^ND$LK1wZE?~>mQS`&F^4aPnVYWk5T=o}0EWkqB; z!Y}8vS*vE5M246bTr(I$0+f38JE9EZdU4a9o)+o+_Vn?CvZ@-Bc;0#u{y&Tr@ahJG zKNXSk{BmZHY2?*&{@VM@yj17p)H_z&z;l{d`HH~^%gzf|KFzm0mi=q7`^sP_ZXb`J zz_|_X<6nd|ykGIgRw5W9p$iI&jED@5roT3%k|X*%@>PVhac$%PaWYtH+tplKElz2` zeMxpEW1Y72I01!Ny6d@h)=Lyok)f&DkSqn^xvB2@L>A$txI(gRd*mtHU=nZrUs&g{ zJlazlq-0ZO;4H743S&-|Sa4pmA+qxu`e_b2q5{S%OSgLPyLTAUajM=PWYyiKXJJaG z-!4CqMJrR!w89$oHtS{QOs&A%XIEwQ^zPF#+ucJUz@x{H=O%WJzHt~|S=nCuiB~`` z|Ja!;qwVyaE&|zII83KoaOd=ll zLfUXYgv9yJMw>8pswQ)CU2LifNX#%<+{>+!_kiT8ME(8Bb_DS;z(_F7#2O0gO1ygoEVLg-9myGss?&^I|YULBbc6@4f0 zGQxiRJc`dV`$Ddn?t#OJ;Jv^7NYkUo{MbJh>vU5eXpDdTpg+-!&a!o*_wbtrI88LY zjSWpo+E2@ZwQ5I);E^A{QOm>H(8bh(o(j9^+IpUbFL%U^i`~uuT=3MN@4=r6Bk=vr zxbiv*qE0l%2pb&hN#}^!kcmyB6NMy6UwN3xD|j#tZ;fVxBG>6gi6ronKvl_m`D#7< zd=^;7G+oZw89&{nRrjB0R2D`ESaO!HRSU5*?K*!Jgkt8ZYSv$d1;BpLh_242^N@%2 zwe~x?1eh+kJia?f_ZcFQRwo88ucbZKZxCIq==4Dlqnpb#nqUjNVH zf%wQz&gFF`nWoJ`e=PqQgep^F-WjrnHSbkbgNpZk{fSmuW#`(_Tx2eA?8J~aszeED?CM>i+NuH{DK*p9A$%ezs}5! z?ir&c_$ueyY1|#W9@@xn!rAhABE7$7-R)bn_BwMUL))Y)p5oQa5;y|S=;wm~CkG>{ahG$QDGnX9Wa zP3Tv)ebR86`ca=bJMmkNEyr`3WepcK_PapJB;T0U})iYY~lvK0j9 z>B_+?pO*V_BYk)WOMEEBw|!VLmigfU+Ljx%q@cjzhW~hLcSrykSaJg8zi!~$@lHOH z@A7V}Igl6Mr&QL|z?&#;_vIxoy+2+yp7DG7=kT_-7M~Uuu_EE$Sou0KITx6x($j7& zhuV$rAFKV{Z)La3oU6{@xaOHF8*RlD=K+_0)OGD;kE8wT9^lU4zzL6zcCgv;_B|o- z!@L7FF=Q z`4AOBN3SIrv$~940F=Qn){!odkPDW|ZFk9fT5;c?cN*)@s<7_?(=X2eHZECD=ySIjJ=jDUA(;PVY>FBcY{6|> z(m&KpU;2=H#B9f)mf{~y#pI@iw{>)jq-5i1;)^@M^FNi2EP|aw_@Nta9uXdgjX`C8=rQlEDpqV*$is2HSo$& zMSB<7oQI}720-l>nH;)@vG$#uLIrXu9)l>3VcNMBY(`eGpn1M5l)1an?Xpa~1x!5> z@;TFZ&EeImMTY}Gk$I++H6T+g)iqXhpYKHOKAk93x1H$8>>(U7_MBWa>qz7Nv-_7! zh_O+HDI4@$z~lpIBIxO{Q(*+w5B>3=qs9ZYUp*M#9%9_6Xe ze7_QDx9MuYD|>HKlVCn+0jE8dzflr(`;STZN|LyuHty$%w79d?(vAc>A^^sxg4B=r zFY-j#;0K%+EFYAiev!fNA6jPkTM+J1IsQNuy57wWUGH|I8>f~X*?9$g?b~vn#F@@T zE!Q(X<%ePeS|e7=PpFKw&%Zr75@OEy+J>qhQBR1(FB$)`j2)?=hy7oBl!iJ-%xQD! z`NIJ(Aui()YmE@#+lJ3K*Wafs7Vspp*yj_gs;d5SEG&-|VQzAS%$4v^Jt1GI{{0}@ zHnb>{ino=Y=jR7}HD);B-nw(;=Sm8NBCzj8n~snmzWF|{$y=(J3o`W2gsseTplQ0t($bXI zWKpL%qn3|vXCXCqGX;-rV*3$%->;68kHKQTd=w+O>lc|NV* z$^w1Ms(BX}eA!jqOQyKF=aalKa>&B8wg{)DJNzPb@cf0!Bk7bM&VYH}Rp%@&?#f(+ zmkD`S7t{vxN8ZH$C)Z&`(DrRfaxb{wr4b_C@Q{w2d~=|C1u+R9oFyXR;v;qw$?fZ5 znz$l)2DlR?O-sX?b((XX<%EU%QMa!Jn9`}M#iD6`bmIW{Kac!mjr^hJ`T-?j*PfjF zC>LVeHW_J^8+!3PS4(H+2n9sjwp?SLAQS_PNQ7CA#>?Fl!ot3KI^%i8^lqSBgJ*u1 zw|c{tTW5-p^XF9?;uCT+tR#TN5a_bq-iW}VPlKyxK|^f{)XegdSrs+1C6=7EoQHK0 zmzmn_VU|l5$eo$#+qW53Ht7amnR)rSHpkC~^5jr!!V^6Y@v)l(O>6%i7xS3ibV7=- zDkMJc+g;ettPDvee3`KsesO8{l*`t-nU{UAYuO54Jf&D|g@d+(-o%tc7R{thNIY$zoz>PW70lXfD2mB9Jh zmi84+cZOj5GX>C99n7U&#Wb_x_p(WL$jftU)XLA4*a(*^e^Qf!`K~;*^Oeb{w+AUw z&2qj|F{p)%ef>*Gc>pGe#?01MiyPgvC)%}2+{0L>C~FQYr{FK~7~`weS`!6# z=6hV66m-<5+}~2#|12};F{-4CYk`3_Bj){Wp=Uc$NPTl)xcyX;F?Md0zEK@`MC=+d zo)-C{f?9O6XeVDYtqOM2KrIS*AA{OXTia`E-bF*s(chw?(PGr_IjUAuQUT6qhNOxh zbmII2*CE#Qpo0PBYLYL99Tvsw$$$6J zymBFmM>yRA{XpW!sa;yVX_t7rt(tAIy%Tg2He(w0-ANaG#Mw(OKPyZ&__(;3Wfm5F zd_v}lo}Od{A%|#&U!LP+x@L2?eJ0Gg$r3w1rt~8(1|Sus(tRQxB8h($-XOFy!!UXe zV{6Y&^~W>jBZ?|aNTYHv!t7~A6f&Oth3M31N|x@X6_Tv19DPK5PZ?^ILGs2grU%jc zdIo8Jb#V%*#^ zDDSQx;hI!OR3(~agJj9ycU`&1=)=Y#Ewq~RpJ3h@Zdz6w#N+|t_*ngs_{4KEEisg8 zJ`nNSo%p%AF0+OS;~=tkQMa=Gj5%x@%hcgk%kVJ5+s3EVXP*l@FdV1lx}@sQRv6nR zsSOj2qNqTg#cN-HVJvxlpz)3FK3gKcQX5tiC~r!|ZF}RM*mPK2K=Am7S?80*A!^x8 ze^2!pnQT9Rl}Y5%u=(wHZ%?1tL8d}1vl0q3>dML#vNK58 zM)f%`Qa}Cmaeb4|+aQJOc3=xB3sE$77Il!2V{=_m0l3{(H+ljXjpS=MwRqsn$xadx z{{ocH=eq1iTUrRDK!Vz%5l7R`jHXw8b-DtrLWd6r#C@*dlr|z>)sRJ`N(_T>_YLFa z&;=x%O3A*Y2?3|;{IDM8K1YN|&UfODL}}O>lW)E6th5ZV(n@GlkEil5qyt|kug#d+ zh6jE66gfH?nu9yjGR5XNWTpY;3jXkggNZNl6e;_CXykfwLAq_h9AJ0xUcLHoobMT_ zGUx7dbOpW#UDOeYFGr%HjMmpH8lq_+?KjC9!imO&I(m%}3&EB=Tg4i}^P`Z>kMbcW z!jJLXqi1C`^#a$gOLK%dsFxDlInPAtD&+6kO4mFL0`qTE`S-qAa!WSI)g|LqQ8|b# zD1~C|2i!}Nb-afYU8ze$L0XCiBW=i7Rdsa`VT9kw5Ec&LRCN>d>&?ip#I2+H<_UEX z*Cb7FQUIR5sN(eNS%YmB&!S|nQBT1q)E$}S_w{_dwmqL{COS9d0!ItZdMJ{c!E-?CgQei8&~$|u`g5e*%3Ac|g?JanVF%pLFZX@|$(9E;IhIV9C_57I$$l9O*F#yFSVX0;qxtVccNhcrd5!vZ(+Pr;;Ay_f@Yp zm^|%y$Y!y0&(iQ{N6RXB}cybq3b3-4R6>uQq5m{Ik&~)yg+CRD_ILpnnUK zTT;>k4Y8?bc+oKzV0)zeTB4)`yo8)`LS@}Ms&BtAZYnjMV`%v61n_dIxh9c;$Xebb zsS`c-hlhvx!$<7$Z6}EE?yVr%yn#Hm)8R9XQsb?eNWqt~C10v{1NuXq?}?0tcNN(t zDw4Yw-)|TbCicyRH*D?Oa$;ni(8Zzu?(sw0=eGL`&`?VyrBmqZEkh5)c4iu%3Gt#q zA~EdVXzz2rm%ny)t-tLg!LJ1fk#@KsqeX$1N$_L>3VPjkqlqUJh>L&QVG)2tCAJjY zMR#V7{M&i>UxQnY`X$@(((wRHQY82Rc@2{1nkXvPWOVx$x~&v#;Y!j);UGWYNdk7D z`~!yR-2s+Plr67HO{%HMsU^UmnRaJHSEa_t1ecnk3+6V;=TzV(-gk`!miKuMEgcx^ zDsx6xhPm}`%*#sgf#OH7&bG3$GOB7F9?+KcAL1B-nI)SRBKS!KeC-xW0`^G}e_#ZO zgjn#vavr$pir*Hcy6caNM)5VuRK}?{-yDR7mY?4Ou$v9Jfgfqat4R1~#%NVs zwHpisth8}6r3t&S<#ac1SpSET3}%X61G@Lzs{}r|5v7a3uw2jGWgRsq`&4anCvN6H zl+WhP%_qbc+C7qmDIX5$6ru~xi~Y7zPEuoGKmH>m+ddm$Rbh8(_r}*|-eNWhK zrNHp{r$}8cXO@|bT$Fy_`xAbr-Iq^4VyIMp&h_T&SLd|DZ!8a|-D~@ikW*UWS@ot* zIj!36j;DC3=hz1wT-Ke7ez?23{-;F)xqSCBN{7;4I54kU(IJTNiV|<=;y*9N=I0ZGu~Xt}`+EBiV=pz#iw&|+m(QvM#=$LF4fwOq4y%u_y&0*2&Y~A*Yk23cl<~c#SNz-p2@bat+ z8PP*2Pxs&EAJIGFt@?j1Yl?GXIpHrTH*ThJk#Y?!&hpQe*^I7gT0J&0+m&A=M@2U$ z{IY2B?c(z4v6Bw$zYVjZcN4GZ>ER(#A0>WyCkkPqq{nr!jXFD1_$36BBDejjaXNf` z(GH1FyokOPLGO0s45F5%-V-YMZuQyO>gid)_37Hl^2Eg)0<-#j>c%r}T&LL4V(R&g zUX8z+j{7=XS1yYgP`vEC-2zK2-;Q~B^iDmz5#DhonUr8Q8?+sZU;QPD!RWRnX)$AZ zT$Ic=o}z7M<3#oFh$`FYYz~b_HlC(eGdJ>g7n?9O$S_g;`1y(aQ~cR(t0&)D zEb(B9-(AGI-cRAtiZ~#%n}a@$OOAI3<}#;Ukq2qm@t+4s+Y^lcmf3+6KTyG|!m!;8 zEI(QOrsu$DJgMH!ELbz~3H*VI|4zhR{GzQ@1PW3Qa6f1!rc{4>696B0yUtC%*h&5|of zQfyKVO=QHMy?0*5KThkqO6MM=I8;F;Tq-5v&N0}7`0**sPZKmvow0T?A@ahF1%|~n(vtNJv