From 25ed765a036215ac43bda5adb57c7714d4fbe3fd Mon Sep 17 00:00:00 2001 From: Bernd Steckmeister Date: Fri, 3 Jul 2026 05:47:18 +0200 Subject: [PATCH] =?UTF-8?q?wip:=20Sicherungs-Commit=20aller=20=C3=84nderun?= =?UTF-8?q?gen=20seit=20April=20+=20Arbeitsstruktur=20(CLAUDE.md,=20ROADMA?= =?UTF-8?q?P.md,=20PROGRESS.md,=20Autopilot)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 6 Wochen uncommittete Arbeit (Voice-Channels, LiveKit-Manager, Settings-Modal u.v.m.) als ein WIP-Commit gesichert, damit nichts verloren geht und der Pi den aktuellen Stand klonen kann. Thematische Aufarbeitung: siehe ROADMAP M0. Co-Authored-By: Claude Fable 5 Claude-Session: https://claude.ai/code/session_01CPrAGBxBT6GfPXzeWQ4AXb --- .claude/settings.json | 16 + .claude/worktrees/reverent-wilson-b7c43a | 1 + .gitignore | 1 + CHANGELOG.md | 53 + CHANGES.md | 1080 ++++ CLAUDE.md | 70 + PROGRESS.md | 33 + PROTOKOLL.md | 386 ++ ROADMAP.md | 96 + analysis_options.yaml | 5 + android/app/build.gradle.kts | 51 +- android/app/google-services.json | 29 + android/app/proguard-rules.pro | 18 + android/app/src/main/AndroidManifest.xml | 76 +- .../kotlin/chat/pyramid/pyramid/BgEngine.kt | 140 + .../chat/pyramid/pyramid/MainActivity.kt | 265 +- .../pyramid/pyramid/NotificationHelper.kt | 107 + .../chat/pyramid/pyramid/PushService.kt | 160 + .../chat/pyramid/pyramid/ReplyReceiver.kt | 84 + .../res/drawable/ic_launcher_foreground.xml | 54 + .../src/main/res/drawable/ic_notification.xml | 15 + .../res/mipmap-anydpi-v26/ic_launcher.xml | 5 + .../src/main/res/mipmap-hdpi/ic_launcher.png | Bin 544 -> 2670 bytes .../src/main/res/mipmap-mdpi/ic_launcher.png | Bin 442 -> 1875 bytes .../src/main/res/mipmap-xhdpi/ic_launcher.png | Bin 721 -> 3572 bytes .../main/res/mipmap-xxhdpi/ic_launcher.png | Bin 1031 -> 5521 bytes .../main/res/mipmap-xxxhdpi/ic_launcher.png | Bin 1443 -> 8024 bytes .../app/src/main/res/values-night/styles.xml | 6 + android/app/src/main/res/values/colors.xml | 4 + android/app/src/main/res/values/styles.xml | 8 + .../gradle/wrapper/gradle-wrapper.properties | 2 +- android/settings.gradle.kts | 1 + assets/fonts/Inter-Bold.ttf | Bin 0 -> 420428 bytes assets/fonts/Inter-ExtraBold.ttf | Bin 0 -> 421796 bytes assets/fonts/Inter-Italic.ttf | Bin 0 -> 417388 bytes assets/fonts/Inter-Medium.ttf | Bin 0 -> 417300 bytes assets/fonts/Inter-Regular.ttf | Bin 0 -> 411640 bytes assets/fonts/Inter-SemiBold.ttf | Bin 0 -> 419744 bytes assets/logo.png | Bin 0 -> 35212 bytes assets/logo.svg | 20 + assets/notification_badge.png | Bin 0 -> 321 bytes assets/pyramid-loader.json | 1 + assets/pyramid-loader.svg | 4 + autopilot.ps1 | 25 + autopilot.sh | 19 + docs/NOTIFICATIONS.md | 136 + docs/PROGRESS.md | 43 + docs/feature-checklist.md | 482 +- docs/matrix-sdk/01-auth.md | 241 + docs/matrix-sdk/02-rooms.md | 436 ++ docs/matrix-sdk/03-messages.md | 463 ++ docs/matrix-sdk/04-dm.md | 221 + docs/matrix-sdk/05-media.md | 355 ++ docs/matrix-sdk/06-encryption.md | 313 + docs/matrix-sdk/07-push.md | 291 + docs/matrix-sdk/08-voip.md | 422 ++ docs/matrix-sdk/08b-livekit-streaming.md | 1487 +++++ docs/matrix-sdk/09-profile.md | 264 + docs/matrix-sdk/10-room-admin.md | 410 ++ docs/matrix-sdk/11-search.md | 238 + docs/matrix-sdk/12-quick-reference.md | 366 ++ .../13-server-admin-continuwuity.md | 437 ++ docs/matrix-sdk/CHECKLIST.md | 433 ++ docs/matrix-sdk/README.md | 122 + docs/server-incident-2026-05-31.md | 87 + flutter_launcher_icons.yaml | 12 + ios/Runner.xcodeproj/project.pbxproj | 4 +- .../Icon-App-1024x1024@1x.png | Bin 10932 -> 94762 bytes .../AppIcon.appiconset/Icon-App-20x20@1x.png | Bin 295 -> 971 bytes .../AppIcon.appiconset/Icon-App-20x20@2x.png | Bin 406 -> 1562 bytes .../AppIcon.appiconset/Icon-App-20x20@3x.png | Bin 450 -> 2191 bytes .../AppIcon.appiconset/Icon-App-29x29@1x.png | Bin 282 -> 1253 bytes .../AppIcon.appiconset/Icon-App-29x29@2x.png | Bin 462 -> 2175 bytes .../AppIcon.appiconset/Icon-App-29x29@3x.png | Bin 704 -> 3191 bytes .../AppIcon.appiconset/Icon-App-40x40@1x.png | Bin 406 -> 1562 bytes .../AppIcon.appiconset/Icon-App-40x40@2x.png | Bin 586 -> 3099 bytes .../AppIcon.appiconset/Icon-App-40x40@3x.png | Bin 862 -> 4441 bytes .../AppIcon.appiconset/Icon-App-50x50@1x.png | Bin 0 -> 1808 bytes .../AppIcon.appiconset/Icon-App-50x50@2x.png | Bin 0 -> 3388 bytes .../AppIcon.appiconset/Icon-App-57x57@1x.png | Bin 0 -> 2121 bytes .../AppIcon.appiconset/Icon-App-57x57@2x.png | Bin 0 -> 4351 bytes .../AppIcon.appiconset/Icon-App-60x60@2x.png | Bin 862 -> 4441 bytes .../AppIcon.appiconset/Icon-App-60x60@3x.png | Bin 1674 -> 7276 bytes .../AppIcon.appiconset/Icon-App-72x72@1x.png | Bin 0 -> 2670 bytes .../AppIcon.appiconset/Icon-App-72x72@2x.png | Bin 0 -> 5521 bytes .../AppIcon.appiconset/Icon-App-76x76@1x.png | Bin 762 -> 3094 bytes .../AppIcon.appiconset/Icon-App-76x76@2x.png | Bin 1226 -> 6069 bytes .../Icon-App-83.5x83.5@2x.png | Bin 1418 -> 5818 bytes lib/core/app.dart | 110 +- lib/core/app_state.dart | 207 + lib/core/background_push.dart | 402 ++ lib/core/e2ee_diagnostics.dart | 83 + lib/core/fcm_push_service.dart | 183 + lib/core/ice_servers.dart | 65 + lib/core/livekit_call_manager.dart | 606 ++ lib/core/livekit_token.dart | 37 + lib/core/matrix_client.dart | 63 +- lib/core/media_cache.dart | 139 + lib/core/notification_service.dart | 660 ++ lib/core/router.dart | 29 +- lib/core/settings_prefs.dart | 136 + lib/core/theme.dart | 159 +- lib/core/update_checker.dart | 96 +- lib/core/voip_manager.dart | 536 ++ lib/features/auth/bootstrap_dialog.dart | 534 ++ lib/features/auth/login_notifier.dart | 6 + lib/features/call/mini_call_widget.dart | 470 ++ lib/features/call/voice_channel.dart | 1123 ++++ lib/features/chat/attachment_dialog.dart | 328 + lib/features/chat/chat_composer.dart | 630 ++ lib/features/chat/chat_input.dart | 211 - lib/features/chat/chat_page.dart | 156 - lib/features/chat/chat_provider.dart | 145 +- lib/features/chat/chat_view.dart | 2115 +++++++ lib/features/chat/document_viewer.dart | 1773 ++++++ lib/features/chat/emoji_picker.dart | 710 +++ lib/features/chat/gif_sticker_picker.dart | 696 +++ lib/features/chat/media_player.dart | 904 +++ lib/features/chat/media_viewer.dart | 255 + lib/features/chat/message_group.dart | 2780 +++++++++ lib/features/chat/pinned_messages_panel.dart | 215 + lib/features/chat/reaction_service.dart | 38 + lib/features/members/members_panel.dart | 263 + lib/features/rooms/room_list_item.dart | 148 - lib/features/rooms/rooms_page.dart | 55 - lib/features/rooms/rooms_panel.dart | 688 +- lib/features/rooms/rooms_provider.dart | 16 + lib/features/rooms/user_panel.dart | 165 + lib/features/spaces/space_admin_dialog.dart | 2278 +++++++ lib/features/spaces/spaces_rail.dart | 535 ++ lib/layout/app_shell.dart | 1073 ++++ lib/layout/panel_layout.dart | 52 - lib/layout/shell_page.dart | 19 - lib/main.dart | 32 +- lib/utils/clipboard_image.dart | 182 + lib/utils/gif_favorite_service.dart | 444 ++ lib/widgets/banner_crop_dialog.dart | 184 + lib/widgets/create_join_dialog.dart | 1047 ++++ lib/widgets/hover_region.dart | 117 + lib/widgets/mxc_image.dart | 216 +- lib/widgets/new_dm_dialog.dart | 346 ++ lib/widgets/profile_popover.dart | 442 ++ lib/widgets/pyramid_loader.dart | 202 + lib/widgets/pyramid_logo.dart | 187 + lib/widgets/screen_share_picker.dart | 233 + lib/widgets/search_modal.dart | 840 +++ lib/widgets/settings_modal.dart | 5517 +++++++++++++++++ lib/widgets/share_target_dialog.dart | 297 + lib/widgets/update_download_dialog.dart | 82 +- linux/flutter/generated_plugin_registrant.cc | 28 +- linux/flutter/generated_plugins.cmake | 7 +- loader icon/pyramid-loader.json | 1 + loader icon/pyramid-loader.svg | 53 + macos/Flutter/GeneratedPluginRegistrant.swift | 30 +- .../AppIcon.appiconset/Contents.json | 132 +- .../AppIcon.appiconset/app_icon_1024.png | Bin 102994 -> 94762 bytes .../AppIcon.appiconset/app_icon_128.png | Bin 5680 -> 4750 bytes .../AppIcon.appiconset/app_icon_16.png | Bin 520 -> 859 bytes .../AppIcon.appiconset/app_icon_256.png | Bin 14142 -> 11306 bytes .../AppIcon.appiconset/app_icon_32.png | Bin 1066 -> 1331 bytes .../AppIcon.appiconset/app_icon_512.png | Bin 36406 -> 38190 bytes .../AppIcon.appiconset/app_icon_64.png | Bin 2218 -> 2479 bytes mockup/App.jsx | 478 ++ mockup/Chat.jsx | 273 + mockup/Modals.jsx | 716 +++ mockup/Pyramid.html | 26 + mockup/Sidebar.jsx | 295 + mockup/callsystem.css | 410 ++ mockup/components.css | 808 +++ mockup/data.js | 280 + mockup/flutter_export/README.md | 136 + mockup/flutter_export/lib/example_app.dart | 159 + .../lib/pyramid_audio_player.dart | 477 ++ mockup/flutter_export/lib/pyramid_theme.dart | 76 + .../lib/pyramid_video_player.dart | 544 ++ mockup/flutter_export/pubspec.yaml | 32 + mockup/icons.jsx | 110 + mockup/modals.css | 976 +++ mockup/styles.css | 224 + pubspec.lock | 152 +- pubspec.yaml | 38 +- screenshots/Screenshot 2026-04-25 142210.png | Bin 0 -> 69069 bytes screenshots/Screenshot 2026-04-25 142406.png | Bin 0 -> 48755 bytes screenshots/Screenshot 2026-06-01 061322.png | Bin 0 -> 79281 bytes screenshots/Screenshot_20260421_051803.jpg | Bin 0 -> 150010 bytes screenshots/Screenshot_20260421_052850.jpg | Bin 0 -> 120343 bytes screenshots/Screenshot_20260421_060108.jpg | Bin 0 -> 72447 bytes screenshots/pyramid_1777119556028.jpg | Bin 0 -> 87863 bytes screenshots/pyramid_1777119787963.jpg | Bin 0 -> 72882 bytes scripts/release.ps1 | 123 +- test/widget_test.dart | 30 - .../flutter/generated_plugin_registrant.cc | 30 +- windows/flutter/generated_plugins.cmake | 10 +- windows/runner/main.cpp | 8 +- windows/runner/resources/app_icon.ico | Bin 33772 -> 1897 bytes 195 files changed, 47784 insertions(+), 1236 deletions(-) create mode 100644 .claude/settings.json create mode 160000 .claude/worktrees/reverent-wilson-b7c43a create mode 100644 CHANGELOG.md create mode 100644 CHANGES.md create mode 100644 CLAUDE.md create mode 100644 PROGRESS.md create mode 100644 PROTOKOLL.md create mode 100644 ROADMAP.md create mode 100644 android/app/google-services.json create mode 100644 android/app/proguard-rules.pro create mode 100644 android/app/src/main/kotlin/chat/pyramid/pyramid/BgEngine.kt create mode 100644 android/app/src/main/kotlin/chat/pyramid/pyramid/NotificationHelper.kt create mode 100644 android/app/src/main/kotlin/chat/pyramid/pyramid/PushService.kt create mode 100644 android/app/src/main/kotlin/chat/pyramid/pyramid/ReplyReceiver.kt create mode 100644 android/app/src/main/res/drawable/ic_launcher_foreground.xml create mode 100644 android/app/src/main/res/drawable/ic_notification.xml create mode 100644 android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml create mode 100644 android/app/src/main/res/values/colors.xml create mode 100644 assets/fonts/Inter-Bold.ttf create mode 100644 assets/fonts/Inter-ExtraBold.ttf create mode 100644 assets/fonts/Inter-Italic.ttf create mode 100644 assets/fonts/Inter-Medium.ttf create mode 100644 assets/fonts/Inter-Regular.ttf create mode 100644 assets/fonts/Inter-SemiBold.ttf create mode 100644 assets/logo.png create mode 100644 assets/logo.svg create mode 100644 assets/notification_badge.png create mode 100644 assets/pyramid-loader.json create mode 100644 assets/pyramid-loader.svg create mode 100644 autopilot.ps1 create mode 100644 autopilot.sh create mode 100644 docs/NOTIFICATIONS.md create mode 100644 docs/PROGRESS.md create mode 100644 docs/matrix-sdk/01-auth.md create mode 100644 docs/matrix-sdk/02-rooms.md create mode 100644 docs/matrix-sdk/03-messages.md create mode 100644 docs/matrix-sdk/04-dm.md create mode 100644 docs/matrix-sdk/05-media.md create mode 100644 docs/matrix-sdk/06-encryption.md create mode 100644 docs/matrix-sdk/07-push.md create mode 100644 docs/matrix-sdk/08-voip.md create mode 100644 docs/matrix-sdk/08b-livekit-streaming.md create mode 100644 docs/matrix-sdk/09-profile.md create mode 100644 docs/matrix-sdk/10-room-admin.md create mode 100644 docs/matrix-sdk/11-search.md create mode 100644 docs/matrix-sdk/12-quick-reference.md create mode 100644 docs/matrix-sdk/13-server-admin-continuwuity.md create mode 100644 docs/matrix-sdk/CHECKLIST.md create mode 100644 docs/matrix-sdk/README.md create mode 100644 docs/server-incident-2026-05-31.md create mode 100644 flutter_launcher_icons.yaml create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-57x57@2x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png create mode 100644 ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@2x.png create mode 100644 lib/core/app_state.dart create mode 100644 lib/core/background_push.dart create mode 100644 lib/core/e2ee_diagnostics.dart create mode 100644 lib/core/fcm_push_service.dart create mode 100644 lib/core/ice_servers.dart create mode 100644 lib/core/livekit_call_manager.dart create mode 100644 lib/core/livekit_token.dart create mode 100644 lib/core/media_cache.dart create mode 100644 lib/core/notification_service.dart create mode 100644 lib/core/settings_prefs.dart create mode 100644 lib/core/voip_manager.dart create mode 100644 lib/features/auth/bootstrap_dialog.dart create mode 100644 lib/features/call/mini_call_widget.dart create mode 100644 lib/features/call/voice_channel.dart create mode 100644 lib/features/chat/attachment_dialog.dart create mode 100644 lib/features/chat/chat_composer.dart delete mode 100644 lib/features/chat/chat_input.dart delete mode 100644 lib/features/chat/chat_page.dart create mode 100644 lib/features/chat/chat_view.dart create mode 100644 lib/features/chat/document_viewer.dart create mode 100644 lib/features/chat/emoji_picker.dart create mode 100644 lib/features/chat/gif_sticker_picker.dart create mode 100644 lib/features/chat/media_player.dart create mode 100644 lib/features/chat/media_viewer.dart create mode 100644 lib/features/chat/message_group.dart create mode 100644 lib/features/chat/pinned_messages_panel.dart create mode 100644 lib/features/chat/reaction_service.dart create mode 100644 lib/features/members/members_panel.dart delete mode 100644 lib/features/rooms/room_list_item.dart delete mode 100644 lib/features/rooms/rooms_page.dart create mode 100644 lib/features/rooms/user_panel.dart create mode 100644 lib/features/spaces/space_admin_dialog.dart create mode 100644 lib/features/spaces/spaces_rail.dart create mode 100644 lib/layout/app_shell.dart delete mode 100644 lib/layout/panel_layout.dart delete mode 100644 lib/layout/shell_page.dart create mode 100644 lib/utils/clipboard_image.dart create mode 100644 lib/utils/gif_favorite_service.dart create mode 100644 lib/widgets/banner_crop_dialog.dart create mode 100644 lib/widgets/create_join_dialog.dart create mode 100644 lib/widgets/hover_region.dart create mode 100644 lib/widgets/new_dm_dialog.dart create mode 100644 lib/widgets/profile_popover.dart create mode 100644 lib/widgets/pyramid_loader.dart create mode 100644 lib/widgets/pyramid_logo.dart create mode 100644 lib/widgets/screen_share_picker.dart create mode 100644 lib/widgets/search_modal.dart create mode 100644 lib/widgets/settings_modal.dart create mode 100644 lib/widgets/share_target_dialog.dart create mode 100644 loader icon/pyramid-loader.json create mode 100644 loader icon/pyramid-loader.svg create mode 100644 mockup/App.jsx create mode 100644 mockup/Chat.jsx create mode 100644 mockup/Modals.jsx create mode 100644 mockup/Pyramid.html create mode 100644 mockup/Sidebar.jsx create mode 100644 mockup/callsystem.css create mode 100644 mockup/components.css create mode 100644 mockup/data.js create mode 100644 mockup/flutter_export/README.md create mode 100644 mockup/flutter_export/lib/example_app.dart create mode 100644 mockup/flutter_export/lib/pyramid_audio_player.dart create mode 100644 mockup/flutter_export/lib/pyramid_theme.dart create mode 100644 mockup/flutter_export/lib/pyramid_video_player.dart create mode 100644 mockup/flutter_export/pubspec.yaml create mode 100644 mockup/icons.jsx create mode 100644 mockup/modals.css create mode 100644 mockup/styles.css create mode 100644 screenshots/Screenshot 2026-04-25 142210.png create mode 100644 screenshots/Screenshot 2026-04-25 142406.png create mode 100644 screenshots/Screenshot 2026-06-01 061322.png create mode 100644 screenshots/Screenshot_20260421_051803.jpg create mode 100644 screenshots/Screenshot_20260421_052850.jpg create mode 100644 screenshots/Screenshot_20260421_060108.jpg create mode 100644 screenshots/pyramid_1777119556028.jpg create mode 100644 screenshots/pyramid_1777119787963.jpg delete mode 100644 test/widget_test.dart diff --git a/.claude/settings.json b/.claude/settings.json new file mode 100644 index 0000000..2c9f0ef --- /dev/null +++ b/.claude/settings.json @@ -0,0 +1,16 @@ +{ + "hooks": { + "PostToolUse": [ + { + "matcher": "Edit|Write", + "hooks": [ + { + "type": "command", + "command": "python -c \"import json,sys,datetime; d=json.load(sys.stdin); f=d.get('tool_input',{}).get('file_path','unknown'); t=d.get('tool_name','Edit'); ts=datetime.datetime.now().strftime('%Y-%m-%d %H:%M'); open('CHANGES.md','a').write(f'{ts} [{t}] {f}\\n')\" 2>/dev/null || true", + "statusMessage": "Dokumentation wird aktualisiert..." + } + ] + } + ] + } +} diff --git a/.claude/worktrees/reverent-wilson-b7c43a b/.claude/worktrees/reverent-wilson-b7c43a new file mode 160000 index 0000000..c9af913 --- /dev/null +++ b/.claude/worktrees/reverent-wilson-b7c43a @@ -0,0 +1 @@ +Subproject commit c9af9134680ec43fc8df9c7eb2b428a558941eff diff --git a/.gitignore b/.gitignore index 3820a95..e26b0dd 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ app.*.map.json /android/app/debug /android/app/profile /android/app/release +autopilot.log diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..fc2d36e --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,53 @@ +# Changelog + +## [0.1.33+34] – 2026-06-11 + +### Anrufe & Sprache +- Anruf-Steuerung neu platziert: eigenes "Dock" über dem Konto-Balken (Discord-Stil) statt darin eingebettet; das doppelte Mini-Panel im Profilbereich wurde entfernt. +- Alle Anrufe – auch Sprachkanäle – nutzen jetzt das vollwertige Mini-Call-Widget mit Mikrofon, Deafen, Kamera und Bildschirmübertragung. +- Ein-/Ausblenden des Call-Docks animiert (220 ms). +- Querformat-Optimierung: Stream-Vorschau schrumpft bei wenig Bildschirmhöhe (140 -> 84 px), damit die Raumliste nutzbar bleibt. +- Ausgabelautstärke-Regler (0–150 %) in "Sprache & Video", wirkt sofort auf laufende Anrufe. +- Geräteauswahl verdrahtet: Mikrofon/Lautsprecher/Kamera aus den Einstellungen werden jetzt tatsächlich auf Anrufe angewendet (vorher wurden die Einstellungen nirgends gelesen). +- Ehrliche Fehlermeldung, wenn Windows-Audiotreiber keine Geräteliste an WebRTC melden (bekannter libwebrtc-Bug; Anrufe laufen trotzdem über das Standardgerät). +- Bildschirmübertragungs-Picker passt sich kleinen Bildschirmen an. + +### Chat & Medien +- Bilder werden nicht mehr abgeschnitten: Anpassung an die Chatbreite, kein Verzerren oder Hochskalieren mehr. +- SVG-Inline-Vorschau im Chat (vorher als generische Datei oder fehlerhaft). +- Video-Ladeplatzhalter passen sich der Breite an (keine festen 360 px). +- Lesebestätigungen verbessert: goldener Doppelhaken, Zusammenführung von globalen und Thread-Bestätigungen, korrektes Verhalten wenn die andere Person antwortet/liest. +- Drag-&-Drop-Overlay animiert (Scale + Fade + wippendes Icon, Akzent-Glow). +- Anhang-Dialog öffnet mit Scale-Animation. +- Tastatur-Zwischenablage (Android): frisch kopierte Bilder erscheinen in der Tastatur-Vorschlagsleiste und landen im Anhang-Dialog. +- Banner-Wechsel: Absturz ("setState returned a Future") und Doppelanzeige behoben. + +### Profile & DMs +- Aufklappbarer DM-Header: Klick auf Avatar/Name klappt das Profil auf – Banner als Hintergrund, Avatar skaliert mit (32 -> 96 px), Name wächst, Handle + Biographie blenden ein. +- Profilbild-Bug beim schnellen DM-Wechsel behoben (kein Übersprechen mehr zwischen Kanälen). +- Profil-Einstellungen laden sofort aus dem Cache, Server-Daten parallel im Hintergrund. +- Persistenter Bild-Cache: Avatare und Banner sind nach Neustart sofort da statt nachzuladen. + +### Spaces & Berechtigungen +- Selbst-Aussperr-Schutz: Berechtigungsänderungen werden gegen den echten Server-Stand gemischt (nie mehr den lokalen Cache überschreiben). Zusätzlich bricht Pyramid jede Änderung ab, die den eigenen Account aussperren würde. +- Space-Banner überleben jetzt App-Neustarts (importantStateEvents). +- Aussagekräftige Fehlerdiagnose bei abgelehnten Space-Änderungen. + +### Präsenz / Online-Status +- Online wird nur noch angezeigt, wenn die letzte Aktivität < 5 Min. her ist (behebt "alle wirken online"). +- Präsenz-Heartbeat von 10 s auf 55 s reduziert (weniger Netzwerk/Akku). + +### Teilen +- "Teilen nach Pyramid" (Android): Text und Dateien aus anderen Apps teilen, mit Raum-Picker (Suche + Vorschau). + +### Performance & Build +- Inter-Schrift als Asset gebündelt (google_fonts entfernt) – offline-fähig, schnellerer Start. +- Bilder laden zuerst als Thumbnail (spart Bandbreite, v. a. mobil). +- 12 tote Quelldateien und ungenutzte Abhängigkeit dynamic_color entfernt. +- Android-Release-Build: eigener Release-Keystore, R8/Minify + Resource-Shrinking, ProGuard-Keep-Regeln für WebRTC/LiveKit/Notifications. + +### Infrastruktur (Server) +- Defekter Space "Just us serious" repariert: sauber dupliziert (gleicher Name/Topic/Avatar/Banner, alle 6 Kanäle, Admin-Rechte wiederhergestellt). + +### Hinweis zur Verteilung +- Wegen des neuen Release-Keystores müssen bestehende (Debug-signierte) Android-Installationen einmalig deinstalliert und neu installiert werden – danach laufen Updates normal. diff --git a/CHANGES.md b/CHANGES.md new file mode 100644 index 0000000..73d02f2 --- /dev/null +++ b/CHANGES.md @@ -0,0 +1,1080 @@ +2026-04-19 19:18 [Write] C:\Users\nordm\pyramid\.claude\settings.json +2026-04-19 19:18 [Edit] C:\Users\nordm\.claude\settings.json +2026-04-21 03:44 [Edit] C:\Users\nordm\pyramid\lib\layout\app_shell.dart +2026-04-21 03:44 [Edit] C:\Users\nordm\pyramid\lib\features\rooms\rooms_panel.dart +2026-04-21 03:44 [Edit] C:\Users\nordm\pyramid\lib\widgets\hover_region.dart +2026-04-21 03:44 [Edit] C:\Users\nordm\pyramid\lib\features\chat\chat_view.dart +2026-04-21 03:45 [Edit] C:\Users\nordm\pyramid\lib\features\call\voice_channel.dart +2026-04-21 03:45 [Edit] C:\Users\nordm\pyramid\lib\features\call\voice_channel.dart +2026-04-21 03:45 [Edit] C:\Users\nordm\pyramid\lib\features\chat\chat_composer.dart +2026-04-21 03:45 [Edit] C:\Users\nordm\pyramid\lib\features\chat\chat_composer.dart +2026-04-21 03:46 [Edit] C:\Users\nordm\pyramid\lib\features\chat\chat_composer.dart +2026-04-21 05:04 [Edit] C:\Users\nordm\pyramid\lib\core\matrix_client.dart +2026-04-21 05:09 [Edit] C:\Users\nordm\pyramid\lib\core\matrix_client.dart +2026-04-21 05:13 [Edit] C:\Users\nordm\pyramid\pubspec.yaml +2026-04-21 05:14 [Edit] C:\Users\nordm\pyramid\lib\core\matrix_client.dart +2026-04-24 05:33 [Write] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\MEMORY.md +2026-04-24 05:33 [Write] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\project_overview.md +2026-04-24 05:33 [Write] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-04-24 05:33 [Write] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md +2026-04-24 05:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_token.dart +2026-04-24 05:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 05:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 05:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 05:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 05:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 05:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 05:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 05:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 05:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 05:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\mini_call_widget.dart +2026-04-24 06:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 06:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 06:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 06:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 07:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 07:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 07:41 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 07:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 07:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 08:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 08:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 08:19 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 08:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\mini_call_widget.dart +2026-04-24 08:20 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 08:20 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 08:20 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 10:50 [Write] C:\Users\nordm\pyramid - Kopie\PROTOKOLL.md +2026-04-24 12:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 12:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 12:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 12:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-24 14:04 [Write] C:\Users\nordm\pyramid - Kopie\PROTOKOLL.md +2026-04-24 14:17 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\pyramid_loader.dart +2026-04-24 14:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-04-24 14:19 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-24 14:24 [Write] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-04-24 14:25 [Write] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-04-24 14:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-24 14:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-04-24 14:35 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\pyramid_loader.dart +2026-04-24 14:40 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\pyramid_loader.dart +2026-04-24 14:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 14:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\pyramid_loader.dart +2026-04-24 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-04-24 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 15:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 15:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-24 16:05 [Write] C:\Users\nordm\pyramid - Kopie\PROTOKOLL.md +2026-04-24 16:29 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-24 16:29 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-24 16:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 16:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 17:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-24 17:24 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-24 17:24 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-04-24 17:25 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-24 17:25 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-24 17:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-25 01:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 01:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 01:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 01:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 01:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 01:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 02:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 02:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 02:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-04-25 02:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 02:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 02:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 02:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\matrix_client.dart +2026-04-25 02:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-04-25 04:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 04:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 04:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 04:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 04:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_provider.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_provider.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-25 04:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-25 04:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 04:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 04:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 08:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 08:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 08:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 08:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-25 08:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-25 13:00 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\settings_prefs.dart +2026-04-25 13:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-04-25 13:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-04-25 13:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-04-25 13:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-04-25 13:04 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:09 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:09 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:09 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:09 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:09 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 13:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 13:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 13:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\mxc_image.dart +2026-04-25 14:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 14:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-25 14:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-25 14:40 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:49 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 14:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 15:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 15:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 15:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 15:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 15:08 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 15:08 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 15:08 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 15:08 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:29 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-25 18:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:50 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-25 18:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\matrix_client.dart +2026-04-25 18:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 18:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 18:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 18:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 18:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-25 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-25 19:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:02 [Edit] C:\Users\nordm\pyramid - Kopie\PROTOKOLL.md +2026-04-26 04:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-26 04:37 [Edit] C:\Users\nordm\pyramid - Kopie\PROTOKOLL.md +2026-04-26 04:45 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-04-26 04:54 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\new_dm_dialog.dart +2026-04-26 04:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-26 04:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-26 04:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-26 04:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-26 04:57 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-26 04:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart + +## 2026-04-26 — Create/Join/Discover + Neue DM + Einladungen + +### Neue Dateien +- `lib/widgets/new_dm_dialog.dart` — Nutzer-Suche (searchUserDirectory), DM starten (startDirectChat) +- `lib/widgets/create_join_dialog.dart` — Raum/Space erstellen, beitreten, entdecken (Pagination, SpaceEditDialog, RoomSettingsDialog) + +### Geänderte Dateien +- `lib/features/spaces/spaces_rail.dart` — _AddButton → CreateJoinDialog; _SpaceItem Rechtsklick/Longpress → SpaceEditDialog +- `lib/features/rooms/rooms_panel.dart` — Header-⌄-Menü (kontextabhängig); _SectionHeader "+" aktiv; _RoomItem: DM schließen, Nutzer einladen, Raum-Settings; Invite-Karten (Annehmen/Ablehnen) +- `lib/widgets/create_join_dialog.dart` — flutter/material `hide Visibility` (Namenskonflikt Matrix SDK) +2026-04-26 05:00 [Edit] C:\Users\nordm\pyramid - Kopie\CHANGES.md +2026-04-26 05:22 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-26 05:22 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-04-26 05:25 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-26 05:29 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 15:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 15:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 15:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 15:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-04-27 15:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-04-27 15:20 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-04-27 15:20 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-04-27 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_provider.dart +2026-04-27 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_provider.dart +2026-04-27 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_provider.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 18:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 19:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-27 19:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\mxc_image.dart +2026-04-27 19:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 19:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-27 19:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-27 19:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-04-27 19:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-27 19:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-27 19:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-27 19:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-27 19:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:04 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\banner_crop_dialog.dart +2026-04-28 10:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 10:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 10:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 10:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 10:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-28 10:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-04-28 10:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\banner_crop_dialog.dart +2026-04-28 10:11 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-28 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\banner_crop_dialog.dart +2026-04-28 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 10:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 10:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 10:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 10:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 10:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-04-28 10:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 10:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 10:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 11:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-04-28 11:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 15:00 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-28 15:01 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-04-28 15:01 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 15:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 15:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 15:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 15:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 15:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 15:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-28 15:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 15:08 [Write] C:\Users\nordm\pyramid - Kopie\docs\feature-checklist.md +2026-04-28 15:15 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-04-28 15:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-04-28 15:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-04-28 15:18 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-04-28 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-28 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-04-28 15:31 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-04-28 15:31 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\xml\file_paths.xml +2026-04-28 15:31 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-04-28 15:32 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:32 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:32 [Write] C:\Users\nordm\pyramid - Kopie\.git\hooks\post-commit +2026-04-28 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:35 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_banner.dart +2026-04-28 15:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:42 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-04-28 15:42 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-28 15:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-28 15:43 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-28 21:54 [Write] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-28 22:00 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-28 22:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-04-28 22:00 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_notification.xml +2026-04-28 22:01 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:01 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:05 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-28 22:05 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:27 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-04-28 22:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 22:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-28 22:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-04-28 22:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-04-28 22:50 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-04-28 22:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-28 22:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-28 22:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-28 22:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-28 22:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-28 22:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-28 22:52 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\search_modal.dart +2026-04-28 22:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\search_modal.dart +2026-04-28 23:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 23:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-28 23:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-28 23:04 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\search_modal.dart +2026-04-29 09:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 09:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 09:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\search_modal.dart +2026-04-29 10:04 [Write] C:\Users\nordm\pyramid - Kopie\docs\feature-checklist.md +2026-04-29 10:11 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-29 10:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 10:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 10:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-29 10:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:15 [Edit] C:\Users\nordm\pyramid - Kopie\docs\feature-checklist.md +2026-04-29 10:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 10:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-29 10:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-29 10:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 10:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 11:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 11:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 11:03 [Edit] C:\Users\nordm\pyramid - Kopie\docs\feature-checklist.md +2026-04-29 11:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-04-29 14:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-04-29 14:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-29 14:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 14:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 14:57 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-29 15:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-29 15:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 15:27 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-29 15:28 [Write] C:\Users\nordm\pyramid - Kopie\lib\utils\clipboard_image.dart +2026-04-29 15:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 15:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 15:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 15:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 15:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\utils\gif_favorite_service.dart +2026-04-29 15:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\gif_sticker_picker.dart +2026-04-29 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\gif_sticker_picker.dart +2026-04-29 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\attachment_dialog.dart +2026-04-29 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\attachment_dialog.dart +2026-04-29 15:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\attachment_dialog.dart +2026-04-29 15:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 15:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 15:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-04-29 19:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 19:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 19:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 19:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 19:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 19:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 19:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\gif_sticker_picker.dart +2026-04-29 19:58 [Write] C:\Users\nordm\bin\pyramid-release +2026-04-29 20:25 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:25 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:25 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:25 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\room_list_item.dart +2026-04-29 20:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\room_list_item.dart +2026-04-29 20:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-04-29 20:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-29 20:35 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-29 20:41 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-29 20:45 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-29 20:47 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-30 10:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_viewer.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_input.dart +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-04-30 10:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-04-30 11:53 [Edit] C:\Users\nordm\pyramid - Kopie\android\settings.gradle.kts +2026-04-30 11:54 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-04-30 11:54 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-04-30 11:54 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-04-30 11:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-04-30 11:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-04-30 11:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-30 11:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-30 11:58 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-04-30 12:11 [Edit] C:\Users\nordm\pyramid - Kopie\android\settings.gradle.kts +2026-04-30 12:27 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-04-30 12:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-04-30 12:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-04-30 12:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\auth\login_notifier.dart +2026-04-30 12:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\auth\login_notifier.dart +2026-04-30 12:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\auth\login_notifier.dart +2026-04-30 12:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 19:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-04-30 19:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 19:13 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 19:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-04-30 19:25 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-04-30 23:30 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-04-30 23:30 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-04-30 23:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-30 23:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-04-30 23:31 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-04-30 23:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 23:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-04-30 23:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 00:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 00:04 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-01 00:04 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-01 00:04 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-01 00:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 00:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 00:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 00:08 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-05-01 11:28 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-05-01 11:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 11:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 11:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 11:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 11:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 11:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 11:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 11:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 11:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-05-01 11:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-05-01 11:33 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-01 11:51 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationActionReceiver.kt +2026-05-01 11:51 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-01 12:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 12:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 12:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 13:21 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-05-01 13:22 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-01 13:22 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationActionReceiver.kt +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationActionReceiver.kt +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 13:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-05-01 13:53 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-05-01 13:53 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-05-01 13:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 13:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-05-01 13:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-05-01 15:32 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-05-01 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 15:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-05-01 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 15:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 15:37 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-01 15:51 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-01 15:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 15:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 15:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 15:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 15:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-01 17:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-01 17:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationActionReceiver.kt +2026-05-01 17:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationActionReceiver.kt +2026-05-01 17:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 17:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 17:01 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-01 17:02 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-01 17:13 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 17:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-05-01 17:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 17:14 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 17:14 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-01 17:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 17:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 17:15 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 20:34 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-05-01 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-05-01 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-05-01 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\update_download_dialog.dart +2026-05-01 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-05-01 20:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\main.dart +2026-05-01 20:54 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 20:54 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-05-01 20:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 20:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:07 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\drawable\ic_launcher_foreground.xml +2026-05-01 21:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:11 [Edit] C:\Users\nordm\pyramid - Kopie\flutter_launcher_icons.yaml +2026-05-01 21:12 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:12 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-01 21:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-01 21:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-01 21:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-01 21:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-01 21:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:57 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-01 21:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 10:21 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 10:23 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 10:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 10:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-02 10:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-02 10:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-05-02 10:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 10:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 10:28 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-02 11:22 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 12:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 12:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 12:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:08 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 20:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 20:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 20:51 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-02 20:51 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-02 20:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 21:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-02 21:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 21:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 21:17 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-02 21:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-02 21:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 21:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-02 21:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 12:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 12:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 12:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 12:19 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 13:21 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 13:21 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 13:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 13:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 13:27 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 13:27 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 13:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 13:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\values\styles.xml +2026-05-03 13:34 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\res\values-night\styles.xml +2026-05-03 13:34 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 14:23 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\ReplyReceiver.kt +2026-05-03 14:32 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationHelper.kt +2026-05-03 14:33 [Write] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-03 14:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-03 14:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-03 14:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 14:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 14:33 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-03 14:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-03 15:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-03 15:00 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-04 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\ReplyReceiver.kt +2026-05-04 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-04 16:44 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\PushService.kt +2026-05-04 16:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-05-04 16:45 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app.dart +2026-05-04 16:46 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 16:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-05-04 17:04 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-04 17:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-04 17:04 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-04 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\fcm_push_service.dart +2026-05-04 17:20 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-05-04 17:21 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\background_push.dart +2026-05-04 17:32 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\NotificationHelper.kt +2026-05-09 18:35 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-09 18:35 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-09 18:36 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-05-09 19:09 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\README.md +2026-05-09 19:10 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\01-auth.md +2026-05-09 20:00 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\02-rooms.md +2026-05-09 20:02 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\03-messages.md +2026-05-09 20:03 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\04-dm.md +2026-05-09 20:03 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\05-media.md +2026-05-09 20:04 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\06-encryption.md +2026-05-09 20:05 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\07-push.md +2026-05-09 20:06 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\08-voip.md +2026-05-09 20:07 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\09-profile.md +2026-05-09 20:08 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\10-room-admin.md +2026-05-09 20:09 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\11-search.md +2026-05-09 20:10 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\12-quick-reference.md +2026-05-09 20:59 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\08b-livekit-streaming.md +2026-05-09 21:02 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\CHECKLIST.md +2026-05-09 21:02 [Edit] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\README.md +2026-05-09 21:13 [Write] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\13-server-admin-continuwuity.md +2026-05-09 21:14 [Edit] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\10-room-admin.md +2026-05-09 21:14 [Edit] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\10-room-admin.md +2026-05-09 21:14 [Edit] C:\Users\nordm\pyramid - Kopie\docs\matrix-sdk\README.md +2026-05-31 07:20 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-05-31 07:20 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-05-31 07:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-05-31 07:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-05-31 07:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-05-31 07:51 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-05-31 07:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-05-31 08:39 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-05-31 08:46 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-31 08:48 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 08:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 08:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 08:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 08:48 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 08:49 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-05-31 08:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 08:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 08:50 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:06 [Write] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 09:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 09:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 09:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 09:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 09:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 09:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 10:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 10:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 11:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 11:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 11:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 11:47 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:01 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 12:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\document_viewer.dart +2026-05-31 13:22 [Write] C:\Users\nordm\pyramid - Kopie\docs\server-incident-2026-05-31.md +2026-05-31 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-05-31 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-05 16:41 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 16:42 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 16:43 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 16:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 16:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:05 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-06-05 17:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:11 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:17 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-05 17:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 17:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\spaces_rail.dart +2026-06-05 18:06 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\settings_prefs.dart +2026-06-05 18:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-06-05 18:07 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 12:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-11 12:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-11 12:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-11 12:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-11 12:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\media_player.dart +2026-06-11 12:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-06-11 12:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-06-11 12:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\user_panel.dart +2026-06-11 12:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 12:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\mini_call_widget.dart +2026-06-11 12:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\mini_call_widget.dart +2026-06-11 12:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\mini_call_widget.dart +2026-06-11 12:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\screen_share_picker.dart +2026-06-11 12:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 12:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 12:57 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-06-11 13:01 [Edit] C:\Users\nordm\pyramid - Kopie\analysis_options.yaml +2026-06-11 13:02 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md +2026-06-11 13:03 [Write] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 13:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\matrix_client.dart +2026-06-11 13:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 13:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\members\members_panel.dart +2026-06-11 13:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\profile_popover.dart +2026-06-11 13:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-06-11 13:30 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_composer.dart +2026-06-11 13:31 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\media_cache.dart +2026-06-11 13:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\mxc_image.dart +2026-06-11 13:31 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\mxc_image.dart +2026-06-11 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\attachment_dialog.dart +2026-06-11 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\message_group.dart +2026-06-11 13:36 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-06-11 13:36 [Edit] C:\Users\nordm\pyramid - Kopie\pubspec.yaml +2026-06-11 13:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\theme.dart +2026-06-11 13:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\theme.dart +2026-06-11 13:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\theme.dart +2026-06-11 13:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 13:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 13:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 13:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 13:42 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 13:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 13:52 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 13:53 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 13:54 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\AndroidManifest.xml +2026-06-11 13:54 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-06-11 13:55 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-06-11 13:55 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-06-11 13:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\app_state.dart +2026-06-11 13:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-06-11 13:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\notification_service.dart +2026-06-11 13:57 [Write] C:\Users\nordm\pyramid - Kopie\lib\widgets\share_target_dialog.dart +2026-06-11 13:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 13:57 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 13:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:58 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 13:59 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:00 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 14:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 14:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 14:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 14:02 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 14:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:03 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:04 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 14:08 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-06-11 14:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 14:35 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:36 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 14:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:37 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:39 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 14:40 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 17:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 17:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:32 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:35 [Write] C:\Users\nordm\AppData\Local\Temp\devtest_webrtc\lib\main.dart +2026-06-11 17:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 17:38 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-11 17:41 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 17:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:54 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 17:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 17:55 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 17:56 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\chat\chat_view.dart +2026-06-11 17:57 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 18:13 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-06-11 18:16 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\spaces\space_admin_dialog.dart +2026-06-11 18:20 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-06-11 18:20 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\build.gradle.kts +2026-06-11 18:21 [Write] C:\Users\nordm\pyramid - Kopie\android\app\proguard-rules.pro +2026-06-11 18:24 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\mxc_image.dart +2026-06-11 18:24 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 18:32 [Edit] C:\Users\nordm\pyramid - Kopie\android\app\src\main\kotlin\chat\pyramid\pyramid\MainActivity.kt +2026-06-11 18:33 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\update_checker.dart +2026-06-11 18:34 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-06-11 18:35 [Edit] C:\Users\nordm\pyramid - Kopie\scripts\release.ps1 +2026-06-11 18:38 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\codebase_cleanup_2026-06.md +2026-06-11 18:50 [Write] C:\Users\nordm\pyramid - Kopie\CHANGELOG.md +2026-06-11 23:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:26 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 23:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\layout\app_shell.dart +2026-06-11 23:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:27 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:28 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-11 23:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:29 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\rooms\rooms_panel.dart +2026-06-11 23:44 [Write] C:\Users\nordm\pyramid - Kopie\lib\core\ice_servers.dart +2026-06-11 23:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 23:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\voip_manager.dart +2026-06-11 23:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 23:44 [Edit] C:\Users\nordm\pyramid - Kopie\lib\core\livekit_call_manager.dart +2026-06-11 23:48 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md +2026-06-11 23:48 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-06-11 23:48 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\MEMORY.md +2026-06-12 00:03 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md +2026-06-12 00:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-12 00:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-12 00:10 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\settings_modal.dart +2026-06-12 00:11 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md +2026-06-12 00:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\widgets\create_join_dialog.dart +2026-06-12 00:34 [Edit] C:\Users\nordm\pyramid - Kopie\lib\features\call\voice_channel.dart +2026-06-12 00:35 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\call_system_status.md +2026-06-12 00:36 [Edit] C:\Users\nordm\.claude\projects\C--Users-nordm-pyramid---Kopie\memory\infrastructure.md diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 0000000..5607106 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,70 @@ +# Pyramid – Arbeitsregeln für Claude + +Pyramid ist Bernds eigener Matrix-Client (Flutter, kein FluffyChat-Fork). Bernd ist +**kein Entwickler** – er gibt Ziele und Prioritäten vor, Claude trifft die technischen +Entscheidungen und erklärt sie in einfachem Deutsch. Die App ist bei echten Nutzern im +Einsatz (u. a. Uta) – Stabilität und Datensicherheit gehen vor Feature-Tempo. + +**Dies ist das einzige aktuelle Repo:** `C:\Users\nordm\pyramid - Kopie\`. +(`C:\Users\nordm\pyramid` und `C:\Users\nordm\MatrixPi\pyramid` sind veraltete +April-Schnappschüsse – dort NIE arbeiten.) + +## Infrastruktur + +- Homeserver: Continuwuity auf dem Pi5 (`steggi-matrix.work`) +- LiveKit/TURN: Hetzner „Leuchtturm" → `wss://livekit.steggi-matrix.work` (API-Key LKMatrixPi), coturn 94.130.78.116:3478 +- Git-Remote: Gitea auf dem Pi (`http://192.168.178.71:3000/steggi/pyramid.git`) – Push = Backup +- Push-Benachrichtigungen: FCM + Sygnal auf dem Pi (Memory „Pyramid Push" lesen, bevor daran gearbeitet wird) +- Vollbackup vom 2026-07-03: `MatrixPi\backups\pyramid-kopie_backup_2026-07-03.tar.gz` + +## Arbeitszyklus (IMMER einhalten) + +Jede Session – egal ob frisch gestartet oder fortgesetzt – läuft so: + +1. **Einlesen:** `PROGRESS.md` (letzter Stand, Stolperfallen) und `ROADMAP.md` + (nächster offener Punkt) lesen. NIE Arbeit doppelt machen, die dort als erledigt steht. +2. **Einen Punkt nehmen:** den obersten nicht abgehakten Punkt des aktuellen Meilensteins + aus `ROADMAP.md` – nicht mehrere gleichzeitig, keine Sprünge in spätere Meilensteine. +3. **Umsetzen & prüfen:** Nach der Änderung mindestens `flutter analyze` sauber bekommen; + wo sinnvoll `flutter test` und `flutter run -d windows` (schnellster Praxistest). +4. **Protokollieren:** `PROGRESS.md` aktualisieren (Format siehe dort) und den Punkt in + `ROADMAP.md` abhaken. +5. **Commit + Push:** kleiner `git commit` (`feat:`/`fix:`/`refactor:`/`chore:`) und + `git push origin master` (Gitea = Backup). Lieber 5 kleine Commits als ein riesiger. +6. Weiter mit dem nächsten Punkt, solange Kontingent/Zeit da ist. + +Wird eine Session mitten in einem Punkt abgebrochen (Limit erreicht), MUSS der letzte +Eintrag in `PROGRESS.md` den Zwischenstand beschreiben: was halb fertig ist, welche +Dateien angefasst wurden, was der nächste konkrete Handgriff ist. + +## Qualitätsleitplanken + +- **Kein Aussperren, kein Datenverlust:** Alles rund um Login, Sessions, Verschlüsselung + und Key-Backup ist heilig. Der Uta-Random-Logout-Bug zeigt: Fehlerpfade dürfen NIE in + einem stillen Logout enden. Änderungen daran immer mit Test: Login → Nachrichten → + Logout → erneuter Login → alte verschlüsselte Nachrichten noch lesbar? +- **Nach dem Refactoring (M2) gilt:** keine Verhaltensänderung ohne Not – Refactoring + heißt gleiche Funktion, bessere Struktur. Nach jedem Refactoring-Schritt App starten + und Kernflows prüfen (Login, Raum öffnen, Nachricht senden, Voice-Channel beitreten). +- **Keine Secrets ins Repo:** Tokens, Recovery-Keys, Passwörter, Keystore-Dateien + niemals committen (Signing-Keys liegen in `Documents\pyramid_keys_20260425.txt`). +- **Modularität (Bernd wichtig!):** Die Architektur muss aus austauschbaren Bausteinen + bestehen – jedes Feature (Calls, Streaming, Push, Chat-Timeline, …) hinter einer klaren, + schmalen Schnittstelle, sodass man einen alten Baustein durch einen neuen ersetzen kann, + ohne den Rest anzufassen. Beim Refactoring (M2) ist das DAS Leitprinzip; bei jedem neuen + Feature fragen: „Könnte man dieses Modul in einem Jahr komplett neu schreiben, ohne + andere Module zu ändern?" +- **Abhängigkeiten:** neue Pakete nur mit gutem Grund, etabliert und gepflegt. +- **Umgebung beachten:** Auf dem Pi (SSH/tmux-Sessions) ist evtl. kein Flutter-Toolchain + verfügbar. Dann trotzdem sauber arbeiten, aber jeden Schritt in PROGRESS.md als + „UNGETESTET (Pi)" markieren – der nächste PC-Lauf holt `flutter analyze` + Praxistest nach. +- **Bernd fragen** nur bei echten Richtungsentscheidungen (UX-Geschmack, Priorität) – + Fragen in PROGRESS.md unter „Fragen an Bernd" sammeln statt die Session zu blockieren. + +## Nützliches Wissen + +- Discord ist die UX-Referenz für Calls/Voice-Channels (Join/Leave, Nutzer-Lautstärke, + Geräteauswahl, Noise Suppression, Streaming-Qualitätswahl). +- `CHANGES.md` ist ein automatisches Änderungslog (Hook) – nicht von Hand pflegen. +- Windows-Build ist der schnellste Testweg; Android-Release über das Release-Skript + (siehe Commit d706ace), signiert – Play-Protect-Warnung siehe ROADMAP M6. diff --git a/PROGRESS.md b/PROGRESS.md new file mode 100644 index 0000000..9260ca6 --- /dev/null +++ b/PROGRESS.md @@ -0,0 +1,33 @@ +# Pyramid – Arbeitsprotokoll + +Neueste Einträge OBEN. Jede Claude-Session schreibt hier nach jedem abgeschlossenen +Schritt (und beim Abbruch mitten im Schritt den Zwischenstand). Format: + +``` +## JJJJ-MM-TT – Kurztitel +**Erledigt:** was fertig ist (mit Commit-Hash) +**Offen/Nächster Schritt:** der konkrete nächste Handgriff +**Stolperfallen:** was schiefging und wie es gelöst wurde (damit es nie zweimal passiert) +**Fragen an Bernd:** (optional) gesammelte Richtungsfragen, die nicht blockieren +``` + +--- + +## 2026-07-03 – Arbeitsstruktur angelegt + Vollbackup (Setup, noch kein Code) + +**Erledigt:** +- Vollbackup inkl. Git-Historie: `MatrixPi\backups\pyramid-kopie_backup_2026-07-03.tar.gz` (510 MB) +- `CLAUDE.md` (Arbeitsregeln), `ROADMAP.md` (M0–M7 nach Bernds Prioritäten), dieses Protokoll +- Klargestellt: `C:\Users\nordm\pyramid - Kopie` ist das EINZIGE aktuelle Repo; + `C:\Users\nordm\pyramid` und `MatrixPi\pyramid` sind veraltete April-Stände (Commit c9af913) + +**Offen/Nächster Schritt:** M0, Punkt 2 – die ~140 uncommitteten Dateien mit `git status` +sichten und in thematische Commits aufteilen (diese drei neuen Dateien mit committen), +dann `git push origin master`. + +**Stolperfallen:** +- Letzter Commit ist vom 2026-04-28 (d706ace), gearbeitet wurde aber bis mindestens + 2026-06-12 → zwischen Commits und Realität liegen 6 Wochen. Genau deshalb: ab jetzt + kleine Commits nach jedem Schritt. +- Git-Remote (Gitea auf dem Pi) enthält Zugangsdaten in der URL – funktioniert, aber + nur erreichbar, wenn der Pi läuft (unterwegs: WireGuard nötig). diff --git a/PROTOKOLL.md b/PROTOKOLL.md new file mode 100644 index 0000000..200a643 --- /dev/null +++ b/PROTOKOLL.md @@ -0,0 +1,386 @@ +# Pyramid – Entwicklungsprotokoll +Stand: 24.04.2026 + +--- + +## Projektübersicht + +**Pyramid** ist ein Flutter-basierter Matrix-Client, modelliert nach einem FluffyChat-Fork, +mit zwei parallelen Call-Systemen: + +| System | Einsatz | Datei | +|--------|---------|-------| +| **LiveKit** (`livekit_client`) | Gruppen-Sprachräume | `lib/core/livekit_call_manager.dart` | +| **Matrix VoIP** (`matrix` SDK) | 1:1 Direktnachrichten | `lib/core/voip_manager.dart` | + +Server-Infrastruktur läuft auf einem Raspberry Pi (`steggi-matrix.work`), LiveKit unter +`livekit.steggi-matrix.work`. + +--- + +## Erledigte Änderungen + +### 1. LiveKit – Qualitäts-Bugs behoben (`livekit_call_manager.dart`) + +**Problem:** Streamer und Zuschauer konnten die Übertragungsqualität nicht ändern. + +**Ursachen:** +- `_screenShareEncoding()` hatte einen hardcodierten `switch ('balanced')` — gab immer + halbe Bitrate zurück, unabhängig vom eingestellten Qualitäts-Key. +- `setSubscribeQuality('auto')` sprang vorzeitig raus und setzte die Qualität nie. + +**Fix:** +```dart +VideoEncoding _screenShareEncoding() { + return _screenShareEncodings[_localQualityKey] ?? + const VideoEncoding(maxBitrate: 1_500_000, maxFramerate: 15); +} +``` +`setSubscribeQuality` wendet jetzt immer die Qualität an, auch bei 'auto'. + +--- + +### 2. LiveKit – Track-Events lösen UI-Rebuild aus (`livekit_call_manager.dart`) + +**Problem:** Kamera-Feed wurde nach dem Publishen nicht angezeigt, weil kein Widget-Rebuild ausgelöst wurde. + +**Fix:** Handler für alle Track-Events hinzugefügt: +```dart +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +..on((_) => notifyListeners()) +``` + +--- + +### 3. LiveKit – Optimistic Mute (`livekit_call_manager.dart`) + +**Problem:** Mute-Button hatte eine spürbare Verzögerung (async API-Call). + +**Fix:** `notifyListeners()` wird jetzt vor dem `await` aufgerufen: +```dart +Future toggleMute() async { + isMuted = !isMuted; + notifyListeners(); // Sofort + await _room?.localParticipant?.setMicrophoneEnabled(!isMuted); +} +``` + +--- + +### 4. VoIP – Kamera-Fix (`voip_manager.dart`) + +**Problem:** Kamera-Tracks wurden nicht korrekt zugewiesen, weil der Renderer bereits belegt +wurde bevor Video-Daten verfügbar waren. + +**Fix:** +- Track-Zuweisung erfolgt jetzt erst wenn `getVideoTracks().isNotEmpty` — kein Renderer-Update + auf leere Streams mehr. +- `_isCameraMuted` wird bei eingehenden Calls korrekt aus dem Call-Typ gesetzt: + `_isCameraMuted = call.type == CallType.kVoice;` +- Bei `kConnected`-State wird `setLocalVideoMuted(false)` nochmals aufgerufen falls Kamera + aktiv sein soll. +- Poll-Intervall von 1500ms auf 1000ms reduziert für schnellere Feed-Erkennung. + +--- + +### 5. VoIP – Optimistic Mic/Camera Toggle (`voip_manager.dart`) + +**Problem:** `toggleMic()` und `toggleCamera()` nutzten `safeAction()` mit 1500ms Delay. + +**Fix:** +- `toggleMic()` flippt State sofort, reverted bei Fehler automatisch. +- `toggleCamera()` flippt `_isCameraMuted` sofort (optimistic), ruft `_updateRenderers()` + mehrfach nach kurzen Delays auf. + +--- + +### 6. VoIP – Desktop Speakerphone Fix (`voip_manager.dart`) + +**Problem:** `MissingPluginException: No implementation found for method enableSpeakerphone` +auf Windows/Desktop. + +**Fix:** Speakerphone-Callback wird im Konstruktor unterdrückt: +```dart +try { + (voip as dynamic).onConfigSpeakerphone = (bool _) async {}; +} catch (_) {} +``` + +--- + +### 7. SQLite-Stabilität auf Windows + +**Problem:** Sporadische "Database is locked"-Fehler durch parallele Zugriffe. + +**Fix:** WAL-Modus aktiviert und `busy_timeout` gesetzt, um Locking-Konflikte zu verhindern. + +--- + +### 8. Einheitliches Call-UI (`voice_channel.dart`) – Kompletter Rewrite + +Die gesamte `voice_channel.dart` wurde neu strukturiert mit einer einheitlichen Architektur +für LiveKit und VoIP. + +#### 8a. Unified Participant Model + +```dart +class _ParticipantData { + final String id, name; + final Widget? videoWidget; + final bool isSpeaking, isMuted, hasVideo, isScreenShare; + final Color avatarColor; + final dynamic originalParticipant; +} +``` + +#### 8b. Adaptive Seitenverhältnisse (`voice_channel.dart`) + +**Problem:** Video-Tiles waren auf `AspectRatio(16/9)` festgelegt — Hochkant-Videos vom +Handy wurden stark beschnitten und falsch dargestellt. + +**Fix:** +- `_ParticipantData` bekommt ein `aspectRatio`-Feld (Default `16.0/9.0`). +- VoIP: echte Dimension aus `RTCVideoRenderer.videoWidth/videoHeight` ausgelesen. +- LiveKit: echte Dimension aus `(videoTrack as dynamic).currentDimensions` ausgelesen. +- Alle Renderer nutzen `VideoViewFit.contain` / `RTCVideoViewObjectFitContain` statt `cover` + — kein Beschnitt mehr. +- `_ParticipantGrid` wechselt von `GridView(childAspectRatio: 16/9)` zu `Wrap` mit + individuell berechneter `SizedBox(width, height)` pro Tile. +- `_ParticipantStrip` passt Tile-Breite an: `101 * p.aspectRatio` für Landscape-Tiles. + +#### 8c. Hero/Spotlight-System + +- **Auto-Spotlight:** Screenshares werden automatisch als Hero angezeigt +- **Manuelles Pinnen:** Klick auf Tile → wird Hero; erneuter Klick = unpin +- Gear-Icon im Hero-Overlay öffnet das Qualitätsmenü (hover-reveal) +- Fullscreen-Button öffnet eine eigene Fullscreen-Seite via `Navigator.push` + +#### 8d. Aktive Sprecher + +Pulsierende Rahmen-Animation (`AnimationController`) für Teilnehmer, die gerade sprechen. + +#### 8e. Teilnehmer-Sortierung + +``` +Screensharer → Kamera-an → Sprechend → Audio-only +``` + +#### 8f. Responsive Layouts + +**Portrait:** Hero oben (Expanded) + horizontaler Teilnehmer-Strip unten (120px) +**Landscape:** Hero links (Expanded) + vertikale Sidebar rechts (200px) + +Beide Layouts sind **einklappbar** (Swipe-Geste + Pfeil-Button). + +#### 8g. Zentrales Mirroring + +`_MirrorWrapper` spiegelt nur die eigene Kamera (`isLocal && !isScreenShare`). +Screenshares und Remote-Teilnehmer bleiben ungespiegelt. + +#### 8h. Grid-Layout mit einheitlichen Tiles + +`SliverGridDelegateWithFixedCrossAxisCount`: +- < 600px → 2 Spalten +- 600–900px → 3 Spalten +- > 900px → 4 Spalten + +#### 8i. Steuerungs-Reihenfolge (alle Views) + +``` +[ Mic ] [ Deaf ] [ Kamera ] [ Screen ] | [ Auflegen ] +``` + +--- + +### 9. Mini-Call-Widget – Steuerungs-Reihenfolge (`mini_call_widget.dart`) + +Gleiche Reihenfolge wie Haupt-Call-Ansicht: Mic → Deaf → Kamera → Screen. + +--- + +### 10. 4K Support + +4K (2160p) als Qualitätsoption in LiveKit- und VoIP-Qualitätsmenüs hinzugefügt. + +--- + +### 11. App-Icon – Pyramid-Logo (`flutter_launcher_icons.yaml`) + +**Problem:** App zeigte das Flutter-Standard-Icon statt dem Pyramid-Logo. + +**Fix:** +- `flutter_launcher_icons.yaml` auf `assets/logo.png` (goldene 3D-Pyramide, 1024px) umgestellt. +- macOS-Generierung explizit aktiviert (`macos: generate: true`). +- Windows ICO nach `dart run flutter_launcher_icons` mit Pillow neu generiert + (16/32/48/64/128/256px multi-size ICO, verhindert das 48px-Limit des Packages). + +--- + +### 12. Lade-Animation – 3D Pyramiden-Painter (`pyramid_loader.dart`) + +**Problem:** Lottie-JSON zeigte inkorrekte Farben, SVG wurde nur statisch gerendert +(flutter_svg führt kein JavaScript aus). + +**Lösung:** JavaScript-Animations-Logik aus dem Original-SVG exakt nach Dart portiert +als `CustomPainter`: + +- `_ease(t, exp)`: kubische Ease-In/Out wie im JS-Original +- `_yawAt(t)`: Yaw-Rotation mit Hold-Phase (80% Rotation, 20% Pause bei π/4) +- `_PyramidPainter`: 4 Flächen, Y-Rotation, Z-Clipping, orthografische Projektion, + 20°-Tilt, Depth-Sorting (Painter's Algorithm) +- Fill: `darken(accent, 0.45)`, Stroke: `accent`, strokeWidth: `1.4 * (size/96)` +- `useLottie: false` ist nun der Standard — kein Lottie-Asset mehr nötig + +**Loader Preview** in den Appearance Settings (zwei 120px-Boxen: Custom Painter + Lottie-Fallback). + +--- + +### 13. Chat-Scroll-Stabilisierung (`chat_view.dart`) + +**Problem:** Der Chat zuckte und zitterte je weiter man nach oben scrollte, besonders +wenn neue History nachgeladen wurde. + +**Ursache:** `DateDivider` und `MessageGroup` waren in einem gemeinsamen `Column`-Widget +mit einem einzigen Key zusammengefasst. Wenn beim Nachladen von History die `showDate`- +Eigenschaft einer Gruppe sich änderte (z.B. weil sie nicht mehr die älteste Gruppe war), +änderte sich die Höhe des Items — direkt in dem Bereich, den der User gerade betrachtete. + +**Fix:** +- `DateDivider` und `MessageGroup` sind jetzt separate List-Items mit unabhängigen Keys: + - Gruppen: `ValueKey('g:')` + - Datumstrennlinien: `ValueKey('d:')` +- `findChildIndexCallback` nutzt eine vorberechnete `Map` für O(1)-Lookup + statt O(n)-`indexWhere`. +- 200ms Cooldown nach `requestHistory` verhindert sofortige Re-Trigger durch veraltetes + `maxScrollExtent`. + +--- + +### 14. Startup-Flash Fix (`app.dart`) + +**Problem:** Beim App-Start flackerte kurz die Server-Eingabe-Seite auf, bevor der +korrekte Redirect zu `/app` stattfand. + +**Ursache:** `isLoggedInProvider` (StreamProvider) gibt beim ersten Build `AsyncLoading` +zurück. `valueOrNull ?? false` ergibt `false` → Router leitet sofort zu `/server` weiter. +Kurz danach resolvet der Stream und der Router erstellt sich neu mit `isLoggedIn = true`. + +**Fix:** `PyramidApp` prüft `isLoggedInProvider` zuerst. Solange noch `isLoading`: +vollbild `PyramidLoader` statt Router — die Pyramiden-Animation überbrückt den kurzen +Moment, bis der Auth-State bekannt ist. + +--- + +### 15. Eigenes Profilbild (`user_panel.dart`) + +**Problem:** Das eigene Profilbild wurde unten links (UserPanel) nicht angezeigt — +nur ein Farbverlauf-Platzhalter mit Initial-Buchstabe. + +**Fix:** +- `_ownProfileProvider` (FutureProvider): ruft einmalig `client.getProfileFromUserId(userID)` + auf und cached das Ergebnis. +- `UserPanel` zeigt nun `MxcAvatar` mit dem echten Profilbild. +- Anzeigename kommt aus `profile.displayName` statt nur aus der UserID. +- Farbverlauf-Initial-Avatar bleibt als Fallback (`_InitialAvatar`) während des Ladens + oder wenn kein Bild gesetzt ist. + +--- + +### 16. QR-Code-Verifikation (`app_shell.dart`, `settings_modal.dart`) + +**Problem:** Geräteverifikation unterstützte nur Emoji-SAS — kein QR-Code-Flow. + +**Fix:** +- `KeyVerificationMethod.qrShow` zu `verificationMethods` in `matrix_client.dart` hinzugefügt. +- `pubspec.yaml`: `pretty_qr_code: ^3.6.0` und `qr: ^3.0.2` ergänzt. +- Eingehender Verifizierungsdialog (`app_shell.dart`) und ausgehender Dialog (`settings_modal.dart`) + unterstützen jetzt beide 3 neue States: + - `askChoice` → Methodenwahl (Emoji oder QR) + - `confirmQRScan` → QR-Code anzeigen (`QrCode.fromUint8List` + `PrettyQrView`) + "Gescannt bestätigen"-Button + - `showQRSuccess` → Erfolgsanzeige + +**Technischer Hinweis:** Matrix QR-Codes sind Binärdaten (`qrDataRawBytes: Uint8Buffer`). +Rendering über `QrCode.fromUint8List(data: rawBytes, errorCorrectLevel: QrErrorCorrectLevel.L)`. + +--- + +### 17. Wiederherstellungsschlüssel ändern (`settings_modal.dart`) + +**Problem:** Kein Feature zum Wechseln des SSSS-Wiederherstellungsschlüssels vorhanden. + +**Implementierung:** `_ChangeRecoveryKeyDialog` mit Bootstrap-State-Machine: + +**Flow:** +1. **Laden** — Bootstrap startet, `wipeSsss(true)` → `newSsss()` generiert neuen Schlüssel +2. **Schlüssel anzeigen** — Schlüssel selektierbar + Kopier-Button; wartet auf Nutzer +3. **Bestätigen** — Nutzer tippt Schlüssel zur Bestätigung ein (`_ConfirmKeyBody`) +4. **Aktivieren** — wartet auf Bootstrap `done` (Cross-Signing + Key Backup im Hintergrund) +5. **Fertig** — Erfolgsmeldung + +**Kritischer Fix (BootstrapBadStateException):** +- `newSsss()` ruft intern `checkCrossSigning()` auf → State geht sofort zu `askWipeCrossSigning`. +- `openExistingSsss()` ist nach `newSsss()` nicht mehr erreichbar — wurde entfernt. +- Alle Post-`newSsss`-States werden ohne `_step`-Guards auto-advanced. +- Bootstrap-`done` setzt `_step` nur wenn bereits in `applying` — verhindert vorzeitigen Dialog-Schluss. + +--- + +## Offene Punkte + +### ⚠️ Screenshare auf Windows (LiveKit) + +`startScreenShare()` wählt auf Windows automatisch die erste verfügbare Screen-Source. +Der `ScreenSharePicker` ist implementiert, muss noch verifiziert werden. + +### ℹ️ Profilbilder in Chats – Lazy Loading + +Profilbilder in der Raumliste und im Chat werden erst beim Öffnen des jeweiligen +Raums geladen (kein Preloading). Ist akzeptables Verhalten, kein Fehler. + +### 📋 Noch nicht implementiert (Settings) + +~~Alle erledigt in Sitzung 3 (26.04.2026): Gerät umbenennen, Alle anderen Sitzungen abmelden, Ed25519-Fingerabdruck, Blockierte Nutzer, Passwort ändern, Konto löschen, Logout-Button~~ + +### 💡 Nice-to-have + +- **QR-Express-Login** (MSC4108): Desktop zeigt QR → Handy scannt → eingeloggt + verifiziert. + Voraussetzung: Rendezvous-Server + SDK-Unterstützung (matrix-dart-sdk ≥ 7.x erwartet). + Aktuell blockiert durch fehlende SDK-API in 6.2.0. + +--- + +## Geänderte Dateien (vollständig) + +| Datei | Inhalt | +|-------|--------| +| `lib/core/livekit_call_manager.dart` | Quality-Bug-Fix, Track-Events, Optimistic Mute, 4K | +| `lib/core/voip_manager.dart` | Kamera-Fix, Optimistic Toggle, Speakerphone-Fix, 4K | +| `lib/features/call/voice_channel.dart` | Kompletter Rewrite: Unified Architecture, adaptive AR, Hero, Mirroring, Grid, Sortierung, Controls | +| `lib/features/call/mini_call_widget.dart` | Steuerungs-Reihenfolge | +| `lib/core/matrix_client.dart` | WAL-Modus, busy_timeout, qrShow in verificationMethods | +| `lib/widgets/pyramid_loader.dart` | 3D CustomPainter (JS-Port), useLottie=false Standard | +| `lib/core/app.dart` | Startup-Flash-Fix: PyramidLoader während isLoggedInProvider lädt | +| `lib/features/chat/chat_view.dart` | Scroll-Stabilisierung: flache Item-Liste, O(1)-Lookup, Cooldown | +| `lib/features/rooms/user_panel.dart` | Eigenes Profilbild via _ownProfileProvider + MxcAvatar | +| `lib/widgets/settings_modal.dart` | QR-Verifikation, Wiederherstellungsschlüssel ändern, Loader-Preview | +| `lib/layout/app_shell.dart` | QR-Verifikation im eingehenden Verifizierungsdialog | +| `pubspec.yaml` | pretty_qr_code, qr hinzugefügt | +| `flutter_launcher_icons.yaml` | Pyramid-Logo für alle Plattformen | +| `windows/runner/resources/app_icon.ico` | Multi-Size ICO (16/32/48/64/128/256px) via Pillow | +| `assets/logo.png` | Pyramid-Logo (1024px) | +| `assets/pyramid-loader.json` | Lottie-Fallback (aus Ordner mit Leerzeichen verschoben) | + +--- + +## Backups + +| Datum | Pfad | +|-------|------| +| 24.04.2026 (Sitzung 1) | `E:\pyramid_backup_20260424` | +| 24.04.2026 (Sitzung 2) | `E:\pyramid_backup_20260424_2` | +| 26.04.2026 | `E:\pyramid_backup_20260426` | diff --git a/ROADMAP.md b/ROADMAP.md new file mode 100644 index 0000000..0b58b4b --- /dev/null +++ b/ROADMAP.md @@ -0,0 +1,96 @@ +# Pyramid – Roadmap + +Die lange Liste. Wird von oben nach unten abgearbeitet (Arbeitszyklus siehe `CLAUDE.md`). +Reihenfolge = Priorität: erst Ordnung & Sicherheit (Datenverlust-Risiken!), dann das +große Refactoring, dann Calls/Streaming/Chat-Features, dann Feinschliff. +Punkte abhaken (`[x]`), wenn erledigt UND in `PROGRESS.md` protokolliert. + +## M0 – Backup & Ordnung + +- [x] Vollbackup vor dem Refactoring (2026-07-03 → `MatrixPi\backups\pyramid-kopie_backup_2026-07-03.tar.gz`) +- [ ] Die ~140 uncommitteten Dateien sichten, in thematische Commits aufteilen, zu Gitea pushen +- [ ] `flutter analyze` komplett sauber bekommen und sauber halten +- [ ] `lib/features/call/` vs. `lib/features/calls/` (leer?) klären – Leiche entfernen +- [ ] README.md durch echte Projektbeschreibung ersetzen (was ist Pyramid, wie baut man es, wo liegt was) + +## M1 – Sicherheit: Nie wieder aussperren / kein Datenverlust + +- [ ] **Uta-Random-Logout untersuchen:** Ursache finden (Soft-Logout vom Server? Token + ungültig? Fehlerpfad im Sync, der zum Logout führt?). Erst Logging an allen + Logout-Pfaden einbauen, dann Ursache fixen. Ein unerwarteter Logout darf NIE + Krypto-Schlüssel wegwerfen. +- [ ] Sichere Speicherung von Access-Token & Krypto-DB prüfen (secure storage / sqlcipher korrekt?) +- [ ] Key-Backup einrichten-Flow: Recovery-Key erzeugen, verständlich erklären, zum Sichern zwingen +- [ ] Key-Backup wiederherstellen-Flow: nach Login auf neuem Gerät alte Nachrichten entschlüsseln +- [ ] Logout-Schutz: Warnung mit Klartext-Folgen, wenn Key-Backup fehlt +- [ ] Geräte-/Sessionverwaltung in den Einstellungen (Liste, Verifizieren, Abmelden) +- [ ] Härtetest dokumentieren: Login → Nachrichten → Logout → Login neu → alles noch lesbar + +## M2 – Das große Refactoring (erst nach M0/M1!) + +Ziel: gleiche Funktionen, saubere **modulare** Struktur – als Fundament für alles Folgende. +Leitprinzip (Bernd): austauschbare Bausteine – jedes Modul muss sich komplett neu schreiben +lassen, ohne dass andere Module angefasst werden müssen. + +- [ ] Ist-Analyse schreiben: Architektur-Schwächen auflisten (Call-Logik verteilt auf + `livekit_call_manager.dart`, `voip_manager.dart`, `voice_channel.dart`?, State-Management + uneinheitlich?, Gott-Dateien?, tote Widgets?) → als Refactoring-Plan in PROGRESS.md +- [ ] Modul-Schnitt definieren: Module (auth, chat, rooms, calls, streaming, push, storage, …) + mit je einer schmalen öffentlichen Schnittstelle; Abhängigkeiten nur über Interfaces, + keine Quer-Importe zwischen Feature-Modulen +- [ ] Call-Schicht entwirren: EINE klare Zuständigkeit pro Klasse (Signalisierung / + LiveKit-Verbindung / UI-State sauber getrennt) +- [ ] Einheitliches State-Management (Riverpod konsequent, keine Misch-Patterns) +- [ ] Toten Code & Duplikate entfernen, Ordnerstruktur vereinheitlichen +- [ ] Nach JEDEM Schritt: App läuft, Kernflows getestet, Commit + +## M3 – Calls: Logik, UI & Audio (Discord als Referenz) + +- [ ] Voice-Channel-Logik robust machen: Beitreten/Verlassen/Wechseln ohne Hänger, + klarer Zustand wer drin ist, sauberes Verhalten bei Verbindungsabbruch +- [ ] Call-UI aufräumen: aufgeräumter, intuitiver, konsistent (Mini-Call-Widget, Vollansicht) +- [ ] **Windows: Audiogeräte-Erkennung reparieren** (Mikrofon/Ausgabe erkennen und in den + Einstellungen auswählbar machen – geht aktuell gar nicht) +- [ ] Noise Suppression als optionale Einstellung (z. B. RNNoise/LiveKit-Audio-Filter) +- [ ] Lautstärke pro Teilnehmer einstellbar (Discord-Style, persistent pro Nutzer) +- [ ] Weitere Feinjustierung: Eingangsempfindlichkeit/Gate, Echo-Unterdrückung an/aus, + Push-to-Talk prüfen – von Discords Sprach-Einstellungen inspirieren lassen +- [ ] Anruf-Benachrichtigung auch bei gekillter App (Push-Architektur nutzen) + +## M4 – Streaming (Bildschirmübertragung) + +- [ ] **Framerate verbessern:** Ursache messen (Encoder? Auflösung? Simulcast-Settings? + Software- statt Hardware-Encoding?), dann gezielt fixen +- [ ] Auflösung/Qualität wählbar für den **Streamer** (z. B. 720p/1080p + FPS-Wahl) +- [ ] Qualität wählbar für den **Empfänger** (LiveKit-Simulcast-Layer auswählen) +- [ ] Sauberes Degradieren bei schwacher Bandbreite statt Ruckel-Chaos + +## M5 – Chat-Funktionen + +- [ ] Sprachnachrichten aufnehmen & abspielen (MSC3245-kompatibel, wie Element) +- [ ] **Bilder speichern → richtige Galerie:** über MediaStore/Downloads statt in den + unzugänglichen App-Ordner (Android Scoped Storage korrekt nutzen) +- [ ] Medien senden/empfangen generell prüfen (Fortschritt, Vorschau, Videos) + +## M6 – Release & Verteilung + +- [ ] **Google-Warnung beim Installieren untersuchen:** Play-Protect-Meldung seit der + Signatur-Einführung analysieren (Signing-Konfig prüfen; unbekannte Signatur + Sideload + löst das oft aus; ggf. Play-Protect-Appeal oder saubere v2/v3-Signierung) +- [ ] Release-Skript prüfen/aktualisieren (Windows + Android), Versionierung sauber +- [ ] In-App-Updater testen (existiert laut Git-Historie) + +## M7 – Design & Feinschliff + +- [ ] Rooms-Icon überarbeiten – passt stilistisch nicht zu den anderen Buttons +- [ ] Design-Konsistenz-Pass über alle Icons/Buttons +- [ ] Onboarding: erster Start erklärt Server-Wahl und Verifikation verständlich +- [ ] Themes/Darkmode-Feinschliff, Schriftgrößen + +## Ideen-Parkplatz (unsortiert, erst nach M7 bewerten) + +- Threads, Sticker, Standort teilen, mehrere Konten +- Watch-Together (z. B. Jellyfin gemeinsam schauen) + +> Bernd: „Das ist nur der Anfang meiner Liste" – neue Punkte einfach hier in den +> passenden Meilenstein eintragen (oder Claude sagen, er soll sie einsortieren). diff --git a/analysis_options.yaml b/analysis_options.yaml index 0d29021..5a64268 100644 --- a/analysis_options.yaml +++ b/analysis_options.yaml @@ -9,6 +9,11 @@ # packages, and plugins designed to encourage good coding practices. include: package:flutter_lints/flutter.yaml +analyzer: + exclude: + # Design-Mockups, kein Produktionscode — nicht analysieren. + - mockup/** + linter: # The lint rules applied to this project can be customized in the # section below to disable rules from the `package:flutter_lints/flutter.yaml` diff --git a/android/app/build.gradle.kts b/android/app/build.gradle.kts index 0f7fbda..165e3e5 100644 --- a/android/app/build.gradle.kts +++ b/android/app/build.gradle.kts @@ -1,8 +1,19 @@ +import java.util.Properties + plugins { id("com.android.application") id("kotlin-android") // The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins. id("dev.flutter.flutter-gradle-plugin") + id("com.google.gms.google-services") +} + +// Release signing is configured via android/key.properties (gitignored). +// The keystore lives outside the repo; see key.properties for the path. +val keystoreProperties = Properties() +val keystorePropertiesFile = rootProject.file("key.properties") +if (keystorePropertiesFile.exists()) { + keystorePropertiesFile.inputStream().use { keystoreProperties.load(it) } } android { @@ -11,6 +22,7 @@ android { ndkVersion = flutter.ndkVersion compileOptions { + isCoreLibraryDesugaringEnabled = true sourceCompatibility = JavaVersion.VERSION_17 targetCompatibility = JavaVersion.VERSION_17 } @@ -30,13 +42,42 @@ android { versionName = flutter.versionName } - buildTypes { - release { - // TODO: Add your own signing config for the release build. - // Signing with the debug keys for now, so `flutter run --release` works. - signingConfig = signingConfigs.getByName("debug") + signingConfigs { + if (keystorePropertiesFile.exists()) { + create("release") { + keyAlias = keystoreProperties["keyAlias"] as String + keyPassword = keystoreProperties["keyPassword"] as String + storeFile = file(keystoreProperties["storeFile"] as String) + storePassword = keystoreProperties["storePassword"] as String + } } } + + buildTypes { + release { + // Falls back to debug signing on machines without key.properties + // so `flutter run --release` still works there. + signingConfig = if (keystorePropertiesFile.exists()) { + signingConfigs.getByName("release") + } else { + signingConfigs.getByName("debug") + } + isMinifyEnabled = true + isShrinkResources = true + proguardFiles( + getDefaultProguardFile("proguard-android-optimize.txt"), + "proguard-rules.pro", + ) + } + } +} + +dependencies { + coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4") + // Required to compile PushService.kt which extends FirebaseMessagingService directly. + // Version must stay in sync with FirebaseSDKVersion in firebase_core's gradle.properties. + implementation(platform("com.google.firebase:firebase-bom:33.16.0")) + implementation("com.google.firebase:firebase-messaging-ktx") } flutter { diff --git a/android/app/google-services.json b/android/app/google-services.json new file mode 100644 index 0000000..c609036 --- /dev/null +++ b/android/app/google-services.json @@ -0,0 +1,29 @@ +{ + "project_info": { + "project_number": "858748942228", + "project_id": "chat-pyramid", + "storage_bucket": "chat-pyramid.firebasestorage.app" + }, + "client": [ + { + "client_info": { + "mobilesdk_app_id": "1:858748942228:android:661405508fbb2f40d30181", + "android_client_info": { + "package_name": "chat.pyramid.pyramid" + } + }, + "oauth_client": [], + "api_key": [ + { + "current_key": "AIzaSyDbqLHYFHqUdPOAexDFTpMvQVkQHY6chFE" + } + ], + "services": { + "appinvite_service": { + "other_platform_oauth_client": [] + } + } + } + ], + "configuration_version": "1" +} \ No newline at end of file diff --git a/android/app/proguard-rules.pro b/android/app/proguard-rules.pro new file mode 100644 index 0000000..3d16a07 --- /dev/null +++ b/android/app/proguard-rules.pro @@ -0,0 +1,18 @@ +# Flutter's own keep rules are added automatically by the Flutter Gradle plugin. + +# WebRTC / LiveKit: native code calls Java classes via JNI by name, +# so nothing under org.webrtc may be stripped or renamed. +-keep class org.webrtc.** { *; } +-dontwarn org.webrtc.** +-keep class livekit.org.webrtc.** { *; } +-dontwarn livekit.org.webrtc.** + +# flutter_local_notifications deserializes scheduled notifications with Gson +# using reflection; stripped type adapters crash on the next reboot/schedule. +-keep class com.dexterous.flutterlocalnotifications.** { *; } +-keepattributes Signature +-keepattributes *Annotation* + +# Flutter references Play Core for deferred components, which this app +# doesn't ship — silence the missing-class errors from R8. +-dontwarn com.google.android.play.core.** diff --git a/android/app/src/main/AndroidManifest.xml b/android/app/src/main/AndroidManifest.xml index 2412157..018de07 100644 --- a/android/app/src/main/AndroidManifest.xml +++ b/android/app/src/main/AndroidManifest.xml @@ -1,4 +1,6 @@ - + + @@ -7,8 +9,13 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/kotlin/chat/pyramid/pyramid/BgEngine.kt b/android/app/src/main/kotlin/chat/pyramid/pyramid/BgEngine.kt new file mode 100644 index 0000000..d07a45d --- /dev/null +++ b/android/app/src/main/kotlin/chat/pyramid/pyramid/BgEngine.kt @@ -0,0 +1,140 @@ +package chat.pyramid.pyramid + +import android.content.Context +import android.os.Handler +import android.os.Looper +import android.util.Log +import io.flutter.FlutterInjector +import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.dart.DartExecutor +import io.flutter.plugin.common.MethodChannel +import io.flutter.view.FlutterCallbackInformation + +/** + * Bootstraps a headless Flutter background engine running the + * `notificationEngineMain` Dart entrypoint and forwards work items + * (decrypt-and-show, send-reply) to it via a MethodChannel. + * + * Only used when the app is KILLED (no main FlutterEngine). The Dart side builds + * a short-lived Matrix client against the same DB to decrypt / send. This is safe + * because callers gate on the main app being dead — never two clients at once. + */ +object BgEngine { + private const val TAG = "PYRAMID-BGENGINE" + private const val CHANNEL = "chat.pyramid.pyramid/bg_engine" + + private var engine: FlutterEngine? = null + private var channel: MethodChannel? = null + private var ready = false + private var appContext: Context? = null + // Tasks queued until the Dart handler signals readiness. + private val pending = mutableListOf>>() + // Pending "Neue Nachricht" fallback placeholders, keyed by notifId. Shown + // only if decryption doesn't replace them in time; cancelled by showDecrypted. + private val fallbackHandler = Handler(Looper.getMainLooper()) + private val fallbacks = mutableMapOf() + + /** Schedule a placeholder shown after [delayMs] unless decryption beats it. */ + fun scheduleFallback(context: Context, title: String, roomId: String, notifId: Int, delayMs: Long) { + val ctx = context.applicationContext + appContext = ctx + fallbackHandler.post { + cancelFallback(notifId) + val r = Runnable { + fallbacks.remove(notifId) + NotificationHelper.show(ctx, title, "Neue Nachricht", roomId, notifId) + Log.d(TAG, "fallback placeholder shown for $roomId (decrypt too slow)") + } + fallbacks[notifId] = r + fallbackHandler.postDelayed(r, delayMs) + } + } + + private fun cancelFallback(notifId: Int) { + fallbacks.remove(notifId)?.let { fallbackHandler.removeCallbacks(it) } + } + + /** Enqueue a task; boots the engine on first use. Must run on the main thread. */ + fun run(context: Context, method: String, args: Map) { + appContext = context.applicationContext + Handler(Looper.getMainLooper()).post { + try { + ensureEngine(context.applicationContext) + if (ready) { + channel?.invokeMethod(method, args) + } else { + pending.add(method to args) + } + } catch (e: Exception) { + Log.w(TAG, "run failed: ${e.message}") + } + } + } + + private fun ensureEngine(context: Context) { + if (engine != null) return + + val prefs = context.getSharedPreferences("FlutterSharedPreferences", Context.MODE_PRIVATE) + val handle = try { + prefs.getLong("flutter.bg_engine_handle", 0L) + } catch (_: Exception) { + 0L + } + if (handle == 0L) { + Log.w(TAG, "no bg_engine_handle stored — cannot start background engine") + return + } + + // The Flutter native library must be loaded BEFORE looking up the + // callback — nativeLookupCallbackInformation is a native method and + // throws UnsatisfiedLinkError otherwise. + val loader = FlutterInjector.instance().flutterLoader() + loader.startInitialization(context) + loader.ensureInitializationComplete(context, null) + + val cbInfo = FlutterCallbackInformation.lookupCallbackInformation(handle) + if (cbInfo == null) { + Log.w(TAG, "callback info not found for handle $handle") + return + } + + val eng = FlutterEngine(context) + engine = eng + + val ch = MethodChannel(eng.dartExecutor.binaryMessenger, CHANNEL) + channel = ch + ch.setMethodCallHandler { call, result -> + when (call.method) { + "bgEngineReady" -> { + ready = true + Log.d(TAG, "Dart background engine ready — flushing ${pending.size} task(s)") + pending.forEach { (m, a) -> ch.invokeMethod(m, a) } + pending.clear() + result.success(null) + } + // Dart finished decrypting — show the real content using the SAME + // native notification (keeps the reliable MainActivity reply action). + "showDecrypted" -> { + val title = call.argument("title") ?: "" + val body = call.argument("body") ?: "Neue Nachricht" + val roomId = call.argument("room_id") ?: "" + val notifId = call.argument("notif_id") ?: NotificationHelper.stableId(roomId) + val ctx = appContext + if (ctx != null && roomId.isNotEmpty()) { + // Beat the fallback placeholder to it — show decrypted directly. + cancelFallback(notifId) + NotificationHelper.show(ctx, title, body, roomId, notifId) + Log.d(TAG, "showDecrypted → shown decrypted notification for $roomId") + } + result.success(null) + } + else -> result.notImplemented() + } + } + + eng.dartExecutor.executeDartCallback( + DartExecutor.DartCallback(context.assets, loader.findAppBundlePath(), cbInfo) + ) + Log.d(TAG, "background engine started") + } +} diff --git a/android/app/src/main/kotlin/chat/pyramid/pyramid/MainActivity.kt b/android/app/src/main/kotlin/chat/pyramid/pyramid/MainActivity.kt index 6310bfa..c9ab274 100644 --- a/android/app/src/main/kotlin/chat/pyramid/pyramid/MainActivity.kt +++ b/android/app/src/main/kotlin/chat/pyramid/pyramid/MainActivity.kt @@ -3,49 +3,270 @@ package chat.pyramid.pyramid import android.content.Intent import android.net.Uri import android.os.Build +import android.os.Bundle +import android.provider.Settings +import android.util.Log +import androidx.core.app.RemoteInput import androidx.core.content.FileProvider import io.flutter.embedding.android.FlutterActivity import io.flutter.embedding.engine.FlutterEngine +import io.flutter.embedding.engine.FlutterEngineCache import io.flutter.plugin.common.MethodChannel import java.io.File class MainActivity : FlutterActivity() { private val channel = "chat.pyramid.pyramid/install" + // ── Share-Target (Teilen nach Pyramid) ──────────────────────────────────── + // Extracts shared text/streams from SEND/SEND_MULTIPLE intents. Streams are + // copied into cacheDir because Flutter cannot read content:// URIs directly. + private fun extractShare(intent: Intent?): Map? { + if (intent == null) return null + val action = intent.action + if (action != Intent.ACTION_SEND && action != Intent.ACTION_SEND_MULTIPLE) return null + val text = intent.getStringExtra(Intent.EXTRA_TEXT) + val uris = mutableListOf() + if (action == Intent.ACTION_SEND) { + val u: Uri? = if (Build.VERSION.SDK_INT >= 33) + intent.getParcelableExtra(Intent.EXTRA_STREAM, Uri::class.java) + else @Suppress("DEPRECATION") intent.getParcelableExtra(Intent.EXTRA_STREAM) + if (u != null) uris.add(u) + } else { + val list: ArrayList? = if (Build.VERSION.SDK_INT >= 33) + intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM, Uri::class.java) + else @Suppress("DEPRECATION") intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM) + if (list != null) uris.addAll(list) + } + if (text.isNullOrEmpty() && uris.isEmpty()) return null + val paths = uris.mapNotNull { copyShareToCache(it) } + return mapOf("text" to text, "paths" to paths) + } + + private fun copyShareToCache(uri: Uri): String? { + return try { + val name = contentResolver.query(uri, null, null, null, null)?.use { c -> + val idx = c.getColumnIndex(android.provider.OpenableColumns.DISPLAY_NAME) + if (idx >= 0 && c.moveToFirst()) c.getString(idx) else null + } ?: "shared_${System.currentTimeMillis()}" + val safe = name.replace(Regex("[^A-Za-z0-9._-]"), "_") + val outFile = File(cacheDir, "share_${System.currentTimeMillis()}_$safe") + val stream = contentResolver.openInputStream(uri) ?: return null + stream.use { input -> + outFile.outputStream().use { input.copyTo(it) } + } + outFile.absolutePath + } catch (e: Exception) { + Log.e("PYRAMID-SHARE", "copyShareToCache failed: ${e.message}") + null + } + } + + // Extract reply text from an intent using all known key patterns. + private fun extractReply(intent: Intent?): Pair { + if (intent == null) return Pair(null, null) + // Only treat intents with our REPLY action as reply intents. + if (intent.action != ReplyReceiver.ACTION_REPLY) return Pair(null, null) + val remoteInputResults = RemoteInput.getResultsFromIntent(intent) + val replyText: String? = + remoteInputResults?.let { bundle -> + // Primary key must match RemoteInput.Builder key in NotificationHelper. + bundle.getCharSequence(ReplyReceiver.REMOTE_INPUT_KEY)?.toString()?.trim() + ?: bundle.keySet()?.firstOrNull()?.let { bundle.getCharSequence(it)?.toString()?.trim() } + } + ?: intent.getStringExtra(ReplyReceiver.REMOTE_INPUT_KEY) + ?: intent.getStringExtra("input") + val payload = intent.getStringExtra(ReplyReceiver.EXTRA_ROOM_ID) + ?: intent.getStringExtra("payload") + return Pair(replyText, payload) + } + + override fun onCreate(savedInstanceState: Bundle?) { + // If this Activity was launched to handle a notification reply (cold start), + // apply a fully transparent theme BEFORE super.onCreate so no UI is ever + // drawn. The Flutter engine still initialises (needed for E2EE send via SDK) + // but the window remains invisible. + val (replyText, _) = extractReply(intent) + if (!replyText.isNullOrEmpty()) { + setTheme(R.style.ReplyHandlerTheme) + Log.e("PYRAMID-INTENT", "onCreate: reply launch detected — transparent theme applied") + } + super.onCreate(savedInstanceState) + } + override fun configureFlutterEngine(flutterEngine: FlutterEngine) { super.configureFlutterEngine(flutterEngine) + // Cache so ReplyReceiver can call back into Dart without starting a new engine. + FlutterEngineCache.getInstance().put("main", flutterEngine) MethodChannel(flutterEngine.dartExecutor.binaryMessenger, channel) .setMethodCallHandler { call, result -> - if (call.method == "installApk") { - val path = call.argument("path") - if (path == null) { - result.error("INVALID_ARG", "path is null", null) - return@setMethodCallHandler + when (call.method) { + // Flutter asks for the room_id embedded in the launch intent (cold-start tap). + "getInitialRoomId" -> { + result.success(intent?.getStringExtra("room_id")) } - try { - val file = File(path) - val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - FileProvider.getUriForFile( - this, - "${applicationContext.packageName}.fileprovider", - file - ) + // Cold-start share: app was launched via "Teilen nach Pyramid". + "getInitialShare" -> { + val share = extractShare(intent) + if (share != null) { + result.success(share) + intent = Intent() // clear so it's delivered only once } else { - Uri.fromFile(file) + result.success(null) } - val intent = Intent(Intent.ACTION_VIEW).apply { - setDataAndType(uri, "application/vnd.android.package-archive") - addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + // Flutter asks for any inline reply that arrived on cold-start. + // When the app is killed and the user presses Reply, Android calls + // onCreate (not onNewIntent), so the reply text is in the launch intent. + "getInitialReply" -> { + val (replyText, payload) = extractReply(intent) + Log.e("PYRAMID-INTENT", "getInitialReply: replyText=${replyText?.take(20)} payload=$payload") + if (!replyText.isNullOrEmpty() && !payload.isNullOrEmpty()) { + result.success(mapOf("room_id" to payload, "text" to replyText)) + // Clear the launch intent so a second getInitialReply call returns null. + intent = Intent() + } else { + result.success(null) } + } + // Supported CPU ABIs in preference order, so the updater can + // pick the matching split APK from a release. + "getAbis" -> { + result.success(Build.SUPPORTED_ABIS.toList()) + } + "installApk" -> { + val path = call.argument("path") + if (path == null) { + result.error("INVALID_ARG", "path is null", null) + return@setMethodCallHandler + } + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && + !packageManager.canRequestPackageInstalls()) { + val intent = Intent(Settings.ACTION_MANAGE_UNKNOWN_APP_SOURCES).apply { + data = Uri.parse("package:$packageName") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + startActivity(intent) + result.error("PERMISSION_REQUIRED", "install_permission", null) + return@setMethodCallHandler + } + try { + val file = File(path) + val uri: Uri = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { + FileProvider.getUriForFile( + this, + "${applicationContext.packageName}.fileprovider", + file + ) + } else { + Uri.fromFile(file) + } + val intent = Intent(Intent.ACTION_VIEW).apply { + setDataAndType(uri, "application/vnd.android.package-archive") + addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + startActivity(intent) + result.success(null) + } catch (e: Exception) { + result.error("INSTALL_ERROR", e.message, null) + } + } + "openNotificationSettings" -> { + val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply { + putExtra(Settings.EXTRA_APP_PACKAGE, packageName) + } + } else { + Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", packageName, null) + } + } + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) startActivity(intent) result.success(null) - } catch (e: Exception) { - result.error("INSTALL_ERROR", e.message, null) } - } else { - result.notImplemented() + "openBatterySettings" -> { + val intent = Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS).apply { + data = Uri.parse("package:$packageName") + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + try { + startActivity(intent) + } catch (e: Exception) { + val fallback = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS).apply { + data = Uri.fromParts("package", packageName, null) + addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + } + startActivity(fallback) + } + result.success(null) + } + "minimizeApp" -> { + moveTaskToBack(true) + result.success(null) + } + "showNativeNotification" -> { + val title = call.argument("title") ?: "" + val body = call.argument("body") ?: "" + val roomId = call.argument("roomId") ?: "" + val notifId = call.argument("notifId") ?: NotificationHelper.stableId(roomId) + if (roomId.isNotEmpty()) { + NotificationHelper.show(this, title, body, roomId, notifId) + result.success(null) + } else { + result.error("INVALID_ARG", "roomId missing", null) + } + } + else -> result.notImplemented() } } } + + // Called when the app is already running (background) and a notification action + // fires — reply and tap both arrive here via onNewIntent (singleTop + SINGLE_TOP flag). + override fun onNewIntent(intent: Intent) { + // Zero-duration transition for all notification-driven intents. + overridePendingTransition(0, 0) + + super.onNewIntent(intent) + setIntent(intent) + + Log.e("PYRAMID-INTENT", "onNewIntent action=${intent.action}") + + // ── Reply action ────────────────────────────────────────────────────── + if (intent.action == ReplyReceiver.ACTION_REPLY) { + val (replyText, payload) = extractReply(intent) + Log.e("PYRAMID-INTENT", "reply: replyText=${replyText?.take(20)} payload=$payload") + if (!replyText.isNullOrEmpty() && !payload.isNullOrEmpty()) { + flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger -> + MethodChannel(messenger, channel).invokeMethod( + "replyFromNotification", + mapOf("room_id" to payload, "text" to replyText), + ) + } + } + // Always send back immediately — never show the app UI for a reply. + moveTaskToBack(true) + overridePendingTransition(0, 0) + return + } + + // ── Share action — app already running, user shared from another app ── + val share = extractShare(intent) + if (share != null) { + flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger -> + MethodChannel(messenger, channel).invokeMethod("sharedContent", share) + } + return + } + + // ── Tap action — open the room ──────────────────────────────────────── + val roomId = intent.getStringExtra("room_id") ?: return + flutterEngine?.dartExecutor?.binaryMessenger?.let { messenger -> + MethodChannel(messenger, channel).invokeMethod( + "openRoom", + mapOf("room_id" to roomId), + ) + } + } } diff --git a/android/app/src/main/kotlin/chat/pyramid/pyramid/NotificationHelper.kt b/android/app/src/main/kotlin/chat/pyramid/pyramid/NotificationHelper.kt new file mode 100644 index 0000000..c3ea032 --- /dev/null +++ b/android/app/src/main/kotlin/chat/pyramid/pyramid/NotificationHelper.kt @@ -0,0 +1,107 @@ +package chat.pyramid.pyramid + +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.PendingIntent +import android.content.Context +import android.content.Intent +import android.graphics.Color +import android.os.Build +import androidx.core.app.NotificationCompat +import androidx.core.app.RemoteInput + +object NotificationHelper { + const val CHANNEL_ID = "pyramid_messages" + + /** Deterministic notification ID — same algorithm as Dart's _stableRoomId. */ + fun stableId(roomId: String): Int { + var h = 0 + for (c in roomId) h = ((h * 31) + c.code) and 0x7FFFFFFF + return if (h == 0) 1 else h + } + + fun ensureChannel(context: Context) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, "Nachrichten", NotificationManager.IMPORTANCE_HIGH + ).apply { + description = "Neue Nachrichten" + enableVibration(true) + } + nm(context).createNotificationChannel(channel) + } + } + + fun show(context: Context, title: String, body: String, roomId: String, notifId: Int) { + ensureChannel(context) + + val mutFlag = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) + PendingIntent.FLAG_MUTABLE else 0 + + // Reply action — BroadcastReceiver so replying NEVER opens the app. + // ReplyReceiver decrypts/sends via the background engine when killed. + // (ReplyReceiver has multiple RemoteInput key fallbacks for OEM quirks.) + val replyInput = RemoteInput.Builder(ReplyReceiver.REMOTE_INPUT_KEY) + .setLabel("Antworten…").build() + val replyIntent = Intent(context, ReplyReceiver::class.java).apply { + action = ReplyReceiver.ACTION_REPLY + putExtra(ReplyReceiver.EXTRA_ROOM_ID, roomId) + putExtra(ReplyReceiver.EXTRA_NOTIF_ID, notifId) + } + val replyPi = PendingIntent.getBroadcast( + context, notifId, + replyIntent, + PendingIntent.FLAG_UPDATE_CURRENT or mutFlag, + ) + val replyAction = NotificationCompat.Action.Builder(0, "Antworten", replyPi) + .addRemoteInput(replyInput) + .setSemanticAction(NotificationCompat.Action.SEMANTIC_ACTION_REPLY) + .build() + + // Dismiss action — also points to ReplyReceiver so notification is cancelled. + val dismissIntent = Intent(context, ReplyReceiver::class.java).apply { + action = ReplyReceiver.ACTION_DISMISS + putExtra(ReplyReceiver.EXTRA_ROOM_ID, roomId) + putExtra(ReplyReceiver.EXTRA_NOTIF_ID, notifId) + } + val dismissPi = PendingIntent.getBroadcast( + context, notifId + 1_000_000, + dismissIntent, + PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE, + ) + + // Tap action — opens MainActivity to the right room. + val tapIntent = Intent(context, MainActivity::class.java).apply { + action = Intent.ACTION_MAIN + addCategory(Intent.CATEGORY_LAUNCHER) + putExtra("room_id", roomId) + flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP + } + val tapPi = PendingIntent.getActivity( + context, notifId + 2_000_000, + tapIntent, + PendingIntent.FLAG_UPDATE_CURRENT or mutFlag, + ) + + val notif = NotificationCompat.Builder(context, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_notification) + .setColor(Color.rgb(0x7B, 0x61, 0xFF)) + .setContentTitle(title) + .setContentText(body) + .setPriority(NotificationCompat.PRIORITY_HIGH) + // Only buzz/heads-up on the first show — the decrypted update reuses + // the same notifId and replaces the text silently (no second alert). + .setOnlyAlertOnce(true) + .setContentIntent(tapPi) + .setAutoCancel(true) + .addAction(replyAction) + .addAction(NotificationCompat.Action(0, "Gelesen", dismissPi)) + .setGroup(CHANNEL_ID) + .build() + + nm(context).notify(notifId, notif) + } + + private fun nm(context: Context) = + context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager +} diff --git a/android/app/src/main/kotlin/chat/pyramid/pyramid/PushService.kt b/android/app/src/main/kotlin/chat/pyramid/pyramid/PushService.kt new file mode 100644 index 0000000..bed947c --- /dev/null +++ b/android/app/src/main/kotlin/chat/pyramid/pyramid/PushService.kt @@ -0,0 +1,160 @@ +package chat.pyramid.pyramid + +import android.os.Handler +import android.os.Looper +import android.util.Log +import com.google.firebase.messaging.FirebaseMessagingService +import com.google.firebase.messaging.RemoteMessage +import io.flutter.embedding.engine.FlutterEngineCache +import io.flutter.plugin.common.MethodChannel +import org.json.JSONObject +import java.net.HttpURLConnection +import java.net.URL +import java.util.concurrent.CountDownLatch +import java.util.concurrent.TimeUnit + +class PushService : FirebaseMessagingService() { + + override fun onMessageReceived(message: RemoteMessage) { + val data = message.data + val roomId = data["room_id"] ?: run { + Log.d(TAG, "no room_id in payload, skipping") + return + } + + val prefs = getSharedPreferences("FlutterSharedPreferences", MODE_PRIVATE) + + // Skip if the Dart app is actively syncing (wrote a heartbeat < 20 s ago). + val heartbeat = try { + prefs.getLong("flutter.notif_app_heartbeat", 0L) + .takeIf { it > 0L } + ?: prefs.getInt("flutter.notif_app_heartbeat", 0).toLong() + } catch (_: Exception) { 0L } + if (System.currentTimeMillis() - heartbeat < 20_000L) { + Log.d(TAG, "app heartbeat fresh, skipping FCM notification") + return + } + + val eventId = data["event_id"] + val notifId = NotificationHelper.stableId(roomId) + val hs = (prefs.getString("flutter.notif_homeserver", "") ?: "").trimEnd('/') + val token = (prefs.getString("flutter.notif_access_token", "") ?: "") + + // Fetch sender + room name on a background thread (main thread forbids I/O). + var title = "Pyramid" + if (hs.isNotEmpty() && token.isNotEmpty() && eventId != null) { + val latch = CountDownLatch(1) + Thread { + try { title = fetchTitle(hs, token, roomId, eventId) ?: "Pyramid" } + finally { latch.countDown() } + }.start() + latch.await(12L, TimeUnit.SECONDS) + } + + Log.d(TAG, "handling push: title=$title roomId=$roomId") + + val engine = FlutterEngineCache.getInstance().get("main") + if (engine != null) { + // App backgrounded but alive — show placeholder immediately, then the + // warm main client decrypts and updates it (fast, barely visible). + NotificationHelper.show(this, title, "Neue Nachricht", roomId, notifId) + if (eventId != null) { + val capturedRoomId = roomId + val capturedEventId = eventId + val capturedNotifId = notifId + Handler(Looper.getMainLooper()).post { + try { + MethodChannel(engine.dartExecutor.binaryMessenger, + "chat.pyramid.pyramid/install") + .invokeMethod("decryptAndUpdateNotification", mapOf( + "room_id" to capturedRoomId, + "event_id" to capturedEventId, + "notif_id" to capturedNotifId, + )) + Log.d(TAG, "decryptAndUpdateNotification invoked (main engine) for $capturedRoomId") + } catch (e: Exception) { + Log.w(TAG, "decryptAndUpdateNotification failed: ${e.message}") + } + } + } + } else if (eventId != null) { + // App killed — decrypt FIRST via the background engine, then show the + // real content directly. The "Neue Nachricht" placeholder is only a + // fallback if decryption takes too long or fails. + Log.d(TAG, "main engine gone — decrypt-first via background engine for $roomId") + BgEngine.scheduleFallback(this, title, roomId, notifId, 6_000L) + BgEngine.run(this, "decryptAndShow", mapOf( + "room_id" to roomId, + "event_id" to eventId, + "notif_id" to notifId, + )) + } else { + // No event id to decrypt — just show the placeholder. + NotificationHelper.show(this, title, "Neue Nachricht", roomId, notifId) + } + } + + override fun onNewToken(token: String) { + Log.d(TAG, "FCM token refreshed — storing for Dart to re-register pusher") + getSharedPreferences("FlutterSharedPreferences", MODE_PRIVATE) + .edit() + .putString("flutter.fcm_pending_token", token) + .apply() + } + + // ─── HTTP helpers ───────────────────────────────────────────────────────── + + private fun fetchTitle( + hs: String, token: String, roomId: String, eventId: String + ): String? { + return try { + val encRoom = java.net.URLEncoder.encode(roomId, "UTF-8") + val encEvent = java.net.URLEncoder.encode(eventId, "UTF-8") + + val event = httpGet("$hs/_matrix/client/v3/rooms/$encRoom/event/$encEvent", token) + ?: return null + + val senderId = event.optString("sender") + var senderName = senderId.split(":").firstOrNull()?.removePrefix("@") ?: "" + + if (senderId.isNotEmpty()) { + val encSender = java.net.URLEncoder.encode(senderId, "UTF-8") + val member = httpGet( + "$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.member/$encSender", token) + val name = member?.optString("displayname") + if (!name.isNullOrEmpty()) senderName = name + } + + val nameState = httpGet("$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.name", token) + val roomName = nameState?.optString("name") + + return if (!roomName.isNullOrEmpty()) "$senderName · $roomName" + else senderName.ifEmpty { null } + } catch (e: Exception) { + Log.w(TAG, "fetchTitle failed: ${e.message}") + null + } + } + + private fun httpGet(url: String, token: String): JSONObject? { + var conn: HttpURLConnection? = null + return try { + conn = (URL(url).openConnection() as HttpURLConnection).apply { + requestMethod = "GET" + setRequestProperty("Authorization", "Bearer $token") + connectTimeout = 8_000 + readTimeout = 8_000 + } + if (conn.responseCode != 200) return null + JSONObject(conn.inputStream.bufferedReader().readText()) + } catch (_: Exception) { + null + } finally { + conn?.disconnect() + } + } + + companion object { + private const val TAG = "PYRAMID-PUSH" + } +} diff --git a/android/app/src/main/kotlin/chat/pyramid/pyramid/ReplyReceiver.kt b/android/app/src/main/kotlin/chat/pyramid/pyramid/ReplyReceiver.kt new file mode 100644 index 0000000..8bb786d --- /dev/null +++ b/android/app/src/main/kotlin/chat/pyramid/pyramid/ReplyReceiver.kt @@ -0,0 +1,84 @@ +package chat.pyramid.pyramid + +import android.app.NotificationManager +import android.content.BroadcastReceiver +import android.content.Context +import android.content.Intent +import android.util.Log +import androidx.core.app.RemoteInput +import io.flutter.embedding.engine.FlutterEngineCache +import io.flutter.plugin.common.MethodChannel + +class ReplyReceiver : BroadcastReceiver() { + + companion object { + const val ACTION_REPLY = "chat.pyramid.pyramid.REPLY" + const val ACTION_DISMISS = "chat.pyramid.pyramid.DISMISS" + const val EXTRA_ROOM_ID = "room_id" + const val EXTRA_NOTIF_ID = "notif_id" + const val REMOTE_INPUT_KEY = "reply_text" + } + + override fun onReceive(context: Context, intent: Intent) { + val roomId = intent.getStringExtra(EXTRA_ROOM_ID) ?: return + val notifId = intent.getIntExtra(EXTRA_NOTIF_ID, 0) + + // Dismiss the notification immediately. + (context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager) + .cancel(notifId) + + if (intent.action == ACTION_DISMISS) { + Log.d("PYRAMID-REPLY", "dismiss action for room $roomId") + return + } + + // Extract inline reply text. Some Samsung/MIUI/OEM devices drop the + // RemoteInput bundle or use a different key — try multiple fallbacks. + val remoteInput = RemoteInput.getResultsFromIntent(intent) + val replyText = remoteInput?.let { bundle -> + bundle.getCharSequence(REMOTE_INPUT_KEY)?.toString()?.trim() + ?: bundle.keySet()?.firstOrNull()?.let { bundle.getCharSequence(it)?.toString()?.trim() } + } ?: intent.getStringExtra(REMOTE_INPUT_KEY) + ?: intent.getStringExtra("input") + ?: intent.getStringExtra("notification_action_input") + ?: intent.getStringExtra("reply_text") + Log.d("PYRAMID-REPLY", "extracted replyText=${replyText?.take(20)} (remoteInput=${remoteInput != null})") + if (replyText.isNullOrEmpty()) { + Log.w("PYRAMID-REPLY", "reply text empty after all fallbacks, aborting") + return + } + + Log.d("PYRAMID-REPLY", "reply received: room=$roomId text=$replyText") + + // Fast path: Flutter engine is alive — forward directly via MethodChannel. + val engine = FlutterEngineCache.getInstance().get("main") + if (engine != null) { + Log.d("PYRAMID-REPLY", "Flutter engine alive → MethodChannel") + try { + MethodChannel(engine.dartExecutor.binaryMessenger, "chat.pyramid.pyramid/install") + .invokeMethod("replyFromNotification", + mapOf("room_id" to roomId, "text" to replyText)) + return + } catch (e: Exception) { + Log.w("PYRAMID-REPLY", "MethodChannel failed: ${e.message}, falling back to prefs") + } + } + + // Slow path: app killed — send the encrypted reply via the background + // engine (no Activity, fully silent). _bgSendReply falls back to the + // prefs queue itself if it can't send, so nothing is lost. + // goAsync() keeps this BroadcastReceiver's process alive while the engine + // boots + sends (otherwise it could be killed right after onReceive). + Log.d("PYRAMID-REPLY", "Flutter engine not running → background engine send") + val pending = goAsync() + BgEngine.run(context, "sendReply", mapOf( + "room_id" to roomId, + "text" to replyText, + )) + // Release after a window long enough for sync + encrypted send (~4 s seen + // in logs; 15 s gives margin). The engine completes independently. + android.os.Handler(android.os.Looper.getMainLooper()).postDelayed({ + try { pending.finish() } catch (_: Exception) {} + }, 15_000L) + } +} diff --git a/android/app/src/main/res/drawable/ic_launcher_foreground.xml b/android/app/src/main/res/drawable/ic_launcher_foreground.xml new file mode 100644 index 0000000..2cbfbdb --- /dev/null +++ b/android/app/src/main/res/drawable/ic_launcher_foreground.xml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/android/app/src/main/res/drawable/ic_notification.xml b/android/app/src/main/res/drawable/ic_notification.xml new file mode 100644 index 0000000..d4fac54 --- /dev/null +++ b/android/app/src/main/res/drawable/ic_notification.xml @@ -0,0 +1,15 @@ + + + + + + + diff --git a/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml new file mode 100644 index 0000000..5f349f7 --- /dev/null +++ b/android/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/android/app/src/main/res/mipmap-hdpi/ic_launcher.png b/android/app/src/main/res/mipmap-hdpi/ic_launcher.png index db77bb4b7b0906d62b1847e87f15cdcacf6a4f29..aa3bda28309ffd27e5a2730a0d07350acfa2d603 100644 GIT binary patch literal 2670 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 AQ2+n{ diff --git a/android/app/src/main/res/mipmap-mdpi/ic_launcher.png b/android/app/src/main/res/mipmap-mdpi/ic_launcher.png index 17987b79bb8a35cc66c3c1fd44f5a5526c1b78be..b2497e88dc1fc5e4e7cf2e08bec4ec3370fcb3d2 100644 GIT binary patch delta 1871 zcmV-V2eA0M1Je$W8Gi-<00374`G)`i0fA{lLr`;4M?xS;MME|*IW{&eGA=Oy04R}l zk-tkqQ545NYGGtyP=iB*gf(TDfz;Aqlm*pb23alo{1y1)@tzUU8ngxlQA@vu`U`3e znuDMyf@qG$qLz}^c`7K8=W_1(-0!{TaPPTbjbxRa-sFQ^zJI8NLqYdKbkS{pqX`!d zY}jIouFlL&L}+MV4_M52=QV3JKKHLV5=mVFON;QRqH0CqN#W_WqH6N4aF>#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={ku4 z%jEAleeYX7^YIEGp)tV@jeMu8c&8h{6ijKhZ1eG-jPX@x^F%j<8eeiGq9i0LKqpFJ(g|B`(aEgz-yZ}TgNM?Jkyws!n;LQOPMQM_(j~k7R zh8yDpf#&7~V1FT7Dj+eM1K^i-=Zw2H+Kmdu+!YFl;IM-Dm z=6c)ddi~fu;29~gv@$nQ6y0bTyAcwA!!L%vPT&~kqx;}iyv?ofM_f2q9G=(IbAR)g zV~&gMIRj*`5-Bs4bh_KDi+TAPrvvDBagkKiOBs?CHEpK;{}kYzd}a$r=cna41|D+& z#V#GA`lj8~Z=30Cd;#Ppij*m_bdnzcJ{>^En8nn>lJ(LRCtF7ScEN7|k^rbKQh1xR zxBxgEK(RZY-B{OQ`osLd=?E%7$$xrj`pPKb(?0I|p7J>lc)~=oq->i?mTU4SoTXX3Me`$;gOVcHbRfMh9G5PjR`L zS#|KcVFT{~G=&l6YDVWr_rZ$;PA{9CM}W#V$rC?o9_hV1YMo zI`%oV9rUyNXn`kj6@~IxXX^riW6ph>+4!xW3|t5pV6mJKZBt2eX4!pIbfnQ@7oP31 z{8rm;I%0RgWd2%lK|zWnIe$V*3DGvI^OD1!iDXIi zl&%K=%-%o<9CLi|a(KM<{o9-_Z~`cwpxEMc$$Brv;{fpFu-PvB{(pkGqprhzwEddZ zz_p^ZIl$T0XYE4q=9fdTCPo;iUnkKQt_#apBqQ$vKo&Tn{ zD)Qvn1U|LMw7H6oGFct6MuWvr*I_#J^X0MgbA9UEd42p^=k@UeyT2ZSOeLLMlqMD!Xz34YU{4$CyN|mGnz_NQLJJoQ}a;d({^3gAsE$1g} zehp?$A=g^3TDwq`p9Fkkyl7o+qFAL#5=Sjz$U#+t=t5QkeZA$1b<{6_Jq7HJ+76Sg zw%z<*>(#N}gY|shU1;1i^^CQn*m-IY(&FgV&!>hJRBG8Ztw_DM_IkTSeFAJbey3`} z7W|@p2^EV5KMIoYx>=f%Pk>Ms?tEfkkNVfz$rAto002ov JPDHLkV1lGmig^G4 literal 442 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 bOlL6Tu=mVDbxs4g-yEQ+rl(q^Y#Z?(*fgM# literal 721 zcmeAS@N?(olHy`uVBq!ia0vp^2_VeD3?#3*wSy!iOI#yLg7ec#$`gxH85~pclTsBt za}(23gHjVyDhp4h+5i=O3-AeX1=1l$e`s#|#^}+&7(N@w0CIr{$Oe+Uk^K-ZP~83C zcc@hG6rikF&NPT(23>y!y&wkt5C($~2D>~)O*cj@FGjOCM)M>_ixfudOh)?xMu#Fs z#}Y=@YDTwOM)x{K_j*Q;dPdJ?Mz0n|pLRx{4n|)f>SXlmV)XB04CrSJn#dS5nK2lM zrZ9#~WelCp7&e13Y$jvaEXHskn$2V!!DN-nWS__6T*l;H&Fopn?A6HZ-6WRLFP=R` zqG+CE#d4|IbyAI+rJJ`&x9*T`+a=p|0O(+s{UBcyZdkhj=yS1>AirP+0R;mf2uMgM zC}@~JfByORAh4SyRgi&!(cja>F(l*O+nd+@4m$|6K6KDn_&uvCpV23&>G9HJp{xgg zoq1^2_p9@|WEo z*X_Uko@K)qYYv~>43eQGMdbiGbo>E~Q& zrYBH{QP^@Sti!`2)uG{irBBq@y*$B zi#&(U-*=fp74j)RyIw49+0MRPMRU)+a2r*PJ$L5roHt2$UjExCTZSbq%V!HeS7J$N zdG@vOZB4v_lF7Plrx+hxo7(fCV&}fHq)$ diff --git a/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxhdpi/ic_launcher.png index d5f1c8d34e7a88e3f88bea192c3a370d44689c3c..22ecbf5723f3c859355272797251b93776ce63cb 100644 GIT binary patch literal 5521 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 literal 1031 zcmeAS@N?(olHy`uVBq!ia0vp^6F``Q8Ax83A=Cw=BuiW)N`mv#O3D+9QW+dm@{>{( zJaZG%Q-e|yQz{EjrrIztFa`(sgt!6~Yi|1%a`XoT0ojZ}lNrNjb9xjc(B0U1_% zz5^97Xt*%oq$rQy4?0GKNfJ44uvxI)gC`h-NZ|&0-7(qS@?b!5r36oQ}zyZrNO3 zMO=Or+<~>+A&uN&E!^Sl+>xE!QC-|oJv`ApDhqC^EWD|@=#J`=d#Xzxs4ah}w&Jnc z$|q_opQ^2TrnVZ0o~wh<3t%W&flvYGe#$xqda2bR_R zvPYgMcHgjZ5nSA^lJr%;<&0do;O^tDDh~=pIxA#coaCY>&N%M2^tq^U%3DB@ynvKo}b?yu-bFc-u0JHzced$sg7S3zqI(2 z#Km{dPr7I=pQ5>FuK#)QwK?Y`E`B?nP+}U)I#c1+FM*1kNvWG|a(TpksZQ3B@sD~b zpQ2)*V*TdwjFOtHvV|;OsiDqHi=6%)o4b!)x$)%9pGTsE z-JL={-Ffv+T87W(Xpooq<`r*VzWQcgBN$$`u}f>-ZQI1BB8ykN*=e4rIsJx9>z}*o zo~|9I;xof diff --git a/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/android/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png index 4d6372eebdb28e45604e46eeda8dd24651419bc0..b2aba576c96d0c9bd7e1d8aced4ecefa96520983 100644 GIT binary patch literal 8024 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 RJz&Qi&`{A)E>p4$`5&|?KGpyL literal 1443 zcmb`G{WsKk6vsdJTdFg%tJav9_E4vzrOaqkWF|A724Nly!y+?N9`YV6wZ}5(X(D_N(?!*n3`|_r0Hc?=PQw&*vnU?QTFY zB_MsH|!j$PP;I}?dppoE_gA(4uc!jV&0!l7_;&p2^pxNo>PEcNJv za5_RT$o2Mf!<+r?&EbHH6nMoTsDOa;mN(wv8RNsHpG)`^ymG-S5By8=l9iVXzN_eG%Xg2@Xeq76tTZ*dGh~Lo9vl;Zfs+W#BydUw zCkZ$o1LqWQO$FC9aKlLl*7x9^0q%0}$OMlp@Kk_jHXOjofdePND+j!A{q!8~Jn+s3 z?~~w@4?egS02}8NuulUA=L~QQfm;MzCGd)XhiftT;+zFO&JVyp2mBww?;QByS_1w! zrQlx%{^cMj0|Bo1FjwY@Q8?Hx0cIPF*@-ZRFpPc#bBw{5@tD(5%sClzIfl8WU~V#u zm5Q;_F!wa$BSpqhN>W@2De?TKWR*!ujY;Yylk_X5#~V!L*Gw~;$%4Q8~Mad z@`-kG?yb$a9cHIApZDVZ^U6Xkp<*4rU82O7%}0jjHlK{id@?-wpN*fCHXyXh(bLt* zPc}H-x0e4E&nQ>y%B-(EL=9}RyC%MyX=upHuFhAk&MLbsF0LP-q`XnH78@fT+pKPW zu72MW`|?8ht^tz$iC}ZwLp4tB;Q49K!QCF3@!iB1qOI=?w z7In!}F~ij(18UYUjnbmC!qKhPo%24?8U1x{7o(+?^Zu0Hx81|FuS?bJ0jgBhEMzf< zCgUq7r2OCB(`XkKcN-TL>u5y#dD6D!)5W?`O5)V^>jb)P)GBdy%t$uUMpf$SNV31$ zb||OojAbvMP?T@$h_ZiFLFVHDmbyMhJF|-_)HX3%m=CDI+ID$0^C>kzxprBW)hw(v zr!Gmda);ICoQyhV_oP5+C%?jcG8v+D@9f?Dk*!BxY}dazmrT@64UrP3hlslANK)bq z$67n83eh}OeW&SV@HG95P|bjfqJ7gw$e+`Hxo!4cx`jdK1bJ>YDSpGKLPZ^1cv$ek zIB?0S<#tX?SJCLWdMd{-ME?$hc7A$zBOdIJ)4!KcAwb=VMov)nK;9z>x~rfT1>dS+ zZ6#`2v@`jgbqq)P22H)Tx2CpmM^o1$B+xT6`(v%5xJ(?j#>Q$+rx_R|7TzDZe{J6q zG1*EcU%tE?!kO%^M;3aM6JN*LAKUVb^xz8-Pxo#jR5(-KBeLJvA@-gxNHx0M-ZJLl z;#JwQoh~9V?`UVo#}{6ka@II>++D@%KqGpMdlQ}?9E*wFcf5(#XQnP$Dk5~%iX^>f z%$y;?M0BLp{O3a(-4A?ewryHrrD%cx#Q^%KY1H zNre$ve+vceSLZcNY4U(RBX&)oZn*Py()h)XkE?PL$!bNb{N5FVI2Y%LKEm%yvpyTP z(1P?z~7YxD~Rf<(a@_y` diff --git a/android/app/src/main/res/values-night/styles.xml b/android/app/src/main/res/values-night/styles.xml index 06952be..9894b63 100644 --- a/android/app/src/main/res/values-night/styles.xml +++ b/android/app/src/main/res/values-night/styles.xml @@ -15,4 +15,10 @@ + diff --git a/android/app/src/main/res/values/colors.xml b/android/app/src/main/res/values/colors.xml new file mode 100644 index 0000000..4e68469 --- /dev/null +++ b/android/app/src/main/res/values/colors.xml @@ -0,0 +1,4 @@ + + + #1A1B1E + \ No newline at end of file diff --git a/android/app/src/main/res/values/styles.xml b/android/app/src/main/res/values/styles.xml index cb1ef88..35889f1 100644 --- a/android/app/src/main/res/values/styles.xml +++ b/android/app/src/main/res/values/styles.xml @@ -15,4 +15,12 @@ + + diff --git a/android/gradle/wrapper/gradle-wrapper.properties b/android/gradle/wrapper/gradle-wrapper.properties index e4ef43f..02767eb 100644 --- a/android/gradle/wrapper/gradle-wrapper.properties +++ b/android/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-8.14-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-8.13-all.zip diff --git a/android/settings.gradle.kts b/android/settings.gradle.kts index ca7fe06..1177961 100644 --- a/android/settings.gradle.kts +++ b/android/settings.gradle.kts @@ -21,6 +21,7 @@ plugins { id("dev.flutter.flutter-plugin-loader") version "1.0.0" id("com.android.application") version "8.11.1" apply false id("org.jetbrains.kotlin.android") version "2.2.20" apply false + id("com.google.gms.google-services") version "4.4.4" apply false } include(":app") diff --git a/assets/fonts/Inter-Bold.ttf b/assets/fonts/Inter-Bold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..9fb9b751e5b2441054f6eef670da7b3f53a3505a GIT binary patch literal 420428 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 45vPrwCj8&%8F=IDq-RRM%sJ98 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 vWmFQ@U>zOvC#@5!#9`t9wl8ZCwcM`Wnasb| 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%0Dc#4jMY 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%0D$nm#m-L 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Ç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 literal 0 HcmV?d00001 diff --git a/assets/fonts/Inter-Medium.ttf b/assets/fonts/Inter-Medium.ttf new file mode 100644 index 0000000000000000000000000000000000000000..458cd0601d28013d3817481aa2839c9bbb5ded70 GIT binary patch literal 417300 zcmeFa3!F~X`Uk%DWv#vU%wR}3LSwG)yze_hni1oYdlC|oN|H))Boy79sZHt$DpVy&dr%4w))JX`f9vDgI^|-LthOMvvAcXV@?TR|*^}4v7GvZk( zw1I7exU$cMy&5$+v&Zvy3+=7x&@$la8?G9@eCeG{aei2cYlByhzB%P@{n{KBs(Vf7 zGzSg8?uLPlth4Z{2bBGv^CA1p0Dz4ZZQ|tEwBX3>9+PQJn9& z;i_AQSNU7DhlPA+7vxihU3J5?fsAvy3AxThbYl38H{Ja4gXhc?ax=~g>5%_HXhIiNL18mCfqokM%iu21Y6(rNqm2hn(4GK3sqF-Qs{IE1UGFS3y^B5@ z_`Lo+aGw4yaHGB%xJBOz+@bFR?$(b2iwwvcU5viK%Z+P**BPULw;Hzt?=_*Q zoNgeLvD-i>qsVZPrMhVY6U+o)l9>doVP*n-rXQGN<^mg=X9Js>&4De=6c{J^WVV#nBM}wGk*jg zFb@C^O5A8^NTf$rkyU`nG8tGyo(4Q!)&~AXHUMVHEMQOufw}T5;Mo%Cl+9!_V1aA} zJXf{_o-fY_ULY?3UMMdFUL<=0FO`=9FPE1C2g~b$!z8XnJ}sXE&Xa!^nyRDz0!&kB zz%11c*ioGa?4@w+s;?RV9H?#rj#jq<$Ey2)xYa`0us*Ur0`9dA1AnuA6NWAAK|-^yw-J~9h5ZHaYx_Uo@3r@V{>lDHXpV5I z0;@UIgyH!dJ}plj21@1Z3%_INeSNoe@nnsC%6eH;fYqF z1w1qHOrS5(2lOYR%p{(hc&;!K+ax08iCq(s&cq&xJ%pavD-kJ7?48&fzWo#X1FuZP zU1nPrg6f$Xbf$g)p04()@6Y*maQM?j5E(#r& zhK|ca$5rA($Wi^NP=jh>Cw2#vE*6Sq;Oa~t)OLd=eI7bE81OTgBcV$oyoJhesW95N z?VTc)cDt}Eu;+!{fRI)p=};IK_k>(}4}?rcj%aD^8o~b4E^CQWo~C>qfJuJh)Ja3> zPfJNX1Qa=4fvV}9z{yPx0#~1h8V$O|;fKBB=zc;#J6%1+WkP0f8fuEPsc8kkF6?8a z?vHlGAv7;U_E?s>Iiq*_a~YG;>!kOFYmh!5D@EO6l=J>m?E8?zVytZbU)l!xXTc_H+DK3kp5Eo z!|9FFm#42!Z<^jReMkCqav4jDbv&0&j#4}z;xY;-e%`xt8VcB-Qu>wb?Mo>`I$-gWNgl3e%gQk?109Ct$WS>I5`X z4S2j;SJB{jgCe&odCyA5;1-tTKvzu3F75wkaonQvV{+$u{_aS(YqX@>)qOAeJR~(e zRtncyTsC9v&0XRCvvhdkz=y4lbEtv4B&4~K+rQ`+_eZxE%UoYFPZ0_^>dpw;i+dx> zWi#FYpF>P_azAo^V(LP|m@O^l>{Om)R9?Be$dh$j;2J6sEN)$c@lZrdNh<6Yd-U>= za-T|oXTfEaS+{9ySUPimiSXRlBXpQ@*MzC?FP|mVnm6D4MO2 z@`X0HC-zb9x87Mvbhp6QtA#Mm^5|$?#4GxOFm`kMLzYXN$9GG~l++R%{zT9CuD3@T zt`Egusx^p?Kbk)Fn8P_49nxj{iEvyR#a422--}m6R5EZ#EK=g!E$$cI^|^bHA1lhz z6ZY{+g1esN+(%1Gy8}w|N^{&^?l(nclqpa8c-w^1am8@TXyd3ib6i`jzQ)I;qnunn zK7A(|swoDLqy$)ncI@$?^98{uLExN|<(chN)vc#xM8Bss&fI_gKS}9$!^PgZo)!q$-v< znWZ7z$0$EmD*OMPt)h|HpO>mw%XZ%{FJ|{8ccbSY-Tx~u#L4&j@5LOs7Wd}}T|QO* zeU8oh@--csZ=^;qFI;T=)W@!93-{u~a@0Qx_1j|lY#7TGw<*Q4r8r?9=s@V>wSTvG z{1c@w&NG>a@1IAxUq;7u{B1(CmI~;+3jB}7+ddZIW0!SrjJ0NWT}d78lO;LFeqMHa zT682H9|kQVnx#yEE6j*J&eNuKxAq$IcG zxqDklPQ~Xgz5gtGtL}M`<+^F{$L1l4387<5?NYX4(XkxAE|zD8TZvN6?3eQJK;S+iDA=8#n0u7gIp1&;?(|?y@O#DCw#29 zcjwN*)#aBLk^5qKzUBEva?{;io?K=8PQ0ABJIad3eF=GRoFkvIbe6|=7e{>EtG!Ye zel{1sU*+Br331|-`zdtjh&T3G3tBpNfxEAyetH@unwR9po_n>h$8&$fu?BP3*Nk=01Bu!4cSf`NTB1 zQ!5ufk{8ADbv^1tQ&6n$7>J7N-_pw5)unk6PQ&8e2~Ou{nEPWle-O)U5>#g4Z| z1$f_AupT=~RKYgvpCY`8*-NOyY37oUn7j12uz226lBiNJw_s1fO9hJxmKA(fu&Ute zg0%%3;I@Z}!^#TK-{a$a z9PzG=_vkA?PmQnQD;y(NLiwbNYSp~ti77=z6tJ2;JyUzOF|*;6>kk}Vq*BTD?jG6M-7g<=56cgWzLg&pO;A6flq+MJI~(zik}tagsc0b&<4P=CalA0! zau^G7Oh+7)>IF*iwXHy0(-GHnl%@9WKE$<8c6AG(c{VgpfMh3S6|E4CT;MK{pCi66 zuz%@}LR{0WBkm~see9dDZ$&;ih@nt!gv4eXKfrN^OIK5972)W*g*M(zizMjT1U;Le zXOl{BkE%rMRgh!J*lW8-p?4GXZi3!T(7Q=g;k;ht&V>HIL;nQm|2y&_6imli`cUK|4RfumD-Ert&WgG5n+r<7p=*`%-x~rUIceYa< zC99g5=$Rw;B$8;WV^c)+n_uoBSaxW zbdsBJPv7VJ+DYz4e%r`*2YVIwLtN{JsygU}NDoRIG!^RRcuem?dt@V@}ZuJG@ULbQ|n#vA4tC z9y?t@e;ogSzw0hY?1|?Ky67U#7c^_&O3aN+L{0Fr$QKL5TG37$t&J9awTYNRRXv#BSG zH_Rqx6S39ojakqin%|q>i;rYoSyyb6^)WwrJI_!4ST@GYm{7;pwvc+dA zpaSA^m8){a7pl1`5MQdx)Mesds-Nm7zE)SNE5*On5cOBFi)RJz#!O&cd}ocYMu>gZ zP1a4~duy~cTI{#(w(b!>Sg%;Gh@Y&5)T5K&AKU;5FtHnX?-1joot^bez$Acb%bj-vhy_E?qm1SZ2MBXpXS(C+E-~+>^tpywPbs?{k&GkUSKcK z&ahvzU(@Q@E9@0oeftgj4XuHr9HpJJ6wC_F*3xJWu$JzOb?(zLoX4CgT9)&) z^R(u7mN-kbfV13LuH`syIIFZ=XSK6hYfN)`wX>WLoo!m4bI3WQos*yvl!iIQ;$~x- znJCkcgUCJEO175mWk=abcE(KZZt@;^uN*7yljG!g`H-9_AC*(&^KzkFB$vs5$mMc{ zd_%r1*UAlYqueClmz(7Wa);Mq$#3Lt`MumPe~>@QpX5P#Nd78+mq+CvvPfylP^MDK zQZ_CwK_#jrRYg@*$*Q`lt?H@zs+)RHO~rif7t}npKrK`MP|MX8OfOEd(yVkV-)e5P zv|3rMt#hq5R$Hr`)!yoF9kKqfiY(U_HtH5?EfahR*$HPS%|JjH08=qa2-!#w6Z;A7euDs7mxa6qwdU>gNzP#MLyu5!#+%ad}^#h|5>`lRTH#KTJg(8|05E+vQ!8HzaRA+;B#s zBJN;bX?Fxym6R{?_T;zA8_jnsJ@3x^&UyFbch4J__i%piyvOq|%bSt+Oy1nQm*5uV zEz4V#w>E!3-iG`^`GfMdgTn8ifH*^O=Im)>=HJmS@>nXmHP%1fn zxX(wB2T8>m({WZOKOI~TlaS{EJjmqN0Ix>=cyPvpnu_{y2=*4C`mq50q<6$M=qY_H zt`(nP8Ng_*Eo#XZv@zNk@wqlndslp+?ZoPoBCJmNLAY3*(m*?1Pt)6K&Go)|U#&0I zo7$!NtNJ4CHhrCvs%Q_>N)>IgQOh__d)(+{^wQQDj~P?7cd-iPBW)vAp&ZsN zTNA)DZLY|vd}wYmBo$v`BcN|U94NITl5R8yR5tPuGZhIzvuvX~3tT(JT^xoE6)?50;);rcadLOL5NYF2#npeNV z{)=5tzsgRx{ra_bzTHY6YIm?Z>7(o}b}#)_s)hA??1Ai%*-^7ZG8}-%BRA-w0mh*)3g#Nbkob#N%mg;Ez9jc@Cb zj_TW-BBw~-o`7z*z9Yd%F!YaUm4&`Dv0Gv{{S%bEaoAg;{IwOGQ4V{;wHLibKhXg# z_RFFh+Uj@2Oz|$t;%izpt)@7Hl~SX{Q7Vzz%FM8*RMruzX*Pd z^>_6VRD$*Us08Z|(poEoz*;MP2G&}gr@v}kVD#00r?pmwL;V8dH0l=^skF+<$e>kL zMk^}c#&{~<##6M`%9urKt&C@=tQ#-TDl20i)>NHiykWLA+Zu0Dxi?mu=bPsnZRillsXl0f0FR~NkH(E_)CYryPMP?e-P8ntn zS&o@YYp2XcWItwOvLEv->YJENsBdEC(b_39A8V%?nN6vOVm8C7sg`DQvN5wIY^;sh znpQZOeX+u6gn5-^Sjrqhc4Cf#oeVceTO+Mo%v-J7th>xHu#j=)y|9Xx&570mYl-=Y z^}4mfoCN<7hZL~^B-cIY2^o|KcEr<|wcqs}wV zGjcL)V~%{xS?Vm6Q^`W)G_nvmoh(GofQ77=Giha#oJA{>I?#FPszlY2HRN^U158p zh-|>L$OcRsHqaGgbJze%_C+ZFNmTmHWLjfr`e}`!8KgCaW-eI*v^;6P1X-*xGzXAX znAfmXjHWe)=EJnc(0r8E7@E_}gRqn75|72q*=#Lyq>>5d^K3Ko*=Am(^@iq4SZ{c` z`HHM9YnuyTKMl-P>kXts;~)X%(S7omLUb+O&#L)}i%-@-MV`%5TucS4Dau}@{lv`-cpgNmY3#vS_J#`M*p6W!l zr_Q4lg6e!H)5%m_$pTe3vOv|HEKv2JRe|avS{0~zku|E`WR2=#vPRX1R{yC>X!W1E zoL2v-0a*9xK0N@As%U{zn7H;rywAquFbMH~W45 zTz{Uwz~9E-DSJ&=Q}A|j{;uA!EcD+AnV$Z>{{H@Jf`k1-{KNgDS#|>Xz@g%<$ocQ_ zkMlq5f80OA|BQdG|0R|m=3m4|J$TZbe}{jWf0ci&e}jKZU@GbL?}%vke-_jOUz~{Z ze;rJT?*by2;@{)nAI$V0Bnkf!;skb`nDaID!UwCKm<#MZ5f^L{9C&OlyD&HzuGyd9 zss?@xIaN%BIh8sFTL)VQk_eB_1rAm0d@TcqxEy9yDvrWHjbJcPC(s~}9`FYm2bu<2 z2HFKW2f7D(2QCW?2n-7L3k(g64BQI06J>f#U~FJ~U{YXeU}oUCz`VdKfyII4fz^R^ zflYxA!*vTELv={8t;bkiY0C(e^^kqXl;u!~iYgZ|cRS9#;CzZH#{)~}M&KyYrUx@o zGc-ZzDU6bs44sc>%**_Szl!Bq7Yeovwq}|tpiamSTELP9rD!$#~16$%%{viw4?kC zo;>HXvyNsi^XdM}{F~Ah>GjzW?U}1UcPQ*u-VsyBz(J))g&SfB^KCQzme^zq&7yWLk9m=ov|>(ZMB+XUPA?)TkKN4O}f3lv44 zd9;6TyqrDRyg*gogg{l#`6l}&XYTNFJ9BO3T8}D${Q_k=-*n%sz`(#j-yFgcZg8NK zF}|;?1U0`imj$R zUZwI04-JmRWhavh%!iv(?DhqAXV=QE7x*;LC2dc3YA_jBTo_oG?V}byJ2yKoyCAzw z+WzcL*_C4S{oc(zAjO=H!=Vrf@y(oKG_Nwf) zX-Bd*WN*pdk^Ncre!t58I$dP%$=;uRF#CvK_?17&U&CL=-vHePzrV4+slR2QHR2BX z+xa{DXZpLRD}QgaD_K4rqf=U!YB|hda>^HZeHdE21M^ zKlOAXy^=to*RKfo4Ul50C(stN*4UQSYx%EFIbAPsJ0usP?z=zm z7221{f$4!+D82Io3z2IJDc=y+O2mekz}beFK7}M=q&NfnGC#w2W?H5<4jh2p7Nxi3 zRG845jC`+$JM0VQ2J?aiXg69S?>Ys$s(-qhj2R^ei2+m zuHjy|U7_QT@pxn*4G+N`_3up8vD=Zpcxu(unyGbDQ&KZwR!vfyrM6DJIkhTeN^t!< zbNi%rNS%}0C*vzn6WDc0ot!!WXFd3=PcFI1IG>d|C$(Sdz|_I1!=UZ<)WX#JAu&01 zdg?6r&I$BLE%N#Zsk_U7xx+bzADES#?ssg3rFx1F458 zY+6E^i5)JuEVwK!IW3uwwXy~Tm*oyltCu^Noc{~LwA3^oj<=`frsd_{9(KW1X$5I* zfNkJ91y_Y#TK}}Za9z`S0{au!e<7PYfu9mqMfL;A>@-bJi3R6^U-Oe zBO!23;VHz7w0qLVr9GVXIBLzN9C8M@&oK2&+T5JpX)mQM3a(9C1`08QT1z|JhO{lg zwdi-P4RlD`5!{gWS=wiW*uM^LAVjhNkVuevl{}kN9+tqFMv>E;)hPSEbho z)gz%J`zFP<-Xslv9qbKq`=zJn_6r05G{T^_%e3s@0xU`p)!C=^v)=%u!Ukrtb|D<*4*8(szZ=()Z>l@=N~_ z{6iiM>S%^ewC6HxuIq+nRL!VKRPJ=oQO%a=BcyZGf^g8q$Beq(u^1<0v_{>?K$ zKw(Cvca{;1>X8=`ozWztSw=JF(s?1m73S>C=#$YQqen&;?ESF!0S?S*N-kp<+~Cmh z=8W4jZV&eyYNyst%|Kr|<9@gaI8OF_GFIlU&%l?wfU}rhnK7T;oQ(P4d1niW%3Yt^ z1?Nk#ugO@Su^IL}Ik!vhYUY?31MDlGV<8Yti?Hv97oRAqkN~GsLWLI z$@CFMTxM=&E}fA)OXhhYA`&r_o!K?B0DGIvPQad-J#$oW3%Sg`nSFu%Y0vDRJ3sT9 z;FiGp;FjD8=q; zkogQep~dQY!>df-4V z8tvR5o=hq1Nkr##_8-b>i6=dmW!1@Qkd>b0_fPWo&T5?1G^<7_PD^?Ul+`__Gd~-; zEN4*GfSfV@L%ExMdhX_|K{;c|WuaEX6C-+NG$w0oPUqZVS>t_GvnJ&X&23g0M^A^M z4U@SH33q$_K0&hnJ6b9Uy`$oet3A?r|X zzpSI^6QO^TGZasf(Ax=a@Yy~)XAq86eJQ@0zPi2?|2ldK<7-0CUwj?#{Gx}i51uRx z^bPh6gS#0c_uGAizzG;9W2EbwTg8*ZDpTjq(oo4%1jJJAubTwX%KL z^|Diep|MW!NC%@FxOk%+8sB&$omD*6!Dz=D>!452&wmIbp0Bg__#0r{)0D?MG|CB& zdD77uH-M`HUQ?#ic@)&NcqBC5-x8ysTQLrrs} zu#cs&kbf%o%g{SPpJHurgI6!sPNn(;HNI6QDOTDC&;`0qy><@NZzK0jIz8o!3? z`oO~6Iko23PQ@5tcu4 zAvZ{^chE%bj6HXK@Fj|k#|z29&r0iv9YuH}h+xlP-(Y{}9#U(5aCmTZ@Xp{p!EwQd zarQV_sF#Z1jNmiDxxtspzhA+x;r0ag2M-31Oa~b+d19C7{0F7Q!Zl9c6bH<=%8=o^NXKK#Ooab`pLE@F1 z#cb2mF06ywlsg@|cA|#fg?N6}@w+VxQHPRHH^ zwOnh|VpJbZr)xuv(g!1&f#?nMI3>3*_kP@s$&j9fmU({e!rY~~E8*6l53sq`(%fyB z5z+y3p&k;#m}X29I_60vVpRamJ~nywv6782``D6sGEXG%?Bhh)LY|A6@NH!~Q5`dC zyNlE05IIEDlSAcDQ6Jww9wr*d5psk$6Z32*iWE6bP7^^nLq08X!Ld?SbQuL7j zlK&FDE6dMfmc+y21@)+!Eas^xYO0v8rmH8!OX_L$tawE|ujYzZ)k3vU zyoMRO%f({Lwvxo_R*ID_R$|U>zIY4scAJYen7i9vyp0*V{l!MCY!PCUZP=#x2=jKg zitYAC_IB}4C)uejzDTH@P+RP#dA#C3G?Q0+OLGUrcZppRyNG>>JuwUYd)%8Td~eR+ zd((*Tjg5O#Uj$?W+@WN?L;1KvjYKZb60gtqDVgt6Q{1PPxGSyj73;rX{&Q>G(Q|R< z+ThN$6}4qM+`lt%|2m0tt4 zQ6_3|nK%t)Vm9bGat`><%jZR+oQqQ8a4B)Plwc)?Tp-THJne{Vg@(XVQiM0!TCUb0L~VarvxrfSkZyc(;?@-RtP|onBYs~vTh`0{PUqSyai?AvO4r^vG{~I)B ze~Vf)|65eY4DclItEei%hne72MIy>&GU)0kowc}hR!8Z?7ndXn4^oj0CZQ?RkT*!R5wwex~mJp>4B2ngiCe?O7<;S?Q<)> zCEh^Yrfvs)hq?pwo$5}|cd5HXD>X)q5zW=#U;{dA0JAAEFa1H0!(Sb*%l6Qg?I8vB zFh#V$ob{=q8LVQusH>iUZ8T=vsL8gG$+i(>+c=%(vSWP{X0rpyHf**H8@ACBH0HL8 zM9gk)FHE)*6SLco2+R82Iw~aQx&I-mVy=6UNU~hZ6;(0k9pB4lD@uSBVLc7afESki zfxSgYdn@e9f?a(i>e$<1T@uz+T_iX)oEoB5oDRAcY_A&Io`miB zL}CKEBf?}0^uFV5vjrxz1)8wHC)ffF%G(8m^7hb^#xE$~dPSv9sg zUEVM8t#h_LDIb*h;yGKOE+@zdpvexUoGd4c#%zr>*%}+LHP&QnY`}I{T~e)Foo%l= z+n&vq)`~67U`zAM*HAZWu(y@aNtPDi8d_s}la;Wy#3*}nU~jvy-s>BQFR(}1TRpb7 z`fP9Y*xu^1z3K9R{27vDbyEH!e*sOlr^~~r^*syJrK|9bakfLLbftqPYt)rg_y#!J z=ugx}TvNhIaJ2cr2Td*CT!**!09hz*1XR#gDQWMlf*!&~- z2S7Gk<6qR{>T%Q>WRuO=CY!2hYMRJpYplW6n9A1J$kMR#$*`(e)nJFoR&}AXHCk+q z7F(mm)@ZXe8rCJ&B_fY)(qNl(*d|rEHklY@lMdUYVw-f>CTrT;Y^*h9%T)Hq_Qyi8 zeI~MfX0Ux`v3+K+eP*$J;_(35M#XKT#g-|#ZM4`jtFdL`%kh6akDSo70Oqr5+D5`Z z7Fqb?z#lJKU-K92iI1<6gYyi_)L~3u4z0Dv+E_wOQwXKsMyP!zKLu^dBcN@Gm6)1^ z8e7v|XWuCvN_>4@A56abV1<87Xs^Z#rkH* zH({*D$mLuX5Up(|)PG|9gU~#maS-E`gvK+B^9c2K2=QkWLi!YlhCT%0V8)9WIfvzQ zM9aSun(s3IEqxCp-zT)|GB#yQVg3|C{6U05^~7RwO{Q|FhnRzvJ=cJTPf!a&BQ&|&SpBzTnbKIqVemU)%J8s42^&6tl*@_a80TFZhz zzp&)hq`^oN4tz&ZE}1PU$IzF8jFmyC@x4at30nW&xC)%%M4LSra|zK#ljMU;7c$b< zpEP|KBd6R*B--HIFu6RNeTZXT%Y3#S;}w>l$(;9?rZ1Ce#xh1OhmzLHYQ{g8r~ z#xDp>PPxft%)Eg(k|i;oBYHLC2aIeZs13o_1`_Jy35|~#>6?t2@i`;b{DaP6Wc}Lj zMC)u#hIe)M5y$jO;C`leGX95=Q)o6OT3i9%v+)9P%q&K(qc8>oM{+x8@?9|bP8oa^ z=B2FRenNxqh|c+}cV>P+LX&Gw#dU?orB_=|wv6>6gfomn;5NqB85c7ej7xO<(Mi0j zKLeTh#L>qwe;wlrLa|*(3!pC}6x*3UlkrT(jf~3(^}bBcW%_ZZpJtpvwSl&c@pZ<< zj0WS9Kfa~diPpz4XC31TLb3gigA_ZV*v|Z!jAt@#WL!q5_hou6(~mR#G@;4m#Ar%2 zk9>l1OtMXxeE0E0gg9L4&{rp#@1T5`=|>nJrvKbXF8^{gb5aP+j!aKxyoqr-k}D&WAy4PgXxDD^BK9+>0C!?eTXB9iW(!YbS`^bx(qJW#;xRQ zD8?Fu+7`w)it-TGdZKkMAv&i}=WEx_WquQue1MV5l0J|5_b^^hXjn}1wdf;@xY4ia+T%vvzX7htvz5+{cN!O_1v4YLhHn^uBE*Q6@G`~@jJ*hrs~P`62n|TNK8op4 z9Q#c6O=LQeVmA^w-rqPSzj5rpQ7FSll2}(rcopLfgjkzTxPx&u;|Gk%jCBb0OhT;= zr5}hZ0@4-zjeQ>?GipI7YV+pRWC0&Y63Oqpv60wAr^7hvGcf+Ht7a zEIFI=)1vek7IQ4l$s*QY#CM^H_<9kCszH3C2B*0Ohpj<(860RZQ%MG^K7sOf#%Ubt z5MvF}hS5KzZ6fQO$Qs@wj(H~YA7TC@oac{lO1PBjQ*zga#$``8rKinC4603gqluq8RJOCn8Y+CBw8n0f10%o<}?iERPk6|?@F}Mm3)mJtg}T3>HcESJeJQRNn;-6lIhilc|^-X#;2J7F{4+5d9~k4=5YO>uVihk z!SHIZMeIA2P&qXrL9#B#HG}aMMz0Qhoax6Hrx9u!@$LuxOvY#FX}n$& zPr~tRfoSa(rWZ4PmckPb?Jc6k2MVpK_z3^R)Wo(Bf}@XP$rX$T7}qgg$oK@I_)7f^ zdfsKuGD5u{({mZuFh0ZhZ;D0R$he(x2jjC^TS}+)6ns|^t=+=(Vy4g1@$^M|i)itI zu2DMmHk3}H^>Hk-g7E<3I>rkbpCA-pX&*qtyUbZesP|)fF5?=;XBhuYI<<|A+ZlH- zK4P2&{$$2G7$0SPjPVi9`N@oYFXSNN%X`@O4(2~fXgx_BqcxQc#Vx+7Pkf`5#Iq&& z1kw2B4&jB2FEKtzsJNEKvuDsI*A;k@O_JjoA7j1oY{=r z)+la;0yNEt)Zp@UIKi;L*g6BOkc-1hGoXE z{3z!9<{@#kTHMOun^_2DG1lPPuLjFcWXVTD*d4J88XW3<=D)}I zsE5Qy&k8cy7M5wo_S=k~STC*7%wO%ZL4s)(0G*X$qleOK+zKfWi$n*@RcQKA-4!0mW z_uP=5)CzmG?z`-}kJ=9Kf%;g+4;bHN{&1!bkfe5)(xx5e*aveu3m6UJX!|&AoN}~` zkkl__$$lPk3)q8D=UxP!t5eAt!km1@OIb!S-GW1H<`m|!X0N|-1M{0R-b{!`@Ia$I z(_YKCokP9PX|6?RBs1qarn#;Vzj4dUq4cvnJuEYXXgx?aVoYTI67KmtN<9$mQR>lY zuQJUwhQ`;f^N2|kxN7~{ee{RaQ3I~OU)+IjCq-`!LMK(DnNc*2NaJrb_N>g7R2d=2 z&~t^@tt(E$>5JzdD;+w+R{({mNhj_n9?Lz~9pF*mtqW6hq;LGvzunwzM7wxS!l9!@ z1pPP8XY=TX=q=_?s8-EX9+f%lbdcPITB)IE%nFvz_S>2Ywk4tY9Q zPbh`%4eq;qK8pW!QvCl_PtrZ&;ySM(E@??+fXn|JY*QT}efCrr=Yu!X*M zUZc3=rxsJ5fG71HO%w69xL^2Rfp7db4@<;9mek8%`S(Pxps)QSEs-mVui`|w(@rGt zafB^h*T+?IVt+HD&|a=li96+6oNIC?oa9&wL;C3H@}IHAxu%$CQ_#jDEwI|O(7!NK z!v3huUlqxrvj~?;v3EvDbx?D%dAAUhaQh?FS0XJWL7WBQR-F93jpgYrSw&komwG}l zQVUe`v`60?_l+o3wihF6yOh|!g;1TuaeK9MvCT(?4U^TmuAEP&xTZq<1*SpRi+Q1* zNi+|VxF*tH=`E$CWON-7eSOf|4YlYJcMzz{yf}*1P#Uo{bO*Z|qyOCtpO{p5_XZ&c zLBm`M;-*E%L>!92J4T~Bs)%}5ox&Pe?uTdz<}8f&e+6+7`z;U+OUj4O-2o^qYtR-o za)(fRLb15l7yUvZ=$}fsTSr-T7a^tC`wI=)ohk5xv{;VNYeIEIQt7|ExdV#!P*`tc z4fo?8(Yf4qP4{$$eIqg)^8|NtD0bmCB0oZ{8dKc%fkW-!%y8WlK7zN<)5Wr(a*lg~ zSj*aq{s{YccOhCs*r)ts$^ZY*A6cTeNDR^3=zkZ5(^vlg2%|$29n;?{=~@1H@wg(o z_cLW_46XJ?^p(Eb$spI+cV63J{ z`eOOzoyE4z|2lQ|vF!9k{}m}V-KA|T*1xi6Wyeri4e{m5PG97o)UhQf{3qfv z^nDh^kNdPB;vb12!mF4%k-uJ3oe+MyKvy2FBPdq4nW&5Y&%Q_sO6CohtXCo$B9aj* zT4RJuRBYW7uRq|P9UXfpwAbH5TFcv_dp6;^`PlkKHecLC) z^oblx#Qxh){G)49IQbbg1R$iErer2UQ@_eskh&bmJSS<1=rXrsCDIN@ctnMt0LF5?vl36Hm$5vo7@-(FDV*WSZTMfCbaWx< zUheJ<^TKl8_z8Y7p^JS_4iSDr+vVh_t56Hq5fw^_sQ&`uy+_F{w#Qu3S9FXDUCQ&n z#o+Syp%;5-+>XEI;?2gDB~uhGx9*K$A8&LKTfR^(Ch)V<7NF?)2%g3gMn4DO^Fl(} z++OZ%l(VQOT3!rA-;r+-*+(dSbna~~&9y9N3#Ths<9A} zI_Z%en?jDiob<7_l1~S4uQx~D8JZD9lP;r@$ z3FMumNAu|YeEjX0bjRoH`Ga}UFiDD{KqU}K+2X!VlUPar@t4g#eEciHGkd38)0{{7pmxwaKFKQ z9NfZUT>?H~yJYJN`MrWS)~|=IsZPoM4>UX)U8voEkv?}t(I#Md*VMrM7g82ACMZrv zscXVJ06cGuY~EWZ{&W4W5w1r?|J%N#U-WtSzxU{weG%uHevXz6)9xK%>ZBj3&hp-X z)4G+|Z8=U0LoAZZXWHXNwLsd1A(_abR8B^`%A`t;`zVI!ck_|-4GyJ>Qi3-{jA4j9 z3v-K)k#{-8tp6$Ec+wZHDdJs7w3Ws4|L^m>_m;8gaOakHO|h~k|BQOY)N6BB9-D6W zpCr#SXUdqH18)Zsm>pAcD={~xgtvRdW0duVsJQkl5w7&9J35vZ+a{grTtC(Nqpt0E zYM`j#;`FGK$TO6TDDM9#=`Ny#c{v@vyO*<93Bf6@J%TQ?v4$VCbH!1v#CK7AZ$S1-S?z2%RWsqgOhv0sB=~R?dQn@*a zkx=2c2FQaSBHTZTs{SX%bJC)5|0r8k$vJ(ol5SBrf5UIQyfHlTeQQM0T^*t0Q{hnX zrBQrn!)SeVBrL@cb@m?;az75sddDa|#UAwJkjCWR+nRV1VNv|OJ?<7Bxw&t7-bJ%r zj3T_Pn}P`d5*G>68y{iF4T=b%LM zDoYn}{TC}89*@OxPu-bUCzjQVsa(9#p`&Rpbj7u9P=moM2F_w(^Ho?TV%diwC8`JRL+Zz z|Agq=6AE2MV7G$wagH7LTA?x`twi6ktdL=T+~-CmpIn56V~*}O-g=4{=5e0H);6A! zV=QAy#~F1vSQ2K+9lMU=9!6NrpL(p+efm>VbmEa!cn`dCQM#o(-l$KWrsGXP<-%2_ zF0Y)XKU3<@Zs||$wYj6+u@r;*hC7xh_kQfmDJ$NvFH4S#Cl#|IM3j7<6)!}5UN|Q5 zjn!FE8bkV0LdVb{y8fk^Ke3zlb|RMdzi{TQF_hA(mu@jKYgFdxaN}V z^6wqqq*P){sDwY&)k!uQ5ZYOWP zC#5+0*`Vi7{X?QKcVj}u*A&)Sv1C}HtS5pMY5K3-hg0%&BAgrLA4|VUipWR3Q@bp} zJ@r&Y_vzH9;LncXf40Ux3GEZlE&qjPbGzS$^OdORzC-wXF=7Amj**$?1dKg?76 z5_6wIGa9_O+^bG)oTpm5`%)-|mZ4+H$&Rr&h7(g9PTz@XIp)wMo{Fo=Dky*aNm^Kf zpA(04HZ7$)dL{>ZmL8p#3R4b)SM|&-N8o?Q>yrPSq{L0hDNmo*oB6-hCYIGhi<`rL zGBf;+@Wj4>_9rJgHaZ%2mo@gLIc4E_WwA2x&thvHlA+L^?9D=o4~w;dP3tvcwkx7% zjf8x{@r*1X>G8d^#XgCPIXhLBaI&6SAA9;@pI3Uh5_t*~_ibGy>tgaI!v3#O)kEp; zRAvc0#-zD*jxoUh2gEDxQS#Ru$M#mreLI}0nD=Eyn0xY%n9Udad@ujx$Kh!V_gqf4etci<|HM`a+dPKrtgsI& zi@#5J3|fy*w7fN4$D=Xc+??ala{^(?{g!H(dMo~xYMDXFBVNs0Zh%lhESfb;u%_pA5(t2x)#F!N`(IG?h@qK?U zj-vkp3*V4IJLINeFP_hhugk=?O-NTsPSknKy2N;OgzJyJu&A)H9>r(8cHpbx)5;UR z%8OP`vUF)K&8eKG%1Rw;FTT8Iez9wOE1QB-FBkJgtG zeUUdD!GAw;}hd1wv}zo;j)uF-y9(?kQbPvWH;Fz|6d#;hnTm@p>n8sn;a&GnYYUka)fz@ zyhlzn@08QzG;^GsA)huMl+Vg%%}3;HIoF&d=gE2I<8r>7Z%)A<#1@)UerdiW|0VxrE|9zAZgZjBBfm3Wll$di z^L6>VlI9v^tE%SvDp^%Gx2f8yzPUsBRF3(%YNVQ&|5o{`nfV`8pxT(Q3`l^*42|JX77T#>sTGP%V^MmTe_TpOs>z%N#4;%9l;7 z=2mn3!?mT=UglYsSbb$ntH0G>wzl?Kd*!*-KI^b-V;!-D>}DHwXW85CZa*z&*w5O} z%YF6&dy)LfUTiOszt}7674lbmmAytDw%6M4$v^Ck_Eu%sAKBYgg8iMnPgQa7kpflC z(VeO)*-3VAWllY(p2~1ioD`MmWINd^%W3K~RX(SU(?(@G9i5KK@0{nHrvgq-r?(0^ zmphlMMoxdHziRB<=nPk9IU}8s>TKsO=RTF^Jm5@Ft(-@kM^t;~QRh+B!FkM?raC%L zI5Sii=P75F>gvpPW~=Vb^UjOvLg!`Y71hUC>?~G&ou$rlb*Zz`S*7|rZ#f&)RnAst zs~YO;aCWF0oNt|jYM67_Ijn9^sGU$--I3r+$X0hIoSl%T#w4~$Y@-SjyCil|cPDmD z?5gfb?3vh0-79qMH&|vHypd@uI^&;t=ZjwW0#IE!~-&$VICn?S!Wwt(I$J_5Z>YzMtVd;U4tN*nG1}ii7vdl8nl@g0 zNSv-s(C8oG6SXJAY1#~J2IwcX+0gU6_5yI8_O5WW_1XqeU)!i{6{*^X+Q*`%wo}_J zs%qb9`+z@aKLCH!j)=P2?|NNf>1XI?2t%)@r-Dw?+X`K8r?XP9F!~2lWR*kH>$dHPl&;04M2>f-_lv5|Xp{AKuUF&kI|htG^(W zK2Ki=nOF7KM0I_!zEq^?uj|V||3m)=e3$DhLBFA|0{>0@EzoQ9HR5vpZT)R<*5Y5< z)%ADrU+H@Kd-%(<(l_cG!P%s5g75qK`=CG2KY;It`gY(B{bR)SiT*k83;hdmrv9bA z3-mYoHwe31{{i%m`p=*b>PJBr>8>ygVQ9iObi)CiU?hloMxs#@bSG>1L9dBuulaSrr`A@}O&&HAGj`^#M`e44OIMH!>TE zJhQRcSky%A-$ZmX&o)sS&8B8k@Xs;NL8xYCGjN)l%@L}=EC8p4*#exFW=l~G?F34! z+16|ex}Dh`bO*Bo=#FM5(C3-wK~HBBwq~Aho{z9y%r2n2;veXm+1>08PA{_;H1{@p zBhA6V?F_S zv`nHFwM;;?Ou%{OOTd@SmqmMXfw@2^bD{YfBo~{Dp>v731aU1jmxBMgxgPxY%njgd zG&hO?<|gysqKdi8+$9psZ_IDRh30N^4`jYIzlHo>bFT=P-%?Ch_ljFo+GlJARLxmj)o=L7ix zI9udakxjh^(C9sgO!OXhi4^&b{016!%iWOQBln0l@>}_>Xe;;1y`aC7-+|sQf5KHC zkUvB6pgf4Uev!X`J|uqy|FAp^`gd6b+QsClWTh!h{6*RT1Z@s`!6l26`&VpsVA5_s!5>sSTMr>I~6X)l>CEM^#_d7pJQu=xu41 zCQi4iSk*+bm26cPHK;Eo(y1>6Y-zOwwz67_4C`F0JtQx|-#xFSeidl+tAvSu71{#p zN9#v%n)Q?QGw6fXFT$`6S%*ZD^{e%(P}X7VF!)ETBO=rK-8w2#tUs(jL=&sXDiS%C zYq_F{P0LVn&@(edwk_=hA?-vvNoaNzyNWRFsy5nv`*izs(6wy*OVa*}U02k$&#==# zr`vw;19mRxMs^c%ntisNC#u=`b}Ql7t?kyLzJ0FUR;1eP?DnFj-NEi8s@mt-okd;r z0(%L|?rmR;uzl=)LbtE5uMk1Izuh17mG)KO53~o0>h{(4H6qQv)*b}2>TX6Udn0g@y-DQS@7tS2ru~7v zMWonU?X93cvOf~d?QQlpk!)|bw}byN{&1gS@3Z#_je5PpM6XwZR*n*IX)AB$?#KZZ;zr6777>w91ZyKAB1Vdcn5KBC zAR?oA_5{J`+m>aB!o+?TKoS0@0HuIeh6tA%O_+hefx zZE5SDimiVedw!3_f0DHLL(<|uPg?vTEdFxr_&;LzXG^<33%mabB@K&zp5mxas!u9c zsPomA*j}ZsRa)~V@R!*ZN}!ok0;iw^-bQ0=LJ#Dj2fkALQUf%S8bFg8;50NqL*lXk zC2$%_pgF3b1#c$TwbrNtUF)uqgGKL!auR(Lmn(y{tF)_?pi~9C6B{ManBI$fSeI#K zgmbTUuX3(b1?Qp)rm_D%w1I{;n65;%`?dSoGXtFvMJLQ={~XkUu05{JWzQ3+g_ERO z(4<=MNwv^iss&#iwcwL#p*d<{mEw~+p*cDM6{M}JRR}(*5SmMc;6ov7;@7`xe^+v) zHprFQKtmgR$evG72q)Dlgl%kpg-$rLS|XOX^$J&SAgMrs|skt+2@Q>izaO1*J1dgD{V-==@2r0U!C?Of;Q`nPNg z1=3h5kW>_iinXm7nsSn%qeg=CFr{Ea3pLWJT8*R`X^LH~MuZM&h7M`2WE-a$EjUuB zk+Y;4$&+fND{7>z5;o32lVn$`5uro;b#%yCC=lvg;~ccdSyFqbM&U7fV-WpVHF~3n z-mHE~SE)Lhp*m*QAB-Q^bJ#e{ zo&;({lWHVIsu5MHk&~qwIa8_;U8)fcHDaS89Mi|~DP{^*bt;;qz0@Q=sYz5c36>>l zq`sm`9iq|a7i3S!46!GS8aWL$lEeSzn!NE_YLZl`Nrp&G(oJfT8_*;zm21sbD3c3B z?;uvP&?h6MJ~?0Nlb%waG?Dtmm73%xsYzV3Cz_NT$>w^`#EUG=&a{m_mURN(ItiDv&~{K>AAs(p@T$bEE?4 zE)~c*Qh{`r3gjHAK+Z7dnsYfX{gJHck7O+r$Y@h2kS3;3Ag!bV$wYxvamE+WAy-Nr z5|KJ2Q|ge2)FGXv4(T9uNJptdI!hhWLF$mxr4H#Jbx2Ee$j4}pPf#N*q#DVTYNVr7 zBc4vzjS=tW!}V z?W7vHMyip%=#W;*MJSNgsE9V`kUl7ob{r$LM_;KuZj`E{#Oh>qQpQN_F;Hrc-%9N< zR%(xdRyV7gGEVf-Dg#6xtujjV(JH+~A1!O4LoSv&WT6L3^ayepE!njpE4e6>y^3bXt@Qw`k~=0VsjX&@HOeEsdpaiAvp~N!{X;x}`a~XK%tp6ZQn%Prx8&E+EqQem ziz*e1CKZe7yo6%Wq+)4MN3k?GPO)^9ilwDgEG?vBX(<&;p;RoHQn9q4hyDxhR4A5n zrDBPpSTrS!i9s)tkM1HRB-Kk6>cv)aQ7O#Go?#uLLDqW<8 zxzv~C%VJw7nM-{^Ux;m?XAIHnuVhPAlO|P7mgx1zE~nR@FomAUka{Lp>KRk&8Lf_< z$*7}eG^uA&&@-h<8hYk-uKW&E&8bq=G?c0)O{$ta-`zfXx239Sh^i?=Z!luOl?Xl4 zj1hzTm9A3HG?aQKP3jrHR5E#WluVvfGI@+7pgGYq^SI_Gee;Qvr_eLGQqQP$^h~PM zGpf`xDN@g*`j-2aE2lB$@B;rOw2dmYjV85?>RXGp(WJIHS!x>IR!n_MCzG{)HAK5p6Mp_j4t&|6GiP@i9%7# zVQEwUCzjM^$1R)Lv-!B?*7|eOEdPe|h<^iJPbXMX8>cqTo*pbZ(QiMt@9aMH!nMDL zQybQ9pWqzH-_i?H!!=9VyyKUQA)%E}nDat%X|Oxo)nD=N!#(j4{)*$`;`rG4b@r@J zt-EZ_o_^}|{I=QC^LI2|)$q|Kh1t`yr#EgGot8bl=I(#aXWHhBO&R6>p>>z^Wi?Co zf!yxd2a-$ph3o_27sOJt=lIXmQ72mbD}LURwf02EryV}QV#$5U^@)D3-IrSNQq*$Byxjsa{t2$7HQd|Dfg`v({#V}Gkh?){bqrh=Ss%Dg{3d=Ci#T3U z5qFr{IHNgRH6=}cCc{Z>d?W^vTjIKcMKxEKH8{2L3DSvJ&TgLF{Kw+qKmW}?rfwLq z0ckzNBCagCb?n-oS94E4?Xx{V&2QWqb+h<*MsIUU94zgqlb z#4qHxImvu?WZmkMyh;AOshiWRW=&H!w_lJ(O^`i3Wm9m2tm`cCOZI{E;VGL)T@e>n z%BEE6x9YeO^>;^%=V}EO5ymFy{S7=`={*X(=V2^(PBw$m0Y(>Z`3yBV9LQ%24!Gc@|e^eC*LZL zNiLj^qviH>X#-QiU+J%8Jy|YW{98`SN-avABRFHH2sd+j@+>vy$=rF#ME-wTYG(Da zBTMu5`)@2Y=M|s+y<*|4(};oEC2d~D5ONuHipY0qJwzGfKDY~UXSH`%$Bs!_5=U7K zgdsvnF2}U2>qS04woOahoNTc~OOnU6F5&&$rd3JXxMaX{~z<_3s#Y1@gaBH>WS-YA8kI0C7DckFFHQ zi;^QgYtr98nb_Wfb#kJ(C9kA5WZ9ghoz|1Q*@HWnN=S{xI<1F@EwQA{<6P@gn`KXz zXRSzWCM`+o0e+=TPqWgOi7R4F7-EsvGl_51UUDBbQJpJI#-X_83es*K$5h8$+GZA+ zb|SRu*xVv>2|1n|Lm5lmk!C5XWh_ zVxGv~6w!ZlA5SF_0yE{sewRHv@t7j^u;1vxlZYDgMqK8Lxb#}>OvEjVdFh%s8|S@; zt=kjjMg{*b_LcGft>!$dK^R&nP=%z;Wx#Pu-8i@1NBl>0Oh=htHX zw={VKcX`zP@M}%lR>^zwi8wIdCyWpH-w#C&PgL0l6SJK+U_FQ&%4mr)g)5vwu9`x+ zPGLsX6w+-9Go_|DSHnq!N`!b*&Y3h@4a8sh}sCei~ z-1UN*_z>4M$mmF_cj3NxuY!4+ygv~)W#)mzauGjDD%a)8m=n4EFR((!qRdlVo68k! z<@#K%&pqmBkvnUSmSsd7Ey~FWkFFc`Xpvuk^3kHUc%E_BOnub`Fe=X&|mhxXq`LCt?*HZp#DgU*U|60m_E#<$KGG=&8$u^%M^*55E{sx;U zF`trp2SmO*yw4)XS|M^&;JCc|KIxmR*^bM{++P*rlB?X5%^XL6Zo@}QDQiI{E7N>mvS z!=K?X;JwMl9H3kqyw}W_2T#I$cnT^-Euh@vtR_xghIPbCCUJ74rrJO*AvaLEONrT1 za!hGW`6ot8DVfETOp$X+iP=(OwvQL)%1|s5^ak!UNRuBII&HE+^!2LM|udazZXAG~HX+X@CgjfCi{nCJqRKZD9wf)*{E|4YY0bHZqvD=>IC1=o zvlJ6U#l%oCF;q+p6%#|n#85FYR7?yN6GOG_HZfFdGjNt-Vyc*!Dki3iIZH7yRZL73 z6H~>+R53AC{LAl!(kxQ@C*F&!yKD zeeo-ljhcE%S|4@G3HH}fWhGx+=W%wyO^J@?B)ALihB9~tUW89!JNK{ycETRMe*^pA z03;F}Ed?|%!Af+r(;yuJiH^?OiH=Ic$< zT*Mg{amGcQ@p;a;h%+wYjEgwqBF?y|rd{OBi#YQl&b){-FJi{ev90S(i3-kK!I>*K za|LIv;LJRc0!O#H6`Z+(Ggolt3eNmEXRhGP6`Z+(Ggolt3M+*)O$AzI&R)UUD>!=v zXRkQn*_UwkC7gW;XJ5kEmvHtaoPEhLXJ5kEmvDBT9)SapNG##(OE~)y&c1}RFX8M} zoV|*($2t2F&c1}RFX8MFWoB(aqZ7en^w+AnNuhsjk=0566V~vJ)D&7B>@89wuBJgcb=QAdv%F7zl~f#} z-uhRm5+`or*d}polekQkMnB8qT7K-t3$MW&P;I4Q z$9Te0!<+^8)RwsPiZzRg{q`%19Mu zq>3_9MH#80j8suZswg8>)-8#bt#PnW8AKVWqKs5gMubW`%Ic@gR591@S8DBLo_UQc zdJ~S+E5bHEV$B~Zy;b&MECa6mgn8)HU%kzHpEmCU5N+Sb#G`2cw!$ZHq#Z0F?*2^N z{h7GxXMax}bBMh3Mxq~is-N>F+Z$xw>gT+}=id|Y6zU=7DhhS+YqZcO$`PUmN3_~C zx#CFcEpkNBPs$Or@O5*7O!=d(TKgbz&%d-SKIXSAuoXT5VQU;tJcqsUoS}dU8t7nv z2^O5d1~I-!++*xa++%8>L(SbCxvN^6#JMkVk24)+CZ2O1Og!gXm$>KXxc&uKEv%#} zuDXh=uHvezxaumdx{9l=;;O5->MAU!Dx;3&^b4=LimR@YSKZ>MT4)M2!O_~!J5Kxk z(wgXHYN2&?YNR)7Yb6hr>Y-9SRH}zU^+YX&LOs5wx;9x`p;$eoRqnhWZRnJ~4b)(1CyGpBLuKuUQ z`_EIceb88CEeldj&JL_9s<#HVmwnNxFccSnthT`iE=fLH_yHa^t zLSc@N!qW(f(huLR4l1k0}k%dZ5>uLR4l1k0}k%dZ5>uS9(U=zmdP zfmh*OzW)Q>gMY$icppB158)&D7`DJx_yj(MZSV!q|BK=-pgGmj-_jpxGfHVQN@+7nX){XoWSjAeawxTLDQ!k6ZAK|=h8*XRE#fc9v8Ytqlv3K1 zf17iuxl3jH-kbC-B7KWU-y+hti1aNYeTzunBGR{r^erNNi%8!h(zl58Eh2s6q;H(` zjjPy0D!rTP+wcx-g1^JN^eLgdcl1KXV`<7Yz;xQOrl6Gfzd5$Rt<`p2E_^emkN z^kb0^%E<@i&SKfqR774V^4-NYBVXi)BJx8y`Jvob!9IGjeDqwAH{#@tIC&#Z-iZ75 zun`w%l&N6fCqrSA^I_@^m6zkRKTBr9!~uspqEpB1Re!? zJ9T}q`>EP};=HC5Yh@(XPl6N}+T z?U#v^vO57A-?+lAw zhc{sZyoJ^FHoZif;O{^l(#b=V%5t5)4*heWze6Wa>EtQ>OV|bEEqyn94SV1l*bDn$ zKYR;^;0KupjWwe;26@=bll^wG?~%MX%Q*`xuN#~V_ww8Q zKo6HgUn+G|vTyRf#4Pe+-1jW|mcjGDm=XDK7Wr@%`EVBbaF%k}v3XBgiT_*k--&JO zU&l)QHS*^X8@$$AU@8CB0 zJ(R-jFahoWN{mj4(J3)HB}S*j7&no(D7}o$mKdM&xtCH$YBGLbWuk1&0OUX}G=Q5D zD^S%dP}M6;{vTz%0%g6zyqE3i@C@6__~g3HDnvE1#?3Q?|GBxdTMYvxo2B zfH?O)J`X@5u>$42!lG6~eXl@$uRwjTu(&R?)(TYj3RL$B`&&x+b-;Z(+^55RqQ6%7 zQ0Bhwa1LA!MKB8H!E=eKl+&RtwZaX@LSp9xmWuda|M zCMv1BE2+CHsk7zyu3KPrCy? zNP$%FLmH$*05YH+WI}z&0!F};AcPEMtK4(Z^K4!#@V9$=&-h4@J!ep1DFMF}nP&mMcEMJ}a9E~P~-rA3a@BFAZw z9Gxkc0Uqy>wWrZ2b&jEVMtOi)1)nl?)0Hs&}aV&s17C;<}v>1!D7>l$RYoN-R z3V(oUa6ild>_#kumi2X%;C+C=pu@ztCb3JTGD9lb!=oN2CPi{+ka$8ciX{3@jMWx261W-r^a7k1rWCeacdB_#wz$LtOnxOAbyRPVI6FP z&tN<3g0EmVd<}cx8#n;p!9n;Q4#5vV+K|cocvbTA%(9;+mi>5A^3yx%=P6}B&nV+1 z34*|N@$96ZCnx>%So#?m@-s5zcW!_Ya3c_pJWJ?zZh>(y9v%knhv)nJ4%d!15cMT)gWISFw^0vnqaGxFAPv$X02xpZGNC?XK{f;-1YyX5TxbA!kPi)^ z03r~D7&L;$a1u0ulc6b`0?pu5Xbz`A3upAuWC(Eq);_ejzP>AuWC(Eq);_ejzP>AuWC(Eq);_ zejzP>AuWC(^=&EjZ7KC_DfMkB^=&EjZ7KC_DfMkB^=&EjZ7KC_DfR6(>f3G9wT0BR z#mqvjlJhRx@!5gzNBW71jdR&|k(~8X#GK_~>dtM{o!h88w^4U)qwd^B-MOt!KTOm&dhb%ZBdP5($5ct>_ z0Wc6yaQYQ62vBnRl`t5tf+27<42Ao-wi!SRf=(+#rDomPfUD?_K1q0`FHX=UiNGIUxQI;{+yR)$V1L#LIY z)5_3kW$3grbXu8?ePoOT)Tn_PH6{Y8+dy?2sBU92+zs?o8T3;bWq=)KV22slVFq@X zf#xz$(+2jKF$1v2jG6Et(2r;Q5f;EgSOkmV89><@*k%T{nSuH?s^A6q3#@<_VI{l- ztKhG&8rHyCcp26KcC3LNYkUUSvBoa=3UkjHkEZVe|9EyYx6bY<|Hf zC7oV}@$@>3r^jJDJr3jPaTsqYpn(Y%*ol_bEs5?Zo$mBHjHlOOJiQL%?Y;Cu?2}{u zo$T+KiGPR^s3-hbM6@^9&m-VQARjnm;T9MN<6$Bt_)eGvcfn-18>Rp%3GG|vkX8=q z6>EgTsufZFMPFPT#oHse&26&6@w-e(TFE3@hywpb=`-o$#D?ip1?H1cygKsW8 z0Z+nwcnY2d@_~=@_(*r(JFtmfkx-%(jm?u23O=9kx}@M~sYvOhjAQZerBsH;CE+o3 z0JF_rS8i3_!e3G;{!!mkCMuhitsJopn)!YAqs)rVK42c$owxA25?n<_k-&SNj$ zjMNZ*jNVpT;x{>0?IOGrsT1%^G(f!*56PFQ&*Oz?s9Gib52+l3EO zb%*dUr0&GG(BtZtcoKR;-6uUMH^A%9R;@8Ues*asgH01+U7A<_eEKT2JX) z`2xK7WN8-)|2^8J!gG&y1)h8QYEy)_9_>E-^jxA%$2ZSVZ6^MB#%PZTe>~c3;fY6k z93MOnXmjzqvrzks@U^4;U3g*E-V>g6w2$znb3ogMFJ@Ky4u3h=m-ytue;crI&qw%Gw>a+0s;?o!5-z7_5iU*gFzEb#W(N_t7E&5;a z)KZ|YHlt=#Uu!lqo9QnLA1(Si{IYb_UlG1o^w)$J7X5YMb46b-e6Hwk3ZE ze+zFbck3JRt#Yrv$-K|JPk+~ZzK_Wf zDf-94Z;HM}cudi^;xXkJ{S)EGS>Go7qv$(@e-!;o{G+_4e}zw!xAd=t9~6C`@Pnf7 z7k*Im@9=~2seTaOCtv7?%rDI^4Fyjp`wUh1H8H4iEX}a+Ut$|6!e@!WLs58nPRBP% zo)NGLtO6qoFCf1)vW4dl;|$^R!#Gp;{4m-JpC3jS;qAldCj5LD=LioUMxpTVVVo;` zHyb^LKM$iXo;-FL9)3Ia8U2Nq4&yT6yV5PWY0jO&HJ4dVvk56~EaC%{vU zoA9O4$(VrujGo3lc*q!JJcuWZ@x~MQw3ueB#&^Xd#@oWsgvV!NyYQiB z><}KGjW2}9XJfbUl4tD4+r(SOxA>NL$2cUsN*IUnB*CCGej`#%O?ZhgZQ&)t^!ajp zIcBP_fiKVW`cziZ56yD*?%Y{z`^9tb|&KxAXDVSG^XIjmxgf|6q zi14OhUM)O6n?u!y@dW28-QgVQ0b&vFT|5_hLVpm?1Pp*n;8M5@2EyfV1q^~BxDp1# zRlqEHh38b1p}=f;h1v27Gar=epct-)-@tIV0Y<=$FcNNpQE)Sih7uS9zlE`I3yg<} za3@THyI?Zh4fnvG;W3yEbKr593s1m2coOErQ&0&{!vcuILf~lug{K7+o)%DeCP!HU zJd>mFDsw>L@%#pzsud!czpwD)=j`hBdGjcxDX`*{;G9 z1=Rg6b-&B|PhI?EyR-nV@^^R_{sG%zhvKRM$bfo~3H2chf)Ii*6i$I=a4Iy1)1U>kgjUcR+Q8}17S4b(p*?hfj?f7@12bEAM#NRm zf^P6z7z?++I3VrRTj6(53b(@qxC2O2l{8gJQ;3dM+NgU2Psb3G?A8s08wb zM!wL<7aIA3J`flGc&AHIbH@Esh4@8J-$ixg1d0vH3tFHiHiI`^z|&pP+4bIBN^l7oGs(O())T;!P*s zbmC1X-gM$kC*JU>=i*V%)fdAvifi~F1=688oCf48yxF<!Y$$)y03H2chf)Ii*G=MzdyiP+XfCxk(294lU;C>zM z7tc_x(;qH|D`7BP1;ubZ{04@@M7R?s!Cf#JNNZ;b+yiAm8aa;wY2=Vb4r%0&MtEs* z@h$7(N7ltpl8b*N7w<@}&j8{Lzeujn0n!6sNUnH>7Eebm9$Q_!8M*jlb$!2s+u(MX z0Cxb_fR9xdUqr5ND*OS+KY06b@%7{SK8GFf1&H$!w|Fge@k;9Alhnl{sjDvd|FY!~ zGbc%v|Fx|TDfFwfJlUimx&ME(^=Zd^lry;oO8);u3#3w0s??M!H6?bGt5OP8N})Hb$* zNoElLk{0qOw@$P)vV}UEPtsPlQl#&{YN-rrQ!@=t2J-B&tyT3*+Y`4~m(VKxZ)vq? zsqwph;?`>j`>$qp_E5Nn?O`Bh3m5ZwJ^TiS1LfscYqd_HbrCHVv%!C~)w+{oPSkQ? z3H_wjtGeaVy3ulZXeJNMQoQS=)rhi>xFO&+?*LpOQoCJ)`@p_@E(lZS5d&`ln? z$wN1J=q3-{4J z<)ODc^p=O-^3Yozddov^dFU+elPTPw$hDq_2#lTd$gb)Vp%_43eo z9vaU><9TR24~^%c@jNu1hsN`?k6{aJg->7`de8Ts^?JdVq2D0ORTb#?=Fis|OfY56~)ljI9S4TMsa{9$;)ez}R|#vGo9B>jB2r z1N!A~1q^~BxDp1#RWJmuhM_Qqu*jq6PY?a+p+7zJr-%OZ(4QXq(?frH=uZ#*=`j`` zpoR6&e;)eJL;rckX+Zfv|9R*?5B=vEln0|TPexM)jI;S9|IxyFMh~{hgJ?kyE$E>I zJ+z>Q7W8Og2N@#?e*)YA6M?rw7?a>Gm<)Hr6u1YN&&D`^fN}l+rM zFwP%foIk)ge}HlRfbk%d!yjQGEP}=G3_J(R;CWaMRqz7*1y;a|uo7N^Rq$6>4QpU6 zybSArv1`Wp1B~+r80QZ#&L3c$KfpMDfN}l+rMFwP%foIk)ge}HlR z0OR}tlYC;5FU%AmUr39Cd|=iG-lt{;fw~I|#KQvd(90fr*<KFQB$XAkY{p`Gc!g+1^M>{SBH9|)kKJv6k3hW60V9va$1Lwjgw z4-M_1p*=LThlcjh&>kAvLqmILXb%nTp`krAw1cO zt_;E&8HASh(9#}S+CxiwXlai*48j_bzH;hVBSK?)SR)?Rh=(=eF~1?e{DuJY8v@L4 z2r$1P!2E^)^BV%pZwORdD;^r#Lt}erY!8j?p|L$Qwui>{(AXYxAOg&R2rvgCz#NDG zb07lDfe4_zJ+!xn_V&=;9@^VOdwXba5AE$SM7WdHN9$MT(i+jBNWDr)3haUIP;~sk4LyvpB*<=t_jmLb80P`&Z%(n=nEe71D^Z%f3k;p3U-Om`S)`DQ{fLV4eo>Ka6im| z2Y@Ge6rMrDvijfIBmFAZMQey<^`G@dXET4~f4)y(%}?$VU?!*99nOIs;6foV*G^@w zok|{7$-^pnSS1gu{LEd06ca7sCL!1TKZkU?5x$SHK`Bf-7M# zTm?hmY8VRFz%aNLu7hH@9)1JE;RYB1%=J@8!c8y=ZidlN0%PE}SeIkr78nQP;Z~q0 zPrZ%be-EW>-wqRi9z86_6Zg88v7cUHo-O-X-i_3Goa0HD4^KfQJPivV4hvxsEQV*` zSy%!~;W=0a&%<)4f*0T~umWC$mGBa*g1^FQSOaU}Wmw1DsaN3DL=o2Of1~f^-;We5 zQaaH0(t(+k9q4cAKz~aI`dd2C-_n8pmJal@bfBN51N|%=ctW=W7HS79)DBpvYp_t) zV4-%vI_*H;${MWGHCU%>c)oZI&lj)xpYB`1I(4y5nF|0q7+``0Hqfh#bt;~NUW0Y& zVx78Jr!Lm1i*@Q^ow``3F4n1wb?RcBx>%(s?Mb+JxetWy{3)Wte=u})pAQy1&h#X9}@qa&ycW~&!5TfKP5^(FJd-&5wp>Y zcn+gMlWJEdJ(hHi9>59Z$W-MoyXPL^do?WbG7wg%@ zdUmm%U94vp>)FM6cCnsatY;VN*~NNxv7TM5XBX?)#d>zJo?WbG7wg%@dUmm%U94vp z>)FM6cCnsatY;VN*~NNxv7TM5XBX?)#d>zJo?WbG7wg%@dUmm%U94vp>)FM6cCnsa ztY_C)11LJIXBX?)Wfp%Cv#w@iMY~whE>^T_>_8Fh;`1xm4PV0^_y+dz+kW^K4)Fau zI0)avA@~8v=UCM)R<(;&?P68CSkq$tVB&9%6egpHIM(Fdv?Rr{P(SUk1+u`5g=0#X>(a zvi27H-{Jcv_#Ae?7eIbv9%>QuP>Yy{TEslmqS{fni?HidMNv|e^$PF7?NQjfzxu-P zt45DdS1JQ}1KtMScK4CGowwZ`(0D!Z)rI8 zMp*C5JKP5A*Xbkmv3jXKS)ayR*dEpA=?nE``bvGBzJWKceZ+g!cIyWWUc$q>noqgv zs^O!JE3Ovn(N|w}^ELXEtFOLcq)~eHm{zUzX{_7mGg+Um&tlzHe~k4R`aIU{^aZTX z)SqSDUSH0-gTC_WF|AwaYgxC}UuWG$-^luO{aw~=^$&&)FTU0oI&{R1H|U=X8+Fyy z#pSk6Q8)4)ws!c5 zXrt)ooZUZSOuXR2-Vx*7eivR4F`LWuRr6XXObt-f(Ej9ibD(00@4j1;-<_$7A--pP zqL|{-T$=oD4oH5cS61(@tlnRk{0wAOhnJBI&n&9`y+!S($X~ppruz3e$>XVs<@wDy z)t@VqpO#Vm$y=Gk|Jlu}KPM$Wc{{A!&%0lfpZ%&ohgaXn#^iUdL!Q^!QT=^%^?9p5 z(?(QZ-~8k!EtS0gnoo0H@_7Gyd^%i5Ecr=GC%@Cu8DhUNKY3g#Z=My`n>r!+nO+^Q z>3fskd7GO2o&Qgsr~3F%)8u}qI$dz_k-Y9n$=<(3|EI=lfGuh z6c^qEF#qn14|J7WNzO8!ytI1Ejn~YD5 zcboT;TZY+!_sk75$MVflOmn6s-rly{d|iab8)n7*_jV4kzJS_QRr>h+tS{s}N~+SA z83ii+2aQ?x^NE~#k*_W5{=UwvFZT6dJ;2wS^(EA@D(_snf;FC1Sl5?pyrHm-j}z8J z9qUZF?jqOc$aOt?H2Ztl;*MPz4~4c!jdN|0XL{P#vp&zhj&(1480+)pe|3^;F+W#T zy2|xgtTnkMKHDiB<@av%bx`z_mP#w-bfqoZ7A4J;vEfrv`JSd^DM4!2Ts%lNR3f}3 zwXxDfX{t0+l6kvJ`mFSY>8sPyKhQL=G-F1+htnGdItO0Q zsI0dvt#5j(K;QK4X@k@I2Zjc=WUNjfmOeHxHgF(gbG?m$vW)bMy%~+``Rnbh*ErLv zucc4P=vc3FW~6?@EGMIHz5baU>vzm*k}<5_@XY@82W0h7lthAS5%;KZ)lBo`x^2?Y zM~lFdIb3_X!keKL-V05PXK@!f+(!fMB%gaJ;BKPaPb2Q=B*HnFyAmOu{4+w#{x5_n zV*A&=&d^T?Q_bm1T&X#WiA^;AHHij-Pxn%jK*jG6h>9FoKoKTI$6xyCiTQQoAKWYDVY40 zmou1eDeNDq7&&cn+U0cQ%o^8ZFjqH6z_;Oer{~B>fm5rG;k{qETXIC%R)~9!%AH3oHAWsO_MIm7`K^D?Wub+dJkHOIc+evA7$tT?>AEt|Kw)%Vq7&aQZS zo0ijyV|$qctsYj1b+0woo?&lfZ%_92Hm|VGv&LD|t*7jn_S@_&WbXy$Agj0aJL>^! zf&HNU4tsmBw~tw5^|fxd{%9?>%k53q+|o`)~5zw9wQrX&mm! zeTsY4LKDNpY`A^(ca^j?aw^0US}pHBzxucVp@SlBpmp`0UbN-OJ+%8`E2lkfp^B1A zXtF%EAo)vZGqFlOCSALWHN zDWUzxF2RUA<`nK=8sl?cVcCAI?coWDy*weYU;9=&pnazu)V^o-`D0wk+o2x0!%p6z zq-8G)^*r&yQM`5Dnr%I9Jz>qW=3AB4(^j1KWiGOoTF+U}Tg$8^)-%?#9M_TKrdVax zRO=7ceb)Wf3~Q$KpjB=?WIb#>YCU4jvMQ`Uab=^G`c|&h;HQL{o1x_MPR%cvhySI$ zi+5@6W-k67`y1Y&xsP{eG9%wkI0|peJnR_E$yXhXw`hKE{n=V>e`g;`W+avTq0(lm z#H@(mHEhw65A&S~u-%t&vmV{K=Wc{W+A2 z+CO~c*ZEUZ>U_aqJnEaM32XmUVb|3DslwK&{bLS8oj*0B&KE_kchomw5!L>w!fvYl zQ?qI}*-*3VeA7Y;lvDI)^%wNF^fmfY{jd5G{dxTj{W&z(Yx`>itbx|$ z))m$utH`?28f;x<4Y97ahFaHH!>ntq>#Snydh0jVaO(zZgmt4e(z=N^%8s_iSij|& zlJPuIavRT+lv)$4JFJP;oz`TYE4hoXM-leP;*Gex5BF5wgL|6QLc9T&_usa$PPf{M zci-~n+xAum-g(=Jcind39k*xkZrihYv#o0tT0N~^*7?>2Rv+s^-f!EFx7+sTt+wLr zwp#9HrNw`m)Bbg>p#N6U8Wt*T{+nkItzxn@%Fz1<1^0d%XW+l%Ctu$XU zSBa;C%r)j(^JR0L`HH#4{LVbcdyEg6KbVKbn~Zsnu_oSM%+o)9p5KYuG4Y;W`y{)G zeX`xuKE-Zrx3F8F241cwE$4~__q3XTbm3*Hu-5S$d8 z5}X>G9-JAh2tFKqEI2nfKe!;cF}OImG`KvtBDgBJHu!3AJ$p6<-wS>a+!EXt+!5TR zsIe`a|KEl4Z$b&~3GNRb3?2??A&bX#(nFb{U??}#Fw{L13pEKf3$+Nf3AGD#40UBs zVW?NAPpDsLKxkm72+O0D(nUOFW}d}+zq^~~nBvXf=kl!C`8?nC0Z(^r;n}W-coX+* z-n#vW`Dd9fA_s_^@C>qZd%rWL~&9UY!<~Vb_d8_$5^ER{8yxp8&-eFEO?-cJM=S}2yi#L$- zjNI>e`}kDz59T!5XSFeUF&Epp(Ntd=tNqASNGG}Jq+~EFjn^3QuJ~FjGReyQHW7PgfZ-Vt0@yH5>PDk{AvYH&`SeY{;PNIVCp)!8?Z?<3*XI{UPuHOh%h$S1VHG3DwiR(2&lf;s}o_!zH?i&?i$zI96jn(_q z80jA#rs%<}U{*Al2lQ~iaK9*eD~y#HtF^VmXrXY|Se+P%WpGS0j^UH=#I=~DmRz#? za+V?0XEB2Zl1p|s_V%mYyM>y7CA$@SMZZAu%HPJ?dpmN7lzv-Lqs!%9;x@EG(L*aj zE24E`k}Fn2^As(6fY{LrWR;mgRlQ%& z>Xy|l!kq_+0r6SA-^d;%maI04T7ND3j_eg>0(n;lu| zQ@-lssh2-pv9mLdEcGwtm+NbO$=ZKpso#TN22}sTb!5|vn*B*~DR{N^y0rRZ3l{S0 ztBPKKY;v3b5qGZFFREWuFq7Z#Ym(fm{>99inq2DlQPj*W?5(*=Gi!8mso#-b)*toD zz%04cN1`za$1bz)wWr#Du&3Gg+0(HkX4Kl_f3z#?KiRWb9{ zAF&^`|7_2;=N$9xF?*insz0q}$t1_s z`=s_>$ffm1*DRUDK)t##VAa30X33;1)H_lZw7hre^Q*L{skp?bqzr?KkZ8_M7$w z`z?E8jT*84Zog~)!+wwDpY~?^eftCZL;GWU%Q4?RvbWiv*<0;T>`&#^cKdUY(=z8C zS?bY#Wz^_>kw5Ir$w!uYW0V9lzq0x;o9({KHC7@Ct04>#%S}W8aj9 z_F~_ZVcnEt+sp~h4>t}S3NFO5c>%j-U2uKa2)-TmQ)WNHs@X}&K0rHXV2Na4hvZ>{ zG!3-~_eNn44UY`p8lD`U5q>mW8D17@i%rrEi==mW18r)HaC_{MOG8DWp`q(TBST|C zw}vK!Ces75I@~>+6`B#wqn3X(G&fWk-WggPKA7W#mQf$B4!s)M5ZV;l9NH4v9@>Rf zf0!BHC+I==PiU5@QIPKskWrjzRUc@jU}2{`qfOsBq+ z!4vt}KE*lDr#c}g%#-;!PA*U8=Q#^G$N5fg=K^QBPjm8py3^1pa3W6BXE-sZk#myM z%xUU0c203l^_fm{=QO8<&vIHht(}%m8=mTK>zv_qblN%Xoes{KJm25R>FjiM&T_gr zXFKOO-JKqe>)@})>B&?77dm|%&*|q}d7zBFfobBA-gFJ1I25uX#CyPZ3oyPV0+ zBnMw4&OIlH-Fuy>&L5m<&UEKK{1nV^9&lzl58{nrt+U4Yhx4xUp0nBcr?b)do3mc{ zC2-z!{_bqRH^J-HV^)>3-Pz%M?tI`2IA1y|on6j5&il@X&PUG2&K75@^NI7Rv(5R; z+3Os14mdwJ`<-u{@11?lcg|PNZs%)fkMoUl*hw%>qZMpX&#}V)E{(}E|1y1@{F<~C zDQo4_P1|J3s?-0krff~Rej(B{nW8o6d2DJX(^4OCBrWwjl4<$tq$K6_#Omz7rpcU* zsr{V4q44W!t`lkfo5)k-rXSH+_txYx=gXwt`YAmCGB^IRyhvxAehclGs*e$CW*e&X z9;pQzU?X5n7i@xe#jhssGp2L#Yq8colE*W;QLtLtU#i-i zKC@BuInTy6d|B@6YWAfUZ8W{mk7F&all!`x7tyD73w_e_u^nHN`&{#4`q*xzkNRnB z$v5P_p5~?WxRugly$H*a^yR!~oBimK`z<}%^RPT$71u3%1Ywrnu1}VCK@2o}Om5w) z%;bF+*-kd2UECe9d>6-wqg8pd7!T9y{x|+$?hqqmO1%@7M^PF@f5~pq2O^F-VUIa| z@ASZnzW8O<^Bjf8Ozk=Cd1kn*(O%JB!(-B0+S}SYR<4pA$%wQlc(-70!JL8>1)~ef z3VM=Wk%G1j4;7?0e7)i3h6@|6XjtBGPD7C=>sxo9us5GRe0uUlpZ+8C>c605=I_Zr z)X-{}(J;4R{%jHA~PZn zN9IKqM_!1mjcka#7x^TzD{>&JMg7rWG!ktVZ5!MGZs! z@}{}Le9PQu{*9dT3Ayxn>+=*wT9ta*#o9np;|gssXTL_fhV$OV(}8|DdYvw7(G2bH zJVTeMeaMq;Id}*gptREm>O++dvgG!lBu`fg@dWm^a;d&a|A%rJ{=h!ty~v;I-zwMZ zhx8v5S_@Ib7wiB^Qo$}D=N8Z>QLq>G!vQ!5^v94QYJ^%O!u>@IpcafcK+O>GLpo$Y zCeV8lp$?CPAs6zXAw(bs=*$RuJJJ-IL33yUt$-eiNLy$J?V%%dhOW>Jx&wU(kwWMR zy`VSrfxgfW`ojRY6b8Z-Py~Zv2n>Z`a2;F^!(jxBgi$aW#=uw@2e-m)Pzn=ZB20qG zFa^qBDolgvFau^nIaI(bco-gq$6yZ3g?TU^Dq#UEgvIbIEQMvT9A1DGuo70mYFG>F z;8l1X*24za2yeqCrG4a3)QVzaoE5{(}5v)RnL2Z_59OnsRUc zVM_GQ$lkn>d1LcR^Css_%PWt(n>Um*9#{7BTI99Q>z>y;Z$RGQyzBEu=iSEf)AMHK z&COeww>)ok-uk?E^S0#e%-f%@eO-k3)+D$@?0$ag240 z{H{@tQR7BhkjJ%1TXMHX{n?FmH*&N_{nndxZ;^{>MIMst*>e4eT$78~PyS*3XGIs` z5QZLUAL&Y|&?DU=Jt+yg2!Y(MM+QW$5ILTsKbC897Te@4*5oc)t%uDgDU3r*W43}Bv6yX=83|LqO|gzNrv7flHtR?` zYV7W8vliDyxirO^8hkM2&lGD~rcsnLORSl-GLalKjc=19Q)xvisNLuC?cvBAYWanc zrIZAV+J1RtB`wSA-*Qj=dV&5Ze^ntfa;^$F{__ z$9Bc`#tt@88d;6}jWQdB$qT+}%Xe9|?fZ?TDE`>)*#6j||HIpRz*$YKfA}+*B!|fY zBA_6!=j`q|yC@(cA}SWVii%yaH$=sTy?4dlm9ByXK~S*^Vi&}Qy`<&K))l)IdtwF8J0QS4pZs<<6F)}=f(#r2Ebi@l0{irW@BZ-Y zvx>8e?-b`0Kc^f^iYtrX7Jn}OSqe)D`Tmlp_V>E5u6bQsN<6Q)sJNUm|5*IJ6qK5k zT9(?DI+UtPb){~lo~C2Tl;TqJQtMLtQod9wbt&~I^)78y+OE{Uv`1;*(!r%crDIAb zmQF97Te`S(Md`ZIu+o^)?c^I$I<<6m>B7=wrE5wzl}44umd2MRmmVxVUV5tZLh0qw z8>RP3AD8Bq7L=Bj8cW}oeyugNu?cd^8QK!$R(P(txs}YK2y&~KM-k*28S5M5Rx_6( z$bIculkpz>PB7+!@llNX=t6jC+?DXKxEtZXnBNt~f$%HBI1t)j?i*%72aE{eY|DMi zZ0I2O9rK|BMu==e{Cnm_2aFTxO?X_q8R79U=T7biW@-eC9NB{SkBl@97(>FZQSK+c zgBav~W)^k8n363CPl~r9JUQN)@RXRIK*pH#B|I(WcPsj`*=L0Fnte*x(Cl-<1+ z7%gh{1>uzF7{UjlV+m(Or?TZWjAsrQHoFe-KYVM#KYbfgLccbl^Q{Q2=jpy#Ama|B zBb$9f_)By;;jhsdgug|M$77tuS%iN^=TH(Golh7<7ZAGWLc%b*h%kySCTt#ELU?yP zf$*95S@!sgUyJbfW*-^H_?pgfd-RC72lH(lqiQok~ zj0PRVUH(SQi4Wr|qWj`~qT`5N8QmZ68y!#VsrasFP_ws9#1sESo=pG2^&;X)e-h97 z+edp5KbsM1H^nu9isun&*Sc7c-%kQhxi4IUmF?k67hS<9n3@Az3dw8 zNBm;Ow2g^(kM<{i38UL?iT8*OAU>3FZnwtr>m2bEF+Mt+_rJblV#fSTkMD>k$9prj zJ!bsRlQF;c@qp-P{9BJ-(W!^>K_~**`ju>zh3H z|IGt}SAAEmzH;5INUyssx$fS>I}s*F53v4Jd@=2)?-{0j`c%B0jHWOh8BejuR7NYg zHs-k!H#eKhSP0W6{v-aw(8f$nygY6+HrY2BM0jMvJ$Q0nGL&#wavR}Y3D@~#Vls*F z{^S9|M-!gel4%L|HOX_y^Mo^#7YScVxF=5DP393cBn^ZMlZAwflf{JJCEPhCza_sD zu1VG~v@EO$3FC@pgh@q0*s5Y}!nPIb5auiLgjE$>#VcwnY6&~bEQX366&n-wt>{a* zZ^gcZ$5$Lrcv{72a@S3gVW z+c)h8%pm&uKVI*5{+E7?k@(6U!s9TNU$j;F3m_v;;%oU;Ymw`a>zM15>zUhxy>Ev_ zTl_C&=x2GaXj3WfXC70z9Q;hiDFdaeV%T-oo|n1B9q zh3j)Hds2>_D98U-cF4xzq`!pe2pk!O^+(hAtADjh6=Sc|GX4KnqFer7t(*TlWeQB8 z$p=$|4`#byu<6Ww!j)#1)I&EUxRLh(oe zel#-?zr;MgN>h*TYI^W{@H_LI|8)DBSKa>ZU|Z=9b!Xce?lCT~Tk{6-YwWh-4Y9k4 zH^lBm?fq;|bbo}+?C@~EsDr&j-qIZ$m5Xz6Fqn5aw+xQzAQ?;NtcN9-?NoB!c%?K3QkHz#fVEt>Ay4&%P z`{xKQ@tw+j9M?|H=YRJKWuwsk%Sf}#Z)8n=m;Ao@f%)U|r{^!sUzH!0AB&Il;rvti zS$Iu9&e!Lc=fBVYS!h;hUFcM(EA%Mz!56qk;Xu6TC*n09TDYz-s&HrFKKy0R6<#g8 zhqr7|p|S9DRlpP8x>Z#?(e>gfvp-Lkhw|KZD$nCr@RW9I)r6`Cc`}>Hlh~Z9c~wh! z`uaD&15Z%(K!n)h}1SQ~hc6g6fskKh~I)x*PL8)E_bIl)QsWIbV|)Mo>6Ake84^E5}pfwErvX8wC6sv8~2^t7I!J`%l+kX z#nZXBys9{i`^tNY4;P=}?(wbS$J{wCFMiKmV>9mgI&l}+qtvI=k9)lXOGk2_cXnwg z_jsd9cb4wsPVTwVtK7wXURuN*+|RW^ZS&f7YpZIz)b^^~rnZ0WfZ9WAkEuPi_War_ zYHzB&wRS@7gSFFZXV$*Kz3aT%rM2I37aG^Ks_Rf!s_S02dEIt(yVdPqH>hq%-I;Y4 z*IiRLqVD#($#subcEQilr*bXKezx~5*< z{;8K&uPwW#9>v{g*9*-asTX5F>c!Y6^%|*mZeUE~e&!~|G#+SfrpIG@GYs#{j)wc3xW5^Jmu6Qp z5>L&ZW)$~GXPVL65uIbka4&S8xrIBQ3(c+E+wdhf?w)QiW4Twl*^J{ZX}Gzad!kY1 z4(@txHFt7%HObt?z0`eXJafNDs?(<{t6-m`V73ZZ`Mg`x#;G zV}#0VbH8|j%oO}UZ<_}hqw=14DD4}0IQ4Nql6t`(rRV!FGd1l8m_~2N4Q6`k`^FQ; zIC|bHX4YYzR~5gv+nYVi0p>v7K6s2d&75nlHzT;F$UKfoW-{;od(F(|jeDPPU6fJy zKbqh8{zNO=20wA7&D%QL8Gmt4yNTV-?r#sWhugvSJp9L3*{kg}c7z>iN7*s<7JHW+ zZy&Nx*y;93`;>jw&agA>tM(21E_0CIw;%E)i@A25t+(IWAM6@#iz|ZWL5rXzBlWvC zjmqCK*onEwhX#iQ#|9?{=LJLYE#FK#xFvWXcrbW~C(~)c6Y|@V_D*~j%%w#v3swXx znWOQe%+GMng?O}ExwTz8*VT1*z1$XVPdwa5xFg+BTnkTOCh}?Sbaw{V#4FsD%t+R` zE+gD1H^EJG_qa*SPUcIaZYm?^pJ!aWjF5kkQSq-aHvSX$nVaY4y9I8c`^v3yUx#6s z<7*R7g-`#>2w1rnlD?<;<6E7p5WdyX0e*T}wJYVwPdgHYZzTDG1iKmo*j_02iJwZS2Q_<7R#N`XY(eu#@ zJh{w|XiNWf6nECfR_l1~w9hxmRpgp;7v3_rR<2cU?Of|zn_S!6I=OXo?Q-pN>!oe+ z|5i)P(QlPIId=--NxT~|h!*=g33EK{M^kh3uDf-kdAX|eF9~Nv;|OnwZYLa@#<`;+ zj<<}EXCS*CS1-dH%<|vqH~_;N=XmmtR^{Z$dsPnKLpl64hX;bVgumwSPY`avQ}Nej z{R8F6oi)}@Q&-7$umsz|8f=GqZ}R5qay)C3YgMj!s$b*l3;CNAN+Qop@}F74xo+k4 zRDVtX{)2q-x9qJ{&ae7M`u88v*Jb^K`4r{tHpPA|$7CzIRJJ2A@|DvhmZfFu{UQ6~ zI)LXUEgQuv#{*)FoB!LAEQO;;m;E*0Khyqsyn4**(ATQR|JNMYe@p%Q{{E*m zOb#ztG%XFM6FTurlvPsYZ%v<8PM?;p?PO#}x_o*$eR?^4I_U}Rh3&8;i%n~aWlLpy zx>UB9#j>TcRZWxaW-(n#&hk=;=~9VhOS3Jr-KM2dTG@(>N6{@yEX$jfnPugr64Rv; z)4Z(Tv^3kYq-9I9Ewitk z$)z#Lr!mQ?u`I9HMbpF@SuD#tjcZ_*mgSwstSwEGBhO-4UOBcbEz3Kdxn5aXmUl)| z-Wg5%ozavRuU9#T%oEeRGn)20vnlV)ro1zo^3H6^JF_Y8%%;4vn)1$S$~&tm@2sZ0 zvzqeGO7lL%b@$}l!)eGk72=GXCwwdoA5TMO#**?x8ct8cC)4n$G<-S@pGiaUpPrn1 zE)Abg!xz$!(N?6-Ov4w`a8??=l!h;-;VWtQY8t+lhO^TU4+44LNW(YN@U1j_I}P7S z!*|p0y)=A34L?XjMro0EP8u@HocPCS_(>Y#l_ur0G{iSe{EIZ4n}%Pe;k-1QpN0)- zxF8Md({M=|@|#QEg=x4b4Hu{3(llI_hNlvqlshdA@m3SZTTO_!nh{?!pWxS;{)se{tGN6n zS8dhl=vw7#OBR!5nwBkt|JVl3skI!H$IWEUjEZ3W>7do=wD z%Y*ik9$>>{IB)Hi@N2?5T_0H*?JV)=APG%hN#RW?LA=V+2IA$sV^X&EI`Kx!SrD(b zv}#gl)yc4+TGk1w2v_k2L-rWR(vfZtNq2k7nvOOfH#*vUyxP%vNujMK!@><@ov@3< z#UGpu=NXlCOh0<3+t^xJYU?E3c9!&DM~MeJrSbl<4kMs~WE?(5S^6X?9bF)~cweFH zC6sjAig1}-o0O5ZwJc@sw4}F9_cAC=If8J7J(6|C*rSLy+QI2Mv(lw6rAuEW>`r_HPw-+TvFb>^JRso#Y080VE^4r%jX9Y3GII#= z$V_DE2y;)m=A?8@+AZ6s-C}cEb%nKD&1ffF&9J~bgv;%_vedpO>)ZEbefv$C{%xA_ z9pOm(J>dxZL%Q@w*>4~v92-c1BXqs}E+w zTxB~*+;)_u@>IeR(PEQ3Z6ztIZ9%qXX}uMZjUWzq-#DXTMHf{J}h{c zTsEL3&|1EbHJ!Ad6^`~p+n{wN!`wW{<>pH+S5JJjy;PRk%Ltd*%Sjo@n_Yu=rM;5) z8he$jZ?Bg1@olr^V7aUlER|frGRY;+Xq35u@Xla`tQo9I*K8z=9JRyVrFND%YKL=K zYGQz*~iwB(e8btnnzQ?_KRqdcrbd02a-% zI68Pn)(oB{Tpm0pd4p+$!-DCuK3@QmcKHG+qj)1N+u_}`991xj^p(L&#Mkf*h9LRD zyh+Lm^A_Q9^EN3X%xi?hc*7vuG4B$tGVhTx%DhiF4&NbVFdq|+!HY;a&4he6j`$f}GK{U#qSym1ia0HbJsd?i%+Rjb_R+*g;j5Ib9!ogR97i}3-=%Du znqog^5N|Zc6RtGWHG7b{9&4y&u70P;-U3;=B1l_8khX+Cwl*xFJzxoG38Mnm=Zs)| zeobf(*yB8wt`5#8J|?(;cw=xOTk9HJMA$93m~g}362k6*lxJliqs|2m1 z!dqHLMMq1E;QZp+Mf(~{xZI6n9Xx1+!`x_68r|)LtK1!=jBy|DJC3xX zhkXK@4CDBwr@GueDauhimHxfLGUqyO#4a<$R;pcN@A?C*rj1CD|-xC8OVfRfX0rJSRKc9f(hpj7PZ4^l=2l#SL) z$!WKgoOX*%Xt7v>7K;UFv0{Pl_D{m~abE-#8w8ec-yk6D5{Ruv24b1-gS7~M3=+1s zGDs~Dh^>YP>#=5g*OBxUt`p&MS4sK^*PeKzqg1q+Jn>ZyOVV1Z2!C_r;%>7$>8ssF z#K*WEY^ST+n6R7cNw}fggs{7-X6Z;*LpaWrSbwFfCBDYh5q|GFv(CnDed5F2282Jl zE`&e3uB6wxZp0V64G9;?8_v>m4UZnWLf&PTo@*V_zZ*>_bQEoc_i~{tOkR}wUkjz( z;d^w+aBO=B$~kKfO?8DmOq3cNnEu^p_eQ0i4oKVMD!VU#OTPWe?Q?%oTEzjWt;N1u0Ji(_3<#I z>EbVu<>D<-)%BS%RQ_AnpI%-cpF*0BN1?2`KHh}#-?~1Yg!FIx2xZmv@gbD|*7flp zl>gTC@g1ap<2fj+u8-HC{I{-;$AI^DW*)9AHmxabdQ)shQ*35aEXym_(!64?ESBXJ zn`LQPUa^~|iRH3bmRCGYSz4AC&rDNVmRGE(>xmt+Se938nWbfU#h#ib7R_Q=Ua@MH zmgN=8W@%Yov96|xeY04WS8SZ6WqC6@%TuW4m6+z0nC6w3=9QS{m6+~Vo?ElLnVlsq z%bVF*(z3jnoz+(;rBYvE7R&NVJI&IvywX-REwi)u*s?O?0c%>C<;4Tml$Pbq>`a-O z@@96Hv@CCCXGzQQW_A`oUbbI6VC8*ec9x~telt7E^Ss(hVwzWCnpa}FUx{g6iRpgD z1CZs->?~DXfENjY}*;&%Eyjgpev@CDd zp2csO?KiWtq-A+CJ4;%YH?uSQZ_1n5S<Ho7q{?vb>p{#s8|uE3s_9nVlsq+izxPNz3+28Pb{&-))wc z-ptOjUY0krvv_;6yqTRPEz6tPS<?~=Tm%WzDEHT}$#I(#3 z)4UQ>TS+X-o7q`>&{^Kh&XShp&Fm~`S>DXf9Ai`7%+8XQ<<0CYX<6RP&f@3J_M6#R z(z3jnoh2>HOZn6Kz>ZCMGdoLKmN&Drq-A+CJCo9sH?y;(WqC6@OPb~-XL-L8(=tm; z?JP0PD>1dR#In4Zo!M(s-ptODmgUXtENNNZ%+8dvDQ{+HNz3wPc9yg(Z)RtXtSN71 zXGzQQW_FgeEN^CKY|)fAv$LdSc{4jpT9%h%PwNQlHRa9hENNNZ%+8WFi$19nA zF^6K4@NNDcs~Ws*?%>OZbi2lm)WC%GCRsDU+`Wdss=*A{XZL-~OnH-XZswo7y)ie_ zHqxz19yU5Kk~dvd@f;#OvC>m(c>8i1=RI1|ODlgnJi3Oz!*w?&=K>OQW&uksHV@kV z_N8Fo;DX=^M#kL3c$dUAcYFuXt>ZenB5&XC#@qL|XS~ZPjFh^BH@e>7?q=l5m+nXR zYj|FGN4O^1sAXT~wY8}1Sh;=W&Xv0}r)@yxft80;9$k5R<@m~HD?h3Hs&ZN75BYJ0 zwF>JLDhr(peG5Ajb}t-IIH+();jqF*g{upX6s9pZ|HHx;h1Kc&-ioTuRr^&PP<43K zX;n8>-Cp%b)f4HAC>eYAb+xT_%=+`yZK~Tb$EmKmE3=$>R&QCod-dVfmsDR>eQot^ z%v5@;`ibgitKVZL(wyq~)r+gYs$O0b)WkJw)wE`|QNE^YO>bru4XQc1=GJ1w7`x8J zuEn9ntBcnc-z^nO$CchKEw7zWJEeAN?US|7*S=W$TJ4*)@76A)ti@cds|~ z74==~cd6gA{?Ph?^+W21)?Zyeynamm#QNv!->P3y|3gFEkTk5-(59h%Lrp`ep-aPN z4O=(t-!QP@sD_ss<~KAfcx}O_3+6WF8k5G>jcps-HP$xn(703MX^mGj-rRUwxs`QTb`*Qszzmp1-5es?eUf z?CTe{WmfxMjZ&ycgpvFQ<-&Ro~AD%c+d9)H;?~W?IJ)b-eap>UeO?=%S;J zYn$r$9qM>cX*zX0o;rS<(T&eAzVT&7IA(PmmFsxOztr(i>iCCp9k>3EbsW?;ukTjB zYyDpJhf&8T)L&YEP5p@aTk7wrpItw<{yXZ}H#BcpyP;h}by~+=8#Zs)rs06Jjz4Ii zk{8Tg@L8j6^o`BaI<9Q2qmKJGp5AzMo4u9}B7$pRnMj1vf6Z!I(v?yXfg`yNej>vgC(!?V(F#M9yFS zE&F8IcZ)w>ObcE7>oR#0qgk+W@#l*_n}6`4&lX?BKCflTrf}Bcsf6PfZ@GAz#r+mv zxA?Nf$1gs1QJy`ufnUCD~tNT#tT1Q`2IrP|FvYpgkIXr=C7W=v_4r-FlL_r^2E72&+RdH zuem#Zw)mq9zTEbcD~_6f#Ce0}ciyRLbk)4-pNy&D3S4Yanpay}yO}YyM*`R4E(dS0 zSW2?N{0-)AFlU1gH+ZM+IAiKKp3mw#>VYCC(Klh(PZUB`Bv zmsG5{_cvQe6dai|2}6AKV^Hb4$a|qn~+?`5w%Px+=Gwte^eMZIi{Q>&+P# zz9YI9Z*!ZMtLKf)jm?(&nt!gr;FdY?aT$3#AOAd>#6m?sO=$mKoTQH_&cZs#^rrMO+g*3|8a+h=|Gj9L> zPnPJ?e=cdcO-srk`Sf4Qzu2JV<}LfQ+^XevE&KgFU$*`~wIwD0-~P3v&9v;0t(E;% zF7d%F56zZ{w%i{E{%eZ--Ev6F6aO`><%unak$z{IgRtcUT^fJGsJ*wD@lqMT$J~Io z*Ol= znozsw2e+QP&5d>A7@@m7*qOeO3cR1q@qMaZEe;nTZVf5b(r}u6IeRm`2xtmBY-TlFR<{f%S-lc!!J$gsp4`!MV zg2#O+c-vM4AJ|sGXMTX~5G=JFgJrf;u-w-LU)k!Q!FG4e?MAMJ?crM5&3JwK&Mt3v zaRs}ptFmXi{`OLLsJ+Y`W-oUG?M-foz1f{0?bFGhyy`W5Uk9tNqL^wLiNxzRK759sG{bwoyNSsNc<>?9cLN z`*Zx6W?*oXueHVCW8azCI&DqMz?lz&7n!qDZKt`r?GtW-o$e;uC*3{vDK{y&l6UGi zH?8n5Zxd9Rn}Siy61vT<9ei$gcQtkoSM=3>``|;r9^WKC!i=Uj^pLUb&GwxnH!kujI zbeH?0-^<(+Oz|592m2oWaQjnec&|+h<}RIK_jYx5fa`4caqHWC-3Incw=!7byt^oP z%@6WNnC@opU{_mXC%fZA>o@jC^3BZGd{1*;aGY%(ylyXX``8=Y{&t~T7Ib7D(&oVq z{(#_s;6T5X-`4*lJUcvx`|fjjyUs|zb8vgO$Zru$3MK>-gQvrBylH14vl|xqeVuVO zSi{|Xjyw4s+|GV~f1o?SAH)~54t58*qunv?IKQ>u+i$~N{RQq;f1*FhedIoOKQl8b z@Z0%*eiy%|-^2IG#r~-9tl$oRs?53y{%`~Qu73C6Najin^as0(gW-NBKiD7b`v;SQ zd*kl@0^YE`xxdh#@6Y3n>V2axqPZ2lqc)v|^izEi1OD=vmRLVw0p-vPrUI(mmNY=@B?wY3 z(%I}|yM$ByTmEhTj=9QQ9q#Kd4)?IPnx$r$Z5i$q_7DHzFST3vtN1o#556I}lfNk3 z$Xprr2z%PiZJ%(Hu($1Mp0%g>%lzg33V&s|McBt*9c~$J9c~wHANC9RN@TcmxJ$Te z&?#ITE(yO1mj{=IE5cP_qrX4=I{YF0IsDb_7_M=91^Y(EeHU4`C<>!E@=+2sk6J_( zQR}Ep)Hb**xIDPqPmbETGnv)*R`5~ODq1@j?;r3}-1kxBukjE1YooRNb^alLy?@x> z;2-ff`bYgu{xN^Ef7}oAQ^U<%zi^+ZlOOJ<`4Mgxe~*7XDKVe+{N#euJj}Q6L#J3+pt&oon0sV-aHWgW*!QE4|k8& z4fl-N`%!+nAMKy?WBgP87XP&UD01Oe(R$%FQ7-HoH4C>59u4=3I`~`tGyXO|);}9= z8h+!)g+H1pd=>J+@K1lcf6lHS{=yu^je|BhO&-5?Zv;50`ynlt~upiv7Jahl%e)4zwSN$daUO&OV7IqJp z*^i^ZPxQ0-&VhX8U}L^)&^!H}!60VA^ThnH@_zC`a&|I5sb^O40@Iehy6qSUigB3O(th9w-m8}XIZLJGzopZLc3vEx= z%5LJ;w!K_yyQynq_j6tB{;sP%z;&|+x()5QZV!8&+tXg?n7t9qmrDW8CTX7I%id%Uxl|yDRP8?kYRMU2UIr_u1#%{q}h`g;|>q*ct9Y`?~ws zzTrNxZ@ann9rvYu*L`N+bMx%`Zod7{EwFRkLOai`vfqcX{UOZRAH!zBBg_D*ca6b1 z!Oi{{JJuh|yU|*jb?HZKM=xr7`cT)S2ekwJryYaXbfO2fGB74j?`eU)(<-~hoW_WO z(-|*t2BQVeWURnhj1)MVaRTQsO5ogJsQH-D7M}#K*n?bmd$8Nc9^!h~L*2&qFxS%# zbeq`2T`xPxZEBBjz3q{1GkcWV+zxhI*qQDj`=Wc;&T@PO**$7sc8}Rt+~f9DX2i~S zt8Kme+BUdv>;m_#-^3s1d->!2rhZ6xV0ch?aCk^~Xn0sSFg*M(-}c(TbTN;a$IVnT z%{*bIndMg?4%PPWW#4Uig0aLHJ=f zC;TW}CtNpd7q$=A3p<1z!%pEK|7AGT&kJwx^TT_6z1!X|2w(CG!;k%9BVSb8)b!@7 zMVp%~OrP+^@TTzQa9B7z91)HTN15l$^X3IJ!^|`aR z%!h@rDy$A`!eUqoYr~VnQ%qOW&1`5kGFv8>`6bDv$<4_P;plKocuRO|c$>N0Tw$Iz z&zP5!E0U{{Yr^}&`@<=|A$%Zw&@3{G%@Xrfa%FOLa&7o>_)7SyUlcwTJ|4an&bBM; zO1p}=z!#;nvTh6)gbVG-_SCR4Y!lWcHzk)RRY^7Ta`2T#PbP(=CY>8A?@H6RrhOPU zi#>C8o=w_D_0jyKP5fQ_e*8f+C;BM*IQlgDEc!fY6)laHCF@3`qH)PON&BRAvUajo z^h|thG(MUT-5T8%jfqCYl``WeS&tcF9g>d8K1rvfGRgD4#*O~+eG|TF!naN2D<{4F z{fc_)W_rR7-pK1;H9)FbK{^@+MhoAMpN&e7&k zm#BAebX1Bqh&G9OMe9c!Mctweqm84ws5YvJHj9eU7SUG80OqPa$9US4LhV^;JV@tg5m@!RopiT5WYNm9Ywqz=r* z>Bu~!%BDF)X+UHL8K6LS0H_RH`lR&B?HJePw&6XOEt%WYoViZx@x4<03e|gVKX*v9pgd3SDBgl2-%*n9!|0c6 z{RAPls9mt+>J_p;S~_y3fKhQRk8A&sNEF19=f|?rB3!xtk`l-#Y)-s zQtUbC-io~#9iZ5u=st>-@<_SCjzjlT?0qOc62Z4OVINbCuO@pi6){K zD$%3pMM`uJda)AyjE-00Z&9fmh(@CmlqiqNwjioPB|k(Dqmz`VfKFB-vFE)?EP16p zK|B||Ux{0yQiR)209*EnavOkD^M5UcgC4C2Uni7lM zo>1H^=yWCSgg&W6i_xc)_$%~jCEgx=Mv2!$pH-q2=yOW^BKo`%i@u=5v(Om|zB6NH zf}}<8Qkf8axr{?!DboynwanJ&Yh|Qe&4xE&5WEHNfc!0OSCDnzQ}{}+VXSTnqp%Gl zb`7I*4dWRN<8xCO$!HkEn_}hs`b3GoN5yu)ct&GB1L}}5s)jqo6vjd0fLB6~&R3kY z-+G0yjfOkQ6h=7GeV{PTk!}ek=zuO#f(lgX1A=wYB}yP|OzH-L-O;5$dttP%;r#_E zjPs@A0~$$}dRwh99@?0%m2f}w8^y(_w0n+~5st?EpfI-4m>(5JI2!Yl63OzP6-GE3 z^9yi&Vl1sOa%{jTT4VlD7~5^kpGvSZx<X-$OT4@Jk!pU6J$HZlnY=(H@GN({^Kpw=o&pQ{mg(hFKLUj9f6x ztx%-SH&p`3+q+CFbTfr{PR4Go_yOn^WyJP<6y}#0yJZ=vhpiN5oEW=x8L5+P6lSFu z+gD*;jvQ?odYTv7_Q>uZ+-E#5VmEW{nue zW-D@hyDF|3x?7o@(cKj%?PZTLl5bCi(anZ2+lp*sZ^cPF5*rC;!#;|W{qI}mQglDX z9g6N><}&mE#T|woSmtu{AjJ(t4=!^PdWhnNpt3FDW{~{gPCzA(Fbob?oScJ$%E-BJ zgyK#@k1TULdX(a%%!A9^fy#LcPRcCjDtKwva(;pviXKz;B33yAgVWv=wj_ zsI(73+Qs-XJD_(ft^+zj@#~`#6)(1uvI)klD2~EHlvc09yD`}YDnqpd_ z?^#M+h0a%k=4icQTA>XJ{j7`|RK(9= z7b-y&x=1lMp^FvzV~t&+7>R$S1h=8mZiKaAnZoR6W0#kab76(T3?5@wme~VcrMM#6 zsCcpGYQ=Aleys#z-)|K9fsOrE5ubtmP6>`czgNs?^aq9hVqSVv)oU;3OT&uVhL5IYL) zUbMX;zYp|HrMQ#P4vJi(gN_RGiA~T+@kO*!q5qx_Y%Ah-kmtaZDQK1AH$thWl!MV4 z#rHsETj1rm#1xdsHAD2{V0=v8J3x~bx%UG!GmMd)T_ zUPCvBEjV_mJ87>Ve%4@1MSO(8R%LcYw^rmCDB#*5$ZuWHS8>Oq+bW^7_kSo}%D$b# zCnoC2p}H>xr?t;`zqbj2m;8H&rH zXDUvv4QDA%>?w8uC&ze>;>E6F7w}?Nu@^Y8^ZAND2)#gYvd+bd!|s8!18}m=P`H%1 z*yb|Di7hTyytL~p6fbptmExt1U#&RV-ZhGoeO{}$ThZ&_ddev_lXeE~BlJeaeU9Fw zxS!FR754`^ObG*YgyOeDrS8G^Lq{oI+W2V2OPd{|cxlVGD83IWWrAFc-llkIFJqNZ zY%g^$+yT;_z*Cp$-;(w|+*xKGdRG}K^LWK^ZUlELp7SkjXS6jh=h?(EN22$X8H`R= z{6O?x#Y=tNr?`vJ`^yYRrzn0W^Z|H~?aOu^Qha~(VR!^&+m9-7cl0sEOMN}A#68fd zO1wEbP4O3^PbmI;bh_ecbBu3DiMK|dQsTbo)9{Qj(HH2mN=0wI$0+-N zSnRM!N%la+c92NB5_>@+*PpMHWLH$m1c{t?%ao))x*S%JE@>-a6>+KGMkNxvu2zzb z(68Yq){*-CSxKavzrY&O`*OW7O3ZehRbuwz0)_V%7{^LN%zj*`#Oz!A)B^7>Fmjz0 zcsGF&AC|!T4vgFf2+U|Va$Od91A-BMnZVl(jNJPQF~{WED9J78I!baY+EL*P2S)DQ zg_vWN`x_zVSmmBZ?q7KChH>4LPy7;eM>vxBUFcD83h{l>GvO@a zwdmQ3_zUIPSn$-9T#Mzt#?wya+95=eF53m$0=+_sX=mGFrI;G@Y9*5NYZU1p zbJr^7QS>^+(01Joiai#+Ns(tJce4_2MF2VFi#qQKwD0L$B0Y;8V z>IvkzMEa!!>En{$8zH35oYVoB&rq>7h+mxdb)-n&w)oLfU)lz!*d1(N^iCxd`-t7a z9)pfo!j|aWiukeQ8C3|^Lhn(;w;|7>f;>CQy}l5(LS-4q^RBxO?k9b1bc$l6E*?I3sIerM`IHW!xd_%!rYC43!yt;}L{Hjoy+iN2wP zVte@;LdxXcDkJsvwh~Gi-%&zIld^)Bd{VymiHmKe-Oph=>!Tkjq3q{l#Y@|e^+4u{ zxVeg#b-q-*Zxy-Ub>As+y?5U$;&XLBC|;x5M z{(*AN2%h#J?Ou?+3u)_umoltXW^=TaVtSyo-IQ)4l1tqA*;p$&!GDsC@S>KNqNEIkH}gXUtw z?G&q2W${Yo7x3-B`)n~HzktxwL9!dy0i-^$KI4d z>_0$}d*pB*#ZN}1d=N=n*iVt)I=Ozy^-u2M!UGk#w+at}gIT{7dWaH?M-Nr}1L$Fj zpMnllvE6@MLiwBjE^k5T;f=&_1_7(Gt$ zH=xHW{t?IZuS$;a(+@GRUzBd&2!n)E=FpcsXv_2l(megNhd$ z$UeY7i9W1&vBx8de+qq6@nW0D6#q2(xMDv-rz(*{r^i&5AE>l@Fk;s?%KVAGsd#A@Zz*2N{V+W^eQ}#fvRJ zSNt957m63V&Q<)K=$DEY8_!exUFdwpi@od13_u%{s3W>Sv0I`G6;IuW&rXmr5$W&f zV(LrkYKdY`N54|sPUuoa`m4ibikJFauGq8C6^fU-mGc?=cyyKGrJfrVxkpQ{L94m8 z{6PF`Mef%^X%is#bm6y(`wf+I8{ALm_llQuTk?aKwj+7KUxLbd;O|9$R{R81_6=Uz zm+VjI4zdqHj!)VISgFrHlqf*|RQyDAjpAvW(MF2wuVr5)!seAm@u#3I6n`4pQSsQh za(gB2jACmcrma@?hn}vQiwM}se2*b6y0Bmd!q-yfu#3A4^d+3 zz4AyU9)upH#K)t9;b_)B5xrfBH$bUNA?}7gtHj%)GZar7shkP4i$s)mAn=tzQ%T)d zzD``yIA?|A2$XZS@&n>5tK|Hu#NLUN>k}n;AN>@*BK;Ut_5lfbDwipI_0Uw(4l8K` ziEM*$bt#zbP^XB$KOZWFI>|?h`2O>;V)~&uMfw5q%@ji& z&P`h21oY@e@C#Q&aet{CbgPkRu8!_bzBIS5@#2?nCA6mu}Twh|nUwpI-FnQx;6 zgHSn6Fw|Xs9YuWJ`E?a@6537?|98HDdtp^#w`Tr zq8M5**P{hR{L1+%#f(9#74iAzYZNmHEh^$$&6gB28Ld^s-vcU8onm)}jX`=PrlPU>n8MaG@wxxNWb>TNH@9)Rwxh(9ksK#}oi z`F#{8^|`NNrA^8{z{$2{yI{{lWn186KawBpRp>#AI|7yS4eZtEA&U41^M@+-8uTzl z{Dt{}ioF&+TycZZL5hqy%FA{^e2aP67RdOcyyORWDk^!vjz*7G+-c}BiXDRITFomp@;zGtdhZ@z3Qi zRP5{MMT+|vy;!ktpqD7(Z^{o>Tt)#Vtf{Qe+%W{$|CkLWe2#dvv%W zKBxQ$#r}YfRKyRJm-YnqM^xGnh+ir%?FOWeDlcsX#K)Y!RdMy`ZHj9|$0{<0B0o+E zq+E9>{uuO5#mc(U&VX5}CNFIZjO3N}1TwxOFKr0Sy68kj#&qQGQA|5@k|JYI@{<+Q z9=%ry9@|m zs+e=p*OXu=I$JRxqpvH{UznG356ma%n~L-w=HF86L8zRE;JTylDE46VUBzvL$~gx1 z5cGY;^*}#R?4hWfSKu~A=O{9^IRBC2dZJQ3ka5O&DHFI&&`%W^cbxxBalO#b6*~z1 zLUEg-a}|38`laG}qw^GdBsyP_{-u1qVvj-_6zOxyFHr1YRL*&DTcC>+I}=^3NdH5A ziDIP=zfzAqq$NXwV`Y!Tc zD^}|N8^ujUzg4Up>vxKieBUcpj{65ieEInw6)QIQNfG~k{%6ICJ$_Nd-=F_g@lr>> zDgHS0cg0H`{h|2d(LWV0b+ktDLyVk;roeSV{Feo;3x%~vD59-k9nv|c3hkki^o!6c z=uG+*==!h`>DZ^x1E|mNE|mH!^d+6PP}mlBpzgLt`@`9 zg|ietA3a+UKUU!!#n+?fD$);HI8X7^OF?V|;fP+^9WT#C+A63SQLyb=#AXk?q$p{tcd>Wg!-z_~4croxZ#6LD!9KPy)1+2px9|hn3f87PBv!Rnq9;(cB}BB3s$1^ zdX!@mB5YOFSxKb4v{51c4($OO6PGgdgkG#a2i+7lBmOD6xsr$twtzmQQ*TvUDv2EH zR!TGq-CBvpq1z}4cB$&CBw~YYl|*d$4<*6ARof}aTIlvl#5q>gPl;(`RXZrrcyvc4 znt<*E{VCh6=*~(s2Hi!8MxeVYG3}vhH`tx^IajOpP!j5Vw{+L|xHIO0+3DS&6!%_bO3m^gbn$wtT-5bwQ^n zQE&7CB{&*=P>D+DLrSy(`Y=2~c{V{GQ=;|J#})CpR!xOztkVsBLWwp;pHiYa^l2rk zMW0ck8uU3O+6;YOiR4^=L5a3NXDHED=u9OUfPSGQvhG|Zk?nm6^BDJd61r4LWE)>A z$-;E_jj6WO#mB^*k_*sCi9bSPC7y$NB`52)QIb8;b(I|3s&1#mt`NRwRPP4|6MqRk1O^g+13g@cv0?QfxP;%bW$5KfA~xXs68s71m2eepI6<#f zV(OxLn38LT4p(v=&=E?m1v*m6bwo!gIkDwvCCBxudJJ$L<-{iU!xZ9T*GJ(o;zyxV zmE4i&G$luSuBIIdxg${8TlKTVIp*s3lw1Y+fs$*5&QWsh(RnbR^^Zdr!D8aapkFDu zz0l=K4jb15N=)6>(0+ut7L64dds4HO5>wwbYb!DBpoU`;qVG^_B*Z0@;}qfoN?Q=( zBHCMt7NY%?=qHr=5~6R=!EiM3MihJ2V8`5e^cE#I5xrH(P2jfNDLL9mF;sHTFD)VUa#a1LTQ&mj&c{@RdTe! z62~bd*tx{A67`U~4xJ9HmpcW;{z8s+S34d!j$B`KiW0qmKCa|8MQJBOj_XM++Yxe` zp-(C~&Zk=1iIAq#UTUSyNIK_(kn4qVjS_O3qcfFUZ}dea*9U!BNz-2;4r%(U#39!Y zeND;jh`yo3*s}IbCASUAu?o4Z(IrasG`d>JonQ=EQgS<^5yY&|wV-Y*B}W^nJ3`6r zf*!5pc14E(+ep?&v7wM7U*|STt|!_~$!&t}ujF<>2P?VV(4lY*d9On$n~?k;%)NPh z6h-5D3_ojiiihW=ZPW2~6(W&h}MbQ)SJSB<_`6xXtik>4$ZGaCIy@e#T1>LFWf5S2aeWjug z#S=2rj$nG@2{pMJGquh)7YCPA7;<^$~>dzCX$M_rs-Kl8Qzx60+ zPs_z~1IknQd>NikqdbexRd_y!@;p8hz8gi+rr^0r6zy6(H=}F;%nUpsvj<wqAOA)u!wSAx)Hoqj-Yv zsU#f3GeHzL#_&)gN;2w?6ZPDiS5(B%WSMxRfhEhO3hlo+kuHk-0-jl-$mrXNmMFz|*PVElp!CCM@ZX66qPQmD`4^Py zAq!XGIa3r3e01UlQS=RX-YAMr?avZLKaA&1qUcBPoQ-lT@CR?4xJ?wDXmvZvT-5)9 z=RA}J`20US7mA|)hUX$tbd39nrJ}em!;|`X58zMZxe{e9#^|qjg72v$Q2hge&Yp`!gHNk&MNghXuN?Zk_urQq2ar5kX54$n%Ii}86Io>%iCX_>Tz}5xaIn15J2BkAM8#r)t z>tR;}R!X`{)AX4VlhVB`eR2l#mSoCl9&g%Y$y3Zy3q7fmr9vM|NiIy8EG0`h*~vMR zkus9qa%3*cE@gRH*?E(ttkx{QMHYgAEsEl0m)^oPS<<99Rg0T~tXrlOsLEui0B3;~ zz^^DviAi$eWGP8a+qD~zu63SUM!|5Q;*e^-=KMTSB!{F6?#86JG0Q28@BOx|q7v4F9Q1$G7SKMU;NZ|wTw z3l^wF)ykE|t{F3S)f&5MYZ<=YRT~HxymtEGQy0oj21dA$OzT?Ye?;^TPy zAKVpq6pz}#!AFCETIJw)s1)+6y5_j{f!k80_JKA@OqJLm3Ab`GRh|M}G-9v|XWg=q zYzT~oIDqLMk4JOov@2&m=2v`**H>CnQVJFAQvoti!ASCH*T(IhZ}`Vn3)!g zc0$@KU|3_A6*kOKR&-XFBka?&!Qj5r{3c*dig!V5PqF2ajc43J3kSC!^)4xHi>z#R zQCB#OF~s$vZvD1Y{8rN4H58e#`#QvGLpv^=YU2INEg0OrdQmhCy~nlB!m&~NHl1)Y zYZLv8n{Bs$Lb_hGuQZ~!1Lin0$0Tap?00F$q%oqMD44(5?+USk=)MqN>I-a`I`)rf znBdREyH}Ec*}ubYur{5Q`Q_XZO#Ga zuT8@2wENID77Xu$$;ape=i_tf1IAe+ePQ*<8h558oZhlijBaQr7de7~a&tZD`V)&v zxq}3l1sVHHn0+=3CM?%;uCEEEoM0BFY&T)H+c2Xr@Ba@lrO=45a{#p{fkVkVLmUe4 z0*sz&!raGU7RQ3oPMa|EIn0t+FnYWR1G@+BS{e&RyF~9q_(*#>%pIfl5Z1tFkICDF z^Kh&(2?q8n+F3Sgs|mB!gb_OUEc%4Y;1Fv(W9g+3>^|2VEz5+_5|-}{nluaw8cK>( z9_kI46;g_nCAEer^_{BunKc~q%d+Z^K;;MBQ4CsQfd4TGFAe>LGUt! zJmlbIz}mdbVX;yGtl(*ab?~&2=HzLDrZqR91#c@(-Zs*lyv<=@^8;4!cq3RRk4q&u znS49b(RvLm3BjYb%%EKduk&_i@OA~yH*VL#^Jo`5PwmQE>~?M5N8cR0PwmPt@pgp_ zP`kDafM$;QBmM_=5bZJBCQ6iif&4hIBrGDhQwA$CETK+h2}y}kqQ|4gWeYQi2@8l> zCXn&1Fn)|5$^21z3d^VAE$}&bMPCMfN`ZCXFVI_xml#9hwv3(4GK}mvNmJtxWWh_v z<254&W2d02Izg9Ru8}Uhn5<7*4m=*WyCq?e0qfH$3QSRdIqnx)7ra2O4^EdqY^Vwv zTNqF3 z&g0YFS?$U_zOu~BjC4)U$d~cZ{KdX9nCm5eUxoEyy@ei{kr*!jE`OWrfj+P?t61n)RB+RykW=G-M5XMdf(>SX=9+&i3S{3Zg2D= z8o*|#<^6-?*f!~UV;J=ZG_YWnal68rZh1S#LMIG#=GG_}NTv$TfKKU^jCZ+vhmIKU zKt9lp@ebFT3f6pBCjurHE5P>BP21hfrLjQ+Hz#4uR}#k*S(BBSSfsgB%{5tPvTTtO zHz-wueL%^)K&c6crC76&Re^N45!;p&`F+?-kSpc-I+n%5#`jjF`WllS+*O#7!7RGl z1JIpaAc5*$Is`c4%>DbNw$kvx z&{T|Iw3H;E-j=nE zk3c=EqHDMEvaAfk9*fB4dU169qw5BBEbC z=_CQOI#xS`vxN`rO^!2koWLv1#@#laF(TK)UYQMhr4W)gGVs?V7$#CWll2U!FCUX} z)6O7_FoW3w2Y{^BVt2Q$Ds$t=mRUj}&Kl?xFrcEiYA~>4NpY7Jqq#zVT5)<>X*|pq zm$$^^zO2e}J(F`_DYKc+Uswub$l^&hZq%AB#EF9jT(t4hTh?bEPPw$Z@xTRrELQy6 z#4&vn*tn8XaOk+#m}?Zf;%DN_!IWYQGK z(zUiMxl|dquhl}PR9Ts8OAzl1=g+Y$rYx~CH7z4uR{e!VC8gzDhDbjX{<^@=P^@w4$Xgz1rcEMZ!{`n&nW zcS7D_UtydvKG4;!5zvhZm_u6!ib>>2(L?R&x4_Me}Ot=ryZc`T0U49;A7FX`k} z=6p6~+7rNf)8?FbQtE3O2ev8S_?(lv|rJ^1_oYh)iz%f4eUyk3orA~qNq>(Y8+ypbN6EeXx@F=&y z0OjVZ5Z#?emWgF|Wvo}837#)3F0!-wzGYPGw((Lg=d?$I&^Chw$`N71Pbc_WBOheRSax#n8<1b5KWJSXnfjK2LNydy`O%@rv5qW{m_>H{y|L~KlKw)-vI&@Zc zUUpt?PI^{40tvvw%e4sq$K9%(tJ3fB!4g2=K!Hx7qIu-=uQ$qT#vt=qy^ zYgvNv+9GBI->+O+YpiRt==s-PbM1TeRa4)*hT9!qHTni;vJZ?3uGw-S1MJr9?*91m^?)u6S5JxcMdS{PvPdTKRL`~4zmDza0LwaXqYhXa$i_A zyMexUjU|y34=H;@DYBC#xQv%3}y_#2;W>|n6@U& zKRJx>Q#fEk&}^>rwJhqFbQmyt!t&6SA@YY2)}}w~9BIULtAnmW*OINv<)WE6e5Bp*ahb~CRNR`+nUWzCF)!ey`nQ*=GNU)!LbMOwD1$}P?>jB6@ zpBuwfYSSx~2Rei25N2{oSPm)V4NwtPga<&_a3CUC%{8teg=pLB*I+Fx72Kw*u&3Kp zUt!y{qLd*QST8g73^c~=RFqET+IV_x!x`hKrQ`c@n`Rjwkveu=q<%wx5&u@xcz-(v z+M#!fx)^u~NrBk2k*1I^X{e*qT5h|rh^T1|B2w{*wq?V?)GZD(PEX7FZp6MAMr+exmw5y<0964(aTi`DOul2*89dko_U^ieB&{u zJ)3i+&0DMIzBg;uhl{p+sT!;0L5~^#Nq?D*ICg@KeChUY>K5K#durRZKj-g#;ninf zHIA?0@=N&c=W9H~x8R%TBX2TZ7aVN7&V3VNZ977%mpV$92Zno~LDQf>6~4BObE$Dy zK1hm-7PW{MYH>O_dYp^fc&nQfV=eZ#%*)Bn@TMkXdE1e7Oo-@eX0z+tsBYi%k4yO) zw{Ymi&33-uMXi?bWp0^qOJgcPKKYpO`GwN}>(jqR@{A2bawK5t*{mjD$UYJY=Dt1Nj&>Xl%n19)!J|de-0eQ5!Yw~= za}NAWh#xf1uaqePhRqAKYX(x+M+#qz>C~tSWHIcMh~V)eRut*ih{@v~ze3k&{&JUg3l>p(>$MdmL3eG*nHjrmV#nZ zs1w{d=fv^}7NyG1;TQ4opcuJ<5`?5w1@f3AQW7G>r8Dd7{=bP!BMQclmnP^KOJc$V zjo?>K&$GykfN5T41WfZX1DKdHBYxYw%y5{q$c%uAB{P_hUBfVExTVrS5o8FL*Q=9d zjMs?48g!pBQfX{Ym3y#SM1h^>S^vHK-QmN*eAm9yUL82m4_&gYw1q{JmT^(f3#%v)+;N90O)`lQ5*4L_2ltx9E1T)(_)CYmDDx ztub7~crJ%%XQi}CwBuYG7#BvgQ_rTHx>(F9r!MAmip*`o|8n~vi@dt<(<-h6cyHV; zX)=f`Gq*e$4mNGXU^2^joB(EYdW0RF1Us5#_&J5~Z-qs19mcflzcUX9TOFP==dgST zly4;;QlEbG%t<1=8viJ3W9+B$=<^_|wB8ub$2LQ%2$aEAkueZttH5S~2A_<3!xij5 zl4aVgK)Yi!t&PTw6<8~}-m)FDtregm1|9Z_@}SqBGPFl9|9cvIW6vPdUQtSdQv@HJ zy4SQ>j9o4f9{^2}C(>U;_uA=WL>hq?e@Ez8+yuNM zN17@ohXNvpW|9Nz2wkrdN=vq9g`!v>vTQ0h=X8*nk(SC+s^Z`lSEU@5Bc=nX0?QAJ zhUw%TtpGvORc+dj#*YHmAMRbec*Xa|5jbf7_hj&9V0??bq#eXxI>x1{441o}q zOmKS|G{xUor)YPfKc&)R&8<_k7x_BnG1kmFMSF{{3m$83of0SV10HK`of6kxv?DjO zPKnDjVVYT|#1)$`O{`ORzQQD)L-3fKiNVznJtoB9+!UNJtS5XW`Up2vq_Q3F@8R>aa?M87eX1nU?B4tq0)6>CO< zwbzVBnsY1&R^7v4W8`%J)-fg=_7I1Sk>3GW$JlV#4>)X$JP*J+#)!jy#bIOQdmv8k z7%L8&$6;gSeE`-mW*pYfVWaau)+6?9>voA^>8hnm7{#X*DJPH#?+AI-E$@ILDINv! zSO$?~%f6?Tj%%NgEd_aJ@UMcBND+Vd1}!IV5$z8I2e^A5%@cEC9-k9KhmCRarCcxaHnbC=tf+a40Rs`g7BELc zlcVQ5yr%=7TLsJ!%Xb=%U4>o-%#C4~gjFHoBgYEgif@I$Bl2LKd}$lq*P&)9w+$d&IBM8+bSVhF+Ics-4Io+>LG+~<2{pwH?rWxI@jx%AJ(f!IJT=(y3PWLMtxbEN6r0zcl z-aIEB#~dPG%jb|iXPZOLHm+m`IeFpi;|$wr1QJy)2EVw;*F~nKTn)=kWS=z|^$~ti zSWmu;5iHL5Q~u33#q{0kCA)W@*|D4RA#a!KKJ1bp-4~kDSZ>6-x$YA%M?=#Ej6?UC z_(8S^2D9J8TstpN(OTNFSdK27dRPCSXYS ziFcg{eb@xd5F6%r=zmSXkbgzcre5k14Py*ZmRfzM*bOj?hW! zuUsb`VNVk`n6?mkmmPj{)!;hd2;0tKV*1UsfdWQ>UjpsK^qXswO&DSS#q^tNmzpqf zyq%bSb8Wl{lf_}8{N{Y^_ZZhnN8~FwOiX*!^)%N>N96GwCdwW)$KotJ!^fgo-U}hi zK<&tN(h*xH`C|L=)wlUvgJ>%GR|+N-aw{dYt9 z(XTH1>%2va=Bb5e4t@<6BjJMgs0WF^Spu*pUqZC363kxUV#2t4%Wj;@$vqNx@uj=70B9zHlg7n_BOmqc%OR&gOx^=5$ zK8F8wxJ#7oa|W=-Sz&O8Jk0pjXa$svB4husHN)7)!CM<%khdK)+S9w&!=K9aAxlA% zlvnT^#|d+Ti_0?Aqpz!3ls&|KD-Ia#2#bzMBL^_tKG`U2ca)q`{)3GJBVj-j z$g=hbXp&6vka#TEkryc=hfT)TD0?ksBR>^VtmS3w{BT_iKbgaNQ^@U-GNSY=_=4I8uLFkj#Xt)W zwY`>W)w??}F@IC8rwz}?`O3&K#QMe{7_#Aco2B3dz|eSyXs+UMXdeH!bIUk?E_AjF z-dNtaUGQ*UCk*D<9Z@iCprfv%v1B=Y$S%0C&0#anc$kYNjW=S>>JVu*4NfmS6}WugGW1@#I?3Kb9|N zT_{6ju{i9SR+%j8*uhdFmm*`=vz`rO{ZdL=d(v8$q_6-R{%@C(dtRBx`1md3gWOBo zA#~;1*YI@fd8_*NURB#h8HuFn!r@H0ee~A*IyQW(6!u}#okN~^uzSO|oR86&r}=mn ziSd?W=C1$-HUQ%=33c*AF?eDa_0s|KNEDsnbJHhTFywP{O||%j|5l^+X&d)La zHf0R%G$~Um3i#4AB#T)jb!fm$Dbtf}YCs=DQea65`MZ3qqg;vvXwXrYyZFbI#pyp9 ze;V<{eTH?@6F|9T=WUoaeNR9c2D;_+xUuf4yAPb-aM;4jHHFrq3@ku-C)hU;5&sdm z1BT`S0doYJJPHPS75EDnhtHk#s^hoNtHYvy8wsNwWh0t^q4DB4V7#Pg80cOb2a-uy zi7{RaoiK=ZwT}VQ*9n7pZ$u=Fh*uK~WT11PLrxN=V9ZyF#1O3>WV%J*usX&N`ZMg%b*#ZuoN??X#&s>c#6nKtr@kII7D;7+PC3a4SOZ7= z=K_u@oYW%*6Q&$VE2LhO?aA@-kh)%O*b#!AP{{ z4evtCv7ZW0p3vI%dVn+GP zNI`ZyMFZ?~c%FW0*^Zu6Cgo(Mw(_(>)IEizXc1vVk$GBL*3HV{<$3W++8f5ln>Mj7 zZ@j^CdH23C56K1Z&Etu@b}sx*Vca*2w%5C zYQ3tA)F_#&h9qIk;5g=TNi}AkMc%;8`2Z`R928Aary`CM8!k{}gOF>0!%0!iRaFIY z3Vlp!+uGN;uybx!IySi_>QVtKhzMwz}po^k?$S>87cDUcbTfZ_Idq z{HWxVi8pLAVv}8q(=uLpWz5Jcjn7|?B0uqspe^ZmLEEFOCI)T6JA57xFh^uzBRlgB z8?^)7Il758^%#%Fabe6TNiE9F?wyTCIO zC^v^_LiOB!qxw=&PxhOMuXFEDqxWdXq_s`p0zatPrw|((yHB)-+JreFZ4@vLpAUam z7{*<~(wcY|&6k3Hb+Y@c?>a7<^3<4qs^@Rllk0ir*cN~GV)rDCi))6r=7*`P50g1{v2RBGzo*8RY5~{$5=4b zFH5#C2XMLJHVpMI_TKF<&-F9y+~(v_z%(z{9Hwb{aXV486I1t6AGF8OPti{7v4MUL z_fzO+T9cW&Bub_*)*8_b<2o99rtZbuRf@mAM~|)CQHtN$xubx2gM47D7sJj8+XqH4 zwhs(2ABlDt){=mU5eGy(J6FKSu;^_c8119BV}*d}X2LAyFfrnOfGIFxuH!H<;(dVW zWWpdH7w?LS^BD%s+q93`l*8r5=iK8&{Suj@ieqli#K|z&PicD$%vrwcU>%d4*!5Nc zvkHk;dAV6Fvs-3(J*i@*kBf`g`NroS=Hokc7&gB7GBcy*`QReu#*E)LZT^Ejx#{~9M&4FSjXSX8_Y922Ds?g7NI1M3gU+UBX+IFiNkiez|Gk^q)i z;?uZi#N4c@`F$Sjb`o1;*UOpD{V?-}AD%ZpVYz>+t9#P;k89t&ukXC`>v_RHr7F=49cAscn6lPEICk>uHu=Nk_;2UUY%jE(V4$@#9WcI6U$Kg(i%vwn?C>fCu+Q+bfE+-R;JAfGduU0M=w5%Rrj(0uvNkUwYo{_&r!2Ygoqx}}^^32UUwpZ> zeyAM~h)^mY8}Cdo&TQz)et)t5!Tarn1Uy>Q4`aAC68f~I)Iqu}kdl`u;|MIIX~7kV zm9I!oDuk7;)acmBr3kZMu0dRHJT2JS1Q_o%v_HCp)Fn6Ql^XD4Q-D>0j8=$&loscA zXw?C4ZCO(6_s3&o86+LO%h3D<9*-aU(k+EhmYG#v0eu>=fO5_2JJeUyagg!0yZgV_ zykva;=%cK~OZWe~(rr}T_sYmIuii8N^~qObJIASeyLNOvm&h_$?M-*Q!^R%`nqBes zk{REfKC&wK=)=MK6%Fg3KeH4)0WC--PjY$75uRjZsF94(`Av=;_DDN7y|_79UJnUb zmnf`25m#z7_Jouzs9{foD?`~ex&6#KRbSlc-$A!zoou9+COIIXE@i8oE{X9qxLZe zgru*VXovKefT?45M8m+hYvW0F8e1P_hmw!@Bws&JUrGfGtskTp&>pwxg#XtvdU*dA zI@<;8KO)=3jP#`Opn6Krz()K6NNWE;pDZS8YH3TbIau7K49d;PR@6&Um~^p14j%}t zgtR#v8{xv&BPrd!8pG{kLklr6dAnrm8j=#R$(W8%;KS@!O0lm94xh5D%Hm3;+*{)J z!Jm&UyQRu!J@2i@s9$U}7@z8T@-H_Wf99~9*}bdZc(df`Z|^Q?Z~TW{zGznW3$^=y z=h*f$m_7LDt?u*tWY#TtGHWG5IR%3y#4lVY1($dnh3*xl=c3yjKs4Q2Y zb#%YC6si@~Lgakw<>VK>pI%oxe&HuaPX081{^uvQ7*BowJ-&4~9Ywn5#=f^eN65faawVH{L}j3B66nkZ;fM+Z-$3)pNOv?7 z1>)>%UrX;pvOJ!6zB`n1P%TUw%h#(!`oZEn-1 zA;$r3I7XmbIS$z{4?>`G5VErJ6*_D~UVFy)JmGM{Yx7sU{KU;0U;OBcnHD-M0yoIL{a&sc>bVR9#@_EKa5!w?<}Sr9BD?Q#&s*)g3#6|^ zzbqS-=tJ%E*ah{A^a|SN?;%`b$CXUJz*>ra)0j_WCCEW_uEH4 zwshVG_qWR8pVqGV`L2&%+<5a7FRz&Y8korVJm>ni=T5w*re|77O8LkE)wj-=bki%- zroAzL?XE7J3#x0TFPe4Bhn9aEGB^Y>$j|w}c10-{N{!To$hHT&oAxl~ZkckOt;kd> zsa0W-uO!VMhrMIv@F|!3GFUf`wC0CQ3d`7E!F+`Xs{HF8@=eAAE5Dh$;HPzm4lP@| zcG(U#)R^(MdfvPHUN$;uRofRYe&^a<^XJ^W^g;I0t}|PSzLbmcFW{!r89@l)!1SmF z;Vo;C_>mu#Na1WRwr7#uH%eV>bUExw-o5+uudZZ(V5~=hhtUrB;Q{&$_Wa%`>ZyG$ zBdEvNuaYOC7%j56^e}mUvkFwvOEwbX2r2B)uZ6Vf zkXzQAv}95bVOJ;yeI%>e;>3wz{d*lZCFM$#bCT3kO;KX*hy?C5nl`# zo#tr{7<*qyGrD{q9x;qN_A%19duVS!3c3MLI;Jqf)tnG$nO5Usl2k*wH#sq0;XNp-$?*aME)s zb~{WC#CuW_u}KT@!-1O6q zVC@Xmb=#GkuZ4U-9}!<81{C_qH2`$;QvB0Ik0vQfX5q>wCD|RXxoBY_l39v)=+lwS zqRJ+kSOr z`RoPEahx3z6*J@gBA>l@S3MIkglK$D3K;0KQ*0C0NsasaCFGyC@5B@Sc<_kzTlbY< zkQnqtjJXLqaG$xr?S!;iwD0gya~!z;S->1U2bf>a0p{nXU>rPfOqv_rUrtY2s|b8T ztamic5#zOK0zHlK75Y^U+Zu=oI$>~z!^ub;OgxEmRh;dtV*R3F2p-k zS~&mL;u9yG;U{*!tB(B|`(0uBz$g9h=)MD=(;Vh$E=Ntth!dtMS#!WN^DdGR@vfLM zf__1_STL~58ud$(L#IMN!BU}hPAi%r5_Fe>ll^2VUXkEa;@*b%czLzt3 zNbv9qjZ8HlT^-n>&e9Ak@P0`?iV@S4u5`fE-JUL=hWj<~%&(7v~N5Ir8F!hE% zFrOmMV^r8X#`OR0&u;6@XqWrV>92FzXL#FX?f=!d+BkJQ-JhE3%cRacGvS}pr~h+; zGNR#`ntfMay{|?YfjpWU20l|WX2WF-WKN4d>Ys96{DAtHuu2{j#jl`)6Gl5K4?io+ z5ttv1^{i-zbh>!gO7?(&ap+0`LpGj(sgoO`+cAa_JsmKiNI3+}E5R3Vm*P|u*hbzY zIK;xN;mAzNlCsjW(|B$sV?K-KK76)lT`6Z8sVsg^&%Q-P{VsfuDTYT*HU9Xm@*;m> zuk-$p&&d0YuSVZIp#PlFtR&dE!C+TiI<C(lZ{%`19Y5q9=IB<$!^GA>zyta?4?e z=DZ!uKjxet$%|-*YzOf!}VM15sZ%o13mI~Bu_{8 z9r}KIbUVCXr0>PMPDpzqVPJP7o7puJyx@T~*)33>1%*Uo6mRKtrbtsvoo+f;VMTi+ z(&g|}c@l6qE4J7&j2iRdXn&s<|0ynCme5$PnF#v)^u6(u@!sKA84k+b@&b#0)!1qr zOBej3KC;-T3~rJyW$!I!<;F);7W)M!SvrZ+LZd#Q-=m>_5`k|i`+_}>QMcl!7*9KX zD#pC|@x;R<-#McJ2dgCYS5k zSocuwY=(rhSc{8HEbYD6}TC3@M|Zryp0W6_E2v1QBR;h@I|8euLZM zc6qUXNSll6FE*IkKDfB#vUZo;JCL1OqiiXkRIak!_cv5mUegU9F#i1AT;~5vy@SlJ zjG~i(AvxqQke@r7fFU^)Fsm&el_L+U(YvtjH~m;n82GV7ey#PcrBSjv8$JdH4E*7n zBVnK`XJgGxH1$zLF$1yC1oFdzwv_6Kvp8j0sfG&(iqks$b};B|r92jbzTU``M_(*b zQ^KSC2R~G(VP|ZrJ8~YQ2Ecg2IBJan*H7p(=AW6;Yg{%>zQ8;~_0*?9>Q3}2m%QOg z=u>hWES)U$D;o}lh)zMbhyzq?r$UC8t{>6KA(ktg3LO>rwV-9dIr%Di@ofsyy&x?48#3T;$Occ#6illgOv+EH!C60iO`V6tefukn z$4K*gLK{nNMA3?im{e3&T-GX|PB)VL%rDm6rjro?2-C?}N=`<~9QRistj2TWDv(jm z{f+FSY0qAD$!%+g)-Snc>a}yTJ}z1D;#Ga_U-H*~x_yt0tg7voI`ziFv5RNt488x_ z>RSgC#d~skXk#aj@80dITh1%EY~7q-?%LinwhWlr`yQMsuOZK>b_4<`oy}LC$@{iaaHPKS$i# zTWvJLy+cHOKO6Us&Uzb1O*^*BIUWfnyq2(XucIEj5(JJ~!U=444Ub>4)jsH57VeWe zUDP}J;>;-%<6yO^Cmd&89c^0lptC#gh*b|8qu5d3*~TFxEehAWzOr!Ej*m5QHb$sj zE!?0lu9Dk_;rUuq@Z4thx0v}7SIS)4vi4;b(6Y*@lb;h zeX;(n%u1I1g&k#VjL0a5VN9oXXCOksqnGk)S3lQ`ZkXTK)D7zF#>$~$qEHU<4>6R3 zr5ivejpV}m+m>-XQYUDQcvezKw`hMrr4MAN@YDiCp z^I)Lf(y`&(t_rsbgQ?_~`60RkeNIlrNO;oqI*? zC8T)AFBs~dXer(P)k8*JfAakyPdqbhNb%CAt{Hp5=nC02dc>u}p@f4A{x*z4zJjLO zA0#7kD^yS(?wjFy(hp|+5&5BTJ&g&km!F~0Fn~MO@(gDEdE=mot&yUXw_%Pw&fE)89J1{TJZxJxa|IVU}J6xpZ z&&D>o6gtr^lVys-`}k?!BE*WDzi3`dmNBo1VWM!WT)yoOz~b) zTYmSwt5>XA-Fso?olM=fgUNUF8{^+`=J8EMWBb1H)uxUA{N~B)woVbW<9+8e@^ji9 zVKX?5L_Ovrnb(6)al!y-&Fe}3i+apm2Sq(>wsFMQyq@MRz;m5BHEQl^+(sL#4H^eW z+kcIy$J}MUv#ql}j63G8m%}(Z>Q_1HYaH#jlXf|9CqALR(%gl1&Jp+aRvV3Q?+{Us zxy!`8qqE+|5p&m{c(p}e(gPeGb632hp5`vIo-TI`!(;9e?PKn`I@~AH&s6W|i*xQ0 z<6yN(bJsPFHZ6M4+_fuKJ?1V9S}Sw-1JIIR*;PPe&vemew35wX`eV6N?RDhF6 zYXd1sSZOCCjWeA(PI-WK$7!{KI}Dodcw?ZL9WV6p4L%(UJLYC14x50E7g!s7%#J%R zDQ?UXw{n{)H0+iMp0>AmR6mG`X$SNJ!oA6X}re(4+2 zZ&^s%w#_i^+A($8jO(^c-oJUv0q_PNckNw^H=sLSgyut#hHZY?+M{0&z3$*2z|?Vl z?$jgoSc^Mguoizg5{B$QLuolBHZ39RlN3vB5$w1eFe}S z5LkNWeS@#f-kaVvB>9R3;+y*i>T4MOL~qVB#<6$%GWRy>ND7-}jBT@QblKo8!Jcuv zFDb?(`A+%GICSqy#LY}vuW^~ZGVi@nS?kiAY)UYuGY;TJ$I-xMiZQx{ES?%WDo^K| zrl%okLYHvYjp-dQ2Oz7&90h-2R#tPPF@1FWqQ$;)kKDfWx;7PYT9ZRlc->@|`n-PI zhRn>UF{1g9#)!{9m!NNyn{$ylUxAI%<0T~pVUdZG%zF`*F$Nout+VS z#4)70lcx}QjlzdTQycFrR23}#3A8yBnLGYMCbcOo?Bwr+o@RPdz>q%XqZy7-t~aeg zohChXmM^5>cthT|Fzb1T)g8vWap>hlXTLR`>Jz-u?zu4>(W1YgySAk-D6p1ig3FhY zwQmxEkFTo-pZ7Y@yyu0sNQcU3L3!}8=RI>Y#WapPi<}d_J?~jVj?>*EH_DnDTU(d- zIuv%mh9Vr+333$J^PZ(3k@QZvcH!%&nqA~1KDlmSM?dDirq?>G*qr>%lt-<39DFY9 zopkEHwcaZvZD~4%X=mXUg!naQ*_6V484H0NGG+esT;8t<+c&m7qELe zM%hN=Y0VqfDS)Ypw0rnmu+Rwu+h{=ynCvhN^z~1ym%st%xj5TjB|R7Y+t87?pP{o% z{1rp}75(6{9!K$LoI}BG9=O>HTRt&A8?z|x{KN8P5Zo8Js7o>H;*g@w;uNYTuSQxv zi&qd(h}W6;Mje#LD_xP5RaI4@Z6DZw1e{J_H{>wVO3583LxAWCN@UUD93Zqzb~SSA z8UaG3+F*m-EH2Lei~oqQY}4eAXt_nd;YykOg#v$^mQMR~;^QrBNDfTItoKFzG|(md zD=2%I7!>P;oxu+%=2$iU4f+E}s0`KVuq8!1g;3wiqMfZNuCy zKa<_|SHu}qt2e48&Y%JBj!gy$GE1mU1WQRuyi|(;7=b}U`!zcBO7-9*mXIL)mi)|- zxEd)gt|pGgl3qE$(SRzcRs)jTZT%iP+x|%IHENG9RWUV7lHFXOUo$OXn7OH}SBn#= zn{Edqp4xdQEB4;7?3Z=(zgn4Yd}TAnsKLV**AARF_*wR@yP-OoL6$#e zxD(^&?3%UU?HR+@O%H`Rh3l%BVH*kO8cZV_3GrZEdN9;c>`UT41G;cD)R9(*q-TCo zM_`SVh3qTrEP(@quaU5kOc5K&EbBl~9OgRR-GMAxx|%YJWks6nNVj+Ro6SAO@=fdi zJAdAP9-Mdho`xT_=a!9G-16hr|1&b=3lo>mTeLQ71(P>E$F$YtE`I#kVMDqsd{o}B z=<(-G{s)fSr#1=v0H4}PJdoo{b~@b$*b07+w(tdv4U9@+8tgS)%gOe_@sW>n+i_`Q zyj#}eu=>#DDPnC!u648khEWvGXyXSbfRjhNh7=S?Qit|!S{IZQz|W4BTNM{(q?IOO zS5M<*7J8{<+Ftci1s74%J_&E7Ka=U@CHL=`c^f+1=c0SoJU(TK(e0K_m7>!xR1JBA zsn@pjEm|92HEyTIzPWr$64qN^4q(#LL<3rHU2(y0ZwxWsNamEtFvhE8tU!Byjxp(v zhvb5P)d6`v_Yqxa9YJ&>*K?mRuZK_gJx4vQ zYean=yF%3C&NuLqRqviC_i(`5c*4)?c(08=e5gM-`$hgp(SAsJ#%v$s9c~}%qi*5$ zxnG#W<32YB{^5Gu;bzujUbfqTZ*`UQeDu6byk)%$40S>p7aPW=53SdL57vt|onT)$ z+JJpAD!L7lKbred4}O>JxmONY1gxJlrST$>xv|M}7My>N`Z#lV4lVtfN&= zINSJ;FCAmW{m%k-XAIla9aw*&jkEG2`NVl&g#6m@6m#G>2)aQhjX|t&xH`+BlVF38 z3qeIz|76Il&_vvaz||AKoith}A&AI5vY5MZM5d2>arDw|-Ixf6$vxNqJb&Jg57vIa zQptr*8oMa}AFcn#jt1Z4I!T?i!Z0>IXPkB_rC=3TN=*6}Cf@J0Y;2zB7f7JH!sB6= z$#6avV9N7A&2SAf4p%Vn%}IHI6pSBIS{XJa@S3WC8#UN_QCuWWHxxVZOlMPu=U-#* ztLj~yRi4_paA-gE+bMVV&xqfuCJwpeOaKkh8GrI|ygys22_&RqcbA7DAH#e<1+}f}YBD z;Fl$h*-q%uf|7=^Wf(QeXTiQ97}`~c0BYJujg!*!Y{mFikP<1h9&Zs46r0i_$Vg#W zSdl)@kDq=D6!W_wN3i9P{_Hm+$t0pnebqJOk_o^Vy%%&;CIC;bG-A8BqF&&c7iKxa zm=3e98ccM=jcs`dgW|Wud{N&C64I@Nz)@W2W|Pmxu0D)gKlZDU%!%i~46@9}SKkF$ zMxF%e3)rGt%`?u-dn4dO9`mcW2uS9x+px-fk!pR12BY#T!<&x(f!pL*g{2EXWt%3Y)Os30sj#W7r-inuQ(JDa%ut)&Xtm4T<_GjxJyZwf>yb( zr(jK)7h=)kyOK@|LuQm%fQNVLQWzQAa~0>xL!R>Hkxo0)`&>V2-lN|10rMs;`t&x6 zDbK&yo4S9=_jMFdu36aYUZekti6aXJl+Bs{Rq=?6Zu{+ptsxOxUbXtw(ei>fpL^=l ziO){^+xsAgpogm`{7oID9%Ne;LCX|F%YZH#?!5+GkgjGb8bn!i-Rv->E;uPe&IVAX zb0;Qs>)NSD=N_%G>)hpn=!VV{YV?xk8W%PIT1z(iN ztB9v?7V_NCAQ6KL4I(pIz^FBR-UJM6fK`?)Mm)uB1W{iv37+S?rjZRL>g$ju8g6HS zRqwuuAiGW8m%pt*YqF|$$<1hF(f zaJmKVFU`vEq$H7lzJL`(r8fBa+$tPEm40L+(*E(w9yqq}jw7pY`(R<}!JN6{7d-vs zvN_A;KiCJiewlI?V_UW{d0F*S*Iicq){Yl8Ls#e;Ly=~D-F z@D~p5(kfMNvOj}HOiz5)RXx9b$Hv_fx?Amu^$N~m2^3+zpc6ZItOo~U3#YUKisMFB zKMrZYaj<#(#+7mp&*DK&q=)asW-|_aRq@OX&+hwX?zJ=Op5kY?Ix+(iV#x>N> z&bb4N1Mth;uwU^m@WsQRDee>d91qkhm_zM)9#5Xb{piRQH{;1T=m2@QglCB~B5+v? zOos3PLELd7`5-L#afCy>3uc(6@yoE{Yv86SrIi$}#Ue#Wm)EtSEwBaoV4G~Zt&5ze zNp4NW?u-(*PQJy`3R*fxG$Sp_c zE%We%>cMcM3gQ?0{jerr_Ylb)er*dgdmOANZpG6xpWS=F8jf)2_QPu?g+~Q85a>$y zlt`BahGjvUW;4x|@1U>CsZV8Ds{xVuA~kZ3p%{D~PId?rl>{;dQDYz5Bq_ zDJ&pOU6U6m7BHH|4M0_7EMT}I;o!u{V3H5Qji@1R5R22KVpeSGB{Q3t*b3ogbJXZ; zuCi`v9&lM2PE|Rz<>1`wZ&-8S%jDLN&wuW-3#!^)anEJnvZW`}|NWo;-MWOh3S#xy z*s1^AYy5KEtaeYZD_P-+6~>dsfW4$g>y5kBp6WQr@?W;Y%)<5%;V#Q05eDiI=?TEv zii76`G9#)aY}E!F8&dV6L)ht(K%Sz{tsx)*r(BR3Ob3bWR|p37N%$BrkwJRPztG^vH}6>Dt(dk5q0@8-DE24ta90yn1+qjjtDxRD1?7o`b zo`R&z%C@6dU%`bM7dTD7e)9g0*_xr}tMV32?X&z^V=)OeI*NBt--f$xLf_g*_Y36H zJn-b;fLFPcX{K+Hk=`VDK#6CpsWPs0NL06;A8%BIM1CZ2}`&q;^l zjQS@?&+99M{wE(t=;FrvJ)&S%N5k;FB|UYrM=+0&%^f=3xE;vCFz1{CKS%VL`S9QX zAM8Ie+gWLdb5xyos?-}7Mzm8eeI9vVB<3&5RdLK;h{r^qqfdIDU^IFcelrJ{ui&=U zR`8UTP}hJ5$uRzz0U73Zo}s2noSV%rOtkJiqiwkL2h?$A9tQxuAIs?*@tYEv+S28% zbblJ?{TvMDQQSw#>v8AV1H67S>P1eZs6T2v!s|ao{dwHK!|SyZhQaIiLL_?HxRwyE z6VL6eoiMCA4m3p@4k&wXE$~7nf_!P?_K-!^CUlKy!Cu2tg{Tk5h#uUA6*wIY z4X5|;byv1suffLTv>=o#UZWUjGl&S8`jJ*W+HZYk2)B z+-3H>)epMMY`tio*E?{hdOmup|2Vkd3HI7qhN^gC0=vW{d#x> zrU;lI@H|kKl+T~4(0MVmurtr8S^dqe)?yzjQGAycN8Gh$Z^)4vjZP zv2|#JSYwAah;@j7;dldvVgLk#U3zs$Ul;e$b4X5;b7(KN>;RW0_+6TVd#OM-Q$9HV z(rM)+C0G^Ju@Ig>p3Y*FALjIM-oI7Fjj*Qg-=fqKA0=F7blv(wYe`%PVRUk{%yG+N7-lVT~ymj6sF<;l?^ zrb^cN-Y2#$oqpipPpt0>`O313y0`CHW{hI%Zn(W(`LQ8qOYX=AYS=aBb!gjdOb3!# z-Z$Q7tSdQ%U7Qv;8$zz;d`)~nvdR6*p~m&A&H9+ML;FqCLl0Zyd=Tw79$~IqRoY*k zNOu&t6LieZwA!KQl2VIbz*giQs_^!H9790I&Fg!kwss*qWc=4y zIt@Gbx3Mpb{NN(?`!wSwp~vyAgHomx2=qiCT*CHkh65|fX$VUn2a(EZEhLQ_IE5#xfn z=_)=iqaL~f^pBoTBVn{7z`gOlSDJI}_DScki+OCpq5Jt<>43ppIWrOlw97Q^Rt`fp z5~V9%q+tT(OiMP`x`B!x!NBzuY;YkT0sBjgBCl1d1sLu3O9GT*G-(;-7o%C}Q4SwS zHwGAgvNw$amcr&tQ^(=Zg+WGZ_MLp2fsiHCHR%VM!>{6aK|fghLu*iJG4NuG`P*)C zyhzJ6uP17PZPamihl6dzJJ<~H=vnVPoqroM3$(U`DmChgk{P8VZ42y?-0|9)TWt7iBkLgOhbkGN%{}BP9a8$LB>j+ z$mx-o+`s_wgwp|}!N3m0nN?V~Ku2)T2v#Q(Xk8Aa3|>u7Oo-E^RF+B^y5uuNf)dc_ zW~L)K5|G$&k$`ldcK``T#)-%*BiDaVuTH15BJ|UdOGLI^7H}&OW9a&p4VEX0SyP^9 z`uPAOXLI>INaGw+HhUS_#8;4gz+h7N=`bFq9rZfTNvSJdylMZ)^5O2EZv@^k+JYSkUvwYcs;;t=PCYEMj z5_i`^^}{pc`=76>8}%g6B^~Wk9KS^V*@qJa+&84FLUL3P-TZ#5_`Zg|pLS>DU6}NH zTna|Nzns3G^`+zY;D3CtjK=r*SVayCAj?T-S@68bgA(E}ImF{2WCc>dH;U*wcMEa% z1;61PL7rBvnAECGtJXz@c{%B6DdcXz@jg;M%XbSlz(_`}}jTh%p4il3{=NZ}jK3&iZya*ok<3T)%-wGb3 z`Y?}Tz6rw9QP*4Sw#QyteZ{xvZ#XiL@Wv72zjj(B)K z`8HR|W6LDh7Q9*rrNMxYqw_%MY$6<9hz7+bSB7tS&Z+ffRUj2#`XxX7Jn7J?@yIKK z1{GT~tqq#cuR^1SKh*DawR`TWYgYQ&zA^jCN2?Fqe)*KyU*1qPW|=x}?~OBVyYBj1 zMm#ewm@FTdaaHYA!LIU=QPbz$61*5pLGua6zrA!zAjRJjHdokzE7AsAk@H8Z!Ra&P zXQPBaOyXo9k?)+_wtnygS>v*-*TgYhuZ{tQ5EjGf*uGX2AF$n#?OA(~KN{uZwY%83 z_o=QSgFE{DL;BjCJP_G?%QZPGva?Q7G|V#nlgH8ban{(W+??TKCx*+~ip<9ldJAJ` zeSu*TM;C}OL{dSlv4b^J%Dp|}->{yu6<&o$Te?qe_xzO@ymq^8p77W>=ir@rJUo2z zufZbfk^EsWlZH=z5jfEJjpKbNmAVGH5CcNt;w(ZD(ItN!MhXr)8kW&IS+J!Nj&&yX zDkkn?p7OI|NS;R5Gwvp^Jdl8uRI_-VdE6Lh&1u?FzRrOE0(R~Z`7TF2#kY7p?sGvb zm-LG|hy6GmT+kV{so30DH>j_ubpcjyjMscBU$iYEq&6F=!I`_9;6G%>l zy_OGK3X=rl3SkGUNQkt|W^1zxm#qT60s-Dp-fh|sLyN}%Zl9nHF*MnTkQ?RLVFyBm zLs8g$5|_V{e{r4h4&#nhvvaHuPM+tE#kD*%M6nX9n_`QB*&q0_rz6{~CXnn!f52Zz z7NG0oM1Lr`AhJK2l z#4b3D2Z|0A;ly;DjV#wjbUGzqXN(gAyLP&ubLYNhu6%x@AvOGq8XL8oUqi1_+zGU4 zA%S1rI71fG0YU;4&$IZIav5lD^IKc@-gPR12Ik7|D9A;jH}u>>CroTVHS!Q` zJkd_9`(9}-7)$;%jsyHGs_ExZKM=YIItn`!aPCx5z~>3yFN(QavCqZEVNT9}dZ}Mlzc5Z4t1E{46;&MjF;iTv*hc~_Am3=@sUkk@k^&g-=kU=gan zEcB_mK)uU?cMk;8v{okg2VEm1x=(PLkPfKpMi&KITZ+hCh@R#JoEHT`gc|KUGQrI4 zRN|h%oNOFKj7^_XL8I+dUCQV`tZ2=v0{wnEzdT}Fx!6$0N%hl12-7J;pBdcx^*21j zt6~yOtxGQ1_xi>`hwq6ZoS=oE9mx^Vi1LVE3e%3um#BB{cbpZj2j9LBh9|$j+0Jok zMYx{){-Pdvo}W4Dt@mo$m$PEx135L@M}9H*&T7X!Nk&Q_jWN~R?=2Pe=tt!H!|yrv zi}O8*37B|=r0rq6=&S}_k8_4J2Yk5RU2?Ufo_w%oJI;Ncvut=epF!v+PH+86yZv9B z?dTU+_3omGdJA4he)ByJJneeqH=FhF4cc_#`e_okvFxaYB^Qn{T*F4hY7_az4qmWv z*4^!!sP7O_kNjdm6L&|eo^Z3@TPk?Rfn($R;s-e_t*=PGo8wI~>Zo_}tD_#d)aVn0 zSIG1qT&DZ68gYDjh2)M;!PP--{c2mjaTZ!- zjGs_zy1NGZTDUi@sh?9)>Hp_ z$D}^JdtKDCNB8r(b?wrxtY5S)OBLQ9u{ZKub(t3l+K7SZevvnTSa~_}$IhmS5VZRj2sdl@aDt(TvtpZ)@AOOa9nd?b=>iGn4C&VWjiHtKc&SFFNIg z&lfh|mhkz)0*J|!dD1c|ml9>Cgy9jYJHg?(2ol~ak3_BEI1(;j=$qJwh zymW7BrY93?8F&cIG#zXItaWM%zl6}oIU&*xxMNjvaBFhi!}6fiRf`wZMcV=|FJ1aF z+rMbrHlS$HENU!b+6MYM*fFM#k|!yB(Ew}!7!Vb(sk~Sb#kwo7YH;LTf$8bUQ)!i+ zj}6k+Wr1-LE;JB#1=8LFN~xwaZ&B#7KsvpQQj+A64}5paoP+C>?}G2MZ;e8^Tf-mw zN6hWhw|3;cr`M*eJzc-U_|Ilz|BElmzf5}S%9JagGUpIuM0{=-cjX6lBgY-~qPhz8 zbQaE(9oPad&cY$ZLAwHk?||~x%>^^%{V2+4a$@<=0E`#MI5vi<3Z&!MawPWA82}VF z!$!$C3S85fY~d4dXum}%4!;fGgNClwf1YNafO7{Of|AJc$6E*Cz{r($IF5Y5xi~lg zcYxz492%E3=vzJdmW#~L8G-b6ZChk3$Uja?O~Foo?0-PC&sxurn+~g3sgU|3lV_lW zceIE)T7Zt?3p2|Hxr>cKxZkHuso#fJ<+d&M=z60*YC6B0(ClZHxO>VB;#QWf`P}Or zFpm!V8Q5pa%V+jkNfh2L=&$}wjQ-#7gWBEwq(2znO?Q!+t z02?$@fZ^d6*?A-K8_zm~RunXRbWg02yv{ng=IiE06mrV@#dRuT(|mpxx=_@UJ;m#> zz7prYnY;}hOZAkmKh8Y&tw^fb;l(9l{Mljswj%x+{yRkHy##X4jSu}lSD{yTzGXxGzpjQk z>oyE4y)3?0t#uhVyRkxfs$Icrb3~(ZK@9AB&SOjI6{;CRrC{f(Jj!!WdIjG)EyduK z6LHzH#F2G6uDqpunMkdaM=XndWhoCztI(XO&eRIx(DHHRJQd~Z=UJw&PD^y`addaq z>C>usbgS#i=B9dmYQUaa!$Ygs$NduGLwP9r&^EXGz~UnKf^RwVpiJOXP7bY=iY5c6 zGg_z@jyi=YbEiWmyB|I<2`1z|@iNkCT})gY5zkKA6t4AO`o*lx4$U(9)wPaVDR)2A zWq>SRmAvNR=E-Cz};aKYhzcK*`1gpHr-4?~W@ zhXI;Ept_h>3VaF(bi*xf$5sFyrM1)s@WcwW>@}#iGs2@qCy^spMuW$btYO|JgD>ew z2v`9+1&}B&?F?IQ`tv||6q^yhRX#U(Zf~JMYa_)%S9?NMv{^Is0zNPpJ7Sekf!Q91 z98c{G|uwbdD%!MviqaD2Nu$pJMg4t#%%czt49-5F8eWCyOC zoR;wHclfgt?eUZg$$i9JF!gXIL1JQ{5SUOp-;pO@fL2F;Ft9>R|K!^3$BFkA?r5SH z&*<7tbd*==v^%HM5CI(--Dd_LiP-R5?5QZt1pY7Q7FVxXqy!n5Rf^k8ap19+^G6Ov_L6*KX#r^@fchu^wc@^jwk zG1Cz*G!P&(On!U#rt@MMWo`HN?YaV;ptJ0f`_dnfWrB$?K0R7l)mm z`rf64v!VTacbU+t>mgQY%w_ZX<>hvEsxi=7uHNr`RJD=li{2Bai zPji{j4QKHoXu(FYNj4Mu6{<&3lRVBn?+T63p4k= zH7sxGq{$t!$K(zhG)HbZ<#2Y_y_3f8iVyVvbj^fgIVY#~9gu%wVb`8{llv8&Bv?xx z$R7aK%E-C&LC&8X#Y6Jc$IibEmr3$E>W=5a^ z`WZQM>1YiBVrU5OF-!_pma1S?Nt3AItXe>i<$n9{*q{^RY?TsgXJ^;>_H4JUi@Zl6ANQ!-Mc)nS9&7SFGM$oTxvMwL0DGD24 zpS8*cYIc|iVTtKxqcPYP%nJli1%uKNWY}ehEpgWA-vhY`#*&Tv z?OulFNsyFAqdA_!K7%ue{qZi*l%7el(+!+C4C?WB@zw#YO+k}q1D;zNd?9hWPc~J$ z?b5Ys*CcRNt_GMB)=n!wal+VKTmTqD$--uWXC4s`C~L-HECrj>%g(iAN9W45Dsn;Gq()bBiY=Jlq zaQF)7+r#^%A`ec`&6I#Qfpx%NXz&YJ&V&}2?<@EcevAe^>H&GY^ay_y9u=*=!toDMu3(3)9|J4DH4 zj|zl5{?)xT#3{fi5c;mlEfnGt1J!T>4qt8iJVX&ZL@X>t5rpu9dtx;eVx?io>Pce} z5Sv&V#r2Y2*ZUBDD0cF`J`-!m6lw`O?Y^mzqQM`uj1{P+Hq=~`)3n?I1)%;nBSed;`}S=jF_UgQ$56rT7L_h2ZgZRN#i_fFD+?vHq>9wGo!8GOV}X zE<7ksb}A4}Pv){h>b)KSy0& zVG-9!i0^)ZXk9)ITR{cZN@%D?5I59f@A2Jm;?3H3abFvVN6<5gXB)!Rand<(0rydL z4(6l9e23u9<@zq4qt<}*%(V!?J!+%#`TQQW^98*q1aYkQ-E$Df`sMR;N-lADLR|1H zQa)7SLEk+N5B6#q<_yJ|45qwxkG(=9eLhy@Q9s9He^BCuHpW>cr?iZLd}*N(3gpY` z?axUUxhX^o#U-{v9BzN))8hsPzKE=69my4_-1%SwDAFV3(k)0WJ_AT}+0b)(>9|xu z!xktso-*Y{dGfwBeqih1ph>eKO;oZCw(LID#4Sw-5D!s;{ew+doWpTS^(|26V6eKc zgrl9DCNR!vBJ~BDSO%H^9)WBAUH$zA>UYNxemPC>@8bSk^a4##Jhbb(oF;lazn4N2 z(8Oft^EpjC7wZW4{Xi4v+;cz^2cCaU$xaRr(S!=mB4y1>XyOkoAHC&!$dKlF`D6$W zCJCmR!Lm_4ODh0u)<$_C7c6ARf#aW`B{&mE)bL<_xUk3+q7T5%?0TZ zv#W*M7)md1PyDf6FRU>Bt1tHHi!1PD67M9x#A(<^qEMUH7Z!UUA9a~2)-V-25JB3q zXBr_D*4FF0Q1vLQ`WX(5nuf^3>f~NXDnx{xHcPD{6(vMjEmSIit_8u^1y#nYzkr*@ zYazc#ms>n=(A>h*toYiuQ_HQXRbxpiS+*QK7v|+H6gL(hN>4ewGp9-It`2BoB;Wtg zSpYlrEgp<$TOVG@fG8&xMHP@8fkvo4VEp7|0P1~wST=}DEhA=q*$jL})0~_K*e~7f zm`a=YQBo0fNiCB4rR|P&mfeK-(L1jmIa0`ezj;#$B6<_wo$L4kn7{GG%(?76r3wAa z9Yj%~9<;^p%S2lg%cRBfaatrlw>tg{!~K!?N9l3Iqi8XKG|p{k>imboJdgPl%f!bK z%XH0Se6wqOIg9fccfJ=fPNOt95wkRba(T7qtQAMTWIpl(J>lW8MD$+7B*7liKJ##V3dGWoa)=PC4 z+qv+0pVQ9@S}*J^ZaVQC_oOS2@zT%XJdU2D#g21%)slD|V8%Gfjpt$G^8F#=Ldo8W zm`*qU<|ajcA@K7>6G)jtDKwKJ@v)%v%CM{=gIvtH`K0jK)0L zzjz+#T^`?cpUKkW&NI1;&!;#<^m|Bxi-nO+`H;)r zFrlJ7^*M>^4Cmpr7mTZ@ze;~-a;6$ic@m6Df0Z*(U?;@jCd0k)$99*dL@quZ-(0`% z#HV_G&H@fPZ)$uConiHyV4R+!NoJ_?-7p>6Tv;9l+JM3>7?ghyG5c~v-Jx0%v-qDmS9Hf`)wQntg5yt_F| z4_13s!&AbpE1e(Rj7$zTB}d$RpmauDcz)xhjTz)tA- zY{sk-qJz-pSh6zlEZh2!o*kSNS@@7`C$FkFQGL22U+#`Q<8X6aTvzw3A^xIq&lZh~ ztU%fK^F(t-WMq|yiG>r)RU#v*giriM*?V(NL`8FW#fUlZ8dd6iW5$%PyR$EpN?mT` zPW`GI`=V$wyWR0@-@c!;S7HG>hl}%;ukm`4o%iuKuZd9_UIDgjE&HB>t>V%HUQcYg z(dt@*E`qhZPw+-$gik6QZ_bE_Ob5KIl?S|l?F$uRr4su>g;=SCb;PO=v)dfsD$JzE zs4y>Kt6w&*|CMcg>G&@q>}RgElV3r7&SI^X&1=XD!(OT5w4Y*=();Q9E}a+kyURsy zC*HWcGz&JnHP|1qZEo_G-B}Q@mzcs$JXV6SbgdhE7APEnGMpj}udyl0>St3DUXO~( zN}TqmvW!iBx&lqvBQmY4(B(4jLbW03=|ieraD46f>`~SJl`HqJ`bdQfvVztGTwy;K zvntNDYBGezAw#a=FXw!$RnO-$Ar$9#j@%C#cn7<8jFEboaV?w*m4wp@VQ^=x64~D6 zY~(G=ayk`tb$^sq`XjYI7Ys6%#86A3!3(xZCZ&noUx0HRj5g}QaCOnG0SlK{O}61_ znS=@z($l+)X`gz8mAk9-dJ>V4o`!)p+m}76+<;Tbz^-Lg@H=kp+CkYUra43lXYq>YL&!UD67dHa;G0ZFoRCxj3 z%g+-z;eluRONB=_2(eT)l4%AoBQH3I;?dTJijGj&gU}1}xKD%MDgj_bk`>_z2=>aN za7MK*wWOp(e>W!+al8v-!jWo-dh7U^o3=}-AA>VP}_IAu5!gu9Bl6w zmqRd%E*wT8gB4z*xIiCovOYJ3!Y83nEeKl@`coP*AZDx=>0)J~C`^$wu?VZtN7cki z0W85pETsoq&>c)?(db@ov_$!WqgI3VuQh$9JQ~d=y!l|N@~d*cs=5J^aenb_pjm@g zESS%lDF^9i{w8%FK+k;Nxx6LBlMIJT;l*+2Un||?Tz>NX(m%x2$336U5q}QO5tzN} zIdtyT@#Sz}xW|bn@p0VsHfZB5i4N6q&PztWz)PNk89IVmtDcW@c|*^H>}~7;8$Yuc zcfmwDDt|Y0)MM`PSFVlpN&Z}wMqSTwt^vA7C%jLS*Ms$5I7^v!Z+@0Ytg4|+emG3s zox(NBPX82oXtK7`d)gUeh9sLFQv%g1>kPR(qU*!hT+&#drx`CKK0UjNo(lzY$em+841{7V{74 zjLjFXIPQs&j(8=PKXVe|bsTsm_y15l6f#|@_6io+1OMQBL4pH_2bEwH9-w$*JQpI= z9R$^=s13{{5t(sPXUB(PhZUmYb7He2z~=;~2krS-3j%>)hpa6eFR7=+vDM?oX(mi6 z@sU#iL$J`DYNIm|tdrM9Cjn3f#vtf!BLIxkunIi}#e!82Y!rPgb2ouzc6ER1s_k9b z7;h!Rua4ZSys3=}H{1lF(ty|6IyO4tXAM_uebTf+Z`Uf0E*wU;)WmkOD~% zRW5|S)+297wX_;lVynI0w0Ga$>pG>@Y-V>smpZsd(-zT|^_k-q*Qo_V6T#V9{t|G8 zkspI%0^v-QDH|B&LMh-y>->d%g-e@u7}ly%0WVZ47@bW~_?z0iY5_0UXxC;tqeSH{ z$~i|DC*s5oh-gemqe#%zF7TA?&Ui+F(*fs^6c9!{5+?!YN*yPj$H&3*pz*rKi7(JN z;x#7Yua}H3agHl3iH@CghUb)jf#*$9W_ZrQ8E#j44&)E27Rqx_Dvf1IkSdC4B;+cPkkjgQcp;Ji zc@$Qo+{j_Sqq}zJ;{o~p98ZAm3EZ9%;l)M zSE7Yk)5UP+Eru19h@UHO`B9~(Gg2|wf-s`wfo?xyA}G(*O7*f)${jil6+cF(X)l0Q z1x8xu?Knd~_ZUidiL=I8<1G>9pjcz9n(*T7MOO3#N_a^~uPjr-i~M}*E0&cZnNBKS z?A^;Mojl1Z?A@zeIXU(Gm@((4=6*J2%xCN!$DWX*to@_kScjuWm3M!8q`Z6Na_+N3 z@BN*d`}cc?p5=;pd-f3A;Fj`L4Hv#tWeNUPf?NkHuI8QrT8P6Tm4MLV<%PIj!OPbR zzIE9EA2m|{fh2E25^)OcXNKIO=zY0*aiFyA%o$z4nKO>*r%tJRr$g;4U>E0_t_jI!37yQAruHpYwojU}0GHU$ zTFj}QHn18?RQ^+EN_yQjoyFR_*_N~}2?-r4vWa`oNK#_g>dKW?%7q3a%1P20P7lZR zTl8UwSttW~0Dpl<)`=7&;OC8!_)I^*3!R3buIUWCo{+8wx(bQ97SYjRVK9PQqph(q zVP(R~AcrPY2n{nD!;Jn=&UG0!l{B(oItf#$!w@PVnHxR}X3R8YR1u{zpDGvj>|q(7 z7JkYy_UutEd|G(zzyD=>@kib1hW)IxAONl-za}e z=Zn)&_vo8%5D7v%Pv=cP47iRE5U&g4J{AFo%K(%a(NJ7LY;H7$ARHt($jb}ndKef5 z9X2jO;8sSU7RE*d?C2KVQjRH?3zf^tv0E(;t|(k_umz6zNM)aL$V=(THhRI*(2^}s zChoh@Tarc=FOYiQ*vDZQf&D&#^JS$Pf$?Fe*T+kuYq3UEwB9AS@SyYq-)dCRu^G)t zM!M2~Ff({Ex${IBLb2(nl@4rK2=L_94dJYTZ&zbIXReR1=?Kw23P<t8)m~yLm58j9G_FrnfC_49IZD<$pWmsg&r~ocwUG($V4pZSK`oC@1Q4f z`PW%7dE!w>^1dfk=Fe2|iJZ+67d|o91D||uO+Ht}E6sJ`Ofh-lRj?6WnZf&>JQpuk z*W)?Y1HbfK`5pdT70;sQUf{VNc;<5#^SLU%pP%c2Z$5VupR3~ixw)Qrr@3TJ06nPq zr@1ctD<)6;^SQ7%VXnFlG*{aPVT59$GYS3Ngmq*6qE$VskcCIUFOr0^_M~ur5p4=i z2N^=5l~?oB^@1kV4c>lZc(M`tCj69DOj%q(^z!{|;E6-1v69P00XLYC_~T06cYz0J)dlG#j-`xp5Lhn;F< z%gLBQcEPr#??%vb;?awwD)zwyDT!NGJpQouxmR=r@wiUQ@d?&@i!!|hK# zfBf;x3B#v4^+kP&;4Q@3%cya50EwBy4+Q?Fs zYn-QqC~Z(b0`&vECzlrloA1aUz>ItwLfa69&dLdWJA4+18wKS)0N;Yt2Emg2@(|aI zDy|^n1}n7?IZ^c=%nii5Lyg`BiV{Qv0#jBny`P}KFBViJ>YQ7-O?6{s>HO~RicY>O z{^)pU4Q{8L5apDW%?0xd)LvBAu&G+^H-e<|~> z-?^&HRQ_f+l{yS{EO(*}!f0`x)cIKh$XVB$*00M~nJ<2@ll@AqIP<8d%4xJFwLCxw6G zww!~TD-j89eWXvuLxtxrMjPOfRAm%`pcz{9I9rH1M3OgAH)vZzc5LV52JO=P8%yuqag@|B zcG|PxOwAn|q* z3W(SCMeq`kL)QTgl9WwG8I@q*iVhF9=)hDg00@R<3wPe&*rg-t)XMZj7bS)}{$T9= z+O47ASAVC-@hrac!V#Zk*OYUVZp(|_9L9u|Y)et)7GvyqHP`ju(O1!z#k-%^^-0Iq zGs6JV`AOH;|IfNU$ob{EzLBe~HtM1Q&Me+Ot=wO+f|*bMc$%44tWfTsK6mk=(gA;T zJmtNKg@5=V3*Y2@3co8qfB2#DGk%w!7B369b^iRV;?2@v{)>j!4}m`?UhBgy!uMG@ zVW^AoK+d&sLurdbki@h}LdNl;kNTdleX8`Pax4(5H1elS14VMja5AcvK>?dcR z&xM}xMnMU#5G|_oOYKp_#lI*I@9bQXy}#MryRAPK<9~9ni^?0T7i6T01?Y}4r*bCN zz6>=$C|;HWN3*ruEGNui*eZF>axcrYc(x%E!Q&n-AL!_gc-qfsJIN4fskz+ z1VB#(ljGnwTX?|C!D4%gWZh2f6>c0geYlB;fHS8H@8z#6io} z^#t>@=(vP62I;|ukS0MS!GE^iVfSvcyLbPdi`)Gl{B|GkPnvel4g2|?)K>RI-x_~I z#zNdy!Z_&>kZjl%HLH&_2e&4{g*)V$zrP^(hx&&E1(2YC70QdMGh~1$RaF8q7QgZY z!_MMNR_`&3QttiX`06gJH|MRl=72^WpZ#_9Ylkkx@rmQ!^6BH|a@YXF3=Ug;f=xIp z|HEM;9p_t&`+$N`iJUkREQ7EBaTx+0*%Mp|+J>*MZ?LZ^-k1%sjZA_O7A5`jiY_=?$>Uwhz15(pqR1_8>fkLXh?ETZ%TK8 zUKAV*%_u53GAx7=)&V4#iLWNTIL$bB4jQ-u zNN@p#{bE9Y+*5`^|BvJL89hSi^>QwpW+Kdqxg=4seN?N)&pwLE1*pcC| zxS*}I7GD*I(rh?Ru-w^_()slz3rC43*Hft?r{O^szu2l2Z8P7E{(8Z_KSLY`#3oU{ z?Ob@H%)N+ROt+p)d3%&AA=7?bx@5)UUrv2{XT{D35Ol(zp1N(4bQwe8mQtl#c(FNFP!xQaSq`3L6=8e2eDbhz^Sz*d?#Poo z?337+Ntap5TTavD7FO{~$6)Y)Up#G;bl$7tOc9L-!TN-I12VA?>Pu-ikfsQ?qe}w} zta04_V?iN7I5v&p@kmVyB8?Dv>6Uma&KwHs@VYt@{>^VR@|-)$WrJS1syJA~*|SI9 z+a-qGQGVXKWbxZ#y5n=PbNaU{3a*U<$wVxjG8y-Jl945E$+rLtbbp}J;M+?0+Bwe8 zp-m1@$7R(AMY_va7k$Adj�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 z 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 literal 0 HcmV?d00001 diff --git a/assets/fonts/Inter-SemiBold.ttf b/assets/fonts/Inter-SemiBold.ttf new file mode 100644 index 0000000000000000000000000000000000000000..47f8ab1d68144fc004b310d65d95180d502b449b GIT binary patch literal 419744 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�# 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 literal 0 HcmV?d00001 diff --git a/assets/logo.png b/assets/logo.png new file mode 100644 index 0000000000000000000000000000000000000000..11938954406b16bcea41b364c1176213053c1e0f GIT binary patch literal 35212 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 + + + + + + + + + + + + + + + + + + + diff --git a/assets/notification_badge.png b/assets/notification_badge.png new file mode 100644 index 0000000000000000000000000000000000000000..5f15c675ca18ea8107f81a73e134cd0fb0e14b23 GIT binary patch literal 321 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`jKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WCij$3p^r=85sBugD~Uq{1quc!E2r_jv*HQTZ0t&m<$D6lqPzptUF_(Vo|{) z)amkxMaKUDrwwE06V3x$mjDHvwzY6?|8mLM;N*(CGjEn{zxqqv@7lMyTPJTeWR6|! zD$##?UX1mFcPEdl%kJbooEV<% + + + diff --git a/autopilot.ps1 b/autopilot.ps1 new file mode 100644 index 0000000..5b1abfd --- /dev/null +++ b/autopilot.ps1 @@ -0,0 +1,25 @@ +# Pyramid-Autopilot: startet Claude-Sessions in Endlosschleife. +# Läuft eine Session ins 5h-Limit, wird alle 20 Minuten ein Neustart versucht, +# bis das Kontingent wieder da ist. Stoppen: Strg+C oder Fenster schließen. +# +# Start: Rechtsklick → "Mit PowerShell ausführen" +# oder: pwsh -File autopilot.ps1 + +Set-Location $PSScriptRoot + +$prompt = "Lies CLAUDE.md und arbeite ROADMAP.md Punkt für Punkt weiter ab. " + + "Halte dich strikt an den Arbeitszyklus (PROGRESS.md pflegen, kleine Commits + Push). " + + "Arbeite so viele Punkte ab wie möglich." + +while ($true) { + $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + Add-Content autopilot.log "`n===== [$ts] Neue Claude-Session =====" + Write-Host "`n===== [$ts] Neue Claude-Session (Log: autopilot.log) =====" -ForegroundColor Cyan + + claude -p $prompt --dangerously-skip-permissions 2>&1 | Tee-Object -FilePath autopilot.log -Append + + $ts = Get-Date -Format "yyyy-MM-dd HH:mm:ss" + Add-Content autopilot.log "===== [$ts] Session beendet - naechster Versuch in 20 Minuten =====" + Write-Host "===== [$ts] Session beendet - naechster Versuch in 20 Minuten (Strg+C zum Stoppen) =====" -ForegroundColor Yellow + Start-Sleep -Seconds 1200 +} diff --git a/autopilot.sh b/autopilot.sh new file mode 100644 index 0000000..04561cf --- /dev/null +++ b/autopilot.sh @@ -0,0 +1,19 @@ +#!/bin/bash +# Pyramid-Autopilot (Pi/Linux): startet Claude-Sessions in Endlosschleife. +# Läuft eine Session ins 5h-Limit, wird alle 20 Minuten neu versucht. +# Start (am besten in tmux): tmux new -s pyramid './autopilot.sh' +# Wieder reinschauen: tmux attach -t pyramid +# Stoppen: Strg+C in der tmux-Session +cd "$(dirname "$0")" +export PATH="$HOME/.local/bin:$HOME/flutter/bin:$PATH" + +PROMPT="Lies CLAUDE.md und arbeite ROADMAP.md Punkt für Punkt weiter ab. \ +Halte dich strikt an den Arbeitszyklus (PROGRESS.md pflegen, kleine Commits + Push). \ +Arbeite so viele Punkte ab wie möglich." + +while true; do + echo "===== $(date '+%F %T') Neue Claude-Session =====" | tee -a autopilot.log + claude -p "$PROMPT" --dangerously-skip-permissions 2>&1 | tee -a autopilot.log + echo "===== $(date '+%F %T') Session beendet - Neustart in 20 Minuten (Strg+C zum Stoppen) =====" | tee -a autopilot.log + sleep 1200 +done diff --git a/docs/NOTIFICATIONS.md b/docs/NOTIFICATIONS.md new file mode 100644 index 0000000..511a9f7 --- /dev/null +++ b/docs/NOTIFICATIONS.md @@ -0,0 +1,136 @@ +# Push-Benachrichtigungen & E2EE im Hintergrund + +Stand: 2026-06-04. Dieses Dokument beschreibt, wie Pyramid auf Android +verschlüsselte Push-Benachrichtigungen verarbeitet — inklusive Entschlüsselung +und verschlüsseltem Antworten **bei komplett gekillter App**, ohne dass sich die +App öffnet. + +## Überblick der Kette + +``` +Matrix-Homeserver (Continuwuity) + │ (event_id_only Push) + ▼ +Sygnal (self-hosted: push.steggi-matrix.work) + ▼ +Firebase Cloud Messaging (FCM) + ▼ +PushService.kt (FirebaseMessagingService, nativ) + ├─ App lebt im Vordergrund → App zeigt selbst, Push wird übersprungen + ├─ App lebt im Hintergrund → Haupt-Engine entschlüsselt (warm, schnell) + └─ App gekillt → BgEngine bootet ein headless Flutter-Isolate +``` + +Der Flutter-eigene FCM-Dienst (`FlutterFirebaseMessagingService`) ist im +`AndroidManifest.xml` **deaktiviert** — alle Pushes laufen über `PushService.kt`. +Push-Format ist `event_id_only` (nur die Event-ID wird übertragen, nicht der +Inhalt — datensparsam). + +## Warum dieser Aufbau? + +Die E2EE-Schlüssel (olm/megolm) liegen **nur** im Matrix-Client (verschlüsselte +SQLite-DB), nicht im nativen Kotlin-Code. Kotlin kann daher Sender + Raumname +(unverschlüsselte Room-States) per HTTP holen, aber **nicht** den Nachrichtentext +entschlüsseln. Dafür braucht es einen laufenden Matrix-Client. + +**Sicherheitsregel:** Niemals zwei Matrix-Clients gleichzeitig auf derselben +olm-DB — das korrumpiert den Ratchet-State und führt zu dauerhaften +„Unable to decrypt"-Fehlern. Deshalb läuft der Hintergrund-Client (`BgEngine`) +**nur**, wenn die Haupt-App nachweislich tot ist (`FlutterEngineCache.get("main") +== null`). + +## Die drei Zustände + +| Zustand | Erkennung | Pfad | +|---|---|---| +| Vordergrund | Heartbeat < 20s (`flutter.notif_app_heartbeat`) | Push übersprungen, App zeigt selbst | +| Hintergrund (lebt) | `FlutterEngineCache.get("main") != null` | Platzhalter sofort → Haupt-Engine entschlüsselt + aktualisiert | +| Gekillt | keine Haupt-Engine | `BgEngine` bootet headless Isolate, **decrypt-first** | + +## Gekillter Zustand im Detail (decrypt-first) + +1. `PushService.onMessageReceived` holt Titel (Sender · Raum) per HTTP. +2. Statt sofort einen Platzhalter zu zeigen: + - `BgEngine.scheduleFallback(…, 6s)` plant einen „Neue Nachricht"-Platzhalter, + der **nur** erscheint, falls die Entschlüsselung > 6s dauert oder scheitert. + - `BgEngine.run("decryptAndShow", …)` bootet das Isolate. +3. `BgEngine` (BgEngine.kt) startet eine headless `FlutterEngine` über den + gespeicherten Callback-Handle (`flutter.bg_engine_handle`) und führt das + Dart-Entrypoint `notificationEngineMain` (background_push.dart) aus. +4. Dart `_bgDecryptAndShow`: + - `_buildClient()` öffnet **dieselbe** DB (`pyramid.sqlite`, + `MatrixSdkDatabase.init('pyramid')`, `NativeImplementationsDummy`). + - `client.getEventByPushNotification(...)` entschlüsselt mit den lokal + vorhandenen megolm-Schlüsseln (oneShotSync nur als Fallback). + - Gibt Titel + Text per MethodChannel `showDecrypted` an Native zurück. +5. `BgEngine` zeigt via `NotificationHelper.show` die echte Nachricht und + bricht den Fallback-Platzhalter ab. + +Ergebnis: Die Benachrichtigung erscheint ~4 s nach der Nachricht **direkt mit +echtem Text** (kein „Neue Nachricht"-Zwischenschritt). Die ~4 s sind der +Engine-Bootstrap (~1,7 s) + Client-Init/Entschlüsselung (~2,3 s). + +## Verschlüsselt antworten (gekillt, vollständig still) + +- Die Reply-Action ist ein **BroadcastReceiver** (`getBroadcast` → `ReplyReceiver`), + **nicht** MainActivity — die App öffnet sich also nicht. +- `ReplyReceiver`: + - App lebt → MethodChannel `replyFromNotification` an die Haupt-Engine. + - Gekillt → `BgEngine.run("sendReply", …)` → Dart `_bgSendReply` → oneShotSync + + `room.sendTextEvent` (verschlüsselt). `goAsync()` + finish nach 15 s hält den + Receiver-Prozess am Leben, bis der Versand durch ist. +- RemoteInput-Extraktion hat mehrere Key-Fallbacks (OEM-Eigenheiten) und + funktioniert auf Samsung S23 trotz der alten „getBroadcast verschluckt + RemoteInput"-Warnung. + +## Gelöste Fallstricke (NICHT wieder einbauen) + +1. **Loader-Reihenfolge:** `FlutterCallbackInformation.lookupCallbackInformation` + erst **nach** `flutterLoader.startInitialization` + `ensureInitializationComplete` + aufrufen — sonst `UnsatisfiedLinkError` (native Methode, libflutter.so noch + nicht geladen). +2. **vodozemac doppelt:** Wenn Decrypt- und Reply-Task dasselbe wiederverwendete + Isolate nutzen, wirft das zweite `vod.init()` „already initialized". In + `_buildClient` in eigenem try/catch schlucken — sonst gibt `_buildClient` + still `null` zurück und die Antwort geht nicht raus. +3. **`database_closed`-Rauschen:** Vor `client.dispose()` 2 s warten, damit der + asynchrone Key-Backup-Upload fertig wird. + +## Relevante Dateien + +| Datei | Rolle | +|---|---| +| `android/.../PushService.kt` | FCM-Empfang, Heartbeat-Check, decrypt-first-Routing | +| `android/.../BgEngine.kt` | Headless-Engine-Bootstrap, Fallback-Platzhalter | +| `android/.../ReplyReceiver.kt` | Stilles verschlüsseltes Antworten (Broadcast) | +| `android/.../NotificationHelper.kt` | Native Benachrichtigung (Reply/Tap/Dismiss, setOnlyAlertOnce) | +| `android/.../MainActivity.kt` | MethodChannel `install`, Cold-Start-Reply-Fallback | +| `lib/core/background_push.dart` | Dart-Hintergrund-Isolate: decrypt + reply | +| `lib/core/fcm_push_service.dart` | Pusher-Registrierung bei Sygnal | +| `lib/core/notification_service.dart` | Vordergrund/Hintergrund-Notifs, Heartbeat | +| `lib/main.dart` | `registerBgEngineHandle()` beim Start | + +## Debugging + +`flutter run` verliert die Verbindung, sobald die App gekillt wird — daher direkt +`adb logcat` nutzen: + +``` +adb logcat -v time PYRAMID-PUSH:* PYRAMID-BGENGINE:* PYRAMID-REPLY:* PYRAMID-INTENT:* flutter:* AndroidRuntime:E *:S +``` + +Erwartete Log-Sequenz (gekillt, Erfolg): +``` +PYRAMID-PUSH: decrypt-first via background engine for +PYRAMID-BGENGINE: background engine started +PYRAMID-BGENGINE: Dart background engine ready — flushing 1 task(s) +PYRAMID-BGENGINE: showDecrypted → shown decrypted notification for +``` +Reply (gekillt): +``` +PYRAMID-REPLY: extracted replyText=… (remoteInput=true) +PYRAMID-REPLY: Flutter engine not running → background engine send +PYRAMID-BGENGINE: (sendReply → sendTextEvent OK) +``` + +Hinweis: Kotlin lässt sich nur auf einem Rechner mit JAVA_HOME/Android-SDK bauen. diff --git a/docs/PROGRESS.md b/docs/PROGRESS.md new file mode 100644 index 0000000..2c79278 --- /dev/null +++ b/docs/PROGRESS.md @@ -0,0 +1,43 @@ +# Pyramid – Fortschritt & offene Punkte + +Stand: 2026-06-04 + +## Erledigt + +### Chat / UI +- **Reply-Zitat-Karte** im Discord/WhatsApp-Stil (kein „In reply to @user" mehr), medien-bewusste Vorschau, getönter Hintergrund bündig mit Akzent-Strich. +- **Per-Message-Selektion & -Hover** — einzelne Nachrichten statt ganzer Sender-Gruppen werden markiert/hervorgehoben. +- **Scroll-Stabilität** — Crash durch doppelte Keys behoben, Pagination (kein endloses „Zurückziehen", lädt aber bis zum echten Anfang), Bild-/PDF-Platz wird vorab reserviert (kein Springen beim Laden). +- **„Neue Nachrichten"-Divider** — korrekte Position, scrollt zuverlässig hin, blendet beim Erreichen des Endes aus; erscheint nur bei echten ungelesenen Nachrichten von anderen. +- **Composer-Höhe** bündig mit dem Profil-Block; **Verbindungs-Statusbanner** bei Sync-Verlust; **fehlgeschlagene Nachrichten** bleiben mit „Wiederholen/Löschen" stehen statt zu verschwinden. +- **„Zuletzt online"** nutzt echten Presence-Status + Frische statt `currentlyActive` (kein falsches „online" mehr). +- **Members-Panel** mobil schließbar + schmaler. + +### Medien & Dokumente +- **Media-Cache** (LRU, byte-budgetiert, geteilt) — zuletzt betrachtete Medien sofort da, ältere automatisch verworfen. +- **Datei-Vorschau** — höhere Auflösung (PNG statt JPEG), viele neue Text/Code/Daten-Formate, **immersiver Fullscreen-Viewer** (Pan, +/− 20%-Zoom, Ctrl+Mausrad, Seiten-Navigation, mobil-optimiert, Tap blendet UI aus). +- **Eingebettete Link-Vorschauen** (Open-Graph-Karten) — serverseitig in Continuwuity aktiviert + Client-Karte. + +### Suche +- **Lokale Suche** über entschlüsselte Events (server-seitige `/search` funktioniert nicht für E2EE) — Nachrichten, Medien (mit **Thumbnail**), Personen/Räume. +- **Sprung zur Nachricht** aus dem Suchergebnis inkl. Cross-Chat, mit sanft ausblendendem Highlight. + +### Benachrichtigungen (Android) +- Bei **gekillter App**: Hintergrund-Entschlüsselung (decrypt-first) + **verschlüsseltes Antworten** ohne App-Öffnen. Details siehe [NOTIFICATIONS.md](NOTIFICATIONS.md). + +### Einstellungen +- **Mobile Settings** im Element-Stil: Kategorie-Liste → Untermenü mit Zurück-Pfeil (statt gedrängtem Icon-Block). Desktop unverändert. + +### Server (Pi 5, steggi@192.168.178.71) +- rclone-Mount für Pixeldrain-Medien repariert + Boot-Reihenfolge abgesichert; Medien liegen nur auf Pixeldrain. +- URL-Preview-Allowlist in `conduit.toml` aktiviert. + +### Lesebestätigungen (Element-Stil, mit Haken) +- **✓✓** an der zuletzt gesehenen Nachricht des Gegenübers (auch dessen eigener Antwort), berechnet aus `room.receiptState`. Wandert mit, statt an der eigenen letzten Antwort zu kleben. +- **grauer ✓** nur auf der eigenen neuesten Nachricht, solange sie noch ungelesen ist; verschwindet sobald gelesen (dann nur ✓✓). + +## Offen / geplant +- **Weiterleiten** von Nachrichten (Forward) — später. +- **Presence-Genauigkeit:** Nutzer, die den PC vor ~10 min unsauber heruntergefahren haben, werden teils noch als „online" angezeigt (Server expired Presence nicht zuverlässig). Außerdem: Online-Status im Chat-Header und in der Chat-Liste sind nicht immer konsistent — sollten dieselbe Quelle nutzen. +- PDF-Seiten beim Upload vorrendern — bewusst zurückgestellt (geringer Mehrwert wegen Caches). +- Selection-Menü-Politur (kein Bug, optional). diff --git a/docs/feature-checklist.md b/docs/feature-checklist.md index c80469e..dfd4303 100644 --- a/docs/feature-checklist.md +++ b/docs/feature-checklist.md @@ -1,6 +1,19 @@ # Matrix / Element Feature Checklist für Pyramid *Stand: April 2026 — Pyramid v0.1.x (Early Development)* +*Letzte Tiefenanalyse: 2026-04-29 (Vergleich mit FluffyChat / Element Web)* + +--- + +## Legende + +- ✅ `[x]` — Implementiert und funktioniert korrekt +- ⚠️ `[~]` — Teilweise / fehlerhaft implementiert (Details in Technische Analyse) +- ❌ `[ ]` — Fehlt komplett +- 🔴 P0 — Kritisch (Kernfunktionalität kaputt) +- 🟠 P1 — Hoch (wichtige Funktion defekt oder nicht vorhanden) +- 🟡 P2 — Mittel +- 🔵 P3 — Niedrig / Nice-to-have --- @@ -15,17 +28,19 @@ - [x] Verschlüsselte Nachrichten anzeigen (Entschlüsselungsstatus) - [x] Nachrichtenverlauf paginieren (ältere Nachrichten beim Scrollen laden) - [x] Ungelesene-Nachrichten-Tracking +- [~] Nachrichtenbearbeitung (Edit-Event erkannt, `getDisplayEvent` wird nicht gerendert) 🟠 P1 +- [~] Nachrichtenvorschau bei Reply (Zitat-Preview vorhanden, kein Jump-to-original) 🟡 P2 ### Nachrichtenaktionen - [x] Nachrichtentext kopieren - [x] Eigene Nachrichten löschen (redact) - [x] Nachrichten anpinnen / Pinboard anzeigen -- [~] Auf Nachrichten antworten (in-reply-to vorhanden, kein visuelles Zitatfeld) -- [~] Nachrichten bearbeiten (m.edit im SDK erkannt, kein vollständiges UI) +- [x] Auf Nachrichten antworten (in-reply-to) - [ ] Nachrichten weiterleiten - [ ] Zitat-Styling (visuelle Blockquote-Anzeige) -### Textformatierung +### Textformatierung (formatted_body) +- [~] Markdown-Rendering — `formatted_body` / `org.matrix.custom.html` wird nicht gesendet und nicht gerendert 🔵 P3 - [ ] Fett (**text**) - [ ] Kursiv (*text*) - [ ] Durchgestrichen (~~text~~) @@ -33,7 +48,7 @@ - [ ] Code-Block (```code```) - [ ] Aufzählungslisten - [ ] Klickbare Links -- [ ] @Erwähnungen (User) +- [~] @Erwähnungen — Button vorhanden, `onTap: null` 🟡 P2 - [ ] #Kanal-Erwähnungen - [ ] Spoiler-Tags (||text||) @@ -62,14 +77,118 @@ - [x] Mehrere Reaktionen pro Nachricht - [x] Kategoriebasierte Emoji-Organisation +### Tipp-Indikatoren (Typing) +- [~] `room.setTyping()` wird **nirgendwo aufgerufen** — Einstellung existiert, aber Composer sendet nie "tippt…" 🟡 P2 +- [ ] "X tippt gerade"-Anzeige empfangen (kein Widget) +- [ ] Timeout nach Tipp-Ende + ### Threads -- [ ] Thread-Antworten (m.in_reply_to vorhanden, kein Thread-View) +- [~] Thread-Button vorhanden (`onPressed: () {}` — leer) 🔵 P3 - [ ] Thread aufklappen / eigene Ansicht - [ ] Thread-Benachrichtigungen - [ ] Thread als gelöst markieren --- +## Lesebestätigungen (Read Receipts) + +- [x] Senden von `m.read`-Receipts via `room.setReadMarker()` +- [x] Privacy-Toggle (kein Senden wenn deaktiviert) +- [x] ✓-Icon (Nachricht gesendet/zugestellt) auf eigenen Nachrichten +- [x] ✓✓-Icon (gelesen) in DMs +- [x] Sende-Status (Uhr/Fehler/gesendet/gelesen) +- [~] ✓✓-Logik nur für DMs — in Gruppenräumen wird `receiptState.global.otherUsers` nicht ausgewertet 🟡 P2 +- [~] **Off-by-one**: Divider erscheint *über* der Gruppe die das `fullyRead`-Event enthält, nicht darunter 🟡 P2 +- [ ] Gruppen-Read-Receipt-Display (Seen-by-Avatare wie in FluffyChat) 🟡 P2 +- [ ] Hover-Tooltip "Gelesen von: ..." auf ✓✓ +- [ ] **Notification-Cancellation**: `cancelNotification(roomId)` beim Setzen des Read-Markers 🟡 P2 + +--- + +## „Neue Nachrichten" Trennlinie + +- [x] `_UnreadDivider`-Widget korrekt gestylt +- [x] `_sessionFullyReadId` einmalig beim Öffnen erfasst (stabil für die Session) +- [x] Keine Anzeige wenn Raum bereits gelesen +- [~] **Position falsch** — Divider über der Gruppe mit `fullyRead`-Event statt darunter 🟡 P2 +- [ ] **Auto-Scroll zum Divider** beim Öffnen eines Raums mit ungelesenen Nachrichten 🟡 P2 + +--- + +## Presence / Zuletzt Online + +- [x] `_PresenceLine` im DM-Header mit Live-Updates +- [x] 4s-Debounce gegen Sync-Spike-Fehlmeldungen +- [x] Relative Zeitanzeige (gerade eben / vor Xmin / vor Xh) +- [x] Guard: eigene Presence wird nie angezeigt +- [x] Presence-Dot im Rooms-Panel und Members-Panel +- [x] `setPresence(online/offline)` in den Settings +- [~] **Kein Auto-Heartbeat** — `setPresence` nur in Settings, nie periodisch während Nutzung 🔵 P3 +- [~] **Kein `WidgetsBindingObserver`** — App-Lifecycle (Hintergrund/Vordergrund) löst kein Presence-Event aus 🔵 P3 +- [ ] Presence-Dot in DM-Listen-Items (`room_list_item.dart`) 🔵 P3 + +--- + +## Benachrichtigungen + +### Local Notifications (App im Vordergrund) +- [x] Android Local Notifications (`flutter_local_notifications`) +- [x] Windows Toast-Notifications (`local_notifier`) +- [x] Windows Taskbar-Badge (Progress-Error-Mode) +- [x] Tap-Handler navigiert zum richtigen Raum (Android) +- [x] Guards: nur fremde Nachrichten, nur aktive Rooms, nur `Membership.join` +- [x] `notificationsBlockedProvider` + Banner in `app_shell.dart` +- [~] **Alle 4 Notification-Prefs werden ignoriert** — `notifDesktopProvider`, `notifSoundProvider`, `notifPreviewProvider`, `notifMentionOnlyDmProvider` haben keinen Effekt 🟠 P1 +- [~] Android-Grouping ohne Summary-Notification 🔵 P3 + +### Remote Push (App im Hintergrund / geschlossen) +- [ ] 🔴 **Keine Remote-Push-Integration** — FCM/UnifiedPush fehlt komplett, App muss laufen +- [ ] iOS APNs-Setup +- [ ] macOS-Notifications +- [ ] Android Icon-Badge (Zahlenbadge) + +--- + +## E2EE Verschlüsselungs-Pipeline + +### Implementiert +- [x] Vodozemac (Rust-Olm) via Flutter-Isolate — modern, performant +- [x] Bootstrap: SSSS, Cross-Signing, Online-Key-Backup +- [x] `_decryptLegacyEvents` — entschlüsselt ältere Events in-place +- [x] Device-Key-Preload vor erstem Senden +- [x] Key-Verification UI (SAS Emoji, QR-Code, alle States) +- [x] Megolm Session Export/Import (Element-kompatibles Format) +- [x] Encrypted-Attachment-Handling +- [x] `m.fully_read`-Marker beim Timeline-Open +- [x] `timeline.requestKeys(onlineKeyBackupOnly: false)` + +### Fehlerhaft / Fehlend +- [~] **"Entschlüsselt…"-Placeholder bleibt dauerhaft** wenn Key fehlt — kein Recovery-Button 🟠 P1 +- [~] `loadAllKeysFromRoom` Fehler werden silent geschluckt (`catch (_) {}`) 🟡 P2 +- [~] **Kein Incoming-Verification-Request-Handler** — `client.onKeyVerificationRequest` wird nicht abonniert 🔴 P0 +- [~] **Doppelte Bootstrap-Implementierung** (page vs. dialog) mit leicht inkonsistenter Logik 🔵 P3 +- [ ] Device-Trust-Indicator in der Timeline 🔵 P3 +- [ ] Unverified-Device-Warning beim Senden 🔵 P3 +- [ ] "Schlüssel anfordern"-Button bei dauerhaft verschlüsselten Events 🟠 P1 + +--- + +## Suche + +- [x] Suchdialog öffnen (UI vorhanden) +- [x] Server-seitige Volltextsuche via Matrix `/search` API +- [x] Filter: Alle / Medien / Personen +- [x] Ergebnisse: Raum + Absender + Body + Zeitstempel +- [x] Keyboard-Navigation in Ergebnissen +- [x] 400ms Debounce +- [ ] Jump-to-Message bei Klick auf Suchergebnis +- [ ] Suche nach Absender filtern +- [ ] Filter nach Datum +- [ ] Suchergebnisse im Chat hervorheben +- [ ] Suchverlauf + +--- + ## Raumverwaltung ### Grundfunktionen @@ -79,14 +198,12 @@ - [x] Raumname & Avatar anzeigen - [x] Verschlüsselungsstatus (Schloss-Icon) - [x] Einladungen annehmen / ablehnen -- [ ] Neuen Raum erstellen +- [ ] Neuen Raum erstellen (UI-Einstiegspunkt) - [ ] Raumname bearbeiten - [ ] Raumthema/Beschreibung bearbeiten - [ ] Raum-Avatar ändern - [ ] Raumvisibilität (öffentlich / privat) -- [ ] Zugriffsregeln (invite/knock/public) - [ ] Verlaufsvisibilität konfigurieren -- [ ] Raum-Aliases verwalten ### Direktnachrichten (DMs) - [x] 1:1 DM-Räume anzeigen & öffnen @@ -94,261 +211,214 @@ - [x] Echtzeit-Presence-Updates - [x] Sprachanruf aus DM starten - [x] Videoanruf aus DM starten -- [ ] DM starten (neuen Chat beginnen, nur über Suchfeld) +- [ ] DM starten (neuen Chat beginnen) ### Mitglieder & Rollen - [x] Mitgliederliste anzeigen - [x] Mitgliederanzahl anzeigen - [x] Avatar & Anzeigename der Mitglieder -- [x] Nutzer in Raum einladen (Raum-Kontextmenü) +- [x] Nutzer in Raum einladen - [ ] Nutzer aus Raum entfernen (Kick) - [ ] Nutzer sperren (Ban) - [ ] Power Levels bearbeiten -- [ ] Nutzer zum Moderator / Admin befördern -- [ ] Bans aufheben - -### Raumeinstellungen -- [x] Raumeinstellungen-Dialog (Name, Thema, Moderationsregeln) -- [ ] Raumverschlüsselung aktivieren/deaktivieren -- [ ] Erweiterte Raumeinstellungen (Fluffychat-Level) -- [ ] Widget-/App-Integration in Räume --- ## Spaces & Gemeinschaften -### Spaces - [x] Spaces in der Seitenleiste anzeigen - [x] Zwischen Spaces navigieren -- [x] Space-Avatar anzeigen -- [x] Space-Banner hochladen & anzeigen (Discord-Style) +- [x] Space-Avatar & Banner anzeigen - [x] Räume nach Space filtern -- [x] Virtuelle "Rooms"- und "DMs"-Spaces -- [x] Unterkategorien (Sub-Spaces) als Kategorien in der Kanalleiste +- [x] Unterkategorien (Sub-Spaces) - [x] Drag-and-drop Kanalreihenfolge für Admins -- [x] Space-Verwaltungsdialog (Name, Avatar, Banner, Einladungen, Mitglieder, Power Levels) +- [x] Space-Verwaltungsdialog - [ ] Neuen Space erstellen - [ ] Räume zum Space hinzufügen / entfernen -- [ ] Space-Regeln / Beschreibung -- [ ] Space-Entdeckung (öffentliche Spaces durchsuchen) - -### Kanalorganisation -- [x] Kanäle nach letzter Aktivität sortieren -- [x] Ungelesene-Badge auf Kanälen -- [x] Sprachkanal-Teilnehmerliste (Discord-Style, mit Echtzeit-Updates) -- [x] Kollabierbare Kategorien -- [ ] Favoriten / angeheftete Räume -- [ ] Räume stummschalten -- [ ] Räume ausblenden / archivieren -- [ ] Kanalreihenfolge für reguläre Nutzer +- [ ] Space-Entdeckung (öffentliche Spaces) --- -## Sprach- & Videoanrufe +## Sprach- & Videoanrufe (LiveKit) -### Sprachanrufe (LiveKit) -- [x] Sprachkanal betreten / verlassen (Toggle) +- [x] Sprachkanal betreten / verlassen +- [x] Mikrofon stummschalten / Deafen - [x] Teilnehmerliste im Sprachkanal -- [x] Mikrofon stummschalten -- [x] Audio-Ausgabe deaktivieren (Deafen) -- [x] Anruf-UI im Profil-Panel (aktiver Anruf) -- [x] Anruf-Ansicht öffnen (Vollansicht) -- [x] Mini-Call-Widget bei VOIP-Anrufen +- [x] Anruf-UI (Vollansicht + Mini-Widget) +- [x] Videoanruf mit Kamera-Toggle - [ ] Klingelton bei eingehenden Anrufen - [ ] Anruf annehmen / ablehnen (UI) - [ ] Anrufdauer-Timer -- [ ] Anrufverlauf - -### Videoanrufe -- [x] Videoanruf starten (aus DM) -- [x] Kamera-Toggle -- [x] Videoteilnehmer-Anzeige -- [ ] Bildschirmfreigabe (Toggle-UI vorhanden, Implementierung unklar) -- [ ] Picture-in-Picture-Modus -- [ ] Virtueller Hintergrund - -### Gruppenanrufe -- [x] Mehrere Teilnehmer im Sprachkanal (LiveKit) -- [ ] Gruppen-Videogitter -- [ ] Spotlight-/Galerie-Ansicht - ---- - -## Benachrichtigungen & Presence - -### Push-Benachrichtigungen -- [ ] Desktop-Benachrichtigungen (Windows/macOS/Linux) -- [ ] Mobile Push-Benachrichtigungen (Android/iOS) -- [ ] Benachrichtigungseinstellungen pro Raum -- [ ] Nicht-Stören-Modus -- [ ] Benachrichtigungssound konfigurieren - -### Presence & Status -- [x] Nutzer-Presence abrufen (online/offline/abwesend) -- [x] Presence-Indikator anzeigen -- [x] Letzte-Aktivität-Zeitstempel -- [x] Echtzeit-Presence-Updates -- [ ] Eigenen Status setzen (online/abwesend/unsichtbar) -- [ ] Benutzerdefinierte Statusmeldung -- [ ] Aktivitätsbasierte Status-Änderung - -### Tipp-Indikatoren -- [ ] "X tippt gerade"-Anzeige empfangen -- [ ] Eigene Tipp-Benachrichtigung senden -- [ ] Timeout nach Tipp-Ende +- [ ] Bildschirmfreigabe --- ## Nutzereinstellungen & Profil -### Profilverwaltung -- [x] Eigene User-ID anzeigen -- [x] Eigenen Avatar anzeigen (Initialen-Fallback) -- [x] Anzeigenamen anzeigen -- [ ] Anzeigenamen bearbeiten -- [ ] Eigenen Avatar hochladen / entfernen -- [ ] Status-Nachricht setzen - -### Kontosicherheit +- [x] Hell / Dunkel-Theme, Akzentfarbe, Eckradius, Dichte +- [x] Eigene User-ID, Avatar (Initialen-Fallback), Anzeigename anzeigen +- [ ] Anzeigenamen & Avatar bearbeiten - [ ] Passwort ändern -- [ ] E-Mail-Adresse verwalten -- [ ] Sitzungsverwaltung (alle Sitzungen anzeigen) -- [ ] Andere Sitzungen abmelden -- [ ] Konto deaktivieren / löschen -- [ ] Zwei-Faktor-Authentifizierung (2FA) - -### App-Einstellungen -- [x] Hell / Dunkel-Theme -- [x] Akzentfarbe (6 Voreinstellungen) -- [x] Eckradius anpassen -- [x] UI-Dichte / Kompaktheit -- [x] Animationssteuerung -- [ ] Schriftgröße anpassen -- [ ] Sprachauswahl (i18n) -- [ ] Kompaktansicht (kein Avatar in Nachrichten) - ---- - -## Datenschutz & Sicherheit - -### Ende-zu-Ende-Verschlüsselung (E2EE) -- [x] E2EE-Unterstützung (Olm/Megolm via vodozemac) -- [x] E2EE-Schlüssel beim ersten Login einrichten (Bootstrap) -- [x] Verschlüsselte Nachrichten-Indikatoren -- [x] Entschlüsselungsstatus anzeigen -- [x] SSSS (Symmetric Secret Storage) -- [x] Recovery-Key erzeugen & anzeigen -- [x] Recovery-Key aus bestehender Einrichtung importieren -- [x] Schlüssel-Caching (lokal speichern) -- [x] Session-Keys von anderen Geräten anfordern -- [ ] Schlüssel-Backup (Server-seitig) -- [ ] Schlüssel-Backup verifizieren - -### Geräte-Verifizierung -- [x] Cross-Signing (Master/Self-Signing/User-Signing Keys) -- [x] Gerät per Emoji verifizieren -- [x] Gerät per Zahlencodes verifizieren -- [x] Geräte als vertrauenswürdig markieren -- [ ] Gerätename / Modell anzeigen -- [ ] Sitzungsverwaltung (alle Geräte dieses Accounts) -- [ ] Fremde Geräte abmelden - -### Vertrauen & Sicherheit -- [ ] Geräte-Vertrauensstatus-Indikator in Nachrichten -- [ ] Nutzer blockieren / entsperren -- [ ] Blockierte Nutzer-Liste -- [ ] Verifizierter-Nutzer-Badge - ---- - -## Suche - -### Nachrichtensuche -- [x] Suchdialog öffnen (UI vorhanden) -- [ ] Volltextsuche in Nachrichteninhalten -- [ ] Filter nach Absender -- [ ] Filter nach Datum -- [ ] Filter nach Raum -- [ ] Filter nach Medientyp -- [ ] Suchergebnisse hervorheben -- [ ] Suchverlauf - -### Nutzer- / Raumsuche -- [ ] Nutzer nach Anzeigenamen suchen -- [ ] Nutzer nach User-ID suchen -- [ ] Öffentliche Räume entdecken (Directory) -- [ ] Eigene Räume filtern -- [ ] Räume nach Name / Thema suchen +- [ ] Sitzungsverwaltung +- [ ] Konto deaktivieren --- ## Auto-Update - [x] GitHub-Releases als Update-Quelle -- [x] Versions-Vergleich (SemVer) -- [x] Rate-Limiting (max. alle 4 Stunden prüfen) -- [x] Update-Banner im App-Header (Windows) +- [x] Versions-Vergleich (SemVer), Rate-Limiting, Update-Banner - [x] "Diese Version überspringen"-Option -- [x] Manueller Update-Check in den Einstellungen -- [ ] Automatischer Download & Installation (Squirrel/NSIS) -- [ ] Delta-Updates (nur geänderte Dateien) -- [ ] Update-Kanal wählen (Stable/Beta/Nightly) +- [ ] Automatischer Download & Installation --- ## Plattform-spezifisch -### Desktop (Windows / macOS / Linux) -- [x] Native Desktop-App (Flutter Desktop) -- [x] Tastenkürzel (Enter = Senden, Shift+Enter = Zeile) -- [x] Drag-and-Drop für Dateianhänge +### Desktop +- [x] Native Desktop-App, Tastenkürzel, Drag-and-Drop - [ ] System-Tray-Integration -- [ ] Desktop-Benachrichtigungen -- [ ] Minimieren in System-Tray - [ ] Fenster-State speichern (Größe, Position) -- [ ] MSIX / Installer-Paketierung -### Mobile (Android / iOS) -- [x] Mobile App (Flutter) -- [x] Drawer-Navigation (Hamburger-Menü) -- [ ] Touch-optimiertes UI (derzeit Desktop-first) +### Mobile +- [x] Mobile App (Flutter), Drawer-Navigation +- [ ] Touch-optimiertes UI - [ ] Mobile Push-Benachrichtigungen -- [ ] Zurück-Geste Navigation -- [ ] Bottom-Sheet-Modals -- [ ] Share-Sheet-Integration -- [ ] Haptisches Feedback + +--- + +--- + +# Technische Tiefenanalyse (2026-04-29) + +*Vergleichsbasis: FluffyChat (krille-chan/fluffychat) und Element Web* +*Format: Befund → betroffene Datei:Zeile → Referenz-Implementierung* + +--- + +## IMPLEMENTIERUNGS-BACKLOG (nach Priorität) + +### 🔴 P0 — Kritisch + +#### [P0-1] Incoming Key-Verification-Request-Handler fehlt +**Problem:** Wenn ein anderes Gerät eine Verifikations-Anfrage (`m.key.verification.request`) an Pyramid schickt, gibt es keinen Listener. Die Anfrage läuft ab, ohne dass der Nutzer sie sieht. Das bedeutet: andere Geräte können Pyramid de facto nicht verifizieren — nur Pyramid kann aktiv verifizieren. +**Betroffene Datei:** `lib/widgets/settings_modal.dart` (kein `onKeyVerificationRequest`-Listener) +**FluffyChat-Referenz:** `lib/pages/key_verification/key_verification_dialog.dart` + `client.onKeyVerificationRequest.stream.listen(...)` in `lib/pages/matrix.dart` +**Fix:** Stream auf `client.onKeyVerificationRequest` in `matrix_client.dart` oder `app_shell.dart` subscriben und `KeyVerificationDialog` öffnen. + +--- + +### 🟠 P1 — Hoch + +#### [P1-1] Notification-Prefs werden ignoriert +**Problem:** `notifDesktopProvider`, `notifSoundProvider`, `notifPreviewProvider`, `notifMentionOnlyDmProvider` sind in `settings_prefs.dart` gespeichert, werden in `notification_service.dart/_watchEvents()` aber nie ausgelesen. Notifications erscheinen immer, unabhängig von Nutzereinstellungen. +**Betroffene Datei:** `lib/core/notification_service.dart`, Zeile 145–168 +**Fix:** In `_watchEvents()` die Prefs vor `showMessageNotification()` prüfen. + +#### [P1-2] Edits werden nicht gerendert +**Problem:** `_isVisible()` filtert Edit-Events korrekt heraus, aber `event.getDisplayEvent(timeline)` wird nirgendwo aufgerufen. Nachrichten zeigen immer die Originalversion, auch wenn sie via `m.replace` bearbeitet wurden. Ein `(bearbeitet)`-Label fehlt ebenfalls. +**Betroffene Datei:** `lib/features/chat/message_group.dart` — Event-Rendering-Bereich +**FluffyChat-Referenz:** `event.getDisplayEvent(timeline)` vor dem Rendern jedes Events +**Fix:** Beim Rendern von Events `event.getDisplayEvent(timeline)` statt `event` verwenden; `(bearbeitet)`-Label wenn `event != displayEvent`. + +#### [P1-3] Encrypted-Placeholder bleibt dauerhaft — kein Recovery-Button +**Problem:** `EventTypes.Encrypted` zeigt "Nachricht wird entschlüsselt…" dauerhaft wenn die Entschlüsselung scheitert. Es gibt keinen Button zum Anfordern fehlender Keys. +**Betroffene Datei:** `lib/features/chat/message_group.dart`, Zeilen ~408–421 +**FluffyChat-Referenz:** `_requestMissingKey()` mit `room.client.sendToDeviceEncrypted(...)` / SDK-`requestKey()` +**Fix:** Wenn `event.status == EventStatus.error` oder nach Timeout immer noch `EventTypes.Encrypted`: "Schlüssel anfordern"-Button anzeigen, der `timeline.requestKeys()` aufruft. + +--- + +### 🟡 P2 — Mittel + +#### [P2-1] Typing-Indikator: `room.setTyping()` nie aufgerufen +**Problem:** `privacyTypingProvider` existiert, `chat_composer.dart` ruft aber nie `room.setTyping()` auf. Andere Nutzer sehen nie "X tippt gerade…". +**Betroffene Datei:** `lib/features/chat/chat_input.dart` (oder `chat_composer.dart`) +**FluffyChat-Referenz:** `onInputBarChanged` → 2s Debounce → `room.setTyping(true, timeout: 30000)`; bei Senden/Leerfeld: `room.setTyping(false)` +**Fix:** Im Composer-Input `onChanged`-Handler mit Debounce und `room.setTyping()` ergänzen. + +#### [P2-2] Typing-Indikator: Kein Display-Widget +**Problem:** Kein Widget das `room.typingUsers` anzeigt. +**Fix:** `_TypingIndicator`-Widget in `chat_view.dart` unter der Nachrichtenliste einfügen, das `room.onUpdate`-Stream abonniert und `room.typingUsers` anzeigt. + +#### [P2-3] Unread-Divider: Position off-by-one +**Problem:** Divider erscheint *über* der Gruppe die das `fullyRead`-Event *enthält*, nicht darunter. Das bereits-gelesene Event liegt unter dem "Neue Nachrichten"-Strich. +**Betroffene Datei:** `lib/features/chat/chat_view.dart`, Zeile ~715 +**Fix:** Divider nach der Gruppe einsetzen, die das `fullyReadId`-Event enthält, nicht davor. + +#### [P2-4] Unread-Divider: Kein Auto-Scroll beim Öffnen +**Problem:** Beim Öffnen eines Raums mit ungelesenen Nachrichten landet die View unten, nicht beim Divider. +**FluffyChat-Referenz:** Initialer `scrollController.jumpTo()` zum Index des `fullyRead`-Events nach dem ersten Frame. +**Fix:** In `initState`/`WidgetsBinding.addPostFrameCallback` zum Divider-Index springen wenn `_sessionHasUnread`. + +#### [P2-5] Gruppen-Read-Receipts fehlen +**Problem:** ✓✓-Logik greift nur bei `room.isDirectChat`. In Gruppenräumen sehen eigene Nachrichten nie ✓✓. +**FluffyChat-Referenz:** `SeenByRow` zeigt Avatare aller Leser unter der letzten Nachricht. +**Fix:** Receipt-Prüfung auch in Gruppenräumen aktivieren; ggf. Avatar-Reihe unter letzter Nachricht. + +#### [P2-6] Notification-Cancellation beim Lesen fehlt +**Problem:** Android-Notifications bleiben in der Benachrichtigungsleiste stehen, auch wenn der Chat geöffnet und die Nachrichten gelesen wurden. +**FluffyChat-Referenz:** `backgroundPush?.cancelNotification(roomId)` in `_markRead()` +**Fix:** In `_markRead()` in `chat_view.dart` die Android-Notification für `roomId` canceln. + +--- + +### 🔵 P3 — Niedrig + +#### [P3-1] Presence: Kein Auto-Heartbeat +**Problem:** `setPresence(online)` nur in Settings — Server setzt Client nach Timeout offline. +**Fix:** Periodischer Timer (alle 60s) der `setPresence(online)` sendet solange App im Vordergrund. + +#### [P3-2] Presence: Kein App-Lifecycle-Hook +**Problem:** Kein `WidgetsBindingObserver` — kein `unavailable` bei App-Hintergrund. +**Fix:** `WidgetsBindingObserver.didChangeAppLifecycleState` in `matrix_client.dart` oder `app_shell.dart`. + +#### [P3-3] Markdown/`formatted_body` nicht gerendert +**Problem:** `sendTextEvent` sendet nur plain text. Empfangene `formatted_body`-Felder werden nicht gerendert. +**Fix:** Empfang: `flutter_html` oder `flutter_markdown` für `formatted_body`; Senden: simple Markdown-Erkennung im Composer. + +#### [P3-4] `requestFuture()` fehlt +**Problem:** Kein Forward-Pagination-Mechanismus. Nach Jump-to-Event in der Vergangenheit kein Weg zurück. +**Fix:** `timeline.requestFuture()` im Scroll-Listener für die Vorwärts-Richtung. + +#### [P3-5] `message_bubble.dart` — ungenutzter Code +**Problem:** Veraltete WhatsApp-Style-Implementation koexistiert neben aktiver Discord-Style-Implementierung. +**Fix:** Datei löschen oder auskommentieren. --- ## Statistik -| Bereich | Implementiert | Teilweise | Fehlend | +| Bereich | Implementiert | Fehlerhaft | Fehlend | |---|---|---|---| -| Messaging | 14 | 2 | 14 | -| Raumverwaltung | 8 | 0 | 14 | -| Spaces | 10 | 0 | 6 | -| Anrufe | 8 | 1 | 10 | -| Benachrichtigungen | 4 | 0 | 8 | -| Einstellungen/Profil | 5 | 0 | 11 | -| Sicherheit/E2EE | 9 | 0 | 7 | -| Suche | 1 | 0 | 10 | -| Auto-Update | 6 | 0 | 3 | -| Plattform | 5 | 0 | 10 | -| **Gesamt** | **~70** | **~3** | **~93** | +| Chat-Mechanik | Solide Basis | Edits, Typing, `requestFuture` | Jump-to-quote, Threads, Edited-Badge | +| Read Receipts | DM-Logik ✓ | Gruppen, Off-by-one, Notif-Cancel | Seen-by-Avatare, Tooltip | +| Presence | Anzeige ✓ | Broadcasting, Lifecycle | Heartbeat, Dot in Raumliste | +| Benachrichtigungen | Local ✓ | Prefs ignoriert, Grouping | Remote Push, iOS, macOS | +| Unread-Divider | Konzept ✓ | Position, Auto-Scroll | — | +| E2EE | Stärkster Bereich | Incoming-Verif., Placeholder | Device-Trust-Indicator, Warn beim Senden | +| Suche | API-Basis ✓ | — | Jump-to-message, Filter | -**Implementierungsgrad: ~42 %** (inkl. Teilimplementierungen) +**Implementierungsgrad gesamt: ~42 %** (inkl. Teilimplementierungen) --- -## Empfohlene Feature-Prioritäten +## Implementierungs-Fortschritt -1. **Textformatierung** — häufig genutzt, von Nutzern erwartet -2. **Push-Benachrichtigungen** — Desktop-Benachrichtigungen für Windows -3. **Tipp-Indikatoren** — verbessert Gesprächsgefühl deutlich -4. **Nachrichtenbearbeitung** — SDK-Grundlage vorhanden, nur UI fehlt -5. **Profilbearbeitung** — Avatar & Anzeigename ändern -6. **Raum erstellen** — Basis-Workflow, derzeit nicht möglich -7. **Sprachnachricht abspielen** — Struktur vorhanden -8. **Suche** — Dialog vorhanden, Backend-Abfrage fehlt -9. **Nutzer blockieren** — Sicherheits-Grundfunktion -10. **System-Tray** — Desktop-Erlebnis verbessern +| ID | Beschreibung | Status | +|---|---|---| +| P0-1 | Incoming Key-Verification-Request-Handler | ✅ War bereits implementiert (`app_shell.dart`) | +| P1-1 | Notification-Prefs auswerten | ✅ Implementiert (`notification_service.dart`) | +| P1-2 | Edits rendern (`getDisplayEvent`) | ✅ Implementiert (`message_group.dart`) | +| P1-3 | Encrypted-Placeholder + Recovery-Button | ✅ Implementiert (`message_group.dart`) | +| P2-1 | Typing: `room.setTyping()` senden | ✅ Implementiert (`chat_composer.dart`) | +| P2-2 | Typing: Display-Widget | ✅ Implementiert (`chat_view.dart` — `_TypingIndicator`) | +| P2-3 | Unread-Divider: Position + leere fullyRead-Guard | ✅ Neu implementiert (`chat_view.dart`) | +| P2-4 | Unread-Divider: Auto-Scroll (Schätzung) | ✅ Implementiert (`_scrollToUnread`) | +| P2-5 | Gruppen-Read-Receipts (DM-Guard entfernt) | ✅ Implementiert (`chat_view.dart`) | +| P2-6 | Notification-Cancellation beim Lesen | ✅ Implementiert (`chat_view.dart/_markRead`) | +| P3-1 | Presence: Auto-Heartbeat (10s) | ✅ Implementiert (`app_shell.dart`) | +| P3-2 | Presence: App-Lifecycle-Hook | ✅ Implementiert (`app_shell.dart` — `WidgetsBindingObserver`) | +| P3-3 | HTML/Markdown (`_MatrixHtmlText`, `_PlainLinkText`) | ✅ Implementiert (`message_group.dart`) | +| P3-4 | `requestFuture()` | ✅ Implementiert (`chat_view.dart/_onScroll`) | +| P3-5 | `message_bubble.dart` entfernen | ⏳ Offen | diff --git a/docs/matrix-sdk/01-auth.md b/docs/matrix-sdk/01-auth.md new file mode 100644 index 0000000..1aaaa52 --- /dev/null +++ b/docs/matrix-sdk/01-auth.md @@ -0,0 +1,241 @@ +# 01 — Authentifizierung & Session + +--- + +## Inhaltsverzeichnis +- [Login mit Passwort](#login-mit-passwort) +- [Login mit Token](#login-mit-token) +- [SSO / OAuth](#sso--oauth) +- [Register](#registrierung) +- [Session prüfen & wiederherstellen](#session-prüfen--wiederherstellen) +- [Logout](#logout) +- [Multi-Account / Device](#multi-account--device) +- [Homeserver ermitteln](#homeserver-ermitteln) +- [Flows & Login-Typen abfragen](#flows--login-typen-abfragen) + +--- + +## Login mit Passwort + +```dart +await client.checkHomeserver(Uri.parse('https://matrix.example.org')); + +final loginResponse = await client.login( + LoginType.mLoginPassword, + password: 'geheimesPasswort', + identifier: AuthenticationUserIdentifier(user: '@alice:example.org'), + // oder nur Username (ohne Server): + // identifier: AuthenticationUserIdentifier(user: 'alice'), + initialDeviceDisplayName: 'Pyramid Android', +); +// loginResponse.accessToken, .deviceId, .userId +``` + +--- + +## Login mit Token + +```dart +await client.checkHomeserver(Uri.parse('https://matrix.example.org')); + +await client.login( + LoginType.mLoginToken, + token: 'einmaliger_login_token', + initialDeviceDisplayName: 'Pyramid', +); +``` + +--- + +## SSO / OAuth + +```dart +// Verfügbare Login-Flows abfragen +final flows = await client.getLoginFlows(); +final hasSso = flows.flows?.any((f) => f.type == AuthenticationTypes.sso) ?? false; + +// SSO-URL erzeugen (öffnet Browser/WebView) +final redirectUri = 'io.pyramid.app://login-callback'; +final ssoUrl = client.homeserver!.toString() + + '/_matrix/client/v3/login/sso/redirect?redirectUrl=${Uri.encodeComponent(redirectUri)}'; +// → Uri im Browser öffnen, nach Redirect den Token extrahieren + +// Nach Redirect mit Token einloggen +await client.login( + LoginType.mLoginToken, + token: tokenAusRedirectUrl, + initialDeviceDisplayName: 'Pyramid', +); +``` + +--- + +## Registrierung + +```dart +// Homeserver-Registrierung prüfen +await client.checkHomeserver(Uri.parse('https://matrix.example.org')); + +// UIAA-Flow starten +try { + await client.uiaRequestBackground( + (auth) => client.register( + username: 'neuernutzer', + password: 'sicheresPasswort', + initialDeviceDisplayName: 'Pyramid', + auth: auth, + ), + ); +} on MatrixException catch (e) { + // e.error: M_USER_IN_USE, M_INVALID_USERNAME, etc. +} +``` + +--- + +## Session prüfen & wiederherstellen + +```dart +// Nach client.init() prüfen ob Session noch gültig ist +if (client.isLogged()) { + print('Eingeloggt als: ${client.userID}'); + print('Homeserver: ${client.homeserver}'); + print('Device ID: ${client.deviceID}'); + print('Access Token: ${client.accessToken}'); +} + +// Auf Login-State reagieren +client.onLoginStateChanged.stream.listen((LoginState state) { + switch (state) { + case LoginState.loggedIn: // Session aktiv + case LoginState.softLoggedOut: // Token abgelaufen, Re-Auth nötig + case LoginState.loggedOut: // Ausgeloggt + } +}); +``` + +--- + +## Logout + +```dart +// Nur dieses Device +await client.logout(); + +// Alle Devices +await client.logoutAll(); +``` + +--- + +## Multi-Account / Device + +```dart +// Eigene Devices (Sessions) auflisten +final devices = await client.getDevices(); +for (final device in devices ?? []) { + print('${device.deviceId}: ${device.displayName} — ${device.lastSeenIp}'); +} + +// Device umbenennen +await client.updateDevice( + deviceId: 'DEVICEID', + displayName: 'Pyramid (Wohnzimmer)', +); + +// Device löschen (andere Session killen) +await client.deleteDevice( + 'ANDERES_DEVICE_ID', + auth: AuthenticationPassword( + identifier: AuthenticationUserIdentifier(user: client.userID!), + password: 'meinPasswort', + ), +); + +// Mehrere Devices auf einmal löschen +await client.deleteDevices( + ['DEVICE1', 'DEVICE2'], + auth: AuthenticationPassword(...), +); +``` + +--- + +## Homeserver ermitteln + +```dart +// .well-known auflösen (Autodiscovery) +final discovery = await client.checkHomeserver( + Uri.parse('https://example.org'), // Domain reicht, SDK findet Matrix-Server +); +// client.homeserver ist jetzt gesetzt + +// Direkt mit bekannter HS-URL +await client.checkHomeserver(Uri.parse('https://matrix.example.org')); + +// Homeserver-Versioninfo +final serverVersion = await client.getVersions(); +print(serverVersion.versions); // ['v1.1', 'v1.2', ...] +``` + +--- + +## Flows & Login-Typen abfragen + +```dart +final response = await client.getLoginFlows(); +for (final flow in response.flows ?? []) { + switch (flow.type) { + case AuthenticationTypes.password: // m.login.password + case AuthenticationTypes.sso: // m.login.sso + case AuthenticationTypes.token: // m.login.token + case 'm.login.cas': // Legacy-CAS + } +} + +// SSO-Provider Details (für Brand-Buttons im UI) +final ssoProviders = response.flows + ?.where((f) => f.type == AuthenticationTypes.sso) + .expand((f) => f.identityProviders ?? []) + .toList(); +// ssoProvider.id, .name, .brand, .icon +``` + +--- + +## UIAA (User-Interactive Auth) Flows + +```dart +// Generisches UIAA-Handling (z.B. für Account-Löschung) +await client.uiaRequestBackground( + (auth) => client.deactivateAccount(auth: auth, eraseData: false), +); + +// Passwort ändern (braucht Re-Auth) +await client.uiaRequestBackground( + (auth) => client.changePassword( + 'neuesPasswort', + auth: auth, + oldPassword: 'altesPasswort', // optional, falls Server es erlaubt + ), +); +``` + +--- + +## Fehlerbehandlung + +```dart +try { + await client.login(...); +} on MatrixException catch (e) { + switch (e.error) { + case MatrixError.M_FORBIDDEN: // Falsches Passwort + case MatrixError.M_USER_IN_USE: // Username vergeben + case MatrixError.M_INVALID_USERNAME: + case MatrixError.M_LIMIT_EXCEEDED: // Rate-Limiting + case MatrixError.M_UNKNOWN: + } + print(e.errorMessage); // Menschenlesbarer Text vom Server +} +``` diff --git a/docs/matrix-sdk/02-rooms.md b/docs/matrix-sdk/02-rooms.md new file mode 100644 index 0000000..d205500 --- /dev/null +++ b/docs/matrix-sdk/02-rooms.md @@ -0,0 +1,436 @@ +# 02 — Räume & Spaces + +--- + +## Inhaltsverzeichnis +- [Raum erstellen](#raum-erstellen) +- [Raum beitreten](#raum-beitreten) +- [Raum verlassen](#raum-verlassen) +- [Raumliste](#raumliste) +- [Raum-Metadaten lesen](#raum-metadaten-lesen) +- [Raum-Einstellungen ändern](#raum-einstellungen-ändern) +- [Mitglieder](#mitglieder) +- [Einladen & Kick & Ban](#einladen--kick--ban) +- [Öffentliches Raumverzeichnis](#öffentliches-raumverzeichnis) +- [Spaces](#spaces) +- [Room Upgrades](#room-upgrades) + +--- + +## Raum erstellen + +```dart +// Einfacher privater Raum +final roomId = await client.createRoom( + name: 'Mein Raum', + topic: 'Willkommen!', + visibility: Visibility.private, // oder .public + preset: CreateRoomPreset.privateChat, // oder .publicChat, .trustedPrivateChat +); + +// Raum mit Einladungen +final roomId = await client.createRoom( + name: 'Projekt Alpha', + invite: ['@bob:example.org', '@charlie:example.org'], + enableEncryption: true, // E2EE aktivieren +); + +// Raum mit Alias +final roomId = await client.createRoom( + name: 'Öffentlicher Kanal', + roomAliasName: 'kanal', // → #kanal:example.org + visibility: Visibility.public, + preset: CreateRoomPreset.publicChat, +); + +// Raum mit Custom Power Levels +final roomId = await client.createRoom( + name: 'Moderiert', + powerLevelContentOverride: PowerLevelsContent( + eventsDefault: 50, // Nur Moderatoren senden + usersDefault: 0, + users: {'@admin:example.org': 100}, + ), +); + +// Raum mit History-Visibility +final roomId = await client.createRoom( + initialState: [ + StateEvent( + type: EventTypes.HistoryVisibility, + content: {'history_visibility': 'invited'}, // shared|invited|joined|world_readable + ), + ], +); +``` + +--- + +## Raum beitreten + +```dart +// Per Raum-ID +await client.joinRoom('!roomId:server'); + +// Per Alias +await client.joinRoomOrAlias('#kanal:example.org'); + +// Per Invite-Link / Matrix-URI +// matrix:r/kanal:example.org +// https://matrix.to/#/#kanal:example.org +final uri = MatrixUri.parse('https://matrix.to/#/#kanal:example.org'); +if (uri != null) { + await client.joinRoomOrAlias(uri.primaryIdentifier); +} + +// Mit Via-Servern (für föderierte Räume) +await client.joinRoom( + '!roomId:remoteserver.org', + serverName: ['remoteserver.org', 'matrix.org'], +); +``` + +--- + +## Raum verlassen + +```dart +// Verlassen (bleibt in Left-State) +final room = client.getRoomById('!roomId:server')!; +await room.leave(); + +// Vergessen (entfernt aus Raumliste) +await room.forget(); + +// Verlassen + Vergessen +await room.leave(); +await room.forget(); +``` + +--- + +## Raumliste + +```dart +// Alle Räume (joined + invited) +final allRooms = client.rooms; + +// Nur beigetretene +final joinedRooms = client.rooms + .where((r) => r.membership == Membership.join) + .toList(); + +// Nur Einladungen +final invites = client.rooms + .where((r) => r.membership == Membership.invite) + .toList(); + +// Sortiert nach letzter Aktivität +final sorted = [...client.rooms] + ..sort((a, b) => (b.lastEvent?.originServerTs ?? DateTime(0)) + .compareTo(a.lastEvent?.originServerTs ?? DateTime(0))); + +// Raum per ID +final room = client.getRoomById('!roomId:server'); + +// Raum per Alias auflösen +final resolved = await client.getRoomIdByAlias('#alias:server'); +// resolved.roomId + +// Ungelesene Nachrichten +final unread = client.rooms.fold( + 0, (sum, r) => sum + r.notificationCount); +``` + +--- + +## Raum-Metadaten lesen + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Basis-Info +print(room.id); // !roomId:server +print(room.name); // Anzeigename (aufgelöst) +print(room.topic); // Thema +print(room.avatar); // mxc://… URI +print(room.canonicalAlias); // #alias:server +print(room.membership); // Membership.join/invite/leave/ban +print(room.isDirectChat); // DM? +print(room.directChatMatrixID); // Gegenüber-MXID bei DM +print(room.isEncrypted); // E2EE aktiv? +print(room.joinRules); // JoinRules.public/invite/knock/restricted +print(room.guestAccess); // GuestAccess.forbidden/canJoin +print(room.historyVisibility); // HistoryVisibility.* +print(room.notificationCount); // Ungelesene Notifications +print(room.highlightCount); // Mentions +print(room.summary.mJoinedMemberCount); // Mitgliederzahl + +// Letztes Event +final last = room.lastEvent; +print(last?.body); +print(last?.originServerTs); + +// Display-Name (lokalisiert, wie FluffyChat) +final displayName = room.getLocalizedDisplayname(); +``` + +--- + +## Raum-Einstellungen ändern + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Name +await room.setName('Neuer Name'); + +// Thema +await room.setDescription('Neues Thema'); + +// Avatar (mxc:// URI nach Upload) +final uri = await client.uploadContent(imageBytes, filename: 'avatar.png'); +await room.setAvatar(uri); + +// Alias setzen / entfernen +await client.setRoomAlias('#neu:example.org', room.id); +await client.deleteRoomAlias('#alt:example.org'); +await room.setCanonicalAlias('#neu:example.org'); // Kanonischen Alias setzen + +// Join-Rules +await room.setJoinRules(JoinRules.invite); // private +await room.setJoinRules(JoinRules.public); // öffentlich +await room.setJoinRules(JoinRules.knock); // Beitrittsanfragen +await room.setJoinRules( + JoinRules.restricted, + allow: [SpaceRoomJoinRulesAllowInner( + roomId: '!spaceId:server', + type: SpaceRoomJoinRulesAllowInnerType.mRoomMembership, + )], +); + +// History-Visibility +await room.setHistoryVisibility(HistoryVisibility.shared); +// .shared | .invited | .joined | .worldReadable + +// Guest Access +await room.setGuestAccess(GuestAccess.canJoin); +await room.setGuestAccess(GuestAccess.forbidden); + +// E2EE aktivieren (nicht mehr deaktivierbar!) +await room.enableEncryption(); + +// Generischer State-Event senden +await room.client.sendState( + room.id, + 'm.room.custom_event', + {'key': 'value'}, + stateKey: '', +); +``` + +--- + +## Mitglieder + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Alle Mitglieder (gecacht) +final members = room.getParticipants(); + +// Vollständige Mitgliederliste vom Server laden +final allMembers = await room.requestParticipants(); + +// Einzelnen User holen +final user = room.unsafeGetUserFromMemoryOrFallback('@alice:server'); +print(user.displayName); +print(user.avatarUrl); +print(user.powerLevel); +print(user.membership); // Membership.join/invite/leave/ban/knock + +// Aktuell tippende User +final typingUsers = room.typingUsers; // List + +// Power Level eines Users +final pl = room.getPowerLevelByUserId('@alice:server'); + +// Eigener Power Level +final myPl = room.ownPowerLevel; +``` + +--- + +## Einladen, Kick & Ban + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Einladen +await room.invite('@alice:server'); + +// Kick (entfernt, kann wieder beitreten) +await room.kick('@alice:server', reason: 'Regeln verletzt'); + +// Ban (dauerhaft gesperrt) +await room.ban('@alice:server', reason: 'Spam'); + +// Unban +await room.unban('@alice:server'); + +// Eigene Berechtigungen prüfen +room.canBan; // bool +room.canKick; // bool +room.canInvite; // bool +room.canSendEvent(EventTypes.Message); // bool +``` + +--- + +## Power Levels + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Power Level eines Users setzen +await room.setPower('@alice:server', 50); // 0=User, 50=Mod, 100=Admin + +// Power Level Content auslesen +final plContent = room.getState(EventTypes.RoomPowerLevels) + ?.content + .tryGet('users'); + +// Vollständig setzen +await room.client.sendState( + room.id, + EventTypes.RoomPowerLevels, + { + 'ban': 50, + 'events': { + 'm.room.name': 50, + 'm.room.power_levels': 100, + }, + 'events_default': 0, + 'invite': 50, + 'kick': 50, + 'redact': 50, + 'state_default': 50, + 'users': { + '@alice:server': 100, + '@mod:server': 50, + }, + 'users_default': 0, + }, + stateKey: '', +); + +// Berechtigungen prüfen +room.canSendDefaultMessages; // Nachrichten senden +room.canChangeStateEvent(EventTypes.RoomName); // State-Events ändern +``` + +--- + +## Öffentliches Raumverzeichnis + +```dart +// Öffentliche Räume suchen +final result = await client.queryPublicRooms( + limit: 20, + filter: PublicRoomQueryFilter(genericSearchTerm: 'flutter'), + server: 'matrix.org', // optionaler anderer Server +); + +for (final room in result.chunk) { + print(room.name); + print(room.roomId); + print(room.numJoinedMembers); + print(room.worldReadable); +} + +// Nächste Seite +final next = await client.queryPublicRooms( + since: result.nextBatch, + limit: 20, +); +``` + +--- + +## Spaces + +```dart +// Space erstellen +final spaceId = await client.createRoom( + name: 'Mein Space', + creationContent: {'type': 'm.space'}, // markiert als Space + visibility: Visibility.private, +); + +// Kind-Raum zu Space hinzufügen +final space = client.getRoomById(spaceId)!; +await space.client.sendState( + spaceId, + EventTypes.SpaceChild, + { + 'via': ['example.org'], + 'suggested': true, + 'auto_join': false, + }, + stateKey: '!childRoomId:server', +); + +// Space-Kinder auflisten (vom Server) +final children = await client.getSpaceHierarchy( + spaceId, + maxDepth: 2, + suggestedOnly: false, +); +for (final room in children.rooms) { + print(room.name); + print(room.roomType); // 'm.space' oder null + print(room.childrenState); // Sub-Spaces +} + +// Kind-Raum entfernen +await space.client.sendState( + spaceId, + EventTypes.SpaceChild, + {}, // leeres Content → entfernt + stateKey: '!childRoomId:server', +); + +// Space-Parent setzen (vom Kind-Raum aus) +await client.sendState( + '!childRoomId:server', + EventTypes.SpaceParent, + { + 'via': ['example.org'], + 'canonical': true, + }, + stateKey: spaceId, +); + +// Alle Spaces des Users +final spaces = client.rooms.where((r) => + r.membership == Membership.join && + r.getState('m.room.create')?.content['type'] == 'm.space'); +``` + +--- + +## Room Upgrades + +```dart +// Raum auf neuere Version upgraden (erstellt Nachfolger-Raum) +final newRoomId = await client.upgradeRoom( + '!alterRaumId:server', + newVersion: '11', // Aktuelle empfohlene Version +); +// Alle Mitglieder werden automatisch in den neuen Raum eingeladen +// tombstone-Event wird im alten Raum gesetzt + +// Tombstone lesen +final tombstone = room.getState(EventTypes.RoomTombstone); +final replacement = tombstone?.content['replacement_room'] as String?; +``` diff --git a/docs/matrix-sdk/03-messages.md b/docs/matrix-sdk/03-messages.md new file mode 100644 index 0000000..c10eb2c --- /dev/null +++ b/docs/matrix-sdk/03-messages.md @@ -0,0 +1,463 @@ +# 03 — Nachrichten & Events + +--- + +## Inhaltsverzeichnis +- [Textnachricht senden](#textnachricht-senden) +- [HTML / Markdown senden](#html--markdown-senden) +- [Antworten (Reply)](#antworten-reply) +- [Bearbeiten (Edit)](#bearbeiten-edit) +- [Reaktionen](#reaktionen) +- [Löschen (Redact)](#löschen-redact) +- [Threads](#threads) +- [Polls](#polls) +- [Standort](#standort) +- [Timeline lesen](#timeline-lesen) +- [Event-Typen Referenz](#event-typen-referenz) +- [Typing-Indikator](#typing-indikator) +- [Read Markers / Lesebestätigung](#read-markers--lesebestätigung) +- [Pinned Messages](#pinned-messages) +- [Fehlgeschlagene Events erneut senden](#fehlgeschlagene-events-erneut-senden) + +--- + +## Textnachricht senden + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Einfacher Text +final eventId = await room.sendTextEvent('Hallo Welt!'); + +// Gibt ein temporäres Event zurück (für optimistische UI) +// Das Event bekommt Status EventStatus.sending → .sent → .synced +``` + +--- + +## HTML / Markdown senden + +```dart +// Mit HTML-Formatierung +await room.sendTextEvent( + 'Fett und kursiv', // Fallback-Text (Plain) + htmlBody: 'Fett und kursiv', + parseMarkdown: false, // Kein automatisches Markdown-Parsing +); + +// Automatisches Markdown-Parsing (SDK parst ** → ) +await room.sendTextEvent( + '**Fett** und *kursiv*', + parseMarkdown: true, // Standard: true +); +``` + +--- + +## Antworten (Reply) + +```dart +// Event, auf das geantwortet wird +final replyTo = timeline.events.first; // Event-Objekt + +await room.sendTextEvent( + 'Das sehe ich auch so!', + inReplyTo: replyTo, +); + +// Prüfen ob ein Event eine Antwort ist +final isReply = event.isReply; // bool +final repliedId = event.inReplyTo; // eventId als String? + +// Das referenzierte Event laden +final original = await room.getEventById(repliedId!); +``` + +--- + +## Bearbeiten (Edit) + +```dart +// Nachricht bearbeiten +await room.sendTextEvent( + 'Korrigierter Text', + editEventId: altesEvent.eventId, // Referenz auf Original + htmlBody: 'Alt Korrigiert', // optional +); + +// Prüfen ob ein Event bearbeitet wurde +final isEdit = event.isEdit; // bool + +// Gerendertes Event (mit letzter Bearbeitung) holen +final displayed = event.getDisplayEvent(); // gibt die letzte Version zurück +print(displayed.body); // aktuelle Nachricht + +// Alle Bearbeitungen eines Events +final edits = timeline.events + .where((e) => e.isEdit && e.relationshipEventId == originalEvent.eventId) + .toList(); +``` + +--- + +## Reaktionen + +```dart +// Reaktion senden (Emoji oder Text) +await room.sendReaction(event.eventId, '👍'); +await room.sendReaction(event.eventId, '❤️'); + +// Alle Reaktionen eines Events lesen +final reactions = event.aggregatedEvents( + timeline, + RelationshipTypes.reaction, +); +// Gruppiert nach Emoji-Key: +// Map> + +// Eigene Reaktion entfernen (= Redact) +final myReaction = reactions['👍'] + ?.firstWhere((e) => e.senderId == client.userID); +if (myReaction != null) { + await myReaction.redactEvent(reason: null); +} +``` + +--- + +## Löschen (Redact) + +```dart +// Event löschen +await room.redactEvent( + event.eventId, + reason: 'Unpassender Inhalt', // optional +); + +// Über das Event-Objekt direkt +await event.redactEvent(reason: 'Spam'); + +// Prüfen ob redacted +final redacted = event.isRedacted; // bool +``` + +--- + +## Threads + +```dart +// Thread-Antwort senden +await room.sendEvent( + { + 'm.relates_to': { + 'rel_type': 'm.thread', + 'event_id': rootEvent.eventId, + 'is_falling_back': true, // true wenn kein echter Thread-Client + 'm.in_reply_to': { + 'event_id': rootEvent.eventId, + }, + }, + 'msgtype': 'm.text', + 'body': 'Antwort im Thread', + }, + EventTypes.Message, +); + +// Thread-Events eines Root-Events laden +final threadEvents = timeline.events + .where((e) => + e.relationshipType == RelationshipTypes.thread && + e.relationshipEventId == rootEvent.eventId) + .toList(); +``` + +--- + +## Polls + +```dart +// Poll erstellen (MSC3381) +await room.sendEvent( + { + 'org.matrix.msc3381.poll.start': { + 'question': { + 'msgtype': 'm.text', + 'body': 'Was ist dein Lieblingsessen?', + }, + 'kind': 'org.matrix.msc3381.poll.disclosed', // oder .undisclosed + 'max_selections': 1, + 'answers': [ + {'id': '1', 'org.matrix.msc3381.poll.answer': {'msgtype': 'm.text', 'body': 'Pizza'}}, + {'id': '2', 'org.matrix.msc3381.poll.answer': {'msgtype': 'm.text', 'body': 'Pasta'}}, + {'id': '3', 'org.matrix.msc3381.poll.answer': {'msgtype': 'm.text', 'body': 'Salat'}}, + ], + }, + 'msgtype': 'm.text', + 'body': 'Was ist dein Lieblingsessen? (Poll)', + }, + 'org.matrix.msc3381.poll.start', +); + +// Abstimmen +await room.sendEvent( + { + 'm.relates_to': { + 'rel_type': 'm.reference', + 'event_id': pollEvent.eventId, + }, + 'org.matrix.msc3381.poll.response': { + 'answers': ['1'], // Ausgewählte IDs + }, + 'msgtype': 'm.text', + 'body': 'Meine Antwort: Pizza', + }, + 'org.matrix.msc3381.poll.response', +); + +// Poll beenden +await room.sendEvent( + { + 'm.relates_to': { + 'rel_type': 'm.reference', + 'event_id': pollEvent.eventId, + }, + 'msgtype': 'm.text', + 'body': 'Poll beendet.', + }, + 'org.matrix.msc3381.poll.end', +); +``` + +--- + +## Standort + +```dart +// Standort senden +await room.sendEvent( + { + 'msgtype': 'm.location', + 'body': 'Mein Standort: geo:52.5200,13.4050', + 'geo_uri': 'geo:52.5200,13.4050', + 'org.matrix.msc3488.location': { + 'uri': 'geo:52.5200,13.4050', + 'description': 'Berlin', + }, + }, + EventTypes.Message, +); +``` + +--- + +## Timeline lesen + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Timeline erstellen (Callbacks werden bei Änderungen gerufen) +Timeline? timeline; +timeline = await room.getTimeline( + onUpdate: () { + // Vollständiges UI-Rebuild + setState(() {}); + }, + onChange: (int index) { + // Einzelnes Event geändert (z.B. Reaktion, Edit, Status) + setState(() {}); + }, + onInsert: (int index) { + // Neues Event eingefügt + setState(() {}); + }, + onRemove: (int index) { + // Event entfernt (Redaction) + setState(() {}); + }, +); + +// WICHTIG: Immer aufräumen! +@override +void dispose() { + timeline?.cancelSubscriptions(); + super.dispose(); +} + +// Events abrufen (neueste zuerst, Index 0 = aktuellstes) +final events = timeline.events; + +// Ältere Nachrichten nachladen (z.B. beim Scrollen nach oben) +await timeline.requestHistory(count: 30); +// Gibt true zurück wenn es noch mehr gibt +final hasMore = timeline.canRequestHistory; + +// Bestimmtes Event aus Timeline oder Server laden +final event = await room.getEventById('$eventId'); + +// Neuere Events nachladen (nach Gap) +await timeline.requestFuture(count: 20); +``` + +--- + +## Event-Typen Referenz + +```dart +// Nachrichten-Typen (msgtype) +'m.text' // Textnachricht +'m.emote' // /me Aktion +'m.notice' // Bot-Nachricht (dezenter) +'m.image' // Bild +'m.video' // Video +'m.audio' // Audio/Sprachnachricht +'m.file' // Datei +'m.location' // Standort +'m.sticker' // Sticker (eigener Event-Typ: m.sticker) + +// Event-Typen (type) +EventTypes.Message // m.room.message +EventTypes.Sticker // m.sticker +EventTypes.Reaction // m.reaction +EventTypes.RoomRedaction // m.room.redaction +EventTypes.Encrypted // m.room.encrypted +EventTypes.RoomName // m.room.name +EventTypes.RoomTopic // m.room.topic +EventTypes.RoomAvatar // m.room.avatar +EventTypes.RoomMember // m.room.member +EventTypes.RoomPowerLevels // m.room.power_levels +EventTypes.RoomCanonicalAlias // m.room.canonical_alias +EventTypes.RoomJoinRules // m.room.join_rules +EventTypes.RoomGuestAccess // m.room.guest_access +EventTypes.HistoryVisibility // m.room.history_visibility +EventTypes.RoomCreate // m.room.create +EventTypes.RoomTombstone // m.room.tombstone +EventTypes.Encryption // m.room.encryption +EventTypes.SpaceChild // m.space.child +EventTypes.SpaceParent // m.space.parent +EventTypes.CallInvite // m.call.invite +EventTypes.CallAnswer // m.call.answer +EventTypes.CallHangup // m.call.hangup + +// Event-Status prüfen +event.status == EventStatus.sending // Wird gesendet (optimistisch) +event.status == EventStatus.sent // Vom Server bestätigt +event.status == EventStatus.synced // Im eigenen Sync empfangen +event.status == EventStatus.error // Fehlgeschlagen +event.status == EventStatus.removed // Gelöscht + +// Nützliche Event-Properties +event.type // String: Event-Typ +event.eventId // String: ID +event.senderId // String: MXID des Senders +event.originServerTs // DateTime: Sendezeitpunkt +event.body // String: Nachrichtentext (entschlüsselt) +event.messageType // String?: msgtype +event.formattedBody // String?: HTML-Inhalt +event.isReply // bool +event.isEdit // bool +event.isReacted // bool +event.isRedacted // bool +event.isEncrypted // bool +event.isBadEncrypted // bool: Entschlüsselung fehlgeschlagen +event.isState // bool: State-Event? +event.relationshipEventId // String?: ID des referenzierten Events +event.relationshipType // String?: Beziehungstyp (m.replace, m.thread, etc.) + +// Sender-User holen +final sender = room.unsafeGetUserFromMemoryOrFallback(event.senderId); +print(sender.displayName); +print(sender.avatarUrl); +``` + +--- + +## Typing-Indikator + +```dart +// Schreiben anzeigen +await room.setTyping(true, timeout: 30000); // 30 Sekunden + +// Schreiben beenden +await room.setTyping(false); + +// Tippende User im Raum beobachten +final typing = room.typingUsers; // List +// Automatisch aktuell durch Sync +``` + +--- + +## Read Markers / Lesebestätigung + +```dart +// Gelesenes Event markieren +await room.setReadMarker( + event.eventId, + mRead: event.eventId, // private receipt (unsichtbar für andere) + // public receipt weglassen für private-only +); + +// Öffentliche + private Lesebestätigung +await room.setReadMarker( + event.eventId, + mRead: event.eventId, +); + +// Letztes gelesenes Event +final lastRead = room.lastReadEventId; + +// Ungelesen-Badge +final count = room.notificationCount; // Notifications +final hl = room.highlightCount; // Mentions/Highlights +``` + +--- + +## Pinned Messages + +```dart +// Events anpinnen +final currentPinned = (room.getState(EventTypes.RoomPinnedEvents) + ?.content['pinned'] as List?) + ?.cast() ?? []; + +await room.client.sendState( + room.id, + EventTypes.RoomPinnedEvents, + {'pinned': [...currentPinned, eventId]}, + stateKey: '', +); + +// Angepinnte Events lesen +final pinned = (room.getState(EventTypes.RoomPinnedEvents) + ?.content['pinned'] as List?) + ?.cast() ?? []; + +// Events laden +final pinnedEvents = await Future.wait( + pinned.map((id) => room.getEventById(id)), +); +``` + +--- + +## Fehlgeschlagene Events erneut senden + +```dart +// Events mit Status error finden +final failed = timeline.events + .where((e) => e.status == EventStatus.error) + .toList(); + +// Erneut senden +for (final event in failed) { + await event.sendAgain(); +} + +// Oder aus dem Timeline-Controller: +await room.sendEvent( + event.content, + event.type, + txnId: event.eventId, // Gleiche txnId → überschreibt fehlgeschlagenes +); +``` diff --git a/docs/matrix-sdk/04-dm.md b/docs/matrix-sdk/04-dm.md new file mode 100644 index 0000000..6c10b14 --- /dev/null +++ b/docs/matrix-sdk/04-dm.md @@ -0,0 +1,221 @@ +# 04 — Direct Messages (DMs) + +--- + +## Inhaltsverzeichnis +- [DM starten oder finden](#dm-starten-oder-finden) +- [DM-Raum identifizieren](#dm-raum-identifizieren) +- [DM-Liste](#dm-liste) +- [Gruppen-DM](#gruppen-dm) +- [DM-Raum schließen / vergessen](#dm-raum-schließen--vergessen) +- [User-Profil für DM laden](#user-profil-für-dm-laden) +- [Verschlüsselung in DMs](#verschlüsselung-in-dms) + +--- + +## DM starten oder finden + +```dart +// Existierenden DM finden oder neuen erstellen +// Gibt immer einen joined Room zurück +final room = await client.startDirectChat('@alice:server'); +print(room.id); // !roomId:server + +// Mit expliziten Optionen +final room = await client.startDirectChat( + '@alice:server', + // enableEncryption: true, // Standard: true +); + +// Navigieren zum DM-Raum +// (z.B. in Pyramid:) +ref.read(activeRoomIdProvider.notifier).state = room.id; +``` + +--- + +## DM-Raum identifizieren + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Ist es ein DM? +final isDm = room.isDirectChat; // bool + +// Mit wem? +final partner = room.directChatMatrixID; // '@alice:server' oder null + +// DM zu einem bestimmten User finden +final existingDm = client.getDirectChatFromUserId('@alice:server'); +// Gibt Room? zurück (null wenn kein DM vorhanden) + +// Alle DMs des Users (Account-Data) +final dmMap = client.directChats; +// Map>: { '@alice:server': ['!roomId:server'] } +``` + +--- + +## DM-Liste + +```dart +// Alle DM-Räume (joined) +final dms = client.rooms.where((r) => + r.isDirectChat && + r.membership == Membership.join, +).toList(); + +// Sortiert nach letzter Aktivität +dms.sort((a, b) => + (b.lastEvent?.originServerTs ?? DateTime(0)) + .compareTo(a.lastEvent?.originServerTs ?? DateTime(0))); + +// DMs mit ungelesenen Nachrichten +final unreadDms = dms.where((r) => r.notificationCount > 0).toList(); + +// Display-Info für DM-Liste +for (final dm in dms) { + final partner = client.getDirectChatFromUserId(dm.directChatMatrixID!); + final user = dm.unsafeGetUserFromMemoryOrFallback(dm.directChatMatrixID!); + print(user.displayName ?? dm.directChatMatrixID); + print(user.avatarUrl); + print(dm.lastEvent?.body); // Vorschautext + print(dm.lastEvent?.originServerTs); // Zeitstempel + print(dm.notificationCount); // Ungelesen +} +``` + +--- + +## Gruppen-DM + +```dart +// Gruppen-DM mit mehreren Personen erstellen +final roomId = await client.createRoom( + name: 'Gruppenunterhaltung', + invite: ['@bob:server', '@charlie:server'], + isDirect: true, // Als DM markieren + preset: CreateRoomPreset.trustedPrivateChat, + enableEncryption: true, +); + +// Oder mit startDirectChat (für Einzel-DMs) und manuell Teilnehmer hinzufügen +final room = await client.startDirectChat('@bob:server'); +await room.invite('@charlie:server'); + +// Gruppe als DM im Account-Data kennzeichnen +// (passiert automatisch bei isDirect: true) +``` + +--- + +## DM-Raum schließen / vergessen + +```dart +final room = client.getRoomById('!roomId:server')!; + +// Verlassen (Gegenüber kann weiter chatten) +await room.leave(); + +// Aus Raumliste entfernen +await room.forget(); + +// DM aus Account-Daten entfernen +final dmMap = Map.from(client.directChats); +dmMap.remove('@alice:server'); +// oder nur den spezifischen Raum entfernen: +final rooms = List.from(dmMap['@alice:server'] ?? []); +rooms.remove(room.id); +if (rooms.isEmpty) { + dmMap.remove('@alice:server'); +} else { + dmMap['@alice:server'] = rooms; +} +await client.setAccountData( + client.userID!, + 'm.direct', + dmMap, +); +``` + +--- + +## User-Profil für DM laden + +```dart +// Profil des DM-Partners laden +final partnerMxid = room.directChatMatrixID!; + +// Aus Room-Membership (gecacht, schnell) +final user = room.unsafeGetUserFromMemoryOrFallback(partnerMxid); +print(user.displayName); +print(user.avatarUrl); + +// Frisch vom Server (genauer, aber langsamer) +final profile = await client.getProfileFromUserId(partnerMxid); +print(profile.displayname); +print(profile.avatarUrl); + +// Avatar-URL in Widget verwenden +// (mxc:// URI → HTTP-URL via SDK) +final httpUrl = user.avatarUrl?.getThumbnail( + client, + width: 56, + height: 56, + method: ThumbnailMethod.crop, +); +``` + +--- + +## Verschlüsselung in DMs + +```dart +// E2EE-Status prüfen +final isEncrypted = room.isEncrypted; + +// E2EE aktivieren (einmalig, nicht mehr rückgängig!) +if (!room.isEncrypted) { + await room.enableEncryption(); +} + +// Geräte des Partners verifizieren +final partnerDevices = await client.getUserDeviceKeys('@alice:server'); +for (final device in partnerDevices?.deviceKeys.values ?? []) { + print('${device.deviceId}: verified=${device.verified}'); +} + +// Fehlende Schlüssel für Entschlüsselung anfordern +await client.requestMissingSessionKeys(); + +// Schlechte Verschlüsselung erkennen +final badEvents = timeline.events + .where((e) => e.isBadEncrypted) + .toList(); +``` + +--- + +## Einladungen (DM-Invite-Ansicht) + +```dart +// Eingehende DM-Einladungen +final invites = client.rooms.where((r) => + r.membership == Membership.invite && + r.isDirectChat).toList(); + +// Einladung anzeigen +for (final invite in invites) { + final senderId = invite.getState(EventTypes.RoomMember, client.userID!) + ?.senderId; // Wer hat eingeladen? + final sender = await client.getProfileFromUserId(senderId ?? ''); + print('Einladung von ${sender.displayname}'); + + // Annehmen + await invite.join(); + + // Ablehnen + await invite.leave(); + await invite.forget(); +} +``` diff --git a/docs/matrix-sdk/05-media.md b/docs/matrix-sdk/05-media.md new file mode 100644 index 0000000..9f1750c --- /dev/null +++ b/docs/matrix-sdk/05-media.md @@ -0,0 +1,355 @@ +# 05 — Medien & Dateien + +--- + +## Inhaltsverzeichnis +- [Datei hochladen](#datei-hochladen) +- [Bild senden](#bild-senden) +- [Video senden](#video-senden) +- [Audio / Sprachnachricht senden](#audio--sprachnachricht-senden) +- [Datei senden](#datei-senden) +- [Sticker senden](#sticker-senden) +- [Medien herunterladen & entschlüsseln](#medien-herunterladen--entschlüsseln) +- [Thumbnails & Vorschaubilder](#thumbnails--vorschaubilder) +- [MXC-URL zu HTTP-URL](#mxc-url-zu-http-url) +- [Verschlüsselte Medien](#verschlüsselte-medien) +- [Avatar hochladen](#avatar-hochladen) +- [MatrixFile-Objekte](#matrixfile-objekte) + +--- + +## Datei hochladen + +```dart +// Bytes hochladen → mxc:// URI zurück +final mxcUri = await client.uploadContent( + fileBytes, // Uint8List + filename: 'datei.pdf', + contentType: 'application/pdf', // optional, SDK erkennt es +); +print(mxcUri); // mxc://example.org/AbCdEf... +``` + +--- + +## Bild senden + +```dart +import 'package:matrix/matrix.dart'; + +// MatrixImageFile erstellen +final imageFile = MatrixImageFile( + bytes: imageBytes, // Uint8List + name: 'foto.jpg', + mimeType: 'image/jpeg', + width: 1920, // optional, für Info + height: 1080, +); + +// Mit Thumbnail +final thumbnail = MatrixImageFile( + bytes: thumbnailBytes, + name: 'foto_thumb.jpg', + mimeType: 'image/jpeg', + width: 320, + height: 180, +); + +// Senden (lädt automatisch hoch + sendet m.image Event) +await room.sendFileEvent( + imageFile, + thumbnail: thumbnail, // optional +); + +// Alternativ mit sendImageEvent +await room.sendImageEvent( + imageFile, + thumbnail: thumbnail, +); +``` + +--- + +## Video senden + +```dart +final videoFile = MatrixVideoFile( + bytes: videoBytes, + name: 'video.mp4', + mimeType: 'video/mp4', + duration: 45000, // Millisekunden + width: 1920, + height: 1080, +); + +final thumbFile = MatrixImageFile( + bytes: thumbnailBytes, + name: 'thumb.jpg', + mimeType: 'image/jpeg', + width: 320, + height: 180, +); + +await room.sendVideoEvent( + videoFile, + thumbnail: thumbFile, +); +``` + +--- + +## Audio / Sprachnachricht senden + +```dart +// Audio-Datei +final audioFile = MatrixAudioFile( + bytes: audioBytes, + name: 'aufnahme.ogg', + mimeType: 'audio/ogg', + duration: 12000, // Millisekunden +); + +await room.sendAudioEvent(audioFile); + +// Sprachnachricht (Voice Message MSC3245) +await room.sendFileEvent( + audioFile, + extraContent: { + 'org.matrix.msc3245.voice': {}, // markiert als Sprachnachricht + 'org.matrix.msc1767.audio': { + 'duration': 12000, + 'waveform': [0, 50, 100, 75, ...], // Amplituden (0-1024) + }, + }, +); +``` + +--- + +## Datei senden + +```dart +final file = MatrixFile( + bytes: fileBytes, + name: 'dokument.pdf', + mimeType: 'application/pdf', +); + +await room.sendFileEvent(file); + +// Mit Extra-Metadaten +await room.sendFileEvent( + file, + extraContent: { + 'org.matrix.msc3554.caption': { + 'msgtype': 'm.text', + 'body': 'Hier das Dokument', + }, + }, +); +``` + +--- + +## Sticker senden + +```dart +// Sticker sind ein eigener Event-Typ (m.sticker) +await room.sendEvent( + { + 'body': 'Ein Sticker', + 'url': 'mxc://example.org/stickerId', + 'info': { + 'mimetype': 'image/png', + 'w': 256, + 'h': 256, + }, + }, + EventTypes.Sticker, // 'm.sticker' +); +``` + +--- + +## Medien herunterladen & entschlüsseln + +```dart +// Aus Event-Attachment herunterladen (+ automatisch entschlüsseln bei E2EE) +final data = await event.downloadAndDecryptAttachment( + getThumbnail: false, // true für Thumbnail statt Original +); +// data ist MatrixFile mit .bytes: Uint8List + +// Direkte MXC-URL herunterladen +final bytes = await client.database.getFile(mxcUri); +// oder über HTTP: +final httpUri = mxcUri.getDownloadUri(client); +// → https://homeserver/_matrix/media/v3/download/server/mediaId +``` + +--- + +## Thumbnails & Vorschaubilder + +```dart +// Thumbnail-URL für Widget +final thumbnailUri = event.thumbnailUrl; // mxc:// URI + +// HTTP-URL für Thumbnail (mit Größe) +final httpUrl = thumbnailUri?.getThumbnail( + client, + width: 800, + height: 600, + method: ThumbnailMethod.scale, // oder .crop +); + +// Avatar-Thumbnail +final avatarUrl = user.avatarUrl?.getThumbnail( + client, + width: 56, + height: 56, + method: ThumbnailMethod.crop, +); + +// Im Flutter Widget (CachedNetworkImage o.ä.): +Image.network(httpUrl.toString()); +``` + +--- + +## MXC-URL zu HTTP-URL + +```dart +// Download-URL +final downloadUrl = Uri.parse(mxcUriString).getDownloadUri(client); +// → https://homeserver/_matrix/media/v3/download/server/mediaId + +// Thumbnail-URL +final thumbUrl = Uri.parse(mxcUriString).getThumbnail( + client, + width: 300, + height: 300, + method: ThumbnailMethod.crop, +); + +// Direkt als String +final urlString = downloadUrl.toString(); +``` + +--- + +## Verschlüsselte Medien + +```dart +// In verschlüsselten Räumen werden Medien automatisch verschlüsselt. +// Das SDK übernimmt Ver- und Entschlüsselung transparent. + +// Verschlüsselter Download (automatisch): +final file = await event.downloadAndDecryptAttachment(); +// file.bytes enthält die entschlüsselten Rohdaten + +// Manuell ver-/entschlüsseln (selten nötig): +// Nutze EncryptedFile aus dem matrix-package +final encryptedFile = EncryptedFile( + url: 'mxc://...', + key: {/* JWK */}, + iv: 'base64...', + hashes: {'sha256': 'base64...'}, + v: 'v2', +); +``` + +--- + +## Avatar hochladen + +```dart +// Eigener Avatar +final avatarBytes = await File('avatar.png').readAsBytes(); +final mxcUri = await client.uploadContent( + avatarBytes, + filename: 'avatar.png', + contentType: 'image/png', +); +await client.setAvatarUrl(client.userID!, mxcUri); + +// Raum-Avatar +final roomAvatarMxc = await client.uploadContent(imageBytes, filename: 'room.png'); +await room.setAvatar(roomAvatarMxc); +``` + +--- + +## MatrixFile-Objekte + +```dart +// Basis-Klasse +MatrixFile({ + required Uint8List bytes, + required String name, + String? mimeType, +}) + +// Spezialisierte Unterklassen: +MatrixImageFile({ + required Uint8List bytes, + required String name, + String? mimeType, // z.B. 'image/jpeg' + int? width, + int? height, + bool? animated, // für GIFs +}) + +MatrixVideoFile({ + required Uint8List bytes, + required String name, + String? mimeType, // 'video/mp4' + int? duration, // ms + int? width, + int? height, + MatrixImageFile? thumbnail, +}) + +MatrixAudioFile({ + required Uint8List bytes, + required String name, + String? mimeType, // 'audio/ogg' + int? duration, // ms +}) + +// Eigenschaften +file.bytes // Uint8List +file.name // Dateiname +file.mimeType // MIME-Typ +file.sizeString // '1.4 MB' (formatiert) +file.size // Bytes als int +``` + +--- + +## Medien-Events lesen + +```dart +// Attachment-Info aus Event +if (event.messageType == 'm.image') { + final url = event.attachmentMxcUrl; // mxc:// URI + final mime = event.attachmentMimetype; // 'image/jpeg' + final size = event.attachmentSize; // Bytes + final width = event.infoMap['w'] as int?; + final height = event.infoMap['h'] as int?; +} + +if (event.messageType == 'm.video') { + final duration = event.infoMap['duration'] as int?; // ms +} + +if (event.messageType == 'm.audio') { + final duration = event.infoMap['duration'] as int?; + final waveform = event.content + .tryGetMap('org.matrix.msc1767.audio') + ?.tryGetList('waveform'); +} + +// Datei-Größe als lesbarer String +print(event.sizeString); // '2.3 MB' +``` diff --git a/docs/matrix-sdk/06-encryption.md b/docs/matrix-sdk/06-encryption.md new file mode 100644 index 0000000..a45004c --- /dev/null +++ b/docs/matrix-sdk/06-encryption.md @@ -0,0 +1,313 @@ +# 06 — E2EE Verschlüsselung + +--- + +## Inhaltsverzeichnis +- [Setup & Initialisierung](#setup--initialisierung) +- [Verschlüsselung aktivieren](#verschlüsselung-aktivieren) +- [Entschlüsselung & Fehlerfälle](#entschlüsselung--fehlerfälle) +- [Device-Verifikation (SAS)](#device-verifikation-sas) +- [Cross-Signing](#cross-signing) +- [Key Backup](#key-backup) +- [Fehlende Session Keys anfordern](#fehlende-session-keys-anfordern) +- [Geräte-Keys abfragen](#geräte-keys-abfragen) +- [Trust-Status](#trust-status) + +--- + +## Setup & Initialisierung + +```dart +// flutter_vodozemac muss initialisiert sein BEVOR Client erstellt wird +import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; +await vod.init(); + +// Client mit E2EE-Support +final client = Client( + 'Pyramid', + database: await MatrixSdkDatabase.init('pyramid', database: db), + nativeImplementations: NativeImplementationsIsolate(compute), + // Oder für Hintergrund-Isolaten (kein compute): + // nativeImplementations: NativeImplementationsDummy(), + verificationMethods: { + KeyVerificationMethod.numbers, + KeyVerificationMethod.emoji, + // KeyVerificationMethod.qrCodeScan, // falls QR-Scanner vorhanden + // KeyVerificationMethod.qrCodeShow, + }, +); + +await client.init( + waitForFirstSync: false, + waitUntilLoadCompletedLoaded: false, +); + +// E2EE verfügbar prüfen +print(client.encryptionEnabled); // true wenn Vodozemac/Olm geladen +``` + +--- + +## Verschlüsselung aktivieren + +```dart +// Raum-Verschlüsselung einschalten (PERMANENT, nicht rückgängig!) +if (!room.isEncrypted) { + await room.enableEncryption(); +} + +// Verschlüsselung beim Erstellen aktivieren +final roomId = await client.createRoom( + name: 'Verschlüsselter Raum', + enableEncryption: true, + preset: CreateRoomPreset.privateChat, +); + +// Status prüfen +print(room.isEncrypted); // bool +print(room.encryptionAlgorithm); // 'm.megolm.v1.aes-sha2' +``` + +--- + +## Entschlüsselung & Fehlerfälle + +```dart +// Beim Anzeigen von Events prüfen: +if (event.isBadEncrypted) { + // Anzeigen: "Nachricht kann nicht entschlüsselt werden" + // Mögliche Ursachen: + // - Gerät war nicht in der Raumschlüssel-Verteilung + // - Session fehlt (Megolm Session nicht vorhanden) + // - Falsches Gerät / fehlende Olm-Session +} + +// Entschlüsselungs-Fehler-Typ +if (event.content['can_not_decrypt'] != null) { + // Generischer Fehler +} +if (event.type == EventTypes.Encrypted && event.plaintextContent == null) { + // Noch nicht entschlüsselt +} + +// Event-Body bei Fehler prüfen +final body = event.body; +// Enthält "** Unable to decrypt: ..." bei Fehlern + +// Fehlende Schlüssel anfordern (von anderen Geräten) +await client.requestMissingSessionKeys(); +``` + +--- + +## Device-Verifikation (SAS) + +```dart +// ── Verifikation starten (ich verifiziere ein anderes Gerät) ────────────── + +// Verifikations-Anfrage senden +final request = await client.userDeviceKeys[otherUserId]! + .startVerification(); +// request.onUpdate: Stream mit Zustandsänderungen + +// ── Verifikation empfangen (anderes Gerät will mich verifizieren) ───────── + +// Eingehende Anfragen beobachten +client.onKeyVerificationRequest.stream.listen((request) async { + // Anfrage annehmen + await request.acceptVerification(); +}); + +// ── SAS-Flow ───────────────────────────────────────────────────────────── + +// Auf SAS-Ready warten und Emojis/Zahlen anzeigen +request.onUpdate.stream.listen((_) async { + if (request.state == KeyVerificationState.showSas) { + // Emojis anzeigen + final emojis = request.sasEmojis; // List + for (final emoji in emojis) { + print('${emoji.emoji} ${emoji.name}'); + } + + // Oder Dezimalzahlen + final decimals = request.sasDecimals; // List (3 Zahlen) + print(decimals); // z.B. [1234, 5678, 9012] + + // Wenn User bestätigt dass sie übereinstimmen: + await request.confirmSas(); + + // Wenn sie nicht übereinstimmen: + // await request.rejectSas(); + } + + if (request.state == KeyVerificationState.done) { + print('Verifikation erfolgreich!'); + } + + if (request.state == KeyVerificationState.error) { + print('Verifikation fehlgeschlagen: ${request.cancelCode}'); + } +}); + +// ── QR-Code Verifikation ───────────────────────────────────────────────── + +// QR-Code zum Anzeigen generieren +final qrData = await request.generateQrCodeData(); +// qrData als QR-Code rendern (z.B. mit qr_flutter-Package) + +// Gescannten QR-Code verarbeiten +await request.scanQrCode(scannedData); + +// Bestätigen dass QR gescannt wurde +await request.confirmQrCodeScanned(); +``` + +--- + +## Cross-Signing + +```dart +// Cross-Signing bootstrappen (erstellt Master-, Self- und User-Signing-Keys) +// Nur einmal pro Account nötig +await client.encryption!.bootstrapCrossSigning( + setupMasterKey: true, + setupSelfSigningKey: true, + setupUserSigningKey: true, +); + +// Cross-Signing-Status +final crossSigning = client.encryption!.crossSigning; +print(crossSigning.enabled); // bool +print(crossSigning.selfSigned); // bool: eigenes Gerät ist self-signed + +// Eigenes Gerät ist verifiziert? +final myDevice = client.userDeviceKeys[client.userID] + ?.deviceKeys[client.deviceID]; +print(myDevice?.verified); // bool + +// Anderen User als vertrauenswürdig markieren +await client.encryption!.crossSigning.signUser(otherUserId); + +// Gerät verifizieren (nach SAS/QR) +await myDevice?.setVerified(true); +``` + +--- + +## Key Backup + +```dart +// ── Key Backup einrichten ───────────────────────────────────────────────── + +// Vollständiges Crypto-Setup (empfohlen): +// Erstellt Secret Storage + Cross-Signing + Key Backup +await client.bootstrapCryptoIdentity( + wipeRecovery: false, // true: bestehende Recovery überschreiben +); + +// Nur Key Backup: +final backup = client.encryption!.keyManager; + +// Recovery-Key generieren und anzeigen +final recoveryKey = await client.encryption!.ssss.generateKey(); +print(recoveryKey); // Langer alphanumerischer Schlüssel → User aufschreiben lassen! + +// ── Key Backup Status ───────────────────────────────────────────────────── + +// Ist Key Backup aktiv? +final keyBackupEnabled = client.encryption!.keyManager.enabled; + +// Alle Sessions hochladen +await client.encryption!.keyManager.uploadInboundGroupSessions(); + +// ── Backup wiederherstellen (Recovery) ─────────────────────────────────── + +// Keys von Server-Backup wiederherstellen +await client.encryption!.keyManager.loadFromResponse( + await client.getRoomKeysBackup(), +); + +// Oder mit Recovery-Key: +await client.encryption!.ssss.unlock(recoveryKey: eingabe); +await client.encryption!.keyManager.restore(); +``` + +--- + +## Fehlende Session Keys anfordern + +```dart +// Schlüssel von anderen Geräten desselben Users anfordern +await client.requestMissingSessionKeys(); + +// Für einen spezifischen Raum +await client.requestMissingSessionKeys( + rooms: [room], +); + +// Einzelne Session anfordern (für ein spezifisches Event) +if (event.isBadEncrypted) { + final sessionId = event.content + .tryGet('session_id'); + final senderKey = event.content + .tryGet('sender_key'); + if (sessionId != null) { + await room.requestKey(sessionId); + } +} +``` + +--- + +## Geräte-Keys abfragen + +```dart +// Alle Geräte eines Users laden +final userDevices = await client.getUserDeviceKeys(userId); +// → Map + +// Geräte eines Raums (alle Mitglieder) +final roomDevices = await room.getUserDeviceKeys(); + +// Eigene Geräte +final myDevices = client.userDeviceKeys[client.userID]?.deviceKeys; + +// Gerät-Details +for (final device in myDevices?.values ?? []) { + print(device.deviceId); + print(device.displayName); + print(device.verified); + print(device.blocked); + print(device.ed25519Key); // Signatur-Schlüssel + print(device.curve25519Key); // Encryption-Schlüssel +} + +// Gerät sperren (Nachrichten werden nicht mehr entschlüsselt gesendet) +await myDevices?['DEVICEID']?.setBlocked(true); +``` + +--- + +## Trust-Status + +```dart +// Trust-Level für Raum berechnen +final encryption = room.client.encryption; +if (encryption != null) { + final trust = await room.calcEncryptionHealthState(); + // trust: .allVerified | .unverifiedDevices | .unknown +} + +// User-Trust +final userTrust = client.userDeviceKeys[userId]?.verified; +// null = unbekannt, true = verifiziert, false = blockiert + +// Nachrichten-Verifikation +if (!event.encryptionHealthState.allVerified) { + // Anzeigen: "Gesendet von unverifiziertem Gerät" +} + +// Eigene Identität +final myIdentity = client.encryption?.crossSigning; +print(myIdentity?.selfSigned); // Eigenes Gerät cross-signed? +``` diff --git a/docs/matrix-sdk/07-push.md b/docs/matrix-sdk/07-push.md new file mode 100644 index 0000000..df5c14e --- /dev/null +++ b/docs/matrix-sdk/07-push.md @@ -0,0 +1,291 @@ +# 07 — Push & Benachrichtigungen + +--- + +## Inhaltsverzeichnis +- [Pusher registrieren (FCM)](#pusher-registrieren-fcm) +- [Pusher abrufen & verwalten](#pusher-abrufen--verwalten) +- [Push Rules](#push-rules) +- [onNotification Stream](#onnotification-stream) +- [Lokale Benachrichtigungen (Android)](#lokale-benachrichtigungen-android) +- [Benachrichtigungen: Pyramid-Architektur](#benachrichtigungen-pyramid-architektur) +- [Notification Counts](#notification-counts) + +--- + +## Pusher registrieren (FCM) + +```dart +// FCM-Token holen +import 'package:firebase_messaging/firebase_messaging.dart'; +final fcmToken = await FirebaseMessaging.instance.getToken(); + +// Pusher beim Homeserver registrieren +await client.postPusher( + Pusher( + pushkey: fcmToken!, + kind: 'http', + appId: 'chat.pyramid.pyramid', // Unique App-ID (muss zu Push-Gateway passen) + appDisplayName: 'Pyramid', + deviceDisplayName: 'Mein Android', + lang: 'de', + data: PusherData( + url: Uri.parse('https://push.example.org/_matrix/push/v1/notify'), + format: 'event_id_only', // Empfohlen (nur Event-ID, nicht der Inhalt) + ), + ), + append: true, // Nicht andere Pusher dieses Geräts löschen +); + +// Token-Refresh überwachen +FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async { + await client.postPusher( + Pusher(pushkey: newToken, /* ... */ ), + append: true, + ); +}); +``` + +--- + +## Pusher abrufen & verwalten + +```dart +// Alle Pusher dieses Users +final pushers = await client.getPushers() ?? []; +for (final pusher in pushers) { + print(pusher.appId); + print(pusher.pushkey); + print(pusher.data.url); +} + +// Pusher entfernen +await client.deletePusher( + Pusher( + pushkey: fcmToken, + appId: 'chat.pyramid.pyramid', + kind: 'http', // Pflichtfeld beim Löschen + // ... + ), +); + +// Beim Logout alle Pusher entfernen +final myPushers = (await client.getPushers() ?? []) + .where((p) => p.appId == 'chat.pyramid.pyramid'); +for (final p in myPushers) { + await client.deletePusher(p); +} +``` + +--- + +## Push Rules + +```dart +// Alle Push Rules abrufen +final ruleset = await client.getPushRules(); + +// Globale Regeln +for (final rule in ruleset.global.content ?? []) { + print(rule.ruleId); + print(rule.enabled); + print(rule.actions); +} + +// Kategorien der Regeln: +// .override — höchste Priorität (z.B. DND-Modus) +// .content — Inhalt-basiert (z.B. eigener Name erwähnt) +// .room — Raum-spezifisch +// .sender — Sender-spezifisch +// .underride — niedrigste Priorität (Fallback) + +// Push Rule aktivieren/deaktivieren +await client.setPushRuleEnabled( + 'global', + PushRuleKind.override, + '.m.rule.master', // DND: stumm schalten + false, // false = Regel deaktivieren +); + +// Eigene Push Rule erstellen (z.B. Raum stumm schalten) +await client.setPushRule( + 'global', + PushRuleKind.room, + '!roomId:server', // RuleId = RoomId für Raum-Regeln + [PushRuleAction.dontNotify], +); + +// Push Rule löschen +await client.deletePushRule( + 'global', + PushRuleKind.room, + '!roomId:server', +); + +// Standard-Rules für Erwähnungen +// Pyramid prüft lokal ob ein Event eine Mention enthält: +final myId = client.userID!; +final mentions = event.content + .tryGetMap('m.mentions') + ?.tryGetList('user_ids') ?? []; +final isMentioned = mentions.contains(myId) || + event.body.contains(myId); + +// Raum stumm schalten +await client.setPushRule( + 'global', + PushRuleKind.override, + '!roomId:server', + [PushRuleAction.dontNotify], + conditions: [ + PushCondition(kind: 'event_match', key: 'room_id', pattern: '!roomId:server'), + ], +); +``` + +--- + +## onNotification Stream + +```dart +// Matrix-SDK emittiert Events die Benachrichtigungen auslösen sollen +// (nach Push-Rule-Matching, entschlüsselt) +client.onNotification.stream.listen((Event event) { + final roomId = event.room.id; + final room = client.getRoomById(roomId)!; + final sender = room.unsafeGetUserFromMemoryOrFallback(event.senderId); + + final title = room.isDirectChat + ? sender.displayName ?? event.senderId + : '${sender.displayName} · ${room.getLocalizedDisplayname()}'; + final body = event.body; + + // Lokale Benachrichtigung anzeigen + showLocalNotification(title, body, roomId); +}); +``` + +--- + +## Lokale Benachrichtigungen (Android) + +```dart +// Siehe auch: lib/core/notification_service.dart und PushService.kt + +// flutter_local_notifications initialisieren +final plugin = FlutterLocalNotificationsPlugin(); +await plugin.initialize( + const InitializationSettings( + android: AndroidInitializationSettings('@drawable/ic_notification'), + ), + onDidReceiveNotificationResponse: _handleNotificationTap, + onDidReceiveBackgroundNotificationResponse: handleBackgroundResponse, +); + +// Notification-Kanal erstellen (Android 8+) +await plugin.resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>() + ?.createNotificationChannel( + const AndroidNotificationChannel( + 'pyramid_messages', + 'Nachrichten', + description: 'Neue Nachrichten', + importance: Importance.high, + ), + ); + +// Benachrichtigung anzeigen (mit Reply-Action) +await plugin.show( + notifId, + 'Absender', + 'Nachrichtentext', + NotificationDetails( + android: AndroidNotificationDetails( + 'pyramid_messages', + 'Nachrichten', + importance: Importance.high, + priority: Priority.high, + icon: '@drawable/ic_notification', + actions: [ + AndroidNotificationAction( + 'reply', 'Antworten', + inputs: [AndroidNotificationActionInput(label: 'Antworten…')], + allowGeneratedReplies: true, + showsUserInterface: false, // BroadcastReceiver-Pfad + ), + AndroidNotificationAction('read', 'Gelesen', + showsUserInterface: false), + ], + ), + ), + payload: roomId, +); + +// Benachrichtigung schließen +await plugin.cancel(notifId); +``` + +--- + +## Benachrichtigungen: Pyramid-Architektur + +``` +FCM-Payload → PushService.kt (Kotlin, kein Dart-Overhead) + │ + ├─ App im Vordergrund? → Heartbeat-Check → Skip + │ + ├─ HTTP-Fetch: Absender + Raumname (ohne Entschlüsselung möglich) + │ + ├─ Native Notification anzeigen: "Neue Nachricht" + │ └─ Reply-Action → getActivity(MainActivity) → onNewIntent + │ + └─ Flutter-Engine im Cache? → MethodChannel "decryptAndUpdateNotification" + └─ Dart: decryptAndUpdateNotification() → showNativeNotification() [mit echtem Text] + +Reply-Flow: + User tippt Antwort → Reply-PendingIntent (getActivity) + → MainActivity.onNewIntent → MethodChannel "replyFromNotification" + → Dart: room.sendTextEvent(text) + → moveTaskToBack(true) +``` + +```dart +// Heartbeat (App aktiv?) setzen: +void _pingHeartbeat() { + SharedPreferences.getInstance().then( + (p) => p.setInt('notif_app_heartbeat', DateTime.now().millisecondsSinceEpoch), + ); +} + +// Heartbeat löschen (App im Hintergrund): +void setAppForeground(bool value) { + if (!value) { + SharedPreferences.getInstance() + .then((p) => p.setInt('notif_app_heartbeat', 0)); + } +} +``` + +--- + +## Notification Counts + +```dart +// Pro Raum +print(room.notificationCount); // Ungelesene Nachrichten +print(room.highlightCount); // Mentions / Highlights + +// Gesamt +final totalUnread = client.rooms.fold( + 0, (sum, r) => sum + r.notificationCount); +final totalHighlights = client.rooms.fold( + 0, (sum, r) => sum + r.highlightCount); + +// Badge für Windows Taskbar +import 'package:windows_taskbar/windows_taskbar.dart'; +if (totalUnread > 0) { + WindowsTaskbar.setProgressMode(TaskbarProgressMode.error); +} else { + WindowsTaskbar.setProgressMode(TaskbarProgressMode.noProgress); +} +``` diff --git a/docs/matrix-sdk/08-voip.md b/docs/matrix-sdk/08-voip.md new file mode 100644 index 0000000..8a24b67 --- /dev/null +++ b/docs/matrix-sdk/08-voip.md @@ -0,0 +1,422 @@ +# 08 — VoIP, Calls & LiveKit (MatrixRTC) + +--- + +## Inhaltsverzeichnis +- [Architektur-Überblick](#architektur-überblick) +- [1:1 Call (Legacy m.call)](#11-call-legacy-mcall) +- [MatrixRTC (Gruppen-Calls)](#matrixrtc-gruppen-calls) +- [LiveKit-Integration](#livekit-integration) +- [Klingel-Flow](#klingel-flow) +- [WebRTC Setup in Flutter](#webrtc-setup-in-flutter) +- [Call-State Management](#call-state-management) +- [Pyramid VoIP-Architektur](#pyramid-voip-architektur) + +--- + +## Architektur-Überblick + +``` +Matrix Signaling (to-device / room events) + │ + ▼ + MatrixRTC Layer + ┌─────────────────────────────────┐ + │ com.famedly.call.member Events │ + │ (Membership, Backend, Expiry) │ + └──────────────┬──────────────────┘ + │ + ┌────────┴────────┐ + │ │ + Mesh (P2P) LiveKit (SFU) + WebRTC direct livekit-server + (1:1, max ~4) (skalierbar, n:m) +``` + +--- + +## 1:1 Call (Legacy m.call) + +```dart +// ── Anruf starten ──────────────────────────────────────────────────────── +// Wird vom SDK über room events (m.call.invite, m.call.candidates, +// m.call.answer, m.call.hangup) signalisiert. + +// Anruf-Einladung senden (nach WebRTC offer) +await room.sendEvent( + { + 'call_id': 'eindeutige-call-id', + 'version': 1, + 'lifetime': 60000, // ms, wie lange das Invite gültig ist + 'offer': { + 'type': 'offer', + 'sdp': sdpString, // WebRTC SDP Offer + }, + }, + EventTypes.CallInvite, // 'm.call.invite' +); + +// ICE-Kandidaten senden +await room.sendEvent( + { + 'call_id': callId, + 'version': 1, + 'candidates': [ + { + 'candidate': 'candidate:...', + 'sdpMid': '0', + 'sdpMLineIndex': 0, + }, + ], + }, + EventTypes.CallCandidates, // 'm.call.candidates' +); + +// Anruf annehmen (SDP Answer) +await room.sendEvent( + { + 'call_id': callId, + 'version': 1, + 'answer': { + 'type': 'answer', + 'sdp': sdpAnswerString, + }, + }, + EventTypes.CallAnswer, // 'm.call.answer' +); + +// Auflegen +await room.sendEvent( + { + 'call_id': callId, + 'version': 1, + 'reason': 'user_hangup', // oder 'ice_failed', 'invite_timeout' + }, + EventTypes.CallHangup, // 'm.call.hangup' +); + +// Ablehnen (Reject) +await room.sendEvent( + { + 'call_id': callId, + 'version': 1, + 'reason': 'user_hangup', + }, + EventTypes.CallReject, // 'm.call.reject' +); + +// Eingehende Anrufe überwachen +client.onCallInvite.stream.listen((CallInvite invite) { + print('Eingehender Anruf von ${invite.roomId}'); + print('Call-ID: ${invite.callId}'); +}); +``` + +--- + +## MatrixRTC (Gruppen-Calls) + +```dart +// MatrixRTC verwendet com.famedly.call.member State-Events + +// ── Call beitreten (Membership senden) ─────────────────────────────────── + +final myDeviceId = client.deviceID!; +final callId = room.id; // Normalerweise = Raum-ID + +// Membership-Event senden (signalisiert "ich bin im Call") +await room.client.sendState( + room.id, + 'org.matrix.msc3401.call.member', // oder 'com.famedly.call.member' + { + 'application': 'm.call', + 'call_id': callId, + 'device_id': myDeviceId, + 'expires_ts': DateTime.now() + .add(const Duration(hours: 1)) + .millisecondsSinceEpoch, + 'backend': { + 'type': 'm.sfu', // LiveKit + 'livekit_service_url': 'https://livekit.example.org', + }, + // Für Mesh: + // 'backend': {'type': 'm.mesh'}, + 'membershipID': 'eindeutige-membership-id', + }, + stateKey: '$myDeviceId:$callId', +); + +// ── Call verlassen (Membership entfernen) ───────────────────────────────── + +await room.client.sendState( + room.id, + 'org.matrix.msc3401.call.member', + {}, // Leeres Content = Austritt + stateKey: '$myDeviceId:$callId', +); + +// ── Aktive Call-Mitglieder auflesen ────────────────────────────────────── + +final callStates = room.states['org.matrix.msc3401.call.member']; +final now = DateTime.now().millisecondsSinceEpoch; +final activeMembers = callStates?.values.where((event) { + final expiresTs = event.content['expires_ts'] as int? ?? 0; + return expiresTs > now; // Nicht abgelaufen +}).toList() ?? []; + +for (final member in activeMembers) { + print(member.content['device_id']); + print(member.stateKey); // 'deviceId:callId' +} +``` + +--- + +## LiveKit-Integration + +```dart +// LiveKit-Token vom Matrix-Homeserver anfragen (OpenID) +// Dieser Flow authentifiziert den User beim LiveKit-Server ohne eigenes Passwort. + +// 1. OpenID-Token vom Homeserver holen +final openIdToken = await client.requestOpenIdToken(client.userID!); +// openIdToken.accessToken, .matrixServerName + +// 2. LiveKit-Token beim MatrixRTC-Service tauschen +// (Pyramid sendet openIdToken an livekit_service_url des Raums) +final response = await http.post( + Uri.parse('https://livekit-service.example.org/sfu/get'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'room': room.id, + 'openid_token': { + 'access_token': openIdToken.accessToken, + 'token_type': 'Bearer', + 'matrix_server_name': openIdToken.matrixServerName, + }, + 'device_id': client.deviceID, + }), +); +final livekitToken = jsonDecode(response.body)['token']; + +// 3. Mit LiveKit verbinden +import 'package:livekit_client/livekit_client.dart'; +final room = await LiveKitClient.connect( + 'wss://livekit.example.org', + livekitToken, + roomOptions: const RoomOptions( + adaptiveStream: true, + dynacast: true, + defaultVideoPublishOptions: VideoPublishOptions( + simulcast: true, + ), + ), +); + +// 4. Mikrofon aktivieren +await room.localParticipant?.setMicrophoneEnabled(true); + +// 5. Kamera aktivieren (Video-Call) +await room.localParticipant?.setCameraEnabled(true); + +// 6. Teilnehmer observieren +room.addListener(() { + for (final participant in room.participants.values) { + print(participant.identity); // Matrix User-ID + for (final track in participant.videoTracks) { + // Widget: VideoTrackRenderer(track.track!) + } + } +}); +``` + +--- + +## Klingel-Flow + +```dart +// ── Anruf initiieren ────────────────────────────────────────────────────── + +// 1. Membership-Event senden (MatrixRTC) +// 2. To-Device-Event senden für Push-Benachrichtigung beim Empfänger + +// Klingelanruf via to-device-Event +await client.sendToDevice( + 'com.famedly.call', // Event-Typ + { + otherUserId: { + '*': { // Alle Geräte des Users + 'call_id': callId, + 'room_id': room.id, + 'type': 'invite', + 'sender_session_id': client.deviceID, + }, + }, + }, +); + +// ── Eingehenden Anruf empfangen ─────────────────────────────────────────── + +client.onToDeviceEvent.stream + .where((e) => e.type == 'com.famedly.call') + .listen((event) { + final callId = event.content['call_id']; + final roomId = event.content['room_id']; + final type = event.content['type']; // 'invite' | 'hangup' + // Klingelton abspielen, UI anzeigen +}); + +// ── Anruf ablehnen (während Klingeln) ──────────────────────────────────── + +await client.sendToDevice( + 'com.famedly.call', + { + callerId: {'*': {'call_id': callId, 'type': 'reject'}}, + }, +); +``` + +--- + +## WebRTC Setup in Flutter + +```dart +// flutter_webrtc Package +import 'package:flutter_webrtc/flutter_webrtc.dart'; + +// Media-Stream holen +final stream = await navigator.mediaDevices.getUserMedia({ + 'audio': true, + 'video': false, // true für Video-Call +}); + +// PeerConnection erstellen +final pc = await createPeerConnection({ + 'iceServers': [ + {'urls': 'stun:stun.matrix.org:3478'}, + // TURN-Server (für NAT-Traversal): + { + 'urls': 'turn:turn.example.org:5349', + 'username': 'user', + 'credential': 'pass', + }, + ], + 'iceCandidatePoolSize': 10, +}); + +// Track hinzufügen +for (final track in stream.getTracks()) { + await pc.addTrack(track, stream); +} + +// ICE-Kandidaten sammeln +pc.onIceCandidate = (RTCIceCandidate candidate) { + // Kandidaten via Matrix senden + sendIceCandidates([candidate]); +}; + +// Angebot erstellen +final offer = await pc.createOffer(); +await pc.setLocalDescription(offer); +// offer.sdp → via Matrix senden + +// Angebot annehmen +await pc.setRemoteDescription(RTCSessionDescription(sdpOffer, 'offer')); +final answer = await pc.createAnswer(); +await pc.setLocalDescription(answer); +// answer.sdp → via Matrix senden + +// Eingehende Streams +pc.onTrack = (RTCTrackEvent event) { + final remoteStream = event.streams.first; + // Widget: RTCVideoRenderer() mit remoteStream +}; + +// Aufräumen +await pc.close(); +await stream.dispose(); +``` + +--- + +## Call-State Management + +```dart +// Call-Zustand in Pyramid +enum CallState { + idle, + calling, // Anruf geht raus + ringing, // Eingehender Anruf + connecting, // ICE/SDP in Bearbeitung + connected, // Verbunden + ended, +} + +// Stummschalten +final audioTrack = localStream.getAudioTracks().first; +audioTrack.enabled = false; // Mute +audioTrack.enabled = true; // Unmute + +// Lautsprecher vs. Hörer (Android/iOS) +// flutter_webrtc kümmert sich darum via Helper.setSpeakerphoneOn + +// DTMF (Zifferntasten) +final sender = pc.getSenders().firstWhere( + (s) => s.track?.kind == 'audio'); +await sender.dtmf?.insertDTMF('1'); + +// Screen-Sharing starten +final screenStream = await navigator.mediaDevices.getDisplayMedia({ + 'video': true, + 'audio': false, +}); +final screenTrack = screenStream.getVideoTracks().first; +final videoSender = pc.getSenders() + .firstWhere((s) => s.track?.kind == 'video'); +await videoSender.replaceTrack(screenTrack); +``` + +--- + +## Pyramid VoIP-Architektur + +``` +Pyramid Call-Stack: +┌─────────────────────────────────────────────────────┐ +│ Dart (Flutter) │ +│ lib/features/call/ │ +│ call_notifier.dart — Zustand, Aktionen │ +│ call_page.dart — UI (Kamera/Mic Controls) │ +│ livekit_service.dart — LiveKit-Token-Tausch │ +├─────────────────────────────────────────────────────┤ +│ Matrix SDK │ +│ room.sendState(com.famedly.call.member) │ +│ client.sendToDevice(com.famedly.call) │ +│ client.requestOpenIdToken() │ +├─────────────────────────────────────────────────────┤ +│ LiveKit Client (livekit_client package) │ +│ LiveKitClient.connect(url, token) │ +│ room.localParticipant.setMicrophoneEnabled() │ +│ VideoTrackRenderer Widget │ +├─────────────────────────────────────────────────────┤ +│ Native (Android/iOS) │ +│ FlutterForegroundService — hält Call am Leben │ +│ Klingelton via AudioManager │ +└─────────────────────────────────────────────────────┘ + +TURN/STUN-Server Konfiguration (from Matrix): +await client.getTurnServer() → + TurnServerCredentials( + username, password, ttl, + uris: ['turn:turn.example.org:5349?transport=udp'] + ) +``` + +```dart +// TURN-Credentials vom Homeserver holen +final turn = await client.getTurnServer(); +final iceServers = [ + {'urls': turn.uris, 'username': turn.username, 'credential': turn.password}, + {'urls': 'stun:stun.matrix.org:3478'}, +]; +``` diff --git a/docs/matrix-sdk/08b-livekit-streaming.md b/docs/matrix-sdk/08b-livekit-streaming.md new file mode 100644 index 0000000..50c26b8 --- /dev/null +++ b/docs/matrix-sdk/08b-livekit-streaming.md @@ -0,0 +1,1487 @@ +# 08b — LiveKit Streaming: Vollständige Implementierungsanleitung + +> **Ziel:** Echtzeit Audio/Video-Calls und Screen-Sharing in Pyramid via LiveKit SFU, +> authentifiziert über MatrixRTC (Matrix-Standard), selbst gehostet auf dem Raspberry Pi. + +--- + +## Inhaltsverzeichnis +- [Architektur-Überblick](#architektur-überblick) +- [Selbst-gehostete Infrastruktur](#selbst-gehostete-infrastruktur) +- [LiveKit-Server Setup (Raspberry Pi)](#livekit-server-setup-raspberry-pi) +- [LiveKit JWT Service (lk-jwt-service)](#livekit-jwt-service-lk-jwt-service) +- [Synapse MatrixRTC Konfiguration](#synapse-matrixrtc-konfiguration) +- [TURN-Server Setup (coturn)](#turn-server-setup-coturn) +- [Nginx Reverse-Proxy](#nginx-reverse-proxy) +- [Flutter: LiveKit-Paket & Abhängigkeiten](#flutter-livekit-paket--abhängigkeiten) +- [MatrixRTC Membership Flow (Signaling)](#matrixrtc-membership-flow-signaling) +- [LiveKit-Token holen (OpenID-Austausch)](#livekit-token-holen-openid-austausch) +- [LiveKit Room verbinden](#livekit-room-verbinden) +- [Audio-Call implementieren](#audio-call-implementieren) +- [Video-Call implementieren](#video-call-implementieren) +- [Screen-Sharing implementieren](#screen-sharing-implementieren) +- [Klingel-System (Ringing)](#klingel-system-ringing) +- [Call-State-Management (Riverpod)](#call-state-management-riverpod) +- [Call-UI Komponenten](#call-ui-komponenten) +- [Hintergrund-Service (Android)](#hintergrund-service-android) +- [Komplettes Dart-Implementierungs-Template](#komplettes-dart-implementierungs-template) +- [Troubleshooting & Diagnose](#troubleshooting--diagnose) + +--- + +## Architektur-Überblick + +``` +┌─────────────────────────────────────────────────────────────────┐ +│ Pyramid App (Flutter) │ +│ │ +│ MatrixRTC Signaling LiveKit Media │ +│ ┌──────────────────┐ ┌─────────────────────┐ │ +│ │ Matrix SDK │ │ livekit_client pkg │ │ +│ │ - call.member │ │ - Audio/Video tracks │ │ +│ │ state events │ │ - Screen share │ │ +│ │ - to-device msgs │ │ - Data channels │ │ +│ └──────┬───────────┘ └──────────┬──────────┘ │ +│ │ │ │ +└─────────┼────────────────────────────────┼──────────────────────┘ + │ HTTPS/WSS │ WSS (WebSocket Secure) + ▼ ▼ +┌─────────────────────┐ ┌──────────────────────────────┐ +│ Synapse (Matrix HS)│ │ LiveKit Server (SFU) │ +│ matrix.steggi- │ │ livekit.steggi-matrix.work │ +│ matrix.work │ │ Port: 7880 (HTTPS/WS) │ +│ │ │ Port: 7881 (TURN/TLS) │ +│ OpenID Token API │ │ Port: 50100-50200 (UDP RTP) │ +└────────┬────────────┘ └───────────────┬──────────────┘ + │ OpenID Token │ + ▼ │ +┌────────────────────┐ │ +│ lk-jwt-service │───────── JWT Token ───────┘ +│ (Token Exchange) │ +│ Port: 8080 │ +└────────────────────┘ + │ + ▼ +┌────────────────────┐ +│ coturn (TURN) │ +│ Port: 3478 UDP │ +│ Port: 5349 TLS │ +└────────────────────┘ + +Nginx Reverse Proxy (Port 443): + /livekit/ → LiveKit :7880 + /lk-jwt/ → lk-jwt-service :8080 + (coturn läuft direkt auf 3478/5349) +``` + +--- + +## Selbst-gehostete Infrastruktur + +### Benötigte Komponenten + +| Dienst | Zweck | Port | Software | +|--------|-------|------|----------| +| **LiveKit Server** | SFU — verteilt Media-Streams | 7880 (WS/HTTP), 7881 (TURN/TLS), 50100-50200 UDP | `livekit/livekit-server` | +| **lk-jwt-service** | Token-Austausch OpenID → LiveKit JWT | 8080 | `element-hq/lk-jwt-service` | +| **coturn** | TURN-Server für NAT-Traversal | 3478 UDP, 5349 TLS | `coturn` | +| **Nginx** | Reverse Proxy + SSL-Termination | 443 | `nginx` | +| **Synapse** | Matrix Homeserver (bereits vorhanden) | 8448 | ✓ läuft | + +### DNS-Einträge (Beispiel für steggi-matrix.work) +``` +livekit.steggi-matrix.work A +turn.steggi-matrix.work A +``` + +--- + +## LiveKit-Server Setup (Raspberry Pi) + +### Installation + +```bash +# LiveKit Binary herunterladen (ARM64 für Raspberry Pi 4/5) +curl -sSL https://get.livekit.io | bash +# oder manuell: +wget https://github.com/livekit/livekit/releases/latest/download/livekit_linux_arm64.tar.gz +tar xzf livekit_linux_arm64.tar.gz +sudo mv livekit-server /usr/local/bin/ + +# API-Key und Secret generieren +livekit-server generate-keys +# Ausgabe: +# API Key: APIxxxxxxxxxxxxxxxxxx +# API Secret: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +# → SICHER AUFBEWAHREN! +``` + +### Konfiguration: `/etc/livekit/livekit.yaml` + +```yaml +port: 7880 +bind_addresses: + - "" # Alle Interfaces + +# API-Schlüssel (aus generate-keys) +keys: + APIxxxxxxxxxxxxxxxxxx: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + +# WebRTC-Einstellungen +rtc: + tcp_port: 7881 # TURN over TLS + port_range_start: 50100 + port_range_end: 50200 + # Öffentliche IP des Raspberry Pi (wichtig für NAT!) + use_external_ip: true + # STUN-Server für ICE (externe Erreichbarkeit prüfen) + stun_servers: + - stun:stun.l.google.com:19302 + +# TURN eingebaut (LiveKit kann selbst TURN machen) +turn: + enabled: true + domain: livekit.steggi-matrix.work + tls_port: 5349 # TURN über TLS + udp_port: 3478 + +# Logging +logging: + level: info + pion_level: error # WebRTC-interne Logs reduzieren + +# Redis (optional, für Cluster — beim Pi nicht nötig) +# redis: +# address: localhost:6379 +``` + +### Systemd Service: `/etc/systemd/system/livekit.service` + +```ini +[Unit] +Description=LiveKit SFU Server +After=network.target +Wants=network-online.target + +[Service] +Type=simple +User=livekit +Group=livekit +ExecStart=/usr/local/bin/livekit-server --config /etc/livekit/livekit.yaml +Restart=on-failure +RestartSec=5 +LimitNOFILE=65536 + +# Logs +StandardOutput=journal +StandardError=journal + +[Install] +WantedBy=multi-user.target +``` + +```bash +# User anlegen und Service aktivieren +sudo useradd -r -s /bin/false livekit +sudo systemctl daemon-reload +sudo systemctl enable livekit +sudo systemctl start livekit +sudo systemctl status livekit + +# Logs verfolgen +sudo journalctl -u livekit -f +``` + +--- + +## LiveKit JWT Service (lk-jwt-service) + +Dieser Service tauscht Matrix OpenID-Tokens gegen LiveKit JWTs aus. +Das ist die **Brücke zwischen Matrix-Authentifizierung und LiveKit**. + +### Installation + +```bash +# Go installieren (falls nicht vorhanden) +# Für Raspberry Pi (ARM64): +wget https://go.dev/dl/go1.22.0.linux-arm64.tar.gz +sudo tar -C /usr/local -xzf go1.22.0.linux-arm64.tar.gz +export PATH=$PATH:/usr/local/go/bin + +# lk-jwt-service bauen +git clone https://github.com/element-hq/lk-jwt-service +cd lk-jwt-service +go build -o lk-jwt-service . +sudo mv lk-jwt-service /usr/local/bin/ +``` + +### Konfiguration: `/etc/lk-jwt-service/config.yaml` + +```yaml +# LiveKit-Verbindung +livekit_url: wss://livekit.steggi-matrix.work +livekit_key: APIxxxxxxxxxxxxxxxxxx # selber Key wie in livekit.yaml +livekit_secret: xxxxxxxxxxxxxxxxxxxxx # selbes Secret + +# Matrix-Homeserver für OpenID-Validierung +matrix_server: https://matrix.steggi-matrix.work + +# Welche Matrix-Homeserver dürfen den Service nutzen +allowed_matrix_servers: + - steggi-matrix.work + +# Server-Port +port: 8080 +``` + +### Systemd Service: `/etc/systemd/system/lk-jwt-service.service` + +```ini +[Unit] +Description=LiveKit JWT Token Service for MatrixRTC +After=network.target livekit.service + +[Service] +Type=simple +User=livekit +ExecStart=/usr/local/bin/lk-jwt-service --config /etc/lk-jwt-service/config.yaml +Restart=on-failure +RestartSec=5 + +[Install] +WantedBy=multi-user.target +``` + +```bash +sudo systemctl enable lk-jwt-service +sudo systemctl start lk-jwt-service +``` + +### API-Endpoint des lk-jwt-service + +``` +POST /sfu/get +Content-Type: application/json + +{ + "room": "!roomId:server", + "openid_token": { + "access_token": "...", ← von client.requestOpenIdToken() + "token_type": "Bearer", + "matrix_server_name": "steggi-matrix.work" + }, + "device_id": "PYRAMID_DEVICE_ID" +} + +Antwort: +{ + "url": "wss://livekit.steggi-matrix.work", + "jwt": "eyJ..." ← LiveKit JWT Token +} +``` + +--- + +## Synapse MatrixRTC Konfiguration + +In der Synapse-Konfiguration (`homeserver.yaml`): + +```yaml +# MatrixRTC / LiveKit Integration +experimental_features: + msc3401_enabled: true # MatrixRTC Group Calls + msc4140_enabled: true # Delayed events (für Membership-Cleanup) + +# Erlaubt das Senden von com.famedly.call.member State-Events +rc_message: + per_second: 100 + burst_count: 200 + +# LiveKit-Service URL im .well-known bekannt machen (MSC4143) +# → client kann automatisch den richtigen JWT-Service finden +``` + +### `.well-known/matrix/client` erweitern + +Nginx liefert diese JSON-Datei. Ergänze LiveKit-Info: + +```json +{ + "m.homeserver": { + "base_url": "https://matrix.steggi-matrix.work" + }, + "org.matrix.msc4143.rtc_foci": [ + { + "type": "livekit", + "livekit_service_url": "https://livekit.steggi-matrix.work/lk-jwt" + } + ] +} +``` + +--- + +## TURN-Server Setup (coturn) + +LiveKit hat einen eingebauten TURN-Server, aber coturn als Fallback ist empfohlen. + +```bash +sudo apt install coturn -y +``` + +### `/etc/turnserver.conf` + +```conf +# Listening +listening-port=3478 +tls-listening-port=5349 +listening-ip=0.0.0.0 + +# Externe IP (Raspberry Pi öffentliche IP) +external-ip= + +# Realm +realm=turn.steggi-matrix.work +server-name=turn.steggi-matrix.work + +# TLS-Zertifikate (Let's Encrypt) +cert=/etc/letsencrypt/live/turn.steggi-matrix.work/fullchain.pem +pkey=/etc/letsencrypt/live/turn.steggi-matrix.work/privkey.pem + +# Auth (shared secret für Matrix) +use-auth-secret +static-auth-secret=ZUFAELLIGES_LANGES_GEHEIMNIS_HIER + +# Relay-Ports +min-port=49152 +max-port=65535 + +# Sicherheit +no-multicast-peers +no-loopback-peers +denied-peer-ip=10.0.0.0-10.255.255.255 +denied-peer-ip=192.168.0.0-192.168.255.255 +denied-peer-ip=172.16.0.0-172.31.255.255 + +# Logging +log-file=/var/log/turnserver.log +``` + +```bash +# TURN-Service aktivieren +sudo systemctl enable coturn +sudo systemctl start coturn + +# Synapse: TURN-Credentials bekannt machen (in homeserver.yaml) +turn_uris: + - "turn:turn.steggi-matrix.work:3478?transport=udp" + - "turn:turn.steggi-matrix.work:3478?transport=tcp" + - "turns:turn.steggi-matrix.work:5349?transport=tcp" +turn_shared_secret: "ZUFAELLIGES_LANGES_GEHEIMNIS_HIER" +turn_user_lifetime: 86400000 +turn_allow_guests: false +``` + +--- + +## Nginx Reverse-Proxy + +```nginx +# /etc/nginx/sites-available/livekit.steggi-matrix.work + +server { + listen 443 ssl http2; + server_name livekit.steggi-matrix.work; + + ssl_certificate /etc/letsencrypt/live/livekit.steggi-matrix.work/fullchain.pem; + ssl_certificate_key /etc/letsencrypt/live/livekit.steggi-matrix.work/privkey.pem; + + # LiveKit WebSocket + HTTP API + location / { + proxy_pass http://localhost:7880; + proxy_http_version 1.1; + proxy_set_header Upgrade $http_upgrade; + proxy_set_header Connection "upgrade"; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header X-Forwarded-Proto $scheme; + proxy_read_timeout 3600s; + proxy_send_timeout 3600s; + proxy_buffering off; + client_max_body_size 0; + } + + # lk-jwt-service (Token-Austausch) + location /lk-jwt/ { + rewrite ^/lk-jwt/(.*) /$1 break; + proxy_pass http://localhost:8080; + proxy_set_header Host $host; + proxy_set_header X-Real-IP $remote_addr; + add_header 'Access-Control-Allow-Origin' '*' always; + add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always; + add_header 'Access-Control-Allow-Headers' 'Authorization, Content-Type' always; + } +} + +# HTTP → HTTPS Redirect +server { + listen 80; + server_name livekit.steggi-matrix.work; + return 301 https://$host$request_uri; +} +``` + +```bash +sudo nginx -t && sudo nginx -s reload +``` + +### Firewall-Regeln + +```bash +# UFW +sudo ufw allow 443/tcp # HTTPS (LiveKit + lk-jwt) +sudo ufw allow 3478/udp # TURN UDP +sudo ufw allow 3478/tcp # TURN TCP +sudo ufw allow 5349/tcp # TURNS TLS +sudo ufw allow 7881/tcp # LiveKit TURN/TLS (eingebaut) +sudo ufw allow 50100:50200/udp # RTP Media Ports + +# Für Raspberry Pi hinter Router: Port-Forwarding nötig! +# Im Router: alle oben genannten Ports → Pi-interne IP weiterleiten +``` + +--- + +## Flutter: LiveKit-Paket & Abhängigkeiten + +### `pubspec.yaml` + +```yaml +dependencies: + livekit_client: ^2.4.0 # LiveKit Flutter SDK + flutter_webrtc: ^0.10.0 # WebRTC (wird von livekit_client benötigt) + permission_handler: ^11.0.0 # Mikrofon/Kamera-Berechtigung + wakelock_plus: ^1.0.0 # Screen während Call aktiv halten + + # Bereits vorhanden: + matrix: ^6.x.x + flutter_riverpod: ^2.x.x +``` + +### Android: `android/app/src/main/AndroidManifest.xml` + +```xml + + + + + + + + + + + + + + + + + + + +``` + +### iOS: `ios/Runner/Info.plist` + +```xml +NSCameraUsageDescription +Pyramid benötigt die Kamera für Video-Calls +NSMicrophoneUsageDescription +Pyramid benötigt das Mikrofon für Audio-Calls +``` + +--- + +## MatrixRTC Membership Flow (Signaling) + +MatrixRTC verwendet State-Events im Raum um anzuzeigen, wer im Call ist. + +```dart +// lib/features/call/matrixrtc_service.dart + +const kCallMemberEventType = 'org.matrix.msc3401.call.member'; + +class MatrixRtcMembership { + final String roomId; + final String deviceId; + final String callId; + final String livekitServiceUrl; + + MatrixRtcMembership({ + required this.roomId, + required this.deviceId, + required this.callId, + required this.livekitServiceUrl, + }); + + // ── Call beitreten: Membership-Event senden ──────────────────────────── + + Future join(Client matrixClient) async { + final expiresTs = DateTime.now() + .add(const Duration(hours: 4)) + .millisecondsSinceEpoch; + + await matrixClient.sendState( + roomId, + kCallMemberEventType, + { + 'application': 'm.call', + 'call_id': callId, + 'device_id': deviceId, + 'expires_ts': expiresTs, + 'membershipID': '${deviceId}_${DateTime.now().millisecondsSinceEpoch}', + 'backend': { + 'type': 'livekit', + 'livekit_service_url': livekitServiceUrl, + }, + }, + stateKey: '$deviceId:$callId', + ); + } + + // ── Call verlassen: Membership entfernen ─────────────────────────────── + + Future leave(Client matrixClient) async { + await matrixClient.sendState( + roomId, + kCallMemberEventType, + {}, // Leer = Austritt + stateKey: '$deviceId:$callId', + ); + } + + // ── Aktive Mitglieder auflisten ─────────────────────────────────────── + + static List> getActiveMembers(Room room, String callId) { + final states = room.states[kCallMemberEventType] ?? {}; + final now = DateTime.now().millisecondsSinceEpoch; + return states.values + .where((e) { + final content = e.content; + return content['call_id'] == callId && + (content['expires_ts'] as int? ?? 0) > now && + content.isNotEmpty; + }) + .map((e) => Map.from(e.content)) + .toList(); + } + + // ── Auf Membership-Änderungen hören ────────────────────────────────── + + static Stream watchCallMembers(Client client, String roomId) { + return client.onSync.stream + .where((update) { + final rooms = update.rooms?.join; + if (rooms == null) return false; + final roomUpdate = rooms[roomId]; + return roomUpdate?.state?.events?.any( + (e) => e.type == kCallMemberEventType) ?? false; + }) + .map((_) {}); + } +} +``` + +--- + +## LiveKit-Token holen (OpenID-Austausch) + +```dart +// lib/features/call/livekit_service.dart + +import 'dart:convert'; +import 'package:http/http.dart' as http; +import 'package:matrix/matrix.dart'; + +class LiveKitService { + static const String _jwtServicePath = '/lk-jwt/sfu/get'; + + /// Tauscht ein Matrix OpenID-Token gegen einen LiveKit JWT. + /// [livekitServiceUrl] kommt aus dem MatrixRTC-Membership-Event des Raums. + static Future getToken({ + required Client matrixClient, + required String roomId, + required String livekitServiceUrl, + }) async { + // 1. OpenID-Token vom Homeserver holen + final openIdToken = await matrixClient.requestOpenIdToken( + matrixClient.userID!, + ); + + // 2. JWT beim lk-jwt-service tauschen + final serviceUrl = Uri.parse(livekitServiceUrl).resolve(_jwtServicePath); + final response = await http.post( + serviceUrl, + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'room': roomId, + 'openid_token': { + 'access_token': openIdToken.accessToken, + 'token_type': 'Bearer', + 'matrix_server_name': openIdToken.matrixServerName, + }, + 'device_id': matrixClient.deviceID, + }), + ).timeout(const Duration(seconds: 10)); + + if (response.statusCode != 200) { + throw Exception( + 'lk-jwt-service Fehler ${response.statusCode}: ${response.body}'); + } + + final data = jsonDecode(response.body) as Map; + return LiveKitCredentials( + url: data['url'] as String, + jwt: data['jwt'] as String, + ); + } +} + +class LiveKitCredentials { + final String url; // wss://livekit.steggi-matrix.work + final String jwt; // LiveKit JWT Token + + const LiveKitCredentials({required this.url, required this.jwt}); +} +``` + +--- + +## LiveKit Room verbinden + +```dart +// lib/features/call/livekit_room_manager.dart + +import 'package:livekit_client/livekit_client.dart'; + +class LiveKitRoomManager { + Room? _room; + EventsListener? _listener; + + Room get room => _room!; + bool get isConnected => _room?.connectionState == ConnectionState.connected; + + Future connect({ + required String url, + required String token, + bool audioEnabled = true, + bool videoEnabled = false, + }) async { + _room = Room( + roomOptions: RoomOptions( + adaptiveStream: true, // Qualität automatisch anpassen + dynacast: true, // Inaktive Streams pausieren + defaultAudioPublishOptions: const AudioPublishOptions( + name: 'microphone', + audioBitrate: 24000, // 24 kbps — gut für Sprache + ), + defaultVideoPublishOptions: VideoPublishOptions( + simulcast: true, // Mehrere Qualitätsstufen senden + videoEncoding: VideoEncoding( + maxBitrate: 1200 * 1000, // 1.2 Mbps max + maxFramerate: 30, + ), + ), + defaultScreenShareCaptureOptions: const ScreenShareCaptureOptions( + useiOSBroadcastExtension: true, + params: VideoParameters( + dimensions: VideoDimensions(1920, 1080), + encoding: VideoEncoding(maxBitrate: 3 * 1000 * 1000, maxFramerate: 15), + ), + ), + defaultCameraCaptureOptions: CameraCaptureOptions( + cameraPosition: CameraPosition.front, + params: VideoParameters( + dimensions: VideoDimensions(1280, 720), + encoding: VideoEncoding(maxBitrate: 1200 * 1000, maxFramerate: 30), + ), + ), + ), + ); + + _listener = _room!.createListener(); + + try { + await _room!.connect(url, token, + connectOptions: const ConnectOptions( + autoSubscribe: true, // Alle Tracks automatisch empfangen + rtcConfig: RTCConfiguration( + iceTransportPolicy: RTCIceTransportPolicy.all, + ), + ), + ); + + // Mikrofon aktivieren + if (audioEnabled) { + await _room!.localParticipant?.setMicrophoneEnabled(true); + } + // Kamera aktivieren + if (videoEnabled) { + await _room!.localParticipant?.setCameraEnabled(true); + } + } catch (e) { + await _room?.dispose(); + _room = null; + rethrow; + } + } + + Future disconnect() async { + await _room?.localParticipant?.setMicrophoneEnabled(false); + await _room?.localParticipant?.setCameraEnabled(false); + await _room?.disconnect(); + await _room?.dispose(); + _room = null; + } + + // Event-Listener + void onParticipantConnected(void Function(RemoteParticipant) callback) { + _listener?.on( + (event) => callback(event.participant)); + } + + void onParticipantDisconnected(void Function(RemoteParticipant) callback) { + _listener?.on( + (event) => callback(event.participant)); + } + + void onTrackPublished( + void Function(RemoteParticipant, RemoteTrackPublication) callback) { + _listener?.on((event) => + callback(event.participant, event.publication)); + } + + void onTrackSubscribed( + void Function(Track, TrackPublication, RemoteParticipant) callback) { + _listener?.on( + (event) => callback(event.track, event.publication, event.participant)); + } +} +``` + +--- + +## Audio-Call implementieren + +```dart +// lib/features/call/call_notifier.dart (Audio-Call) + +import 'package:permission_handler/permission_handler.dart'; + +Future startAudioCall({ + required Client matrixClient, + required String roomId, +}) async { + // 1. Berechtigung anfordern + final status = await Permission.microphone.request(); + if (!status.isGranted) throw Exception('Mikrofon-Berechtigung verweigert'); + + // 2. LiveKit-Service-URL aus Raum-Metadaten holen (oder Default) + const livekitServiceUrl = 'https://livekit.steggi-matrix.work'; + + // 3. MatrixRTC Membership senden + final callId = roomId; // Convention: callId = roomId + final membership = MatrixRtcMembership( + roomId: roomId, + deviceId: matrixClient.deviceID!, + callId: callId, + livekitServiceUrl: livekitServiceUrl, + ); + await membership.join(matrixClient); + + // 4. LiveKit-Token holen + final credentials = await LiveKitService.getToken( + matrixClient: matrixClient, + roomId: roomId, + livekitServiceUrl: livekitServiceUrl, + ); + + // 5. Mit LiveKit verbinden (nur Audio) + final manager = LiveKitRoomManager(); + await manager.connect( + url: credentials.url, + token: credentials.jwt, + audioEnabled: true, + videoEnabled: false, + ); + + // 6. Screen aktiv halten + WakelockPlus.enable(); +} + +// Stummschalten +Future setMuted(LiveKitRoomManager manager, bool muted) async { + await manager.room.localParticipant?.setMicrophoneEnabled(!muted); +} + +// Lautsprecher umschalten (Android) +Future setSpeakerOn(bool speakerOn) async { + await Helper.setSpeakerphoneOn(speakerOn); +} +``` + +--- + +## Video-Call implementieren + +```dart +// Widget: Lokale Kamera-Vorschau +class LocalVideoView extends StatelessWidget { + final LocalParticipant participant; + const LocalVideoView({required this.participant, super.key}); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: participant.trackPublicationsNotifier, + builder: (ctx, _) { + final videoPub = participant.videoTrackPublications + .where((p) => p.source == TrackSource.camera) + .firstOrNull; + if (videoPub?.track case final VideoTrack track) { + return VideoTrackRenderer(track); + } + return const SizedBox(); + }, + ); + } +} + +// Widget: Remote-Teilnehmer Video +class RemoteVideoView extends StatelessWidget { + final RemoteParticipant participant; + const RemoteVideoView({required this.participant, super.key}); + + @override + Widget build(BuildContext context) { + return StreamBuilder( + stream: participant.trackPublicationsNotifier, + builder: (ctx, _) { + final videoPub = participant.videoTrackPublications + .where((p) => + p.source == TrackSource.camera || + p.source == TrackSource.screenShareVideo) + .firstOrNull; + if (videoPub?.track case final VideoTrack track) { + return VideoTrackRenderer(track, fit: RTCVideoViewObjectFit.contain); + } + return Container( + color: Colors.black87, + child: const Center( + child: Icon(Icons.person, size: 80, color: Colors.white38), + ), + ); + }, + ); + } +} + +// Kamera ein-/ausschalten +Future toggleCamera(Room room) async { + final enabled = room.localParticipant?.isCameraEnabled() ?? false; + await room.localParticipant?.setCameraEnabled(!enabled); +} + +// Kamera wechseln (Vorder-/Rückkamera) +Future switchCamera(Room room) async { + final cameraPub = room.localParticipant?.videoTrackPublications + .where((p) => p.source == TrackSource.camera) + .firstOrNull; + if (cameraPub?.track case final LocalVideoTrack track) { + await track.switchCamera(); + } +} +``` + +--- + +## Screen-Sharing implementieren + +```dart +// Android: benötigt MediaProjection-Foreground-Service + +// Screen-Sharing starten +Future startScreenShare(Room room) async { + // Android: MediaProjection-Berechtigung anfordern (System-Dialog) + await room.localParticipant?.setScreenShareEnabled( + true, + captureScreenAudio: true, // Audio mitschneiden + ); +} + +// Screen-Sharing beenden +Future stopScreenShare(Room room) async { + await room.localParticipant?.setScreenShareEnabled(false); +} + +// Android Foreground Service für Screen-Sharing +// android/app/src/main/kotlin/chat/pyramid/pyramid/ScreenShareService.kt: +/* +class ScreenShareService : Service() { + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + val notification = NotificationCompat.Builder(this, "call_channel") + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("Bildschirm wird geteilt") + .setContentText("Pyramid teilt deinen Bildschirm") + .build() + startForeground(NOTIF_ID, notification, + ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION) + return START_STICKY + } + companion object { const val NOTIF_ID = 2001 } +} +*/ +``` + +--- + +## Klingel-System (Ringing) + +```dart +// lib/features/call/ringing_service.dart + +// ── Anruf ankündigen (to-device Event) ───────────────────────────────── + +Future ringUser({ + required Client matrixClient, + required String targetUserId, + required String roomId, + required String callId, +}) async { + await matrixClient.sendToDevice( + 'com.famedly.call', // Event-Typ (wie element/fluffychat) + { + targetUserId: { + '*': { // Alle Geräte des Users + 'call_id': callId, + 'room_id': roomId, + 'type': 'invite', + 'sender_session_id': matrixClient.deviceID, + 'sender_name': matrixClient.displayName, + 'version': 1, + }, + }, + }, + ); +} + +// ── Klingeln abbrechen ──────────────────────────────────────────────── + +Future cancelRing({ + required Client matrixClient, + required String targetUserId, + required String callId, +}) async { + await matrixClient.sendToDevice( + 'com.famedly.call', + { + targetUserId: { + '*': {'call_id': callId, 'type': 'hangup', 'reason': 'user_hangup'}, + }, + }, + ); +} + +// ── Eingehende to-device Events abhören ────────────────────────────── + +StreamSubscription listenForIncomingCalls( + Client matrixClient, void Function(IncomingCall) onCall) { + return matrixClient.onToDeviceEvent.stream + .where((e) => e.type == 'com.famedly.call') + .listen((event) { + final type = event.content['type'] as String?; + final callId = event.content['call_id'] as String?; + final roomId = event.content['room_id'] as String?; + if (type == 'invite' && callId != null && roomId != null) { + onCall(IncomingCall( + callId: callId, + roomId: roomId, + callerId: event.senderId, + senderName: event.content['sender_name'] as String?, + )); + } + if (type == 'hangup') { + // Klingeln beenden (Anruf abgebrochen) + } + }); +} + +class IncomingCall { + final String callId; + final String roomId; + final String callerId; + final String? senderName; + const IncomingCall({ + required this.callId, + required this.roomId, + required this.callerId, + this.senderName, + }); +} +``` + +--- + +## Call-State-Management (Riverpod) + +```dart +// lib/features/call/call_provider.dart + +enum CallState { idle, calling, ringing, connecting, connected, ended, failed } +enum CallType { audio, video } + +@immutable +class CallStateData { + final CallState state; + final CallType type; + final String? roomId; + final String? callId; + final bool isMuted; + final bool isCameraOff; + final bool isSpeakerOn; + final bool isScreenSharing; + final List participants; + + const CallStateData({ + this.state = CallState.idle, + this.type = CallType.audio, + this.roomId, + this.callId, + this.isMuted = false, + this.isCameraOff = false, + this.isSpeakerOn = false, + this.isScreenSharing = false, + this.participants = const [], + }); + + CallStateData copyWith({ + CallState? state, + CallType? type, + String? roomId, + String? callId, + bool? isMuted, + bool? isCameraOff, + bool? isSpeakerOn, + bool? isScreenSharing, + List? participants, + }) => CallStateData( + state: state ?? this.state, + type: type ?? this.type, + roomId: roomId ?? this.roomId, + callId: callId ?? this.callId, + isMuted: isMuted ?? this.isMuted, + isCameraOff: isCameraOff ?? this.isCameraOff, + isSpeakerOn: isSpeakerOn ?? this.isSpeakerOn, + isScreenSharing: isScreenSharing ?? this.isScreenSharing, + participants: participants ?? this.participants, + ); +} + +class CallNotifier extends StateNotifier { + final Ref _ref; + LiveKitRoomManager? _manager; + MatrixRtcMembership? _membership; + + CallNotifier(this._ref) : super(const CallStateData()); + + Future startCall(String roomId, CallType type) async { + state = state.copyWith(state: CallState.calling, type: type, roomId: roomId); + try { + final client = await _ref.read(matrixClientProvider.future); + final callId = roomId; + const livekitServiceUrl = 'https://livekit.steggi-matrix.work'; + + _membership = MatrixRtcMembership( + roomId: roomId, deviceId: client.deviceID!, + callId: callId, livekitServiceUrl: livekitServiceUrl, + ); + await _membership!.join(client); + + final credentials = await LiveKitService.getToken( + matrixClient: client, roomId: roomId, livekitServiceUrl: livekitServiceUrl, + ); + + _manager = LiveKitRoomManager(); + state = state.copyWith(state: CallState.connecting, callId: callId); + + await _manager!.connect( + url: credentials.url, + token: credentials.jwt, + audioEnabled: true, + videoEnabled: type == CallType.video, + ); + + _manager!.onParticipantConnected((p) { + state = state.copyWith(participants: [...state.participants, p]); + }); + _manager!.onParticipantDisconnected((p) { + state = state.copyWith( + participants: state.participants.where((x) => x.sid != p.sid).toList(), + ); + }); + + WakelockPlus.enable(); + state = state.copyWith(state: CallState.connected); + } catch (e) { + await _cleanup(); + state = state.copyWith(state: CallState.failed); + } + } + + Future hangUp() async { + final client = await _ref.read(matrixClientProvider.future); + await _membership?.leave(client); + await _cleanup(); + state = const CallStateData(state: CallState.ended); + await Future.delayed(const Duration(seconds: 1)); + state = const CallStateData(); + } + + Future toggleMute() async { + final muted = !state.isMuted; + await _manager?.room.localParticipant?.setMicrophoneEnabled(!muted); + state = state.copyWith(isMuted: muted); + } + + Future toggleCamera() async { + final off = !state.isCameraOff; + await _manager?.room.localParticipant?.setCameraEnabled(!off); + state = state.copyWith(isCameraOff: off); + } + + Future toggleSpeaker() async { + final on = !state.isSpeakerOn; + await Helper.setSpeakerphoneOn(on); + state = state.copyWith(isSpeakerOn: on); + } + + Future toggleScreenShare() async { + final sharing = !state.isScreenSharing; + if (_manager != null) { + await _manager!.room.localParticipant?.setScreenShareEnabled(sharing); + } + state = state.copyWith(isScreenSharing: sharing); + } + + Future _cleanup() async { + await _manager?.disconnect(); + _manager = null; + WakelockPlus.disable(); + } +} + +final callProvider = StateNotifierProvider( + (ref) => CallNotifier(ref), +); +``` + +--- + +## Call-UI Komponenten + +```dart +// lib/features/call/call_page.dart + +class CallPage extends ConsumerWidget { + const CallPage({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final call = ref.watch(callProvider); + final notifier = ref.read(callProvider.notifier); + + return Scaffold( + backgroundColor: Colors.black, + body: SafeArea( + child: Stack( + children: [ + // ── Haupt-Video (Remote Participant) ────────────────────── + if (call.participants.isNotEmpty) + Positioned.fill( + child: RemoteVideoView(participant: call.participants.first), + ) + else + const Center( + child: Icon(Icons.person, size: 120, color: Colors.white24), + ), + + // ── Lokale Kamera (klein, Overlay) ──────────────────────── + if (call.type == CallType.video) + Positioned( + right: 16, top: 16, + width: 120, height: 180, + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: _LocalPreview(), + ), + ), + + // ── Status-Text ─────────────────────────────────────────── + Positioned( + top: 24, left: 0, right: 0, + child: Text( + _statusText(call.state), + textAlign: TextAlign.center, + style: const TextStyle(color: Colors.white, fontSize: 18), + ), + ), + + // ── Call-Controls ───────────────────────────────────────── + Positioned( + bottom: 40, left: 0, right: 0, + child: Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + _CallButton( + icon: call.isMuted ? Icons.mic_off : Icons.mic, + label: call.isMuted ? 'Ton an' : 'Stumm', + color: call.isMuted ? Colors.red : Colors.white24, + onTap: notifier.toggleMute, + ), + _CallButton( + icon: Icons.call_end, + label: 'Auflegen', + color: Colors.red, + size: 72, + onTap: notifier.hangUp, + ), + if (call.type == CallType.video) + _CallButton( + icon: call.isCameraOff + ? Icons.videocam_off + : Icons.videocam, + label: 'Kamera', + color: call.isCameraOff ? Colors.red : Colors.white24, + onTap: notifier.toggleCamera, + ) + else + _CallButton( + icon: call.isSpeakerOn + ? Icons.volume_up + : Icons.volume_down, + label: 'Lautsprecher', + color: Colors.white24, + onTap: notifier.toggleSpeaker, + ), + ], + ), + ), + ], + ), + ), + ); + } + + String _statusText(CallState state) => switch (state) { + CallState.calling => 'Verbinde…', + CallState.connecting => 'Verbinde…', + CallState.connected => 'Verbunden', + CallState.ended => 'Aufgelegt', + CallState.failed => 'Fehler', + _ => '', + }; +} + +class _CallButton extends StatelessWidget { + final IconData icon; + final String label; + final Color color; + final double size; + final VoidCallback onTap; + + const _CallButton({ + required this.icon, required this.label, + required this.color, required this.onTap, + this.size = 56, + }); + + @override + Widget build(BuildContext context) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + GestureDetector( + onTap: onTap, + child: CircleAvatar( + radius: size / 2, + backgroundColor: color, + child: Icon(icon, color: Colors.white, size: size * 0.5), + ), + ), + const SizedBox(height: 6), + Text(label, style: const TextStyle(color: Colors.white70, fontSize: 12)), + ], + ); +} +``` + +--- + +## Hintergrund-Service (Android) + +```kotlin +// android/app/src/main/kotlin/chat/pyramid/pyramid/CallForegroundService.kt + +package chat.pyramid.pyramid + +import android.app.Notification +import android.app.NotificationChannel +import android.app.NotificationManager +import android.app.Service +import android.content.Intent +import android.os.Build +import android.os.IBinder +import androidx.core.app.NotificationCompat + +class CallForegroundService : Service() { + + override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { + when (intent?.action) { + ACTION_START -> startCallNotification() + ACTION_STOP -> stopSelf() + } + return START_STICKY + } + + private fun startCallNotification() { + ensureChannel() + val notification = NotificationCompat.Builder(this, CHANNEL_ID) + .setSmallIcon(R.drawable.ic_notification) + .setContentTitle("Pyramid — Aktiver Anruf") + .setContentText("Tippe um zum Anruf zurückzukehren") + .setOngoing(true) + .setPriority(NotificationCompat.PRIORITY_HIGH) + .build() + + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + startForeground(NOTIF_ID, notification, + android.content.pm.ServiceInfo.FOREGROUND_SERVICE_TYPE_MICROPHONE) + } else { + startForeground(NOTIF_ID, notification) + } + } + + private fun ensureChannel() { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + val channel = NotificationChannel( + CHANNEL_ID, "Anrufe", NotificationManager.IMPORTANCE_HIGH) + (getSystemService(NOTIFICATION_SERVICE) as NotificationManager) + .createNotificationChannel(channel) + } + } + + override fun onBind(intent: Intent?): IBinder? = null + + companion object { + const val ACTION_START = "START_CALL" + const val ACTION_STOP = "STOP_CALL" + const val CHANNEL_ID = "pyramid_calls" + const val NOTIF_ID = 1001 + } +} +``` + +```dart +// Dart: Service starten/stoppen +import 'package:flutter/services.dart'; + +const _callChannel = MethodChannel('chat.pyramid.pyramid/call'); + +Future startCallService() async { + if (!Platform.isAndroid) return; + await _callChannel.invokeMethod('startCallService'); +} + +Future stopCallService() async { + if (!Platform.isAndroid) return; + await _callChannel.invokeMethod('stopCallService'); +} +``` + +--- + +## Troubleshooting & Diagnose + +### Server-Tests + +```bash +# LiveKit-Server erreichbar? +curl https://livekit.steggi-matrix.work/ + +# lk-jwt-service erreichbar? +curl -X POST https://livekit.steggi-matrix.work/lk-jwt/sfu/get \ + -H 'Content-Type: application/json' \ + -d '{"room":"!test:server","openid_token":{"access_token":"test","token_type":"Bearer","matrix_server_name":"steggi-matrix.work"},"device_id":"TEST"}' +# Erwartete Antwort: {"url":"wss://...","jwt":"eyJ..."} + +# TURN-Server Test (stuncheck) +pip install stun-client +python -c "import stun; print(stun.get_ip_info())" + +# LiveKit Logs +sudo journalctl -u livekit -f +# lk-jwt-service Logs +sudo journalctl -u lk-jwt-service -f + +# UDP-Port-Reichbarkeit (von außen) +nmap -sU -p 50100-50110 +``` + +### Häufige Probleme + +| Problem | Ursache | Lösung | +|---------|---------|--------| +| `ICE failed` | UDP-Ports gesperrt | TURN aktivieren, Firewall prüfen | +| Token-Fehler 401 | OpenID-Validierung schlägt fehl | Matrix-Server-URL in lk-jwt-service prüfen | +| `WebSocket closed` | Nginx-Proxy-Timeout | `proxy_read_timeout 3600s` in Nginx | +| Kein Audio | Mikrofon-Berechtigung | `Permission.microphone.request()` | +| `Room not found` | LiveKit-Key falsch | API-Key in livekit.yaml = lk-jwt-service Config | +| Kein Video | Kamera gesperrt | `Permission.camera.request()` | +| Call fällt nach 4h ab | `expires_ts` zu niedrig | Bei 30min vor Ablauf Membership erneuern | + +### Dart-Diagnose-Tool + +```dart +Future> diagnoseLiveKit(Client client, String roomId) async { + final results = {}; + + // 1. OpenID-Token + try { + await client.requestOpenIdToken(client.userID!); + results['openid_token'] = true; + } catch (_) { results['openid_token'] = false; } + + // 2. JWT-Service erreichbar + try { + final r = await http.get( + Uri.parse('https://livekit.steggi-matrix.work/')); + results['livekit_reachable'] = r.statusCode < 500; + } catch (_) { results['livekit_reachable'] = false; } + + // 3. Token-Austausch + try { + await LiveKitService.getToken( + matrixClient: client, + roomId: roomId, + livekitServiceUrl: 'https://livekit.steggi-matrix.work', + ); + results['token_exchange'] = true; + } catch (_) { results['token_exchange'] = false; } + + return results; +} +``` diff --git a/docs/matrix-sdk/09-profile.md b/docs/matrix-sdk/09-profile.md new file mode 100644 index 0000000..f517945 --- /dev/null +++ b/docs/matrix-sdk/09-profile.md @@ -0,0 +1,264 @@ +# 09 — Profil, Präsenz & Account-Daten + +--- + +## Inhaltsverzeichnis +- [Eigenes Profil lesen](#eigenes-profil-lesen) +- [Profil aktualisieren](#profil-aktualisieren) +- [Profil anderer User](#profil-anderer-user) +- [Präsenz (Presence)](#präsenz-presence) +- [Account-Daten (Account Data)](#account-daten-account-data) +- [Ignorierte User](#ignorierte-user) +- [Tags / Favoriten](#tags--favoriten) +- [Account löschen / deaktivieren](#account-löschen--deaktivieren) + +--- + +## Eigenes Profil lesen + +```dart +// Aus dem Client (gecacht) +print(client.userID); // '@alice:server' +print(client.displayName); // 'Alice' +print(client.avatarUrl); // mxc://... + +// Frisch vom Server +final profile = await client.fetchOwnProfile(); +print(profile.displayname); +print(profile.avatarUrl); + +// Avatar als HTTP-URL +final avatarHttp = client.avatarUrl?.getThumbnail( + client, + width: 128, + height: 128, + method: ThumbnailMethod.crop, +); +``` + +--- + +## Profil aktualisieren + +```dart +// Displayname setzen +await client.setDisplayName(client.userID!, 'Neuer Name'); + +// Avatar hochladen und setzen +final avatarBytes = await File('avatar.png').readAsBytes(); +final mxcUri = await client.uploadContent( + avatarBytes, + filename: 'avatar.png', + contentType: 'image/png', +); +await client.setAvatarUrl(client.userID!, mxcUri); + +// Avatar entfernen +await client.setAvatarUrl(client.userID!, null); +``` + +--- + +## Profil anderer User + +```dart +// Profil via API +final profile = await client.getProfileFromUserId('@bob:server'); +print(profile.displayname); +print(profile.avatarUrl); + +// Spezifisches Feld (Matrix 1.16+ API) +final displayname = await client.getProfileField( + '@bob:server', + 'displayname', +); +final avatar = await client.getProfileField( + '@bob:server', + 'avatar_url', +); + +// User in einem Raum (schneller, gecacht) +final user = room.unsafeGetUserFromMemoryOrFallback('@bob:server'); +print(user.displayName); +print(user.avatarUrl); +print(user.id); + +// User-Suche +final results = await client.searchUserDirectory( + 'alice', + limit: 20, +); +for (final user in results.results) { + print(user.userId); + print(user.displayName); + print(user.avatarUrl); +} +``` + +--- + +## Präsenz (Presence) + +```dart +// Eigene Präsenz setzen +await client.setPresence( + client.userID!, + PresenceType.online, // .online | .unavailable | .offline + statusMsg: 'Im Meeting', // Optionaler Status-Text +); + +// Präsenz anderer User abrufen +final presence = await client.fetchCurrentPresence('@bob:server'); +print(presence.presence); // PresenceType +print(presence.currentlyActive); // bool? +print(presence.statusMsg); // String? +print(presence.lastActiveAgo); // int? (Millisekunden seit letzter Aktivität) + +// Präsenz aus Raum-Mitglieder +final user = room.unsafeGetUserFromMemoryOrFallback('@bob:server'); +// Präsenz wird nicht direkt im User gecacht — fetchCurrentPresence nötig + +// Präsenz-Anzeige im UI +String getPresenceText(PresenceType? type, int? lastActiveAgo) { + switch (type) { + case PresenceType.online: return 'Online'; + case PresenceType.unavailable: + return 'Abwesend'; + case PresenceType.offline: + if (lastActiveAgo != null) { + final mins = lastActiveAgo ~/ 60000; + if (mins < 60) return 'Vor $mins Min. aktiv'; + final hours = mins ~/ 60; + if (hours < 24) return 'Vor $hours Std. aktiv'; + return 'Vor ${hours ~/ 24} Tagen aktiv'; + } + return 'Offline'; + default: return ''; + } +} +``` + +--- + +## Account-Daten (Account Data) + +```dart +// Account-Daten sind private, servergespeicherte Einstellungen. +// Bleiben über Geräte hinweg synchron. + +// Lesen +final data = client.accountData['com.example.my_setting']?.content; + +// Schreiben +await client.setAccountData( + client.userID!, + 'com.example.my_setting', + {'key': 'value', 'enabled': true}, +); + +// Wichtige Standard-Account-Daten: +// 'm.direct' → DM-Raumliste +// 'm.push_rules' → Push-Regel-Overrides +// 'm.ignored_user_list' → Ignorierte User +// 'm.identity_server' → Identity-Server-URL +// 'im.vector.setting.breadcrumbs' → FluffyChat letzte Räume + +// Raumspezifische Account-Daten +await client.setRoomAccountData( + client.userID!, + '!roomId:server', + 'm.fully_read', + {'event_id': eventId}, +); + +// Tag für Raum setzen (Favorit, Low-Priority) +await client.setRoomTag( + client.userID!, + '!roomId:server', + 'm.favourite', + TagContent(order: 0.5), +); +await client.setRoomTag(client.userID!, '!roomId:server', 'm.lowpriority', TagContent()); +await client.deleteRoomTag(client.userID!, '!roomId:server', 'm.favourite'); +``` + +--- + +## Ignorierte User + +```dart +// User ignorieren +final ignoredList = client.ignoredUsers; // List +final updated = [...ignoredList, '@spammer:server']; +await client.setAccountData( + client.userID!, + 'm.ignored_user_list', + {'ignored_users': Map.fromIterable(updated, value: (_) => {})}, +); + +// User entblockieren +final filtered = ignoredList.where((id) => id != '@spammer:server').toList(); +await client.setAccountData( + client.userID!, + 'm.ignored_user_list', + {'ignored_users': Map.fromIterable(filtered, value: (_) => {})}, +); + +// Ignorierte User abrufen +final ignored = client.ignoredUsers; // automatisch aus Account-Data +``` + +--- + +## Tags / Favoriten + +```dart +// Raum als Favorit markieren +await room.addTag('m.favourite', order: 0.1); + +// Raum als Low-Priority markieren +await room.addTag('m.lowpriority'); + +// Alle Tags eines Raums +final tags = room.tags; // Map +final isFavourite = tags.containsKey('m.favourite'); +final isLowPriority = tags.containsKey('m.lowpriority'); + +// Tag entfernen +await room.removeTag('m.favourite'); + +// Eigene Tags +await room.addTag('com.example.myapp.tag', order: 0.5); + +// Räume nach Tag filtern +final favourites = client.rooms + .where((r) => r.tags.containsKey('m.favourite')) + .toList(); +``` + +--- + +## Account löschen / deaktivieren + +```dart +// Account deaktivieren (PERMANENT, nicht rückgängig!) +await client.uiaRequestBackground( + (auth) => client.deactivateAccount( + auth: auth, + eraseData: true, // true: alle Nachrichten löschen (soweit möglich) + ), +); + +// Passwort ändern (braucht Re-Auth via UIAA) +await client.uiaRequestBackground( + (auth) => client.changePassword( + 'neuesPasswort', + auth: auth, + oldPassword: 'altesPasswort', + ), +); + +// E-Mail-Adresse hinzufügen (über Identity-Server) +// Dies ist ein mehrstufiger UIAA-Flow und erfordert E-Mail-Bestätigung. +// Normalerweise über den Homeserver-spezifischen Registration-Flow. +``` diff --git a/docs/matrix-sdk/10-room-admin.md b/docs/matrix-sdk/10-room-admin.md new file mode 100644 index 0000000..e3515a8 --- /dev/null +++ b/docs/matrix-sdk/10-room-admin.md @@ -0,0 +1,410 @@ +# 10 — Raum-Administration & Moderation + +--- + +## Inhaltsverzeichnis +- [Power Levels vollständig](#power-levels-vollständig) +- [Moderation: Kick, Ban, Unban](#moderation-kick-ban-unban) +- [Server-Side Room Admin](#server-side-room-admin) +- [Raum-Einstellungen komplett](#raum-einstellungen-komplett) +- [Raum-Alias verwalten](#raum-alias-verwalten) +- [Server ACL (IP-Sperren)](#server-acl-ip-sperren) +- [Raum-Audit / State inspizieren](#raum-audit--state-inspizieren) +- [Widgets / Bots verwalten](#widgets--bots-verwalten) +- [Room Tombstone / Upgrade](#room-tombstone--upgrade) +- [Reporting (Melden)](#reporting-melden) + +--- + +## Power Levels vollständig + +```dart +// Power Level eines Users ändern +await room.setPower('@alice:server', 50); // 0=User, 50=Mod, 100=Admin + +// Alle Power Levels auf einmal setzen +await room.client.sendState( + room.id, + EventTypes.RoomPowerLevels, + { + // Welche Power-Level für Standard-Aktionen benötigt werden: + 'ban': 50, + 'kick': 50, + 'invite': 0, + 'redact': 50, + 'events_default': 0, // Nachrichten senden + 'state_default': 50, // State-Events ändern + + // Spezifische Event-Typen: + 'events': { + 'm.room.name': 50, + 'm.room.topic': 50, + 'm.room.avatar': 50, + 'm.room.power_levels': 100, + 'm.room.canonical_alias': 50, + 'm.room.history_visibility': 100, + 'm.room.encryption': 100, + 'm.space.child': 50, + }, + + // User-Overrides: + 'users': { + '@admin:server': 100, + '@moderator:server': 50, + }, + 'users_default': 0, // Alle anderen User + 'notifications': { + 'room': 50, // @room mention power level + }, + }, + stateKey: '', +); + +// Power Level lesen +final plContent = room.getState(EventTypes.RoomPowerLevels)?.content; +final usersMap = plContent?.tryGetMap('users') ?? {}; +final adminPl = usersMap['@alice:server'] as int? ?? 0; + +// Berechtigungen prüfen +room.ownPowerLevel; // int: eigener PL +room.getPowerLevelByUserId('@alice:server'); // int +room.canBan; // bool +room.canKick; // bool +room.canInvite; // bool +room.canRedactEvent(event); // bool +room.canSendEvent(EventTypes.Message); // bool +room.canSendEvent(EventTypes.RoomName); // bool +room.canChangeStateEvent(EventTypes.RoomTopic); // bool +room.canChangeNameAndTopic; // bool +room.canChangeJoinRules; // bool +room.canChangeHistoryVisibility; // bool +``` + +--- + +## Moderation: Kick, Ban, Unban + +```dart +// Kick (User wird entfernt, kann wieder beitreten) +await room.kick('@alice:server', reason: 'Verstoß gegen Regeln'); + +// Ban (User kann nicht mehr beitreten) +await room.ban('@alice:server', reason: 'Dauerhafter Ausschluss'); + +// Unban +await room.unban('@alice:server'); + +// Alle gebannten User anzeigen +final bannedMembers = room.getParticipants( + membershipFilter: [Membership.ban], +); + +// Eigene Berechtigungen prüfen vor Moderation-Aktionen +if (room.canKick) { + await room.kick(userId); +} +if (room.canBan) { + await room.ban(userId); +} + +// User-PL prüfen (kann man diesen User kicken/bannen?) +// Man kann nur User mit niedrigerem PL als dem eigenen moderieren. +final theirPl = room.getPowerLevelByUserId(userId); +final myPl = room.ownPowerLevel; +final canModerate = myPl > theirPl; +``` + +--- + +## Server-Side Room Admin + +> ⚠️ **Pyramid läuft auf Continuwuity** — Synapse Admin API (`/_synapse/admin/`) **existiert nicht!** +> Für vollständige Continuwuity-Admin-Dokumentation: **[→ 13-server-admin-continuwuity.md](13-server-admin-continuwuity.md)** + +```dart +// Server-Admin-Status prüfen (Matrix-Standard, funktioniert überall) +final isAdmin = await client.getIsAdmin(); + +// Für Continuwuity: Admin-Aktionen über Standard Matrix Client API +// oder über den Admin-Room (#admins:steggi-matrix.work) + +// Power Level in einem Raum als Admin setzen: +await client.setRoomStateWithKey( + room.id, + EventTypes.RoomPowerLevels, + '', + { + 'users': {'@admin:server': 100}, + 'users_default': 0, + 'state_default': 50, + 'events_default': 0, + 'ban': 50, 'kick': 50, 'invite': 0, 'redact': 50, + }, +); + +// Raum beitreten (Admin kann invite-only-Räume per API beitreten): +await client.joinRoom(room.id); + +// Space-Child-Relation setzen (Channel einem Space hinzufügen): +await client.setRoomStateWithKey( + spaceId, + EventTypes.SpaceChild, + channelRoomId, + {'via': [client.homeserver.host], 'suggested': false}, +); +``` + +```bash +# Continuwuity Admin HTTP API +# Basis: https://server/_conduwuit/admin/v1/ + +# User zu Server-Admin machen: +curl -X POST "https://server/_conduwuit/admin/v1/make_user_admin" \ + -H "Authorization: Bearer TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"user_id": "@admin:server"}' + +# Power Level in Raum setzen (Standard Matrix API, mit Admin-Token): +curl -X PUT "https://server/_matrix/client/v3/rooms/!roomId:server/state/m.room.power_levels/" \ + -H "Authorization: Bearer ADMIN_TOKEN" \ + -H "Content-Type: application/json" \ + -d '{"users": {"@admin:server": 100}, "users_default": 0, "state_default": 50}' + +# Für Synapse (falls Server-Wechsel zu Synapse): +# curl .../server/_synapse/admin/v1/rooms/{roomId} ← dann wieder relevant +``` + +--- + +## Raum-Einstellungen komplett + +```dart +// Name +await room.setName('Neuer Raumname'); + +// Thema +await room.setDescription('Neues Thema'); + +// Avatar +final mxcUri = await client.uploadContent(imageBytes, filename: 'avatar.png'); +await room.setAvatar(mxcUri); + +// Join-Rules +await room.setJoinRules(JoinRules.invite); // Privat +await room.setJoinRules(JoinRules.public); // Öffentlich +await room.setJoinRules(JoinRules.knock); // Beitrittsanfragen + +// Restricted (Nur Space-Mitglieder können beitreten) +await room.setJoinRules( + JoinRules.restricted, + allow: [ + SpaceRoomJoinRulesAllowInner( + roomId: '!spaceId:server', + type: SpaceRoomJoinRulesAllowInnerType.mRoomMembership, + ), + ], +); + +// History-Visibility +await room.setHistoryVisibility(HistoryVisibility.shared); +// .shared = alle sehen vergangene Nachrichten (nach Join) +// .invited = sieht Nachrichten ab dem Einladungs-Zeitpunkt +// .joined = sieht Nachrichten nur ab dem Beitritts-Zeitpunkt +// .worldReadable = öffentlich lesbar (auch ohne Account) + +// Guest Access +await room.setGuestAccess(GuestAccess.canJoin); // Gäste erlaubt +await room.setGuestAccess(GuestAccess.forbidden); // Keine Gäste + +// E2EE aktivieren (einmalig, nicht deaktivierbar!) +await room.enableEncryption(); + +// Notifications für @room: Welcher PL nötig? +// → über Power Levels 'notifications.room' setzen +``` + +--- + +## Raum-Alias verwalten + +```dart +// Alias erstellen +await client.setRoomAlias('#neuer-alias:server', room.id); + +// Kanonischen Alias setzen (sichtbarer Hauptalias) +await room.client.sendState( + room.id, + EventTypes.RoomCanonicalAlias, + { + 'alias': '#hauptalias:server', + 'alt_aliases': ['#alternativ:server'], + }, + stateKey: '', +); + +// Alias auflösen → Raum-ID +final resolved = await client.getRoomIdByAlias('#alias:server'); +print(resolved.roomId); // !roomId:server + +// Alias löschen +await client.deleteRoomAlias('#alter-alias:server'); + +// Alle Aliases eines Raums +final aliases = (room.getState(EventTypes.RoomCanonicalAlias) + ?.content['alt_aliases'] as List?) + ?.cast() ?? []; +final canonical = room.canonicalAlias; +``` + +--- + +## Server ACL (IP-Sperren) + +```dart +// Server ACL: Welche Server dürfen am Raum teilnehmen? +// Wichtig für öffentliche Räume um Spam-Server zu sperren. + +await room.client.sendState( + room.id, + 'm.room.server_acl', + { + 'allow': ['*'], // Alle erlauben + 'deny': ['spam.example.org', '*.badserver.org'], + 'allow_ip_literals': false, // IP-Adressen als Server-Namen verboten + }, + stateKey: '', +); + +// ACL lesen +final acl = room.getState('m.room.server_acl')?.content; +final denied = (acl?['deny'] as List?)?.cast() ?? []; +``` + +--- + +## Raum-Audit / State inspizieren + +```dart +// Alle State-Events lesen +final states = room.states; +// Map> + +// Spezifischer State +final nameEvent = room.getState(EventTypes.RoomName); +final topicEvent = room.getState(EventTypes.RoomTopic); +final memberEvent = room.getState(EventTypes.RoomMember, '@alice:server'); +final encEvent = room.getState(EventTypes.Encryption); + +// Alle Mitglieder-States +final memberStates = states[EventTypes.RoomMember] ?? {}; +for (final entry in memberStates.entries) { + final mxid = entry.key; // stateKey = MXID + final membership = entry.value.content['membership']; + print('$mxid: $membership'); +} + +// Raum-History vom Server laden (Admin) +final response = await client.request( + RequestType.GET, + '/rooms/${room.id}/state', +); + +// Event-Timeline abrufen (Admin) +final timeline = await client.request( + RequestType.GET, + '/rooms/${room.id}/messages', + query: {'limit': '100', 'dir': 'b'}, +); +``` + +--- + +## Widgets / Bots verwalten + +```dart +// Widget hinzufügen (z.B. Jitsi, Etherpad) +await room.client.sendState( + room.id, + 'm.widget', + { + 'type': 'jitsi', + 'url': 'https://jitsi.example.org/#!roomId', + 'name': 'Jitsi Call', + 'data': {'domain': 'jitsi.example.org'}, + 'waitForIframeLoad': true, + 'creatorUserId': client.userID, + 'id': 'jitsi-widget', + }, + stateKey: 'jitsi-widget', +); + +// Widget entfernen +await room.client.sendState( + room.id, + 'm.widget', + {}, // Leeres Content = entfernen + stateKey: 'jitsi-widget', +); + +// Alle Widgets lesen +final widgets = room.states['m.widget'] ?? {}; +for (final widget in widgets.values) { + print(widget.content['name']); + print(widget.content['url']); +} +``` + +--- + +## Room Tombstone / Upgrade + +```dart +// Raum-Upgrade (Nachfolger-Raum erstellen) +final newRoomId = await client.upgradeRoom( + room.id, + newVersion: '11', // Aktuelle empfohlene Version +); +// SDK sendet m.room.tombstone in alten Raum +// Und m.room.create mit predecessor in neuen Raum +// Alle Mitglieder werden in neuen Raum eingeladen + +// Tombstone lesen +final tombstone = room.getState(EventTypes.RoomTombstone); +if (tombstone != null) { + final replacementRoomId = tombstone.content['replacement_room'] as String; + final serverMessage = tombstone.content['body'] as String; + // → Zum neuen Raum navigieren +} + +// Predecessor lesen (im neuen Raum) +final create = room.getState(EventTypes.RoomCreate); +final predecessor = create?.content['predecessor'] as Map?; +if (predecessor != null) { + final oldRoomId = predecessor['room_id'] as String; + final lastEventId = predecessor['event_id'] as String; +} +``` + +--- + +## Reporting (Melden) + +```dart +// Event melden (z.B. Spam, illegaler Inhalt) +await client.reportContent( + room.id, + event.eventId, + reason: 'Spam/Belästigung', + score: -100, // -100 = sehr schlimm, 0 = nicht schlimm +); + +// User melden (via MSC4151, wenn vom Server unterstützt) +await client.httpClient.post( + Uri.parse('${client.homeserver}/_matrix/client/v3/report/${Uri.encodeComponent("@user:server")}'), + headers: { + 'Authorization': 'Bearer ${client.accessToken}', + 'Content-Type': 'application/json', + }, + body: jsonEncode({'reason': 'Belästigung'}), +); +``` diff --git a/docs/matrix-sdk/11-search.md b/docs/matrix-sdk/11-search.md new file mode 100644 index 0000000..0365ed1 --- /dev/null +++ b/docs/matrix-sdk/11-search.md @@ -0,0 +1,238 @@ +# 11 — Suche & Discovery + +--- + +## Inhaltsverzeichnis +- [Nachrichten in einem Raum suchen](#nachrichten-in-einem-raum-suchen) +- [Globale Nachrichten-Suche](#globale-nachrichten-suche) +- [User-Suche](#user-suche) +- [Öffentliches Raumverzeichnis](#öffentliches-raumverzeichnis) +- [Matrix-URI auflösen](#matrix-uri-auflösen) +- [Raum per Alias finden](#raum-per-alias-finden) + +--- + +## Nachrichten in einem Raum suchen + +```dart +// In der lokalen Timeline suchen (gecacht) +final found = timeline.events + .where((e) => + e.type == EventTypes.Message && + e.body.toLowerCase().contains(query.toLowerCase())) + .toList(); + +// Auf dem Server suchen (Matrix-Suchendpoint) +final result = await client.searchEvents( + Categories( + roomEvents: RoomEventsCriteria( + searchTerm: 'suchbegriff', + roomId: room.id, // optional: nur in einem Raum + orderBy: SearchOrder.recent, // oder .rank + keys: [SearchKey.contentBody], // oder .contentName, .contentTopic + filter: RoomEventFilter( + limit: 20, + rooms: [room.id], + notRooms: [], + ), + ), + ), +); + +// Ergebnisse +for (final result in result.roomEvents?.results ?? []) { + print(result.result.body); + print(result.result.originServerTs); + print(result.result.senderId); +} + +// Paginierung +final nextToken = result.roomEvents?.nextBatch; +if (nextToken != null) { + final more = await client.searchEvents( + /* gleiche Criteria */, + nextBatch: nextToken, + ); +} +``` + +--- + +## Globale Nachrichten-Suche + +```dart +// Über alle Räume suchen +final result = await client.searchEvents( + Categories( + roomEvents: RoomEventsCriteria( + searchTerm: 'flutter matrix', + orderBy: SearchOrder.recent, + includeState: false, + groupings: Groupings( + groupBy: [Group(key: GroupKey.roomId)], // Gruppiert nach Raum + ), + ), + ), +); + +// Gruppen-Ergebnisse +for (final entry in result.roomEvents?.groups?.entries ?? []) { + final groupKey = entry.key; // 'room_id' + for (final roomGroup in entry.value.entries) { + final roomId = roomGroup.key; + print('Treffer in $roomId: ${roomGroup.value.count}'); + // roomGroup.value.results: List (Event-IDs) + } +} +``` + +--- + +## User-Suche + +```dart +// User-Verzeichnis durchsuchen +final response = await client.searchUserDirectory( + 'alice', // Suchbegriff (Name oder MXID) + limit: 20, +); + +for (final user in response.results) { + print(user.userId); // @alice:server + print(user.displayName); // Alice + print(user.avatarUrl); // mxc://... + + // Avatar als HTTP-URL + final avatarHttp = user.avatarUrl?.getThumbnail( + client, + width: 56, + height: 56, + method: ThumbnailMethod.crop, + ); +} + +print(response.limited); // true wenn weitere Ergebnisse vorhanden + +// MXID direkt laden (ohne Suche) +final profile = await client.getProfileFromUserId('@alice:server'); +print(profile.displayname); +print(profile.avatarUrl); +``` + +--- + +## Öffentliches Raumverzeichnis + +```dart +// Öffentliche Räume (des eigenen Servers) +final result = await client.queryPublicRooms( + limit: 50, +); + +// Mit Suchbegriff +final searched = await client.queryPublicRooms( + limit: 20, + filter: PublicRoomQueryFilter( + genericSearchTerm: 'flutter', + ), +); + +// Anderen Server durchsuchen +final remote = await client.queryPublicRooms( + server: 'matrix.org', + limit: 20, + filter: PublicRoomQueryFilter(genericSearchTerm: 'linux'), +); + +// Paginierung +var batch = await client.queryPublicRooms(limit: 50); +while (batch.nextBatch != null) { + batch = await client.queryPublicRooms( + limit: 50, + since: batch.nextBatch, + ); +} + +// Einzelnes Ergebnis +for (final room in result.chunk) { + print(room.roomId); + print(room.name); + print(room.topic); + print(room.numJoinedMembers); + print(room.worldReadable); + print(room.guestCanJoin); + print(room.avatarUrl); + print(room.canonicalAlias); + print(room.joinRule); // 'public' | 'knock' | etc. + print(room.roomType); // 'm.space' | null +} +``` + +--- + +## Matrix-URI auflösen + +```dart +// Matrix-to URI parsen +// https://matrix.to/#/@alice:server +// https://matrix.to/#/!roomId:server +// https://matrix.to/#/#alias:server +// matrix:u/alice:server +// matrix:r/alias:server +// matrix:roomid/roomId:server + +import 'package:matrix/matrix.dart'; + +final uri = MatrixUri.parse('https://matrix.to/#/#kanal:example.org'); +if (uri != null) { + switch (uri.primaryType) { + case MatrixUriType.room: // Raum-Alias + case MatrixUriType.roomId: // Raum-ID + case MatrixUriType.user: // User-MXID + case MatrixUriType.event: // Event-Link + } + + final identifier = uri.primaryIdentifier; + // z.B. '#kanal:example.org' oder '!roomId:server' + + // Beitreten (bei Raum) + if (uri.primaryType == MatrixUriType.room || + uri.primaryType == MatrixUriType.roomId) { + await client.joinRoomOrAlias( + identifier, + serverName: uri.viaServers, // föderierte Server + ); + } +} + +// Matrix-URI generieren +final roomUri = MatrixUri( + primaryType: MatrixUriType.roomId, + primaryIdentifier: room.id, + viaServers: ['example.org'], +).toUri().toString(); +// → matrix:roomid/roomId:server?via=example.org + +// Matrix.to Link generieren +final matrixToLink = 'https://matrix.to/#/${Uri.encodeComponent(room.canonicalAlias ?? room.id)}'; +``` + +--- + +## Raum per Alias finden + +```dart +// Alias → Raum-ID auflösen +final result = await client.getRoomIdByAlias('#alias:server'); +print(result.roomId); +print(result.servers); // Via-Server für Beitritt + +// Direkt beitreten via Alias +await client.joinRoomOrAlias('#alias:server'); + +// Lokal prüfen (gecacht) +final localRoom = client.rooms.firstWhere( + (r) => r.canonicalAlias == '#alias:server', + orElse: () => throw Exception('Nicht gefunden'), +); +``` diff --git a/docs/matrix-sdk/12-quick-reference.md b/docs/matrix-sdk/12-quick-reference.md new file mode 100644 index 0000000..0657ca6 --- /dev/null +++ b/docs/matrix-sdk/12-quick-reference.md @@ -0,0 +1,366 @@ +# 12 — Schnellreferenz: Typen, Konstanten & Patterns + +--- + +## Wichtige Enum-Werte + +```dart +// Membership +Membership.join // Mitglied +Membership.invite // Eingeladen +Membership.leave // Verlassen +Membership.ban // Gesperrt +Membership.knock // Klopf-Anfrage + +// JoinRules +JoinRules.public // Offen +JoinRules.invite // Nur per Einladung +JoinRules.knock // Beitrittsanfragen erlaubt +JoinRules.restricted // Nur Mitglieder bestimmter Spaces/Räume +JoinRules.knockRestricted + +// HistoryVisibility +HistoryVisibility.worldReadable // Ohne Login lesbar +HistoryVisibility.shared // Alle Mitglieder sehen History +HistoryVisibility.invited // Ab Einladungszeitpunkt +HistoryVisibility.joined // Ab Beitrittszeitpunkt + +// GuestAccess +GuestAccess.canJoin // Gäste erlaubt +GuestAccess.forbidden // Keine Gäste + +// Visibility +Visibility.public // Im Verzeichnis +Visibility.private // Nicht im Verzeichnis + +// CreateRoomPreset +CreateRoomPreset.privateChat // invite + joined History +CreateRoomPreset.publicChat // public + shared History +CreateRoomPreset.trustedPrivateChat // wie private + alle Mitglieder sind Admins + +// EventStatus +EventStatus.sending // Wird übertragen +EventStatus.sent // Server-ACK +EventStatus.synced // Im Sync empfangen +EventStatus.error // Fehlgeschlagen +EventStatus.removed // Gelöscht + +// PresenceType +PresenceType.online +PresenceType.unavailable +PresenceType.offline + +// ThumbnailMethod +ThumbnailMethod.crop // Ausschneiden auf exakte Größe +ThumbnailMethod.scale // Skalieren ohne Abschneiden + +// LoginType +LoginType.mLoginPassword +LoginType.mLoginToken +LoginType.mLoginSso + +// PushRuleKind +PushRuleKind.override +PushRuleKind.content +PushRuleKind.room +PushRuleKind.sender +PushRuleKind.underride +``` + +--- + +## EventTypes Konstanten + +```dart +EventTypes.Message // m.room.message +EventTypes.Sticker // m.sticker +EventTypes.Reaction // m.reaction +EventTypes.RoomRedaction // m.room.redaction +EventTypes.Encrypted // m.room.encrypted +EventTypes.RoomCreate // m.room.create +EventTypes.RoomName // m.room.name +EventTypes.RoomTopic // m.room.topic +EventTypes.RoomAvatar // m.room.avatar +EventTypes.RoomMember // m.room.member +EventTypes.RoomPowerLevels // m.room.power_levels +EventTypes.RoomCanonicalAlias // m.room.canonical_alias +EventTypes.RoomJoinRules // m.room.join_rules +EventTypes.RoomGuestAccess // m.room.guest_access +EventTypes.HistoryVisibility // m.room.history_visibility +EventTypes.RoomPinnedEvents // m.room.pinned_events +EventTypes.RoomTombstone // m.room.tombstone +EventTypes.Encryption // m.room.encryption +EventTypes.SpaceChild // m.space.child +EventTypes.SpaceParent // m.space.parent +EventTypes.CallInvite // m.call.invite +EventTypes.CallAnswer // m.call.answer +EventTypes.CallHangup // m.call.hangup +EventTypes.CallCandidates // m.call.candidates +EventTypes.CallReject // m.call.reject +EventTypes.CallSelectAnswer // m.call.select_answer +EventTypes.CallNegotiate // m.call.negotiate +``` + +--- + +## Häufige Content-Zugriffe + +```dart +// Sicher auf Map-Inhalte zugreifen (Matrix SDK Extension) +final text = event.content.tryGet('body'); +final map = event.content.tryGetMap('info'); +final list = event.content.tryGetList('aliases'); + +// Event-Inhalt strukturiert +final msgtype = event.content['msgtype'] as String?; +final body = event.content['body'] as String?; +final formatted = event.content['formatted_body'] as String?; +final format = event.content['format'] as String?; // 'org.matrix.custom.html' + +// Relation +final relatesTo = event.content + .tryGetMap('m.relates_to'); +final relType = relatesTo?.tryGet('rel_type'); +final eventId = relatesTo?.tryGet('event_id'); + +// Verschlüsselte Medien +final file = event.content.tryGetMap('file'); +final url = file?.tryGet('url'); // mxc:// +final key = file?.tryGetMap('key'); + +// Mentions (MSC3952) +final mentions = event.content.tryGetMap('m.mentions'); +final userIds = mentions?.tryGetList('user_ids') ?? []; +final roomMention = mentions?.tryGet('room') ?? false; +``` + +--- + +## Timeline-Widget Pattern (Flutter) + +```dart +class ChatView extends ConsumerStatefulWidget { + final String roomId; + const ChatView({required this.roomId, super.key}); + @override + ConsumerState createState() => _ChatViewState(); +} + +class _ChatViewState extends ConsumerState { + Timeline? _timeline; + + @override + void initState() { + super.initState(); + _loadTimeline(); + } + + Future _loadTimeline() async { + final client = await ref.read(matrixClientProvider.future); + final room = client.getRoomById(widget.roomId)!; + _timeline = await room.getTimeline( + onUpdate: () => setState(() {}), + ); + setState(() {}); + } + + @override + void dispose() { + _timeline?.cancelSubscriptions(); // WICHTIG! + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final events = _timeline?.events ?? []; + return ListView.builder( + reverse: true, // Neueste unten + itemCount: events.length, + itemBuilder: (ctx, i) { + final event = events[i]; + if (event.type != EventTypes.Message) return const SizedBox(); + return ListTile( + title: Text(event.body), + subtitle: Text(event.senderId), + ); + }, + ); + } +} +``` + +--- + +## Raum-Liste Widget Pattern + +```dart +// StreamProvider für reaktive Raumliste +final roomsProvider = StreamProvider>((ref) async* { + final client = await ref.watch(matrixClientProvider.future); + yield _sortedRooms(client); + await for (final _ in client.onSync.stream) { + yield _sortedRooms(client); + } +}); + +List _sortedRooms(Client client) => client.rooms + .where((r) => r.membership == Membership.join) + .toList() + ..sort((a, b) => + (b.lastEvent?.originServerTs ?? DateTime(0)) + .compareTo(a.lastEvent?.originServerTs ?? DateTime(0))); + +// In Widget: +final rooms = ref.watch(roomsProvider); +rooms.when( + data: (list) => ListView.builder( + itemCount: list.length, + itemBuilder: (ctx, i) { + final room = list[i]; + return ListTile( + leading: CircleAvatar(child: Text(room.name[0])), + title: Text(room.getLocalizedDisplayname()), + subtitle: Text(room.lastEvent?.body ?? ''), + trailing: room.notificationCount > 0 + ? Badge(label: Text('${room.notificationCount}')) + : null, + ); + }, + ), + loading: () => const CircularProgressIndicator(), + error: (e, s) => Text('Fehler: $e'), +); +``` + +--- + +## Nachrichten senden mit optimistischem UI + +```dart +// Das SDK fügt das Event sofort mit Status 'sending' in die Timeline ein. +// UI kann es sofort anzeigen, ohne auf Server zu warten. + +class MessageInput extends ConsumerWidget { + final Room room; + const MessageInput({required this.room, super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final controller = TextEditingController(); + return Row( + children: [ + Expanded(child: TextField(controller: controller)), + IconButton( + icon: const Icon(Icons.send), + onPressed: () async { + final text = controller.text.trim(); + if (text.isEmpty) return; + controller.clear(); + try { + await room.sendTextEvent(text); + } catch (e) { + // Event bleibt mit Status 'error' in Timeline + // User kann auf "Erneut senden" tippen + } + }, + ), + ], + ); + } +} +``` + +--- + +## Nützliche Client-Extensions & Helpers + +```dart +// User-Erwähnung formatieren +'@${userId.split(':').first.replaceFirst('@', '')}' // kurzform ohne Server + +// Raum-Display-Name (FluffyChat-Stil) +// Für DMs: Name des Gegenübers +// Für Räume mit Name: Name +// Für Räume ohne Name: kommagetrennte Mitgliedernamen +room.getLocalizedDisplayname() + +// Avatar-URL sicher holen +user.avatarUrl?.getThumbnail(client, width: 56, height: 56) + +// Event-Zeitstempel formatieren +event.originServerTs.toLocal().toString() +// oder mit intl: +DateFormat.Hm().format(event.originServerTs.toLocal()) + +// Stable Notification-ID aus Raum-ID (deterministisch) +int stableId(String roomId) { + var h = 0; + for (final c in roomId.codeUnits) { + h = ((h * 31) + c) & 0x7FFFFFFF; + } + return h == 0 ? 1 : h; +} + +// Matrix-Größenangabe +// event.sizeString → '2.3 MB', '512 KB' + +// mxc:// URI in HTTP umwandeln +mxcUri.getDownloadUri(client) +mxcUri.getThumbnail(client, width: 300, height: 300) +``` + +--- + +## Fehler-Handling + +```dart +// MatrixException — Fehler vom Server +try { + await client.joinRoom('!room:server'); +} on MatrixException catch (e) { + switch (e.error) { + case MatrixError.M_FORBIDDEN: // Kein Zugang + case MatrixError.M_NOT_FOUND: // Raum existiert nicht + case MatrixError.M_LIMIT_EXCEEDED: // Rate-Limit + final retryAfter = e.retryAfterMs; // Wann wieder versuchen + case MatrixError.M_UNKNOWN: + default: + print(e.errorMessage); + } +} + +// TimeoutException — Keine Antwort vom Server +// SocketException — Keine Netzwerkverbindung +// FormatException — Ungültige Server-Antwort + +// Verbindungsstatus überwachen +client.onConnectionStateChanged.stream.listen((state) { + switch (state) { + case ConnectionState.connected: // Sync läuft + case ConnectionState.connecting: // Verbindet + case ConnectionState.reconnecting: // Verbindung wiederhergestellt + } +}); +``` + +--- + +## Wichtige Pakete für Pyramid + +```yaml +dependencies: + matrix: ^6.x.x # Matrix SDK (Haupt-SDK) + flutter_vodozemac: ^x.x.x # E2EE (Rust-basiert, empfohlen) + firebase_messaging: ^x.x.x # FCM Push (Android) + firebase_core: ^x.x.x + flutter_local_notifications: ^x.x.x # Lokale Notifications + flutter_riverpod: ^x.x.x # State Management + sqflite: ^x.x.x # Datenbank + path_provider: ^x.x.x # App-Verzeichnisse + shared_preferences: ^x.x.x # Einfache KV-Speicherung + livekit_client: ^x.x.x # LiveKit für VoIP + flutter_webrtc: ^x.x.x # WebRTC + go_router: ^x.x.x # Navigation + local_notifier: ^x.x.x # Windows Notifications + windows_taskbar: ^x.x.x # Windows Badge +``` diff --git a/docs/matrix-sdk/13-server-admin-continuwuity.md b/docs/matrix-sdk/13-server-admin-continuwuity.md new file mode 100644 index 0000000..88dd78a --- /dev/null +++ b/docs/matrix-sdk/13-server-admin-continuwuity.md @@ -0,0 +1,437 @@ +# 13 — Server-Administration: Continuwuity + +> **Gilt für:** Continuwuity 0.5.x (Fork von Conduwuit, welches ein Fork von Conduit ist) +> **Homeserver:** `steggi-matrix.work` +> **WICHTIG:** Continuwuity hat KEINE Synapse Admin API (`/_synapse/admin/` existiert nicht!) + +--- + +## Inhaltsverzeichnis +- [Server-Admin vs. Room Power Level](#server-admin-vs-room-power-level) +- [Admin Room — Befehle](#admin-room--befehle) +- [Continuwuity Admin HTTP API](#continuwuity-admin-http-api) +- [Power Level in Räumen erzwingen (als Server-Admin)](#power-level-in-räumen-erzwingen) +- [MSC3083: Restricted Join Rules auf Continuwuity](#msc3083-restricted-join-rules-auf-continuwuity) +- [Diagnose: Warum M_FORBIDDEN?](#diagnose-warum-m_forbidden) +- [User-Admin-Status prüfen/setzen](#user-admin-status-prüfensetzen) +- [Raum-Administration via Matrix API](#raum-administration-via-matrix-api) +- [Wichtige Unterschiede: Continuwuity vs. Synapse](#wichtige-unterschiede-continuwuity-vs-synapse) +- [Continuwuity `homeserver.yaml` — relevante Einstellungen](#continuwuity-homeserveryaml--relevante-einstellungen) + +--- + +## Server-Admin vs. Room Power Level + +``` +Continuwuity Server-Admin +├── Ermöglicht: Admin-Room-Befehle, Server-API +├── Ermöglicht: User deaktivieren, Räume löschen (Server-Level) +└── NICHT: Automatisch PL 100 in jedem Matrix-Raum! + +Matrix Room Power Level 100 +├── Gilt pro Raum (in m.room.power_levels State-Event gespeichert) +├── Ermöglicht: Name/Topic/Avatar setzen, Join-Rules ändern, User kicken/bannen +└── Unabhängig vom Server-Admin-Status +``` + +**Beispiel-Problem:** +- Du bist Server-Admin auf `steggi-matrix.work` ✅ +- Du hast PL 100 im Space `!xyz:steggi-matrix.work` ✅ +- Du erstellst einen neuen Channel → Server gibt dir PL 100 als Ersteller ✅ +- Du versuchst `join_rules: restricted` zu setzen → M_FORBIDDEN ❌ + - **Grund:** Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig + +--- + +## Admin Room — Befehle + +Continuwuity hat einen speziellen Admin-Raum. Als Server-Admin kannst du dort Befehle eingeben: + +``` +# Admin-Raum beitreten (normalerweise automatisch eingeladen) +# Raum-Alias: #admins:steggi-matrix.work + +# Befehle im Admin-Raum (als Nachricht senden): + +!admin help # Alle Befehle anzeigen + +!admin make_user_admin @user:server # User zu Server-Admin machen +!admin deactivate_user @user:server # User deaktivieren +!admin list_users # Alle User auflisten + +!admin get_room_state !roomId:server # Room-State anzeigen +!admin delete_room !roomId:server # Raum löschen + +!admin get_mem_usage # Server-Speicherverbrauch +!admin server_version # Server-Version +``` + +```bash +# Als curl (Admin-Token erforderlich): +# Admin-Room-ID herausfinden: +curl -s "https://steggi-matrix.work/_matrix/client/v3/directory/room/%23admins%3Asteggi-matrix.work" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" +# → {"room_id": "!adminRoomId:steggi-matrix.work", ...} +``` + +--- + +## Continuwuity Admin HTTP API + +```bash +# Basis-URL: https://steggi-matrix.work/_conduwuit/admin/v1/ +# (Nicht /_synapse/admin/ — das ist Synapse-only!) + +# User zu Server-Admin machen +curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{"user_id": "@todesneutron:steggi-matrix.work"}' + +# Server-Status abfragen +curl "https://steggi-matrix.work/_conduwuit/server/version" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# Alternativ — Standard Matrix-Whoami (prüft ob Token gültig): +curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" +# → {"user_id": "@todesneutron:steggi-matrix.work", "is_guest": false} + +# Prüfen ob User Server-Admin ist (Conduwuit-spezifisch): +curl "https://steggi-matrix.work/_conduwuit/admin/v1/users/@todesneutron:steggi-matrix.work" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" +``` + +--- + +## Power Level in Räumen erzwingen (als Server-Admin) + +Als Server-Admin kannst du via Matrix Client API Power Levels in jedem Raum setzen, +**auch wenn du kein Mitglied bist** (Continuwuity erlaubt das für Server-Admins): + +```bash +# Schritt 1: Aktuelles Power-Level-Event lesen +ROOM_ID="!raumId:steggi-matrix.work" +TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" +SERVER="https://steggi-matrix.work" + +curl "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \ + -H "Authorization: Bearer ${TOKEN}" + +# Schritt 2: Power Level setzen (users-Map ändern) +curl -X PUT "${SERVER}/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "users": { + "@todesneutron:steggi-matrix.work": 100 + }, + "users_default": 0, + "events_default": 0, + "state_default": 50, + "ban": 50, + "kick": 50, + "invite": 0, + "redact": 50 + }' +``` + +```dart +// In Flutter / Dart (mit Admin-Token): +// Zuerst aktuellen PL-State lesen: +final currentPl = await client.getRoomStateWithKey( + roomId, + EventTypes.RoomPowerLevels, + '', +); + +// Users-Map erweitern und zurückschreiben: +final users = Map.from( + (currentPl['users'] as Map?)?.cast() ?? {}, +); +users['@todesneutron:steggi-matrix.work'] = 100; + +await client.setRoomStateWithKey( + roomId, + EventTypes.RoomPowerLevels, + '', + { + ...currentPl, + 'users': users, + }, +); +``` + +--- + +## MSC3083: Restricted Join Rules auf Continuwuity + +`join_rules: restricted` (MSC3083) erlaubt Räumen, nur Space-Mitglieder beizutreten. +**Continuwuity 0.5.x unterstützt MSC3083 möglicherweise nicht vollständig.** + +```bash +# Testen ob restricted join rules funktionieren: +ROOM_ID="!testRaum:steggi-matrix.work" +TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" +SPACE_ID="!spaceId:steggi-matrix.work" + +curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{ + "join_rule": "restricted", + "allow": [ + { + "type": "m.room_membership", + "room_id": "'"${SPACE_ID}"'" + } + ] + }' +# → 200 OK: Unterstützt! +# → M_FORBIDDEN oder M_UNRECOGNIZED: Nicht unterstützt oder PL zu niedrig +``` + +**Workaround wenn restricted nicht funktioniert:** +```bash +# Fallback: invite-only (explizit jeden User einladen) +curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.join_rules/" \ + -H "Authorization: Bearer ${TOKEN}" \ + -H "Content-Type: application/json" \ + -d '{"join_rule": "invite"}' +``` + +```dart +// In space_admin_dialog.dart — Fallback wenn restricted nicht supported: +try { + await room.setJoinRules( + JoinRules.restricted, + allow: [ + SpaceRoomJoinRulesAllowInner( + roomId: spaceId, + type: SpaceRoomJoinRulesAllowInnerType.mRoomMembership, + ), + ], + ); +} on MatrixException catch (e) { + if (e.error == MatrixError.M_FORBIDDEN || e.error == MatrixError.M_UNKNOWN) { + // Continuwuity unterstützt restricted join rules nicht + // Fallback zu invite-only: + await room.setJoinRules(JoinRules.invite); + } else { + rethrow; + } +} +``` + +--- + +## Diagnose: Warum M_FORBIDDEN? + +```bash +# 1. Prüfen: Welchen Power Level hat mein User in diesem Raum? +ROOM_ID="!raumId:steggi-matrix.work" +TOKEN="J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.power_levels/" \ + -H "Authorization: Bearer ${TOKEN}" +# Antwort zeigt 'users' Map — prüfen ob '@todesneutron:steggi-matrix.work' drin ist + +# 2. Prüfen: Was ist state_default? +# Im Antwort-JSON: "state_default": 50 bedeutet: PL 50 nötig für State-Events +# "m.room.join_rules": 100 in events-Map = PL 100 für Join-Rule-Änderung + +# 3. Prüfen: Bin ich Mitglied des Raums? +curl "https://steggi-matrix.work/_matrix/client/v3/rooms/${ROOM_ID}/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \ + -H "Authorization: Bearer ${TOKEN}" +# → {"membership": "join"} = Mitglied ✅ +# → {"errcode": "M_NOT_FOUND"} = Nicht Mitglied ❌ (Server-Admin kann trotzdem State setzen) + +# 4. Prüfen: Unterstützt der Server restricted join rules? +curl "https://steggi-matrix.work/_matrix/client/v3/capabilities" \ + -H "Authorization: Bearer ${TOKEN}" +# Antwort: capabilities-Objekt — MSC3083 ist nicht explizit gelistet (kein Standard-Capability) +``` + +**Häufige Ursachen und Lösungen:** + +| Fehler | Ursache | Lösung | +|---|---|---| +| M_FORBIDDEN beim State-Event | PL zu niedrig im Raum | Power Level via curl erhöhen (s.o.) | +| M_FORBIDDEN bei join_rules: restricted | MSC3083 nicht unterstützt | Fallback zu `invite` nutzen | +| M_FORBIDDEN beim Channel erstellen | Bug in space_admin_dialog.dart | Raum manuell erstellen, dann Space-Child setzen | +| M_NOT_FOUND | Raum nicht bekannt | Raum beitreten oder Admin-Join | +| M_FORBIDDEN bei Power-Level-Änderung | PL darf nur gleich/höher gesetzt werden | Als Ersteller oder via Admin-API | + +--- + +## User-Admin-Status prüfen/setzen + +```bash +# Prüfen ob User Server-Admin ist: +curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# Auf Pi (SSH): User-Datenbank direkt abfragen (Conduwuit/Continuwuity nutzt RocksDB) +# Alternativ: Über Admin-Room-Befehl +# (Im Admin-Room als Nachricht senden:) +# !admin make_user_admin @todesneutron:steggi-matrix.work + +# Über HTTP (Conduwuit Admin-Endpoint): +curl -X POST "https://steggi-matrix.work/_conduwuit/admin/v1/make_user_admin" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{"user_id": "@todesneutron:steggi-matrix.work"}' +``` + +--- + +## Raum-Administration via Matrix API + +Da kein Synapse-Admin-API existiert, nutze die Standard-Matrix-Client-API mit Admin-Token: + +```bash +# Raum beitreten (als Admin, auch wenn invite-only): +curl -X POST "https://steggi-matrix.work/_matrix/client/v3/join/!roomId%3Asteggi-matrix.work" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{}' + +# User in Raum einladen: +curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/invite" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{"user_id": "@user:steggi-matrix.work"}' + +# Space-Child-Relation setzen (Channel einem Space hinzufügen): +curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!spaceId%3Asteggi-matrix.work/state/m.space.child/!channelId%3Asteggi-matrix.work/" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{ + "via": ["steggi-matrix.work"], + "suggested": false + }' + +# Space-Parent-Relation setzen (im Channel-Raum): +curl -X PUT "https://steggi-matrix.work/_matrix/client/v3/rooms/!channelId%3Asteggi-matrix.work/state/m.space.parent/!spaceId%3Asteggi-matrix.work/" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{ + "via": ["steggi-matrix.work"], + "canonical": true + }' + +# Alle Mitglieder eines Raums auflisten: +curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/members" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# Raum verlassen (als User, nicht löschen): +curl -X POST "https://steggi-matrix.work/_matrix/client/v3/rooms/!roomId%3Asteggi-matrix.work/leave" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" \ + -H "Content-Type: application/json" \ + -d '{}' +``` + +--- + +## Wichtige Unterschiede: Continuwuity vs. Synapse + +| Feature | Synapse | Continuwuity 0.5.x | +|---|---|---| +| Admin API URL | `/_synapse/admin/v1/` | `/_conduwuit/admin/v1/` | +| Admin Room | Optional | Standard | +| MSC3083 (restricted join rules) | ✅ Vollständig | ⚠️ Teilweise / experimentell | +| Spaces (MSC1772) | ✅ | ✅ Grundfunktionen | +| MatrixRTC / MSC3401 | ✅ (Element Call) | ⚠️ Eingeschränkt | +| Push-Gateway | ✅ | ✅ | +| Server-side search | ✅ | ✅ Grundfunktionen | +| E2EE / Cross-Signing | ✅ | ✅ | +| Presence | ✅ | ✅ | +| Account Deactivation | Admin API | Admin Room / API | +| Room Deletion/Purge | Admin API | Admin Room / API | +| User Listing | Admin API | Admin Room / API | +| Federation | ✅ | ✅ | +| Application Services | ✅ | ⚠️ Eingeschränkt | + +--- + +## Continuwuity `homeserver.yaml` — relevante Einstellungen + +```yaml +# /etc/continuwuity/homeserver.yaml (oder /etc/conduwuit/conduwuit.toml je nach Version) + +# Matrix-RTC / LiveKit +# MSC3266: Room Summary +# MSC3401: MatrixRTC +allow_unstable_room_versions: true + +# Federation (für Multi-Server-Calls nötig) +allow_federation: true +allow_public_room_directory_without_auth: false + +# Push (für Notifications) +# Kein spezieller Config — nutzt Standard-Matrix-Push-API + +# TURN-Server für WebRTC +turn_uris: + - "turn:steggi-matrix.work:3478?transport=udp" + - "turn:steggi-matrix.work:3478?transport=tcp" +turn_secret: "dein-turn-secret" +turn_username: "" # leer = HMAC-basiert +turn_password: "" +turn_ttl: 86400 + +# Registrierung +allow_registration: false # Kein offener Signup +registration_token: "dein-token" # Oder token-basiert + +# Log-Level +log: "warn,conduwuit=info" + +# Performance +rocksdb_parallelism_threads: 4 # Pi 5 hat 4 Cores + +# Unter Continuwuity: Admin-User beim ersten Start setzen +# Erster registrierter User wird automatisch Server-Admin +``` + +```bash +# Auf dem Pi: Config-Datei editieren +ssh steggi@192.168.178.71 +sudo nano /etc/continuwuity/homeserver.yaml +# oder: +sudo nano /etc/conduwuit/conduwuit.toml # Falls TOML-Format + +# Service neu starten: +sudo systemctl restart continuwuity +# oder: +sudo systemctl restart conduwuit + +# Logs prüfen: +sudo journalctl -u continuwuity -f +``` + +--- + +## Schnell-Diagnose Checkliste + +Wenn du M_FORBIDDEN bekommst: + +```bash +# 1. Token gültig? +curl "https://steggi-matrix.work/_matrix/client/v3/account/whoami" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# 2. PL im betroffenen Raum prüfen: +curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.power_levels/" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# 3. Mitglied des Raums? +curl "https://steggi-matrix.work/_matrix/client/v3/rooms/!ROOM_ID/state/m.room.member/%40todesneutron%3Asteggi-matrix.work/" \ + -H "Authorization: Bearer J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI" + +# 4. Was genau schlägt fehl? (Antwort-Body lesen!) +# M_FORBIDDEN + "Power level too low" → PL erhöhen +# M_FORBIDDEN + "Not a member" → Raum beitreten +# M_UNRECOGNIZED → Feature nicht unterstützt +# M_FORBIDDEN + "..." → join_rules restricted Problem +``` diff --git a/docs/matrix-sdk/CHECKLIST.md b/docs/matrix-sdk/CHECKLIST.md new file mode 100644 index 0000000..dc97bcf --- /dev/null +++ b/docs/matrix-sdk/CHECKLIST.md @@ -0,0 +1,433 @@ +# Pyramid — Feature-Checklist & Implementierungsstand + +> Stand: Mai 2026 +> Legende: ✅ Fertig | ⚠️ Teilweise / Bug | ❌ Fehlt | 🔧 In Arbeit + +--- + +## Inhaltsverzeichnis +- [Authentifizierung](#authentifizierung) +- [Raumliste](#raumliste) +- [Chat / Timeline](#chat--timeline) +- [Nachrichtentypen](#nachrichtentypen) +- [Nachrichtenfunktionen](#nachrichtenfunktionen) +- [Direct Messages](#direct-messages) +- [E2EE Verschlüsselung](#e2ee-verschlüsselung) +- [Push Notifications](#push-notifications) +- [VoIP & Calls](#voip--calls) +- [Settings / Einstellungen](#settings--einstellungen) +- [Benutzerprofil](#benutzerprofil) +- [Raum-Einstellungen](#raum-einstellungen) +- [Suche](#suche) +- [Medien](#medien) +- [Read Receipts & Typing](#read-receipts--typing) +- [Spaces](#spaces) +- [Windows / Desktop](#windows--desktop) +- [Sonstige Features](#sonstige-features) +- [Dokumentations-Vollständigkeit](#dokumentations-vollständigkeit) + +--- + +## Authentifizierung +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Login mit Passwort | ✅ | `login_page.dart`, `login_notifier.dart` | +| Homeserver-Auswahl | ✅ | `server_page.dart` — HTTPS-Prefix fix, .well-known Autodiscovery | +| Session wiederherstellen (init) | ✅ | `matrix_client.dart` — `client.init()` beim App-Start | +| Logout | ✅ | Via Matrix SDK `client.logout()` | +| Login-Redirect nach Init | ✅ | `router.dart` — StreamProvider-basierter Guard | +| SSO / OAuth | ❌ | Nicht implementiert | +| Registrierung / Account erstellen | ❌ | Keine UI | +| Login mit Token | ❌ | Nur Passwort-Login | +| Multi-Account | ❌ | Nur ein Account gleichzeitig | +| UIAA Re-Auth (Passwort ändern) | ❌ | Kein UI | + +--- + +## Raumliste +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Raumliste anzeigen | ✅ | `rooms_page.dart`, `room_list_item.dart` | +| Sortierung nach letzter Aktivität | ✅ | In `rooms_provider.dart` | +| Avatar-Anzeige (MXC) | ✅ | `mxc_image.dart` | +| Vorschautext (letztes Event) | ✅ | `room_list_item.dart` | +| Ungelesen-Badge | ✅ | `notificationCount` | +| Ungelesen-Punkt (kein Count) | ✅ | Bei `notificationCount == 0` aber ungelesen | +| Zeitstempel-Formatierung | ✅ | Heute: HH:MM, andere: DD.MM | +| DM-Erkennung (`isDirectChat`) | ✅ | Typ-Differenzierung in Liste | +| Space-Filterung | ✅ | `SpacesRail` filtert nach aktiver Space | +| Einladungen anzeigen | ⚠️ | Membership.invite vorhanden, gesonderte Ansicht fehlt | +| Raum suchen / filtern | ✅ | Via `search_modal.dart` | +| Archivierte Räume | ❌ | Kein UI für left-rooms | +| Raum erstellen (Knopf) | ✅ | `create_join_dialog.dart` | +| Raum beitreten (Alias) | ✅ | `create_join_dialog.dart` | + +--- + +## Chat / Timeline +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Nachrichten anzeigen | ✅ | `message_bubble.dart`, `message_group.dart` | +| Gruppen-Bubbles (gleicher Sender) | ✅ | Continuation-Nachrichten (eingerückt, kein Avatar) | +| Datums-Trenner | ✅ | Tagstrennlinie | +| Ungelesen-Trenner ("Neue Nachrichten") | ✅ | `fullyRead`-Position | +| Scroll-to-Unread beim Öffnen | ✅ | `chat_view.dart` | +| History-Nachladen beim Scrollen | ✅ | `_onScroll()` → `requestHistory(60)` | +| Optimistische Nachrichtenanzeige | ✅ | SDK fügt Event mit Status `sending` ein | +| Nachrichtenstatus (senden/sent) | ✅ | Uhren-Icons | +| Timeline-Cleanup (`cancelSubscriptions`) | ✅ | In `dispose()` | +| Sprung zu bestimmtem Event | ⚠️ | Infrastruktur vorhanden, kein UI | +| Event-Suche in Timeline | ❌ | Nur globale Suche | + +--- + +## Nachrichtentypen +| Typ | Status | Details | +|-----|--------|---------| +| Text (`m.text`) | ✅ | Vollständig | +| Bild (`m.image`) | ✅ | Thumbnail + Vollansicht mit Zoom | +| Video (`m.video`) | ✅ | Playback via `media_kit` | +| Audio (`m.audio`) | ✅ | Player mit Progress/Dauer | +| Datei (`m.file`) | ✅ | Download mit MIME-Icon | +| Sticker (`m.sticker`) | ✅ | Anzeige und Senden (Sticker-Picker) | +| Sprachnachricht (MSC3245) | ⚠️ | Audio-Aufnahme fehlt, Abspielen funktioniert | +| Standort (`m.location`) | ❌ | Nicht implementiert | +| Emote (`m.emote`) | ❌ | Kein gesondertes Rendering | +| Poll (MSC3381) | ❌ | Nicht implementiert | +| Verschlüsselte Nachrichten | ✅ | Automatisch via SDK, Fehler-UI vorhanden | +| Redacted-Events | ⚠️ | Wird angezeigt, kein "Nachricht gelöscht"-Platzhalter | + +--- + +## Nachrichtenfunktionen +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Antworten (Reply) | ✅ | Swipe-Geste + Quote-Anzeige | +| Reaktionen (Emojis) | ✅ | Quick-Picker + vollständiger Emoji-Picker | +| Reaktionen entfernen | ⚠️ | UI zum Entfernen fehlt | +| Nachrichten bearbeiten (Edit) | ⚠️ | `getDisplayEvent()` vorhanden, Senden nicht im UI | +| Nachricht löschen (Redact) | ❌ | Kein Button / Dialog | +| Threads | ❌ | Nicht implementiert | +| Polls | ❌ | Nicht implementiert | +| Weitersenden (Forward) | ❌ | Nicht implementiert | +| Kopieren (Text) | ⚠️ | Nicht explizit sichtbar | +| Long-Press Auswahl-Modus | ✅ | `message_bubble.dart` — Long-Press aktiviert Selection | +| Bulk-Aktionen (Auswahl) | ⚠️ | Modus vorhanden, Aktionen begrenzt | +| Pinned Messages Panel | ✅ | `pinned_messages_panel.dart` | +| Pins setzen (UI-Aktion) | ❌ | Kein Pin-Button in Nachricht | +| Linkvorschau | ❌ | Keine URL-Preview | +| Mention-Links klickbar | ✅ | `@user`-Links via `url_launcher` | + +--- + +## Direct Messages +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Neuen DM starten | ✅ | `new_dm_dialog.dart` → `startDirectChat()` | +| User-Verzeichnis-Suche | ✅ | `searchUserDirectory()` | +| DM-Erkennung in Raumliste | ✅ | `room.isDirectChat` | +| Partner-Avatar/Name | ✅ | `directChatMatrixID` → Profil laden | +| DM-Verschlüsselung | ✅ | Standard E2EE bei DM-Erstellung | +| Gruppen-DM | ⚠️ | Erstellbar, kein gesondertes UI | +| DM vergessen / verlassen | ⚠️ | Kein UI-Button | +| DM-spezifische Notification-Sounds | ❌ | Nicht implementiert | + +--- + +## E2EE Verschlüsselung +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Vodozemac Rust-Crypto | ✅ | `flutter_vodozemac` initialisiert in `matrix_client.dart` | +| E2EE in verschlüsselten Räumen | ✅ | Automatisch via SDK | +| Bootstrap-Flow (SSSS + Cross-Signing) | ✅ | `bootstrap_dialog.dart` — vollständige State-Machine | +| Cross-Signing Setup | ✅ | Master-, Self- und User-Signing-Key Erstellung | +| Key Backup (online) | ✅ | SSSS-gesichertes Backup | +| Schlüssel-Verifikation (SAS/Emoji) | ✅ | Via Bootstrap-Flow | +| QR-Code-Verifikation | ⚠️ | SDK-Support vorhanden, kein UI | +| Device-Liste anzeigen | ❌ | Kein UI | +| Gerät sperren/blockieren | ❌ | Kein UI | +| Fehlende Schlüssel anfordern | ✅ | `requestMissingSessionKeys()` bei Bad-Encrypted | +| Entschlüsselungs-Fehler-UI | ✅ | "Nachricht konnte nicht entschlüsselt werden" + Schlüssel-Button | +| Schlüssel importieren/exportieren | ❌ | Kein UI (Infrastruktur vorhanden) | + +--- + +## Push Notifications +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| FCM Token Registrierung | ✅ | `fcm_push_service.dart` | +| Pusher auf Homeserver | ✅ | `postPusher()` mit Sygnal-Gateway | +| Token-Refresh Handling | ✅ | `onTokenRefresh.listen()` | +| PushService.kt (native FCM) | ✅ | Läuft auch bei geschlossener App | +| Benachrichtigung bei geschlossener App | 🔧 | APK neu gebaut, noch nicht getestet | +| Absender-Name in Notification | ✅ | HTTP-Fetch von Matrix API in PushService.kt | +| Verschlüsselte Nachricht entschlüsseln | ⚠️ | "Neue Nachricht" bei geschlossener App; `decryptAndUpdateNotification` bei Hintergrund-App | +| Inline Reply in Notification | 🔧 | ReplyReceiver auf getActivity umgestellt — APK gebaut, ungetestet | +| Antwort wirklich abschicken | 🔧 | `replyFromNotification` MethodChannel — APK gebaut, ungetestet | +| Gelesen-Button in Notification | ✅ | `ACTION_DISMISS` über `ReplyReceiver.kt` | +| Notification bei Hintergrund-App | ✅ | Heartbeat-Check verhindert Duplikate | +| Notification-Kanal Android | ✅ | `pyramid_messages`, HIGH Importance | +| Stabile Notification-ID | ✅ | `stableId(roomId)` — gleicher Algo in Kotlin + Dart | +| Windows Notification | ✅ | `local_notifier` (Windows Toast) | +| Windows Taskbar Flash | ✅ | `WindowsTaskbar.setProgressMode()` | +| Ausstehende Reply beim App-Öffnen senden | ✅ | `_sendPendingReply()` bei Resume + Sync | +| Push Rules konfigurieren | ❌ | Kein UI | +| Raum stumm schalten | ❌ | Kein UI | +| Nur-Erwähnung-Modus | ✅ | `notifMentionOnlyDmProvider` — Preferences | +| iOS Push | ❌ | Kein iOS-Build | +| Web Push | ❌ | Kein Web-Build | + +--- + +## VoIP & Calls +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Matrix WebRTC Legacy-Calls | ✅ | `voip_manager.dart` — CallSession | +| LiveKit SFU-Calls | ✅ | `livekit_call_manager.dart` | +| Unified Call-UI | ✅ | `voice_channel.dart` | +| Audio-Call | ✅ | Mikrofon + Speaker | +| Video-Call | ✅ | Kamera + Remote-Video | +| Screen-Sharing | ✅ | `screen_share_picker.dart` | +| Video-Qualitätsstufen | ✅ | SD/HD/FHD/4K Presets | +| Mute-Toggle | ✅ | `setMicrophoneEnabled()` | +| Deafen-Toggle | ✅ | Audio komplett stumm | +| Kamera-Toggle | ✅ | `setCameraEnabled()` | +| Kamera-Wechsel (Front/Rück) | ⚠️ | SDK-Support vorhanden | +| Teilnehmer-Grid | ✅ | Mehrere Participants anzeigen | +| Lokale Video-Vorschau | ✅ | Overlay-Widget | +| Klingel-System (to-device) | ⚠️ | Infrastruktur vorhanden, Klingelton fehlt | +| Incoming-Call-UI | ⚠️ | Kein dediziertes Klingel-Screen | +| Call-History | ❌ | Nicht implementiert | +| TURN-Server via Matrix | ⚠️ | `getTurnServer()` — ob konfiguriert unklar | +| Hintergrund-Foreground-Service | ✅ | `FlutterForegroundService` via webrtc | +| MatrixRTC Membership-Events | ✅ | `io.pyramid.voice.presence` State-Events | +| LiveKit-Token-Exchange | ✅ | `livekit_token.dart` | + +--- + +## Settings / Einstellungen +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Settings-Seite (Hauptseite) | ⚠️ | `settings_page.dart` — NUR PLATZHALTER | +| Settings Modal | ✅ | `settings_modal.dart` — vollständiger Modal | +| Dark/Light Mode | ✅ | `themeModeProvider` + Toggle | +| Akzentfarbe (5 Presets) | ✅ | Amber/Coral/Mint/Violet/Cobalt/Lime | +| Eckenradius Slider | ✅ | `radiusProvider` | +| UI-Motion Toggle | ✅ | `motionProvider` | +| UI-Density Toggle | ✅ | `densityProvider` | +| Desktop Notifications | ✅ | `notifDesktopProvider` | +| Notification Sound | ✅ | `notifSoundProvider` | +| Nachrichtenvorschau | ✅ | `notifPreviewProvider` | +| Nur-Erwähnung-Modus | ✅ | `notifMentionOnlyDmProvider` | +| Presence anzeigen (Online) | ✅ | `privacyPresenceProvider` | +| Read Receipts senden | ✅ | `privacyReadReceiptsProvider` | +| Typing-Indikator senden | ✅ | `privacyTypingProvider` | +| Profil bearbeiten (Name/Avatar) | ❌ | Kein UI | +| Geräte-Verwaltung | ❌ | Kein UI | +| Session-Liste | ❌ | Kein UI | +| Passwort ändern | ❌ | Kein UI | +| Account löschen | ❌ | Kein UI | +| Raumspezifische Benachrichtigungen | ❌ | Kein UI | +| Sprache / Lokalisierung | ❌ | Nur Systemsprache | +| Barrierefreiheit | ❌ | Keine Einstellungen | + +--- + +## Benutzerprofil +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Avatar anzeigen (MXC) | ✅ | `mxc_image.dart` überall | +| Displayname auflösen | ✅ | Fallback auf `@username` | +| Online-Präsenz senden | ✅ | `setPresence(online)` alle 10s in `app_shell.dart` | +| Präsenz-Anzeige anderer User | ⚠️ | Infrastruktur, kein UI | +| Profil-Popover (Hover-Karte) | ✅ | `profile_popover.dart` | +| Eigenes Profil bearbeiten | ❌ | Kein UI | +| Avatar hochladen | ❌ | Kein UI | +| Status-Nachricht | ❌ | Nicht implementiert | +| User ignorieren / blockieren | ❌ | Kein UI | +| User melden | ❌ | Kein UI | + +--- + +## Raum-Einstellungen +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Space-Admin Panel (Name/Avatar/Banner) | ✅ | `space_admin_dialog.dart` — Overview-Tab | +| Power-Level-Editor (Mitglieder) | ✅ | `space_admin_dialog.dart` — Members-Tab | +| Permissions-Tab (Raum-PLs) | ✅ | `space_admin_dialog.dart` — Permissions-Tab | +| Kind-Räume verwalten | ✅ | `space_admin_dialog.dart` — Channels-Tab | +| Raum-Name ändern (normaler Raum) | ❌ | Kein UI | +| Raum-Thema ändern | ❌ | Kein UI | +| Raum-Avatar ändern | ❌ | Kein UI | +| Join-Rules ändern | ❌ | Kein UI | +| History-Visibility ändern | ❌ | Kein UI | +| E2EE aktivieren | ❌ | Kein UI | +| Raum-Alias verwalten | ❌ | Kein UI | +| Raum verlassen (Button) | ❌ | Kein UI | +| Raum vergessen (forget) | ❌ | Kein UI | +| User einladen (aus Chat) | ❌ | Kein UI | +| Kick / Ban (Moderation) | ❌ | Kein UI | + +--- + +## Suche +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Server-seitige Nachrichtensuche | ✅ | `search_modal.dart` → `/search` API | +| Lokale Raum-/DM-Suche | ✅ | Filter auf `client.rooms` | +| Personen-Suche | ✅ | Lokale DM-Partner-Suche | +| Medien-Filter (Bilder/Videos/Audio) | ✅ | `search_modal.dart` | +| Paginierung (nextBatch) | ✅ | Infinite scroll | +| Suchergebnis-Highlighting | ✅ | Suchbegriff hervorheben | +| Debounced Query (400ms) | ✅ | `debounce` in Suchfeld | +| Öffentliches Raumverzeichnis | ❌ | Kein UI zum Entdecken | +| User-Verzeichnis-Suche (global) | ✅ | In `new_dm_dialog.dart` | + +--- + +## Medien +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Bild senden | ✅ | `MatrixImageFile` + Upload | +| Bild anzeigen (Thumbnail + Vollbild) | ✅ | `MediaViewer` mit Zoom/Pan | +| Video senden | ✅ | | +| Video abspielen | ✅ | `media_kit` | +| Audio senden | ✅ | | +| Audio abspielen | ✅ | Player mit Progress | +| Datei senden | ✅ | `MatrixFile` | +| Datei herunterladen | ✅ | MIME-Icon + Browser-Öffner | +| Clipboard-Bild einfügen (Windows) | ✅ | FFI + `clipboard_image.dart` | +| Drag & Drop Upload (Desktop) | ✅ | `desktop_drop` | +| GIF-Picker (Giphy) | ✅ | Trending + Suche + Favoriten | +| Sticker-Picker | ✅ | Pack-Browser | +| Bild-Komprimierung | ✅ | `shrinkImageMaxDimension` | +| Verschlüsselte Medien | ✅ | Automatisch bei E2EE-Räumen | +| Sprachnachricht aufnehmen | ❌ | Kein Recorder | +| Kamera direkt (in App) | ❌ | Nur Gallery-Picker | +| Dokument-Vorschau | ❌ | Kein PDF-Viewer | +| Media-Galerie (Raum-Mediathek) | ❌ | Kein UI | + +--- + +## Read Receipts & Typing +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Read Receipts senden | ✅ | `setReadMarker()` (privacy-gesteuert) | +| Eigene ✓✓ Bestätigung | ✅ | Anzeige auf eigenen Nachrichten | +| Read-Marker anderer anzeigen | ⚠️ | Position-Marker vorhanden, kein Avatar-Stack | +| Typing-Indikator senden | ✅ | 7s Auto-Timeout | +| Typing-Indikator empfangen | ✅ | Anzeige-Platzhalter | +| Typing-User-Namen anzeigen | ⚠️ | Platzhalter, keine Namen | + +--- + +## Spaces +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Space-Erkennung (`isSpace`) | ✅ | | +| Spaces-Rail (Sidebar) | ✅ | `spaces_rail.dart` | +| Space-Filterung der Raumliste | ✅ | Nur Räume der aktiven Space | +| Space-Admin Panel | ✅ | `space_admin_dialog.dart` | +| Space erstellen | ✅ | `create_join_dialog.dart` | +| Kind-Räume hinzufügen | ✅ | In Space-Admin | +| Kind-Räume entfernen | ✅ | In Space-Admin | +| Voice-Präsenz in Space | ✅ | `io.pyramid.voice.presence` Events | +| Space-Banner | ✅ | Mit Crop-Dialog | +| Verschachtelte Spaces | ⚠️ | Anzeige, kein eigener Sub-Space-Rail | +| Space beitreten (öffentlich) | ⚠️ | Technisch möglich, kein Discovery-UI | + +--- + +## Windows / Desktop +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Windows Build | ✅ | CMake + MSIX | +| Windows Notifications | ✅ | `local_notifier` | +| Taskbar Flash | ✅ | `WindowsTaskbar` | +| Update-Checker (Gitea API) | ✅ | `update_checker.dart` — 4h Intervall | +| Update-Banner | ✅ | `update_banner.dart` | +| Update-Download | ✅ | `update_download_dialog.dart` | +| APK Auto-Install (Android) | ✅ | Kotlin MethodChannel + FileProvider | +| PC Update (exe/msix) Download | ⚠️ | Release-Script pusht .zip statt .exe → öffnet Git-Seite | +| Drag & Drop | ✅ | `desktop_drop` | +| Clipboard Paste (Bild) | ✅ | FFI Windows API | +| Resizable Sidebar | ✅ | `panel_layout.dart` — Drag-Divider | +| Keyboard Shortcuts | ⚠️ | Enter zum Senden, Ctrl+V — kein vollständiges System | +| System Tray | ❌ | Nicht implementiert | +| Fenster-Badge (ungelesen) | ⚠️ | Nur Taskbar-Flash, kein Zähler | +| macOS / Linux | ❌ | Nicht gebaut/getestet | + +--- + +## Sonstige Features +| Feature | Status | Details / Datei | +|---------|--------|-----------------| +| Emoji-Picker | ✅ | Kategorisiert + Suche | +| Quick-Reaktionen (6 Emojis) | ✅ | Hover-Aktionsleiste | +| Mitglieder-Panel (Raum) | ✅ | `members/` — Teilnehmerliste | +| Profil-Popover (Hover) | ✅ | `profile_popover.dart` | +| Neuer-DM Dialog | ✅ | `new_dm_dialog.dart` | +| Raum-erstellen Dialog | ✅ | `create_join_dialog.dart` | +| Nachricht-Auswahl-Modus | ✅ | Long-Press | +| Reply-Swipe-Geste | ✅ | Rechts-wischen zum Antworten | +| Immersive-Mode (Android) | ✅ | Status-Bar ausgeblendet | +| PyramidLoader (Ladeanimation) | ✅ | `pyramid_loader.dart` | +| Rich-Text-Editor | ❌ | Kein Markdown/Formatting-UI | +| HTML-Nachrichtenrendering | ❌ | Kein `flutter_html` | +| Message Forwarding | ❌ | | +| Nachrichtenübersetzung | ❌ | | +| Bot-Kommandos (`/`) | ❌ | | +| Matrix-URI Handler | ❌ | Kein Deep-Link-Handler | +| Barcode/QR-Scanner | ⚠️ | Nur in Verifikation | + +--- + +## Dokumentations-Vollständigkeit + +| Doku-Abschnitt | Vollständig | Anmerkungen | +|----------------|-------------|-------------| +| 01 Auth | ✅ | SSO, UIAA, alle Login-Flows | +| 02 Räume | ✅ | Create, Join, Spaces, Power Levels | +| 03 Nachrichten | ✅ | Text, Replies, Edits, Threads, Polls | +| 04 DMs | ✅ | Alle DM-Flows | +| 05 Medien | ✅ | Upload, Download, alle Dateitypen | +| 06 E2EE | ✅ | Setup, SAS, Cross-Signing, Key Backup | +| 07 Push | ✅ | FCM, Push Rules, Pyramid-Architektur | +| 08 VoIP | ✅ | Legacy m.call, MatrixRTC | +| 08b LiveKit | ✅ | **KOMPLETT** — Server-Setup bis Flutter-UI | +| 09 Profil | ✅ | Presence, Account-Data, Tags | +| 10 Room-Admin | ✅ | Power Levels, Moderation, ACL, Synapse Admin | +| 11 Suche | ✅ | Event-Suche, User-Suche, Raumverzeichnis | +| 12 Schnellreferenz | ✅ | Alle Enums, Widget-Patterns, Fehlerhandling | + +--- + +## Prioritäts-Roadmap + +### 🔴 Kritisch (bald testen/fixen) +1. **Notification-Reply testen** — Neue APK (getActivity-Fix) installieren und Reply-Flow verifizieren +2. **Benachrichtigung bei geschlossener App** — Mit neuer APK testen (PushService.kt Ansatz) +3. **PC Update-Script** — `.zip` durch `.exe`-Installer ersetzen in `scripts/release.ps1` + +### 🟠 Wichtig (nächste Features) +4. **Nachricht löschen (Redact)** — Long-Press-Menü → `event.redactEvent()` +5. **Nachricht bearbeiten** — Edit-Modus im Composer → `sendTextEvent(editEventId:...)` +6. **Raum-Einstellungen** — Name/Thema/Avatar für normale Räume (`room.setName()` etc.) +7. **Profil bearbeiten** — Displayname + Avatar in Settings +8. **Registrierung** — Account-Erstellung im Onboarding + +### 🟡 Sinnvoll (mittelfristig) +9. **Einladungen-Screen** — Pending invites sichtbar darstellen +10. **Kick/Ban UI** — Moderation aus der Mitgliederliste +11. **Device-Verwaltung** — Eigene Sessions anzeigen + löschen +12. **Rich-Text-Editor** — Markdown/Formatierung in Nachrichten +13. **Klingelton bei eingehendem Call** — Audio + dedizierter Klingel-Screen +14. **Lautlos/Stumm per Raum** — Push-Rules im UI + +### 🟢 Nice-to-have +15. Sprachnachrichten aufnehmen +16. HTML-Nachrichtenrendering (`flutter_html`) +17. Matrix-URI Deep-Links +18. Media-Galerie pro Raum +19. System Tray (Windows) +20. Polls / Abstimmungen diff --git a/docs/matrix-sdk/README.md b/docs/matrix-sdk/README.md new file mode 100644 index 0000000..d94cca0 --- /dev/null +++ b/docs/matrix-sdk/README.md @@ -0,0 +1,122 @@ +# Matrix SDK — Pyramid Entwicklungsreferenz + +> **Basis:** [`package:matrix`](https://pub.dev/packages/matrix) (Dart/Flutter Matrix SDK) +> **Ziel:** Vollständige Landkarte aller Matrix-Funktionen mit Code-Snippets für den Pyramid-App-Bau. +> **Referenz-Implementierung:** FluffyChat (https://gitlab.com/famedly/fluffychat) + +--- + +## Navigation + +| # | Thema | Beschreibung | +|---|-------|--------------| +| [01](01-auth.md) | **Authentifizierung** | Login, Logout, Register, SSO, Token-Management | +| [02](02-rooms.md) | **Räume & Spaces** | Erstellen, Beitreten, Verlassen, Spaces, Suche | +| [03](03-messages.md) | **Nachrichten & Events** | Senden, Timeline, Reaktionen, Edits, Threads, Polls | +| [04](04-dm.md) | **Direct Messages** | DM-Räume finden, starten, verwalten | +| [05](05-media.md) | **Medien & Dateien** | Upload, Download, Thumbnails, verschlüsselte Medien | +| [06](06-encryption.md) | **E2EE Verschlüsselung** | Keys, Verifizierung, Cross-Signing, Key-Backup | +| [07](07-push.md) | **Push & Notifications** | Pusher, Push Rules, FCM, lokale Benachrichtigungen | +| [08](08-voip.md) | **VoIP & Calls** | MatrixRTC, Legacy m.call, Klingel-Flow | +| [08b](08b-livekit-streaming.md) | **LiveKit Streaming** ⭐ | **Vollständige Server-Anleitung + Flutter-Implementierung** | +| [09](09-profile.md) | **Profil & Präsenz** | Avatar, Displayname, Presence, Account-Daten | +| [10](10-room-admin.md) | **Raum-Administration** | Power Levels, Moderierung, Einstellungen, Bans | +| [11](11-search.md) | **Suche & Discovery** | Nachrichten-Suche, User-Suche, Raum-Verzeichnis | +| [12](12-quick-reference.md) | **Schnellreferenz** | Alle Enums, Widget-Patterns, Fehlerhandling | +| [13](13-server-admin-continuwuity.md) | **Server-Admin Continuwuity** ⭐ | Admin API, Power Levels erzwingen, MSC3083, Diagnose | +| [CHECKLIST](CHECKLIST.md) | **Feature-Checklist** ⭐ | Implementierungsstand + Roadmap | + +--- + +## Schnellreferenz: Client-Initialisierung + +```dart +import 'package:matrix/matrix.dart'; + +final client = Client( + 'MeinApp', // App-Name (User-Agent) + database: MatrixSdkDatabase(...), // Persistenz (sqflite) + nativeImplementations: NativeImplementationsIsolate(compute), // E2EE + logLevel: Level.warning, +); + +// Initialisieren (lädt gespeicherten Session-State) +await client.init( + waitForFirstSync: false, // UI nicht blockieren + waitUntilLoadCompletedLoaded: false, +); +``` + +--- + +## Architektur-Überblick + +``` +Client +├── rooms: List // alle bekannten Räume +├── userID: String? // eigene MXID (@user:server) +├── accessToken: String? // Bearer-Token +├── homeserver: Uri // https://matrix.example.org +│ +├── Room +│ ├── id: String // !roomId:server +│ ├── getTimeline() // Event-Stream +│ ├── sendTextEvent() +│ ├── sendEvent() +│ ├── members // Map +│ └── states // Map> +│ +├── Event +│ ├── type: String // m.room.message, m.reaction, … +│ ├── content: Map +│ ├── body: String // text body (decrypted) +│ └── messageType: String? // m.text, m.image, m.file, … +│ +└── User + ├── id: String // MXID + ├── displayName: String? + └── avatarUrl: Uri? +``` + +--- + +## Wichtige Streams / Provider-Hooks + +```dart +// Auf Sync-Events reagieren +client.onSync.stream.listen((SyncUpdate update) { ... }); + +// Neue/geänderte Räume +client.onRoomUpdate.stream.listen((String roomId) { ... }); + +// Verbindungsstatus +client.onConnectionStateChanged.stream.listen((ConnectionState s) { ... }); + +// Eigener User geändert +client.onUserEvent.stream.listen((EventUpdate update) { ... }); + +// Benachrichtigungs-Events (gefiltert nach Push-Rules) +client.onNotification.stream.listen((Event event) { ... }); +``` + +--- + +## Tipps für Riverpod-Integration + +```dart +// Matrix-Client als Provider +final matrixClientProvider = FutureProvider((ref) async { + final client = Client('Pyramid', ...); + await client.init(waitForFirstSync: false); + return client; +}); + +// Raumliste reaktiv +final roomsProvider = StreamProvider>((ref) async* { + final client = await ref.watch(matrixClientProvider.future); + yield client.rooms; + await for (final _ in client.onSync.stream) { + yield client.rooms; + } +}); +``` diff --git a/docs/server-incident-2026-05-31.md b/docs/server-incident-2026-05-31.md new file mode 100644 index 0000000..e41a874 --- /dev/null +++ b/docs/server-incident-2026-05-31.md @@ -0,0 +1,87 @@ +# Server-Incident: Messaging-Ausfall — 2026-05-31 + +## Betroffene Nutzer +`@uta:steggi-matrix.work`, `@circuitslave:steggi-matrix.work` + +## Symptome +- Uta und Circuitslave konnten in verschlüsselten DM-Räumen keine Nachrichten senden +- Nachrichten von `@todesneutron` kamen nicht an bzw. konnten nicht entschlüsselt werden +- `@jochen` (Test-Account, FluffyChat) war nicht betroffen +- Später: Element zeigt „Verbindung unterbrochen / Server offline" +- Nach Behebung: alle Chats zunächst leer (History nicht sichtbar) + +--- + +## Ursachen (in Reihenfolge des Auftretens) + +### 1. Continuwuity 0.5.8 — `room_keys/version` 500-Fehler +**Endpunkt:** `GET /_matrix/client/unstable/room_keys/version` + +Continuwuity 0.5.8 crashte bei dieser Anfrage mit: +``` +response error: JSON serialization failed: missing field `algorithm` at line 1 column 2 +500 Internal Server Error +``` + +Element prüft diesen Endpunkt beim Start, bevor es verschlüsselte Nachrichten sendet. +Der 500-Fehler verhinderte den korrekten Aufbau des E2E-Zustands → Senden blockiert. + +FluffyChat/Pyramid implementieren diesen Check nicht → waren nicht betroffen. + +### 2. Zu viele unverifizierte Geräte bei `@todesneutron` +Durch die Pyramid-Entwicklung wurden 14 Geräte angesammelt (alte FluffyChat-, +Commet- und Pyramid-Debug-Sessions). Element von Uta/Circuitslave sah all diese +Geräte als unbekannt und konnte nicht für alle gleichzeitig verschlüsseln. + +### 3. Continuwuity 0.5.9-latest — Axum Routing Panic (Folgeschaden) +Beim Update auf `latest` (0.5.9, Commit `0514491`) trat ein Panic auf: +``` +thread 'conduwuit:worker' panicked at axum-0.8.9/src/routing/path_router.rs:406:22: +no route for id. This is a bug in axum. +``` + +Ausgelöst durch: `GET /_matrix/client/v3/user/@circuitslave:steggi-matrix.work/filter/ieOT` + +Circuitslaves Element hatte nach dem ersten Neustart seinen Filter verloren und +sendete diese Anfrage in einer Schleife → Server-Worker crashte wiederholt → +Cloudflare bekam EOF → alle Clients offline. + +### 4. Leere Chat-History nach Behebung +Continuwuity 0.5.9 hat die interne RocksDB-Struktur von 98 auf 100 Column Families +erweitert. Das invalidierte alle gespeicherten Sync-Token der Clients → Fresh Initial +Sync → Server schickt nur aktuelle Room-States ohne vollständige Timeline. + +**Die Daten waren nicht verloren** — Pagination via `/messages` funktionierte korrekt. +Durch Hochscrollen in den Räumen wurde die History nachgeladen. + +--- + +## Maßnahmen + +| Schritt | Aktion | +|---|---| +| Diagnose | Geräteliste, Raumzustand, Server-Logs via SSH geprüft | +| Geräte aufräumen | 14 → 5 aktive Geräte bei `@todesneutron` | +| Server-Update | Wechsel auf `continuwuity:main` (Commit `1faa09b`) | +| Ergebnis | `room_keys/version` gibt gültige Antwort, Filter-Panic behoben | +| History | Nutzer scrollten in Räumen nach oben → Pagination lud History nach | + +--- + +## Server-Infrastruktur + +- **Homeserver:** Continuwuity (Conduit-Fork, Rust) via Docker +- **Compose-Datei:** `/home/steggi/matrix/docker-compose.yml` +- **Image (vorher):** `registry.gitlab.com/continuwuity/continuwuity:latest` (0.5.8 → 0.5.9) +- **Image (jetzt):** `registry.gitlab.com/continuwuity/continuwuity:main` (0.5.9, Commit `1faa09b`) +- **Tunnel:** Cloudflare (`cloudflared`) +- **Datenbank:** RocksDB unter `/home/steggi/matrix/db/` + +--- + +## Lektionen + +- `latest`-Tag vor produktivem Update testen (0.5.9-latest hatte Routing-Bug) +- Alte Geräte regelmäßig aus Element/Pyramid abmelden (verhindert E2E-Probleme) +- `continuwuity:main` ist stabiler als `continuwuity:latest` +- FluffyChat/Pyramid senden auch ohne Key-Backup-Check → können als Fallback dienen diff --git a/flutter_launcher_icons.yaml b/flutter_launcher_icons.yaml new file mode 100644 index 0000000..a60276b --- /dev/null +++ b/flutter_launcher_icons.yaml @@ -0,0 +1,12 @@ +flutter_launcher_icons: + android: true + ios: true + macos: + generate: true + image_path: "assets/logo.png" + windows: + generate: true + image_path: "assets/logo.png" + image_path: "assets/logo.png" + adaptive_icon_background: "#1A1B1E" + adaptive_icon_foreground: "android/app/src/main/res/drawable/ic_launcher_foreground.xml" diff --git a/ios/Runner.xcodeproj/project.pbxproj b/ios/Runner.xcodeproj/project.pbxproj index c0fdae0..32ea1d6 100644 --- a/ios/Runner.xcodeproj/project.pbxproj +++ b/ios/Runner.xcodeproj/project.pbxproj @@ -431,7 +431,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; @@ -488,7 +488,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; - ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon; CLANG_ANALYZER_NONNULL = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-1024x1024@1x.png index dc9ada4725e9b0ddb1deab583e5b5102493aa332..ad5d7666fcefda96f55f912801fe4aae69c83ad6 100644 GIT binary patch literal 94762 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

KHiw$#n=YRhN_yf~hX#Nv5Yu=!8R7!<*E@70*R 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@2x.png index 797d452e458972bab9d994556c8305db4c827017..eca545c0db553cf326d70e2ddb117c1fee7eead0 100644 GIT binary patch delta 1556 zcmV+v2J88j1DXtw8Gi-<004~sxNQIc0fA{lLr`;4M?xS;MME|*IW{&eGA=Oy04R}l zk-tkqQ545NYGGtyP=iB*gf(TDfz;Aqlm*pb23alo{1y1)@tzUU8ngxlQA@vu`U`3e znuDMyf@qG$qLz}^c`7K8=W_1(-0!{TaPPTbjbxRa-sFQ^zJI8NLqYdKbkS{pqX`!d zY}jIouFlL&L}+MV4_M52=QV3JKKHLV5=mVFON;QRqH0CqN#W_WqH6N4aF>#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={k%c!SkWH3_7$;Mv8)PAyf0}GAX3L`6z%1F=n1&3uOms7`!zznQ)QL=zWy4Kj*f-LS z_O9ERHh($Gm9|o-i9X4b{F)}$PruLacYVR&AulY|fLQeyINy4-fSU^yWiqh{J8^OP zbh56QRA7fy)1j0jf&Ss?L5783GOn34prx3oEL<)v0f6xxWvY$G&bX42Vp4z-43M|B zX}bOokpTd9pOI=le$G8O69~>b#iRfmH>k`{E`Js4LO>=fO`O@XNnL$-z%h_=pac`4 z?IwB;0Qdm_4I%xnZ>1VPJ?lE{^0G521-4eJ8?+Rb4FG{~g4~+KQT6T`($MwgRA0(~ z6pqN-YN_2J9EA5^=rQ|pm3r%u@0O*Zpz5K4~;?MH6S?yOL6e*cu?+utVw&P4^jX`x?IND({&c;AS*#!wM@ zz)aV)e0b-xMFZwMAzso{u4;(DLBxpJaH91k%F;vqcTbJn^50z);C>U;%q0^CkO`#- zUGJk+d1!Uyj+(d$pxJ!1@;B%r03SX+=S)x`k}qXZ90xL0OMmTWIouITyE{oA~O zC<1W6OmB+=2T^X+k-&TFPOD~Jugx>&^9Se5F($C7TveRAOp^V8z^G%^QW(*)NuB%d zH;$191}bGDtldOgLn9L^5pNxgv400=VRvmIpZWNVYt-dsqoz0~@Wl#ssg}a180m4y zr4ud&?YrPP%P_$ivz}O;PGa2W?kEp73!F}3($;EHcd&2jdcr`J91-uSrK+Rg5CBLY zp9=Wi@i4Y;h|CAWuf0~Y!Kl5b>GiibJ%scvI47~ zFmU(3bP~G_0N27;g%m;C>Zqso^-Kz;C;7x+3&0wc}F(rvH-X@=5#jF@93< zmVMNBg==22<;EgBBP&hp0DpjAnx9u?zc=8x`R6}@St$wvUo+D6)Bgsa?m6ci?zOo; zik4KOC6H{sRZrBI^+ZOemBx2|aOdl|fM3|$Kke`ntJld2xKAuL zA_zg?&<)?Ug{9qJ9LhH0yCU@5qxJXOLeyj6eCweH{s$!C{b5k-wGICO0000+>eB z?J{?+FLkYu+4_Uk`r_>LHF~flZm0oBf#vr8%vJ>#p~!KNvqGG3)|f1T_)ydeh8$vDceZ>oNbH^|*hJ*t?Yc*1`WB&W>VYVEzu) zq#7;;VjO)t*nbgf(!`OXJBr45rP>>AQr$6c7slJWvbpNW@KTwna6d?PP>hvXCcp=4 zF;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f@?C@RsaA1 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-20x20@3x.png index 6ed2d933e1120817fe9182483a228007b18ab6ae..678e0a16b777525715862ee0e9ba98bf5d70c31f 100644 GIT binary patch delta 2190 zcmV;92yyqq1CJ4q8Gi-<0027t*>V5?0fA{lLr`;4M?xS;MME|*IW{&eGA=Oy04R}l zk-tkqQ545NYGGtyP=iB*gf(TDfz;Aqlm*pb23alo{1y1)@tzUU8ngxlQA@vu`U`3e znuDMyf@qG$qLz}^c`7K8=W_1(-0!{TaPPTbjbxRa-sFQ^zJI8NLqYdKbkS{pqX`!d zY}jIouFlL&L}+MV4_M52=QV3JKKHLV5=mVFON;QRqH0CqN#W_WqH6N4aF>#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={kmxMcDuq&|sK|D-|LyEfcU(9!1As znFif_OxdhMoqLGMbS_)eC7Qk5bWSvLV?Lux%&IsQr_;@%h;9ft39mwxT4=jm(k3?z zecbl;ntw1(a&tZcz2E=G`G2S1{aOb6&w}x^1yCKMz#~0Ifk%3b0#gw(KEkKdf!=Pk z8mXT9sQ|Ce5v`C35MIUZ_A099rW|;T5aBJGD_X^7(kweq^z69NYvBoaW5Uv6MJAVM!vZirWvtl^koNF-OrAh;(z?(~? z8yE_~fU*C5n*jgw7 zu7Apx=o~|54V{*DUUr>YTz=?+>56609#kzs2QF0bW~RoWb8yuK7fTO~qrzB`BlfYF?9 zMK~*4arU-Hgfho3&JZYeoittumZqQqV}I3Mog-R4Om)GvY2mB<)_lpr@AQ53-H&Vo z!O#^n;H7hfs)^6ArnszKXV}~UhYAqcx&@NCx_uo-gP|)Zz-%TBsmv9xbOQ^+b!mKF zoFSO^@zL%x4|}X;vb6;TxGG;#EEh2*xUn+~*QN29!=j_Q`QkZi_IA{gt&MbG8Gj$) zE>{VcdZ;eA>(cmKo+ixv=;!X!ZC%!WGWC%T{AQlGfWxBmyZ{f|rSX}~q_H;@O0z0< zx070BQh~ARmZu38d4UB_T^gUYN`Bgo<30L6?_0Xb(nu*>FMsr*y5Q2GhlO?K)HrlnQZ(n(r90+!GIWv#yscEW zgn`glJ_37fTDWX~Un|W}ZEih4hE7s|lcG5jR0&)aZVTxxJT)yF?jJHVPKiaQro^IQ zdPD!efodfMSf>_iaUy*QpVlxwZ!MK&D5~!74^(Twz>eys`)FlnxZPU1+JD(Oj*nnR z7b71zfsKd9T%IO~{p?hap}Aww=L0`Nz$>yvnSu~H z*H2(N0E`8I@cJh6ZOfqDk~|sJ0Ki`WaMQ7#eSJ?J`k9Z?8S6EYDHXfhuaOQsMu@P= zW(zWKu=w4RGhE*sv47u%0YHSI#nM_+*LV2vZ>AsaJ{%Z&)Eg^71VsvdL9vp*AU=YP zeMo*402+v_ZLN|Y{pqouTQ^%QJ{<-547@=jQ8}vXZS5kM`vE|HvC({|_Oj{6lh+;} zYiPB!y8dBXm$mnkV?AGD*8~|unm2=&JAVc@Gbx%QXCSm&0Do`;00z7q62O*4vMK5h z+v-UJjtggr%4Q3)JXjgCYdBWP`X+NzO9OQ*SGuyf~$p0BY>%A=#2 z7x;OF$-IK($*3Fvt~jbcobByd@gdv68Qek6>dC!#;+&?rQtWJaLrX(0|q2y}bfs_R3A< z&2-!xv+H;a^kSp=ZtZ2$ad&nlD;&1}3cGN&&q<2rNEiqW1OFWW%vtdv@|0MVr#JMQ zJl)SLaFs@aon$d1YCCjd4MW@MT-gCxSgIze=zpYjBwts)#bk5!DJOcmm_mew`y5<*y zqL{?M+dhOf)N9;^N8ra6dm!7#rxM;YkA9nWq{k@mNRLtAkshPKBR&2D|0!>|P~_AK Q00000Ne4wvM6N<$f{~>$4*&oF delta 435 zcmV;k0Zjgn5yAtI8Gi!+000dlDL?=K0EAFXR7L;)|5U~JDYo_jSDRPH_*uvJ?fL$s z;QQnD{*>GM-ShrilfUZt{^9lhT*&z4_x{-O{Rv#2V9EI}xb^~1iQe@7)8g(7UZ4B@ z|4zgB>+<*9=;^^)>d)H7pzGjuM>Jnezy3`@G2r z?{~a!Fj;`+8Gq^x2Jl;?IEV8)=fG217*|@)CCYgFze-x?IFODUIA>nWKpE+bn~n7; z-89sa>#DR>TSlqWk*!2hSN6D~Qb#VqbP~4Fk&m`@1$JGrXPIdeRE&b2Thd#{MtDK$ zpx*d3-Wx``>!oimf%|A-&-q*6KAH)e$3|6JV%HX{HY|nMnXd&JOovdH8X7#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={k3%mt0RV3K7$^(VsN*BGEMsrI=c$xTey##U?7#RMhIP(Wh-1=epled4~)6~*@ zZ^2X^4u2+Ykfm%ajLfC}f?@gdUeBbNr4jl;~e@;oW`8LoBjex3aN)p!uIE#!W~s3fyK;~@ zj~9|JQ7i>vSAA|>2W?Kp16RM_r;4R5k-}L_OpJe_7GSj$gj=ITe5|VrZZn}Q)FpXkWefZ3mLHa6ojjSgzPD@)LoxT z*MC}rQy(eu5VTZRo?SfDl1Fv*@h>KQKe*b0o zPm-k(*1YCgGVBUCdoa9JuZ%F2`M%&$IU*T)+~TguAJz*HL|6oSW>3|JBpipAvt zg8GXNe7g1R*Z+S+S(@(3Z!0g#DvHBWu7B4b|1cf9_2Yz@3WvC)Aj<~^28OrjmW%PT zuod_Ss<*9scb%Z6JRFRy6@fy&Xu-<$_VZu%&1b%xTYdb?fkW56AOH8C;Xf$et<^b9 zLM(aB{Y<$P#rauYFfcH@hFMJy(29lHAc*q?t4C_(lAKLf*&8$Zr~aM6O-j5eB_W+4_lh5=?g(!#vV54hQx zeiZl!D%LE2dkd$fe4I?2@eX_uOAdW{u>RziV|y=uJN)}EN-2aBfP8-F+V_(n403>- zHm6mvIgeJTC9m3~tsiE*`tqVZqE6)=lqo0`vF#&*75!I`TIh@_d&k*HoEtQyV-iD z%Xz2D9EQRbeYh5Nr~y=#0ZD;^+vz0$004MNL_t(2&&|%+4u6C&2tZM$Wf&dzefR%A z(^3-?6X>hnCz2Ba@RH&`m!pgy?n@#@AuLYB&}Q)FGY`?vcft0!vht0Z@M&ZeNCWXh75gzRTXR8EE3oN&6 Q00000NkvXXt^-0~f=auE-~a#s diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@2x.png index fe730945a01f64a61e2235dbe3f45b08f7729182..1e106b300d3495f865127ebecf91e970c0bfa885 100644 GIT binary patch delta 2173 zcmV-@2!i*{1OE_^8Gi-<007~;N+#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={k{f4l~)5%7MVl5yc0$UZvqqKfWdlke~T&hOrq1^y>u{nr5mN>iYdO;ezgO;ezBDP|fclFbCn zyAQ^G3*@>12mN5Nd~1l5Da`n&dqp7E4JfEO5}m#%NmvR1FzGac*~Vt<=RmC;P|zKV z1w{Y=8-E0y6^&mDzxh>R6prj?{0uI{g) zI|kZ8p_|+DWm_D80PiTAH|eFzzrH$fnQm8U2Q?%L=f#Gha~)s+=ja4zu!QwWnO34b zTz}nvna((91$DT&5eEqzkam0;Z_-PPk6kle9UQjN<|?hArEiO~W5duyCr}$cbs=c5 zgcY*cAk*(U`J{@jSZD(k@ffUKMT%`skif~&=hv%!y-r$CQ9E$yLGL(5M?AEFu1*&h zC`HUrToHOMyrVBbSxkhxUMJ1nc&zs%9e?rA0;&`-xtsK|_guIMh#ZCUss)m)BbQAz zo!w*oRL4XM=$1TLsZ_uWA^^1!fwGtgXLpf&@sdM56;#JWIp~ZKwtRKEWF-M4aN0-z z1qx??=SUA#u~7=TJzu^OWh1B?H-W2t)P=kDodpVg)+gPR zxk?%6tZ+_nL9#H<10*2f=)~((6>ny4yddoS9qb_$@lgi)@lxel787BT03~wNdA98? zQW&aRurI9cE(DUI1T;&{S7pTU(|<`o0ymDn1gZ+@pxxgXDFH2CC@=L; zfbeqF84&`n*GcDB)DE=!>#E3_`6jQwrC z#_BUDhXojWmnznJ2?;znO60I@>q7Zk-~4F0|I}==_!6(rpldRuDG@>J2!gbQ!65{v zI;W;bN8v2yGkE2Ba`m?3y|;Xc*C$X83t_CwmKOTpCLr4xxthzg;yDM-_Os22?N$;c1?|+GS40P`@h34Ha|8DelQLjPeLI&3lH-R^uk*f;4WS(f& zr)T=wx_T^LJ#z6HbmwAuj+oC7<3JHdFo58-vwU{c@yG?)yG${s_+U>xZJ_WGNtsrX zX7Rxu($^|!&~PP7RHl_=`T)rW0ECTN?BXkJLoKHo&08$vc8eiVsLNFI z-xQ#XN6&f>_&ceY>{jD&HEQk*Zbwtsh>23r{VS9Pl#Osmfz(OX4KVKOXm%QU4scV%K zs5%l2)+Y#4JV3(l3LUlBm31A%?dNWrE6(4+jF0-QgG48cTI}}Ijpi$G$OH^-wnmVV z8!ymh#POr}DC2hkKq~+MBXTw_0u9z_1PWs__Jk79-NlM*$A6)77X%B=Gyp)<&HKZ@ zR^Bupt!x;q>cea!WWE7Bw^N)6j4!{iWkmeBJjuJW>;q($qE5b>U5*Is{849pSN&C8XB{YAHP0$9*!U} zQ(#CG==2G~%zrc$FBoMboepTsadR%yX#_H3Gv;=EkD&WXlsT~L0{}$8w7k+bbobnC z?C6DNtmd)FYNiT~NRLfctfJQRJsc7~1AS*UUu#Gd=47e)5qy-<_3W1Tr@hM*(HC2> zCU>`SZb7xNyx3F~Z$sU^;rl0U3|5@IWj6YfmQ-nA$aXeb*hnC8;q)IToPuwv700&HO&2%){-RIqcUTYur`9?R8 zg6Un;I@Id!GgJQsoNSr`oot!{oot!{ooxCC?2AbvJQ_(S00000NkvXXu0mjf5qTDa delta 447 zcmV;w0YLu$5Y7XT8Gi!+007oyx*7lg0G3cpR7L;)|5U~J0au$Tw)URh`@-w}Xw3Np zS)Ix4{k7)&ujKrh-TO(x_}20L&+q+}+xr1ilg8}*yXgGl_5RcF{f*iBEV%Z~-t4>5 ziGV;=={^- z?sLQGb)?A{hr$_!z8HbH7kH=vM0x-*R~t>;jsO4v^GQTOR7l6|(&r9>FcgO2dg?%> z;=sK?5%;?Pn^T7LL?Y$@5u?06NuIR*0?Yf$Hf5Afk+lM<^ch*jvO$sU*m9J?JI7eI zGFV6+q|w~e;JI~C4Vf^@d>Wvj=fl`^u9x9wd9R%3*Q+)t%S!MU_`id^@& zY{y7-r98lZX0?YrHlfmwb?#}^1b{8g&KzmkE(L>Z&p6kME1_Z%?`+u)^el0!1<0sd p?Eyu!OMLDifi)An*I;?S-wj=m4RYIt!kPd8002ovPDHLkV1lgP^nd^W diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-29x29@3x.png index 321773cd857a8a0f0c9c7d3dc3f5ff4fb298dc10..7b5fc9609040f90032e6fb7a88ebf1af6b3dd672 100644 GIT binary patch literal 3191 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 CEh6Ip delta 691 zcmV;k0!;n)7{CRP8Gi!+002f7DP8~o0Jl&~R7L;)|5U~JDYo_jSDX9(|M~s@SH}2N z#rS{J`h3&+@cRDr`1>4br2|=<_Wb|z`~RBV`-<24{r>;E==`tb{CU#(0alua*7{P! z_>|iF0Z@&o;`@Zw`ed2Hv*!Fwin#$(m7w4Ij@kM+yZ0`*_J0?7s{u=e0YGxN=lnXn z_j;$xb)?A|hr(Z#!1DV3H@o+7qQ_N_ycmMI0acg)Gg|cf|J(EaqTu_A!rvTerUFQQ z05n|zFjFP9FmM0>0mMl}K~z}7?bK^if#bc3@hBPX@I$58-z}(ZZE!t-aOGpjNkbau@>yEzH(5Yj4kZ ziMH32XI!4~gVXNnjAvRx;Sdg^`>2DpUEwoMhTs_stABAHe$v|ToifVv60B@podBTcIqVcr1w`hG7HeY|fvLid#^Ok4NAXIXSt1 Zxpx7IC@PekH?;r&002ovPDHLkV1l|%Yo7oB diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@1x.png index 797d452e458972bab9d994556c8305db4c827017..eca545c0db553cf326d70e2ddb117c1fee7eead0 100644 GIT binary patch delta 1556 zcmV+v2J88j1DXtw8Gi-<004~sxNQIc0fA{lLr`;4M?xS;MME|*IW{&eGA=Oy04R}l zk-tkqQ545NYGGtyP=iB*gf(TDfz;Aqlm*pb23alo{1y1)@tzUU8ngxlQA@vu`U`3e znuDMyf@qG$qLz}^c`7K8=W_1(-0!{TaPPTbjbxRa-sFQ^zJI8NLqYdKbkS{pqX`!d zY}jIouFlL&L}+MV4_M52=QV3JKKHLV5=mVFON;QRqH0CqN#W_WqH6N4aF>#aC4|p~ z`!%_s@V%+WEBtD5y23vuYmx96SUZH>={k%c!SkWH3_7$;Mv8)PAyf0}GAX3L`6z%1F=n1&3uOms7`!zznQ)QL=zWy4Kj*f-LS z_O9ERHh($Gm9|o-i9X4b{F)}$PruLacYVR&AulY|fLQeyINy4-fSU^yWiqh{J8^OP zbh56QRA7fy)1j0jf&Ss?L5783GOn34prx3oEL<)v0f6xxWvY$G&bX42Vp4z-43M|B zX}bOokpTd9pOI=le$G8O69~>b#iRfmH>k`{E`Js4LO>=fO`O@XNnL$-z%h_=pac`4 z?IwB;0Qdm_4I%xnZ>1VPJ?lE{^0G521-4eJ8?+Rb4FG{~g4~+KQT6T`($MwgRA0(~ z6pqN-YN_2J9EA5^=rQ|pm3r%u@0O*Zpz5K4~;?MH6S?yOL6e*cu?+utVw&P4^jX`x?IND({&c;AS*#!wM@ zz)aV)e0b-xMFZwMAzso{u4;(DLBxpJaH91k%F;vqcTbJn^50z);C>U;%q0^CkO`#- zUGJk+d1!Uyj+(d$pxJ!1@;B%r03SX+=S)x`k}qXZ90xL0OMmTWIouITyE{oA~O zC<1W6OmB+=2T^X+k-&TFPOD~Jugx>&^9Se5F($C7TveRAOp^V8z^G%^QW(*)NuB%d zH;$191}bGDtldOgLn9L^5pNxgv400=VRvmIpZWNVYt-dsqoz0~@Wl#ssg}a180m4y zr4ud&?YrPP%P_$ivz}O;PGa2W?kEp73!F}3($;EHcd&2jdcr`J91-uSrK+Rg5CBLY zp9=Wi@i4Y;h|CAWuf0~Y!Kl5b>GiibJ%scvI47~ zFmU(3bP~G_0N27;g%m;C>Zqso^-Kz;C;7x+3&0wc}F(rvH-X@=5#jF@93< zmVMNBg==22<;EgBBP&hp0DpjAnx9u?zc=8x`R6}@St$wvUo+D6)Bgsa?m6ci?zOo; zik4KOC6H{sRZrBI^+ZOemBx2|aOdl|fM3|$Kke`ntJld2xKAuL zA_zg?&<)?Ug{9qJ9LhH0yCU@5qxJXOLeyj6eCweH{s$!C{b5k-wGICO0000+>eB z?J{?+FLkYu+4_Uk`r_>LHF~flZm0oBf#vr8%vJ>#p~!KNvqGG3)|f1T_)ydeh8$vDceZ>oNbH^|*hJ*t?Yc*1`WB&W>VYVEzu) zq#7;;VjO)t*nbgf(!`OXJBr45rP>>AQr$6c7slJWvbpNW@KTwna6d?PP>hvXCcp=4 zF;=GR@R4E7{4VU^0p4F>v^#A|>07*qoM6N<$f@?C@RsaA1 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@2x.png index 502f463a9bc882b461c96aadf492d1729e49e725..331911b8f620e3fea71fac3ce93f4a2e2015a431 100644 GIT binary patch literal 3099 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 delta 572 zcmV-C0>k~A7|H~Y8Gi!+006nq0-pc?0H{z*R7L;)|5U~JDYo_jSDXF*|5nEMy6F5^ z$M}8I`uzU?*Yf=uXr;5|{0m;6_Wb|A>ik^D_|)+I$?g3CSDK^3+eX0mD!2CP`2NN0 z{dLg!a?km&%iyTt`yiax0acdp`~T(l{$a`ZF1YpsRg(cvjDG_-U$Er-fz#Bw>2W$eUI#iU z)Wdgs8Y3U+A$Gd&{+j)d)BmGKx+43U_!tik_YlN)>$7G!hkE!s;%oku3;IwG3U^2k zw?z+HM)jB{@zFhK8P#KMSytSthr+4!c(5c%+^UBn_j%}l|2+O?a>_7qq7W zmx(qtA2nV^tZlLpy_#$U%ZNx5;$`0L&dZ!@e7rFXPGAOup%q`|03hpdtXsPP0000< KMNUMnLSTaOxiv5V diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-40x40@3x.png index 0ec303439225b78712f49115768196d8d76f6790..6e2ce81a84a19a27b0a87c5a4ecaf9e46bf2d893 100644 GIT binary patch literal 4441 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-50x50@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..5ca5ac5cf2ac9eba28d13a05e87c1dd5ef8ddb81 GIT binary patch literal 1808 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 CyD5MG literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@2x.png index 0ec303439225b78712f49115768196d8d76f6790..6e2ce81a84a19a27b0a87c5a4ecaf9e46bf2d893 100644 GIT binary patch literal 4441 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-60x60@3x.png index e9f5fea27c705180eb716271f41b582e76dcbd90..40f9cacf32b800247aafcfc960df0ecc809a0c80 100644 GIT binary patch literal 7276 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 O0000= diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-72x72@1x.png new file mode 100644 index 0000000000000000000000000000000000000000..aa3bda28309ffd27e5a2730a0d07350acfa2d603 GIT binary patch literal 2670 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 literal 0 HcmV?d00001 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@1x.png index 84ac32ae7d989f82d5e46a60405adcc8279e8001..9803d95326bfe23bceb01224175e17e2ba800488 100644 GIT binary patch literal 3094 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 diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-76x76@2x.png index 8953cba09064923c5daf2d37e7c3c836ccdd794b..42ad51d366875e3f66ed23c540098ce8e70ed80c 100644 GIT binary patch literal 6069 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 delta 1217 zcmV;y1U~z&=UXv0SHh`R7L;)|5U~JDYo_jSDRDC`1<|-SjPDL z{{Q{{{{H{}09Kk-#rR9Y_viNgVafPO!S|ls`uzR=MZfp^{QU=8od8La1X`Tr_Wmff z_5e$ivgQ1@=KMy$_g9a+`TPAle6cOJ_Fc#L7qIpvwDkd1mw$fK`6IOUD75rX!}mad zv(fMTE4=(Nx%L54lL1hVF1YpqNrC`FddBPg#_Ietx%Lrkq5wX00X1L{S%Cm9QY*av z#_Rh5PKy9KYTWbvz3BX9%J>0Hi1+#X{rLA{m%$Kamk?i!03AC38#Yrxs)5QTeTVRiEmz~MKK1WAjCw(c-JK6eox;2O)?`?TG`AHia671e^vgmp!llK zp|=5sVHk#C7=~epA~VAf-~%aPC=%Qw01h8mnSZ|p?tc*y?iZ$PR7_ceEIapF3KB14K0Pog?7wtd+^xgUCa_GVmlD z<^nU>AU_Yn-JU?NFdu|wf^bTCNf-wSBYVZltDdvGBln-YrbeGvJ!|s{#`gjN@yAMb zM6cjFz0eFECCsc|_8hTa3*9-JQGehksdoVP^K4m?&wpA~+|b%{EP5D-+7h)6CE; z*{>BP=GRR3Ea}xyV*bqry{l^J=0#DaC4ej;1qs8_by?H6Tr@7hl>UKNZt)^B&yl;)&oqzLg zcfZxpE?3k%_iTOVywh%`XVN-E#COl+($9{v(pqSQcrz=)>G!!3HeNxbXGM@})1|9g zG4*@(OBaMvY0P0_TfMFPh fVHk#CZX3S=^^2mI>Ux-D00000NkvXXu0mjfWF>>n diff --git a/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png b/ios/Runner/Assets.xcassets/AppIcon.appiconset/Icon-App-83.5x83.5@2x.png index 0467bf12aa4d28f374bb26596605a46dcbb3e7c8..35e486e629352b4de70deeea869f7ec97fd60c23 100644 GIT binary patch literal 5818 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 eU&Ci+>pT`E!l delta 1410 zcmV-|1%3LuEs6_}8Gi!+002YCyxsr+0P|2xR7L;)|5U~JDYo_jSDRDB`2GI>{Qds= z{r_0T`1}6fwc-8!#-TGX}_?g)CZq4{k!uZ_g@DrQdoW0kI zu+W69&uN^)W`CK&06mMNcYMVF00dG=L_t(|+U?wHQxh>12H+Dm+1+fh+IF>G0SjJM zkQQre1x4|G*Z==(Ot&kCnUrL4I(rf(ucITwmuHf^hXiJTkdTm&kdTm&kdTm&kdP`e zsgWG0BcWCVkVZ&2dUwN`cgM8QJb`Z7Z~e<&Yj2(}>VI$fQI%^ugM`#6By?GeadWcu z0gy9!D`m!H>Bd!JW(@avE8`|5XX(0PN}!8K>`dkavs;rHL+wy96QGNT=S@#7%xtlm zIW!++@*2zm-Py#Zr`DzqsLm!b{iskFNULSqE9A>SqHem>o31A%XL>S_5?=;V_i_y+ z(xxXhnt#r-l1Y8_*h`r?8Tr|)(RAiO)4jQR`13X0mx07C&p@KBP_2s``KEhv^|*8c z$$_T(v6^1Ig=#R}sE{vjA?ErGDZGUsyoJuWdJMc7Nb1^KF)-u<7q zPy$=;)0>vuWuK2hQhswLf!9yg`88u&eBbR8uhod?Nw09AXH}-#qOLLxeT2%C;R)QQ$Za#qp~cM&YVmS4i-*Fpd!cC zBXc?(4wcg>sHmXGd^VdE<5QX{Kyz$;$sCPl(_*-P2Iw?p^C6J2ZC!+UppiK6&y3Kmbv&O!oYF34$0Z;QO!J zOY#!`qyGH<3Pd}Pt@q*A0V=3SVtWKRR8d8Z&@)3qLPA19LPA19LPEUCUoZo%k(yku QW&i*H07*qoM6N<$g4XuU9smFU diff --git a/lib/core/app.dart b/lib/core/app.dart index d7fa68c..df12de8 100644 --- a/lib/core/app.dart +++ b/lib/core/app.dart @@ -1,29 +1,107 @@ import 'package:flutter/material.dart'; import 'package:flutter_localizations/flutter_localizations.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/notification_service.dart' show checkPendingReply, setAppForeground; import 'package:pyramid/core/router.dart'; +import 'package:pyramid/core/settings_prefs.dart'; import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/auth/login_notifier.dart'; +import 'package:pyramid/widgets/pyramid_loader.dart'; -class PyramidApp extends ConsumerWidget { +class PyramidApp extends ConsumerStatefulWidget { const PyramidApp({super.key}); @override - Widget build(BuildContext context, WidgetRef ref) { - final router = ref.watch(routerProvider); - final colorScheme = ref.watch(colorSchemeProvider); + ConsumerState createState() => _PyramidAppState(); +} - return MaterialApp.router( - title: 'Pyramid', - theme: buildTheme(colorScheme, Brightness.light), - darkTheme: buildTheme(colorScheme, Brightness.dark), - themeMode: ThemeMode.system, - routerConfig: router, - localizationsDelegates: const [ - GlobalMaterialLocalizations.delegate, - GlobalWidgetsLocalizations.delegate, - GlobalCupertinoLocalizations.delegate, - ], - supportedLocales: const [Locale('de'), Locale('en')], +class _PyramidAppState extends ConsumerState + with WidgetsBindingObserver { + bool _prefsLoaded = false; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + _loadPersistedPrefs(); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + super.dispose(); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + switch (state) { + case AppLifecycleState.resumed: + setAppForeground(true); + checkPendingReply(ref); + case AppLifecycleState.paused: + case AppLifecycleState.detached: + // Clears heartbeat so PushService.kt shows FCM notifications immediately. + // Background Matrix syncs must not re-set the heartbeat (see notification_service.dart). + setAppForeground(false); + default: + break; + } + } + + Future _loadPersistedPrefs() async { + final saved = await loadThemePrefs(); + if (!mounted) return; + ref.read(themeModeProvider.notifier).state = saved.isDark; + ref.read(accentProvider.notifier).state = saved.accentIdx; + ref.read(radiusProvider.notifier).state = saved.radius; + ref.read(motionProvider.notifier).state = saved.motion; + setState(() => _prefsLoaded = true); + } + + @override + Widget build(BuildContext context) { + // Block the router from rendering until auth state is known so the + // /server page never flashes before the redirect to /app fires. + final authAsync = ref.watch(isLoggedInProvider); + if (authAsync.isLoading || !_prefsLoaded) { + return const MaterialApp( + debugShowCheckedModeBanner: false, + home: Scaffold( + backgroundColor: Color(0xFF1A1B1E), + body: Center(child: PyramidLoader(size: 80)), + ), + ); + } + + final router = ref.watch(routerProvider); + final isDark = ref.watch(themeModeProvider); + final accentIdx = ref.watch(accentProvider); + final radius = ref.watch(radiusProvider); + final density = ref.watch(densityProvider); + final motion = ref.watch(motionProvider); + final accent = accentPresets[accentIdx].color; + + return PyramidTheme( + isDark: isDark, + accent: accent, + radius: radius, + density: density, + motion: motion, + child: MaterialApp.router( + title: 'Pyramid', + theme: buildPyramidThemeData(false), + darkTheme: buildPyramidThemeData(true), + themeMode: isDark ? ThemeMode.dark : ThemeMode.light, + routerConfig: router, + localizationsDelegates: const [ + GlobalMaterialLocalizations.delegate, + GlobalWidgetsLocalizations.delegate, + GlobalCupertinoLocalizations.delegate, + ], + supportedLocales: const [Locale('de'), Locale('en')], + debugShowCheckedModeBanner: false, + ), ); } } diff --git a/lib/core/app_state.dart b/lib/core/app_state.dart new file mode 100644 index 0000000..fbf3bd6 --- /dev/null +++ b/lib/core/app_state.dart @@ -0,0 +1,207 @@ +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/settings_prefs.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/livekit_call_manager.dart'; +import 'package:pyramid/core/voip_manager.dart'; +import 'package:pyramid/features/rooms/rooms_provider.dart'; + +// ─── Theme state ────────────────────────────────────────────────────────────── + +final themeModeProvider = StateProvider((ref) => true); // true = dark +final accentProvider = StateProvider((ref) => 0); // index into accent presets + +const accentPresets = [ + (name: 'amber', color: PyramidColors.accentAmber), + (name: 'coral', color: PyramidColors.accentCoral), + (name: 'mint', color: PyramidColors.accentMint), + (name: 'violet', color: PyramidColors.accentViolet), + (name: 'cobalt', color: PyramidColors.accentCobalt), + (name: 'lime', color: PyramidColors.accentLime), +]; + +final radiusProvider = StateProvider((ref) => 12); +final densityProvider = StateProvider((ref) => 1); +final motionProvider = StateProvider((ref) => 1); + +// ─── Shell layout state ─────────────────────────────────────────────────────── + +final railCollapsedProvider = StateProvider((ref) => false); + +// True while the app window is the foreground / focused window. +// Set to false when the lifecycle transitions to inactive/paused/detached. +final windowFocusedProvider = StateProvider((ref) => true); +final membersPanelOpenProvider = StateProvider((ref) => false); + +// Set to an eventId to make the open chat scroll to + briefly highlight that +// message (e.g. when tapping a search result). ChatView consumes and clears it. +final pendingJumpEventProvider = StateProvider((ref) => null); + +// Currently selected room ID (null = no room selected) +final activeRoomIdProvider = StateProvider((ref) => null); + +// ─── Share-Target ("Teilen nach Pyramid", Android) ─────────────────────────── +// Von MainActivity.kt via MethodChannel geliefert; AppShell zeigt dann den +// Raum-Picker. paths = bereits in den App-Cache kopierte Dateien. +class PendingShare { + final String? text; + final List paths; + const PendingShare({this.text, this.paths = const []}); + + bool get isEmpty => (text == null || text!.isEmpty) && paths.isEmpty; +} + +final pendingShareProvider = StateProvider((ref) => null); + +// Space filter: null = all rooms, otherwise space ID +final activeSpaceIdProvider = StateProvider((ref) => 'dms'); + +// ─── Modal state ───────────────────────────────────────────────────────────── + +enum ModalKind { none, settings, search } + +final activeModalProvider = StateProvider((ref) => ModalKind.none); + +// ─── Call state ─────────────────────────────────────────────────────────────── + +final callStateProvider = ChangeNotifierProvider((ref) { + return LiveKitCallManager.instance; +}); + +final voipStateProvider = ChangeNotifierProvider((ref) { + return PyramidVoipManager.instance; +}); + +final incomingCallProvider = StateProvider((ref) => null); + +// ─── View mode (chat / voice) ───────────────────────────────────────────────── + +enum ViewMode { chat, voice } + +final viewModeProvider = StateProvider((ref) => ViewMode.chat); + +// ─── Spaces from Matrix ─────────────────────────────────────────────────────── + +final spacesProvider = StreamProvider>((ref) async* { + final client = await ref.watch(matrixClientProvider.future); + yield _getSpaces(client); + await for (final _ in client.onSync.stream) { + yield _getSpaces(client); + } +}); + +List _getSpaces(Client client) { + return client.rooms.where((r) => r.isSpace).toList(); +} + +// ─── Toast notifications ───────────────────────────────────────────────────── + +class ToastMessage { + final String text; + final String icon; + ToastMessage(this.text, this.icon); +} + +final toastProvider = StateProvider((ref) => null); + +// Remembers the last active room per space section (key = spaceId or null) +final lastRoomPerSpaceProvider = StateProvider>((ref) => {}); + +// Space IDs the user just accepted an invite for. The server confirms the join +// immediately, but Continuwuity's incremental /sync sometimes does not flip the +// local membership from invite → join. We treat these as joined optimistically +// so the UI switches to the channel list (channels load via the space hierarchy). +// Persisted so the user does not have to re-accept on every app start. +final forceJoinedSpacesProvider = + StateNotifierProvider>( + (ref) => StringSetPref('force_joined_spaces')); + +// ─── Voice channel state ────────────────────────────────────────────────────── + +// ID of the Matrix room the user is currently in as a voice channel (null = none) +final activeVoiceRoomIdProvider = StateProvider((ref) => null); + +const kVoicePresenceType = 'io.pyramid.voice.presence'; + +// Local override cache: spaceId → bannerMxcUri (set immediately on upload, +// before the server sync delivers the state event back) +final spaceBannerOverrideProvider = + StateProvider>((ref) => {}); + +// ─── Server-level banner ────────────────────────────────────────────────────── +// Persisted to SharedPreferences keyed by homeserver URL. +// Key in store: homeserverUrl → mxcUri + +class ServerBannerNotifier extends AsyncNotifier> { + @override + Future> build() => loadAllServerBanners(); + + Future set(String homeserverUrl, String? mxcUri) async { + final current = Map.from(state.valueOrNull ?? {}); + if (mxcUri == null || mxcUri.isEmpty) { + current.remove(homeserverUrl); + } else { + current[homeserverUrl] = mxcUri; + } + await saveServerBanner(homeserverUrl, mxcUri); + state = AsyncData(current); + } +} + +final serverBannerProvider = + AsyncNotifierProvider>( + ServerBannerNotifier.new, +); + +// Active voice participants for a room, read from Matrix state events +final voiceParticipantsProvider = + Provider.family>, String>((ref, roomId) { + ref.watch(roomListProvider); // Rebuild on every sync so presence updates show + final client = ref.watch(matrixClientProvider).valueOrNull; + if (client == null) return []; + final room = client.getRoomById(roomId); + if (room == null) return []; + final states = room.states[kVoicePresenceType] ?? {}; + final now = DateTime.now().millisecondsSinceEpoch; + final result = >[]; + for (final entry in states.entries) { + final content = entry.value.content; + if (content['active'] != true) continue; + final joinedAt = content['joined_at'] as int? ?? 0; + if (now - joinedAt > 10 * 60 * 1000) continue; + result.add({ + 'userId': entry.key, + 'displayName': content['display_name'] as String? ?? entry.key, + 'avatarUrl': content['avatar_url'] as String?, + }); + } + + // Optimistically insert the local user immediately (state event may not + // have synced back from the server yet after joining) + final activeVoiceRoomId = ref.watch(activeVoiceRoomIdProvider); + if (activeVoiceRoomId == roomId && client.userID != null) { + final userId = client.userID!; + if (!result.any((p) => p['userId'] == userId)) { + String displayName = userId.split(':').first.replaceAll('@', ''); + String? avatarUrl; + for (final r in client.rooms) { + try { + final m = r.getParticipants().firstWhere((u) => u.id == userId); + if (m.displayName != null) { + displayName = m.displayName!; + avatarUrl = m.avatarUrl?.toString(); + break; + } + } catch (_) {} + } + result.insert(0, { + 'userId': userId, + 'displayName': displayName, + 'avatarUrl': avatarUrl, + }); + } + } + + return result; +}); diff --git a/lib/core/background_push.dart b/lib/core/background_push.dart new file mode 100644 index 0000000..1965283 --- /dev/null +++ b/lib/core/background_push.dart @@ -0,0 +1,402 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:isolate'; +import 'dart:ui'; + +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter/widgets.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; +import 'package:matrix/matrix.dart'; +import 'package:path/path.dart' as p; +import 'package:path_provider/path_provider.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:sqflite/sqflite.dart' as sqflite_native; + +const _kChannel = 'pyramid_messages'; + +/// Port name used to locate the main isolate from background isolates. +/// Registered by notification_service.dart when the app starts. +const kMainIsolateName = 'pyramid_main'; + +int _stableId(String roomId) { + var h = 0; + for (final c in roomId.codeUnits) { + h = ((h * 31) + c) & 0x7FFFFFFF; + } + return h == 0 ? 1 : h; +} + +// ── FCM background handler ──────────────────────────────────────────────────── +// Runs in its own Dart isolate (or fresh process) when the app is killed or +// backgrounded. Firebase calls this after Firebase.initializeApp() is done. + +@pragma('vm:entry-point') +Future handleBackgroundMessage(RemoteMessage message) async { + // PushService.kt handles all FCM-triggered notifications natively. + // This callback is registered for API completeness but never fires because + // FlutterFirebaseMessagingService is removed from the manifest. +} + +// ── Background engine entrypoint (killed-app E2EE work) ─────────────────────── +// PushService.kt / ReplyReceiver bootstrap a headless FlutterEngine running this +// entrypoint when the app is KILLED (no main engine). It exposes a MethodChannel +// so native can ask us to (a) decrypt a push event and update its notification, +// or (b) send an encrypted reply. Building a Matrix client here is safe ONLY +// because native gates this on the main app being dead — never two clients on +// the same olm DB at once. + +const _kBgEngineChannel = 'chat.pyramid.pyramid/bg_engine'; + +@pragma('vm:entry-point') +void notificationEngineMain() { + WidgetsFlutterBinding.ensureInitialized(); + const channel = MethodChannel(_kBgEngineChannel); + + channel.setMethodCallHandler((call) async { + try { + final args = (call.arguments as Map?)?.cast() ?? {}; + switch (call.method) { + case 'decryptAndShow': + return await _bgDecryptAndShow( + args['room_id'] as String?, + args['event_id'] as String?, + (args['notif_id'] as num?)?.toInt(), + ); + case 'sendReply': + return await _bgSendReply( + args['room_id'] as String?, + args['text'] as String?, + ); + } + } catch (e) { + print('[NOTIF-BGENGINE] handler error: $e'); + } + return false; + }); + + // Signal native that the channel handler is installed and tasks can be sent. + channel.invokeMethod('bgEngineReady'); +} + +Future _bgDecryptAndShow(String? roomId, String? eventId, int? notifId) async { + if (roomId == null || eventId == null) return false; + final client = await _buildClient(); + if (client == null) return false; + try { + final event = await client + .getEventByPushNotification( + PushNotification(roomId: roomId, eventId: eventId, devices: const []), + storeInDatabase: false, + returnNullIfSeen: false, + ) + .timeout(const Duration(seconds: 20)); + if (event == null) return false; + // Bad-encrypted body still starts with "**" — keep the native placeholder. + if (event.body.startsWith('**')) return false; + + final room = client.getRoomById(roomId); + final sender = room?.unsafeGetUserFromMemoryOrFallback(event.senderId).displayName ?? + event.senderId.split(':').first.replaceFirst('@', ''); + final title = (room?.isDirectChat ?? true) + ? sender + : '$sender · ${room?.getLocalizedDisplayname() ?? ''}'; + + // Hand the decrypted content back to native so it re-shows the SAME + // notification via NotificationHelper — that keeps the reliable + // MainActivity-based reply action (the flutter_local_notifications reply + // path doesn't fire dependably when the app is killed). + await const MethodChannel(_kBgEngineChannel).invokeMethod('showDecrypted', { + 'title': title, + 'body': _buildBody(event), + 'room_id': roomId, + 'notif_id': notifId ?? _stableId(roomId), + }); + return true; + } catch (e) { + print('[NOTIF-BGENGINE] decryptAndShow error: $e'); + return false; + } finally { + // Let the async key-backup upload settle before closing the DB — otherwise + // it logs a harmless "database_closed" error mid-flight. + await Future.delayed(const Duration(seconds: 2)); + await client.dispose().catchError((_) {}); + } +} + +Future _bgSendReply(String? roomId, String? text) async { + if (roomId == null || text == null || text.trim().isEmpty) return false; + final client = await _buildClient(); + if (client == null) return false; + try { + // A one-shot sync ensures the room and recipient device keys are present so + // the message can be encrypted. Safe here: main app is dead (native-gated). + await client.oneShotSync().timeout(const Duration(seconds: 20)).catchError((_) => null); + final room = client.getRoomById(roomId); + if (room == null) { + // Fall back to the prefs queue so the main app sends it on next launch. + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + return false; + } + await room.sendTextEvent(text.trim()); + print('[NOTIF-BGENGINE] encrypted reply sent to $roomId'); + return true; + } catch (e) { + print('[NOTIF-BGENGINE] sendReply error: $e'); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + return false; + } finally { + // Allow the encrypted send + any key upload to flush before closing the DB. + await Future.delayed(const Duration(seconds: 2)); + await client.dispose().catchError((_) {}); + } +} + +/// Stores the raw callback handle of [notificationEngineMain] so native code can +/// bootstrap the background engine. Call once at app startup. +Future registerBgEngineHandle() async { + if (!Platform.isAndroid) return; + try { + final handle = PluginUtilities.getCallbackHandle(notificationEngineMain); + if (handle == null) return; + final prefs = await SharedPreferences.getInstance(); + await prefs.setInt('bg_engine_handle', handle.toRawHandle()); + } catch (e) { + print('[NOTIF-BGENGINE] registerBgEngineHandle failed: $e'); + } +} + +// ── Build a short-lived Matrix client for background work ──────────────────── +// Uses NativeImplementationsDummy so Vodozemac runs synchronously in this +// isolate — NativeImplementationsIsolate(compute) would try to spawn a +// sub-isolate, which fails inside a Firebase background isolate. + +Future _buildClient() async { + try { + // vodozemac may already be initialised in this isolate (e.g. a decrypt task + // ran before this reply task reused the same engine). Calling init() twice + // throws — swallow it so it doesn't fail the whole client build. + try { + await vod.init(); + } catch (_) {} + + final appDir = await getApplicationSupportDirectory(); + final dbPath = p.join(appDir.path, 'pyramid.sqlite'); + + final db = await sqflite_native.databaseFactory + .openDatabase(dbPath) + .timeout(const Duration(seconds: 5)); + + // Prevent "database is locked" if the main process still has the DB open. + try { + await db.execute('PRAGMA busy_timeout = 5000'); + await db.execute('PRAGMA journal_mode = WAL'); + } catch (_) {} + + final sdkDb = await MatrixSdkDatabase.init('pyramid', database: db); + + final client = Client( + 'Pyramid', + database: sdkDb, + nativeImplementations: NativeImplementationsDummy(), + logLevel: Level.error, + ); + + await client + .init( + waitForFirstSync: false, + waitUntilLoadCompletedLoaded: false, + ) + .timeout(const Duration(seconds: 15)); + + return client; + } catch (e) { + print('[NOTIF-BGENGINE] _buildClient failed: $e'); + return null; + } +} + +String _buildBody(Event event) { + final msgType = event.messageType; + final rawBody = event.body; + return switch (msgType) { + 'm.text' => rawBody.length > 100 ? '${rawBody.substring(0, 100)}…' : rawBody, + 'm.image' => '📷 Bild', + 'm.video' => '🎥 Video', + 'm.audio' => '🎵 Audio', + 'm.file' => '📄 Datei', + 'm.sticker' => '🏷️ Sticker', + _ => rawBody.isEmpty ? 'Neue Nachricht' : (rawBody.length > 100 ? '${rawBody.substring(0, 100)}…' : rawBody), + }; +} + +// ── Notification action handler ─────────────────────────────────────────────── +// Called in a fresh Dart isolate when the user presses Reply or Gelesen. +// Must return quickly — Android keeps the notification's "sending" spinner +// visible until this function returns. + +@pragma('vm:entry-point') +Future handleBackgroundNotificationResponse( + NotificationResponse details) async { + WidgetsFlutterBinding.ensureInitialized(); + + print('[NOTIF-BG] handleBackgroundNotificationResponse fired'); + print('[NOTIF-BG] actionId=${details.actionId} payload=${details.payload} input=${details.input} id=${details.id}'); + + // ── Fast path: main isolate is running ─────────────────────────────────── + // If the Pyramid UI process is alive (app is backgrounded but not killed), + // forward the action directly via IsolateNameServer. This avoids starting + // any new engine and works silently without bringing the app to foreground. + final sendPort = IsolateNameServer.lookupPortByName(kMainIsolateName); + if (sendPort != null) { + print('[NOTIF-BG] main isolate alive → forwarding via IsolateNameServer'); + sendPort.send({ + 'actionId': details.actionId, + 'payload': details.payload, + 'input': details.input, + 'id': details.id, + }); + return; + } + + // ── Slow path: app was killed ───────────────────────────────────────────── + // Main isolate is gone. Dismiss the notification and, for reply actions, + // persist the text in SharedPreferences so _sendPendingReply picks it up + // the next time the app opens (via getInitialReply cold-start flow). + print('[NOTIF-BG] main isolate not running → SharedPreferences fallback'); + + final plugin = FlutterLocalNotificationsPlugin(); + await plugin.initialize( + const InitializationSettings( + android: AndroidInitializationSettings('@drawable/ic_notification')), + onDidReceiveBackgroundNotificationResponse: handleBackgroundNotificationResponse, + ); + + final roomId = details.payload; + if (roomId != null) { + await plugin.cancel(_stableId(roomId)); + print('[NOTIF-BG] cancelled notification for room $roomId'); + } else if (details.id != null) { + await plugin.cancel(details.id!); + print('[NOTIF-BG] cancelled notification id ${details.id}'); + } + + if (details.actionId != 'reply') { + print('[NOTIF-BG] not a reply action, done'); + return; + } + + final text = details.input?.trim() ?? ''; + if (text.isEmpty || roomId == null) { + print('[NOTIF-BG] text empty or roomId null, aborting'); + return; + } + + // App killed — send the encrypted reply directly from this background isolate. + // _bgSendReply falls back to the prefs queue if it can't send (so the main app + // delivers it on next launch). + final sent = await _bgSendReply(roomId, text); + print('[NOTIF-BG] background reply sent=$sent room=$roomId'); +} + +// ── Notification builder ────────────────────────────────────────────────────── + +Future _showNotif({ + required String title, + required String body, + required String? roomId, + required int notifId, +}) async { + final plugin = FlutterLocalNotificationsPlugin(); + await plugin.initialize( + const InitializationSettings( + android: AndroidInitializationSettings('@drawable/ic_notification')), + onDidReceiveBackgroundNotificationResponse: handleBackgroundNotificationResponse, + ); + + await plugin.show( + notifId, title, body, + NotificationDetails( + android: AndroidNotificationDetails( + _kChannel, 'Nachrichten', + channelDescription: 'Neue Nachrichten', + importance: Importance.high, + priority: Priority.high, + icon: '@drawable/ic_notification', + color: const Color(0xFF7B61FF), + groupKey: 'pyramid_messages', + actions: roomId != null + ? const [ + AndroidNotificationAction( + 'reply', 'Antworten', + inputs: [AndroidNotificationActionInput(label: 'Antworten…')], + allowGeneratedReplies: true, + showsUserInterface: false, // BroadcastReceiver path — app never opens + ), + AndroidNotificationAction( + 'read', 'Gelesen', + showsUserInterface: false, + ), + ] + : const [], + ), + ), + payload: roomId, + ); +} + +// ── HTTP fallback — fetch sender / room name without the SDK ────────────────── + +Future _fetchTitle( + String hs, String token, String roomId, String eventId) async { + try { + final encRoom = Uri.encodeComponent(roomId); + final encEvent = Uri.encodeComponent(eventId); + + final rawEvent = await _get( + '$hs/_matrix/client/v3/rooms/$encRoom/event/$encEvent', token); + if (rawEvent == null) return null; + + final senderId = rawEvent['sender'] as String? ?? ''; + String senderName = senderId.split(':').first.replaceFirst('@', ''); + + if (senderId.isNotEmpty) { + final encSender = Uri.encodeComponent(senderId); + final memberState = await _get( + '$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.member/$encSender', + token); + final name = memberState?['displayname'] as String?; + if (name != null && name.isNotEmpty) senderName = name; + } + + final nameState = + await _get('$hs/_matrix/client/v3/rooms/$encRoom/state/m.room.name', token); + final roomName = nameState?['name'] as String?; + + return roomName?.isNotEmpty == true + ? '$senderName · $roomName' + : senderName; + } catch (_) { + return null; + } +} + +Future?> _get(String url, String token) async { + try { + final req = await HttpClient() + .getUrl(Uri.parse(url)) + .timeout(const Duration(seconds: 8)); + req.headers.add('Authorization', 'Bearer $token'); + final res = await req.close(); + if (res.statusCode != 200) return null; + final raw = await res.transform(utf8.decoder).join(); + return jsonDecode(raw) as Map; + } catch (_) { + return null; + } +} diff --git a/lib/core/e2ee_diagnostics.dart b/lib/core/e2ee_diagnostics.dart new file mode 100644 index 0000000..5615c6e --- /dev/null +++ b/lib/core/e2ee_diagnostics.dart @@ -0,0 +1,83 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; + +class E2eeDiagEntry { + final DateTime timestamp; + final String roomId; + final String eventId; + final String sessionId; + final String error; + + const E2eeDiagEntry({ + required this.timestamp, + required this.roomId, + required this.eventId, + required this.sessionId, + required this.error, + }); + + Map toJson() => { + 'ts': timestamp.toIso8601String(), + 'room': roomId, + 'event': eventId, + 'session': sessionId, + 'error': error, + }; +} + +class E2eeDiagnosticsNotifier extends Notifier> { + static const int _maxEntries = 500; + + @override + List build() => []; + + void add(E2eeDiagEntry entry) { + final next = [...state, entry]; + state = next.length > _maxEntries ? next.sublist(next.length - _maxEntries) : next; + } + + void clear() => state = []; + + Future upload({required String serverUrl, required String token}) async { + if (state.isEmpty) return 'Keine Diagnosedaten vorhanden.'; + + final payload = utf8.encode(jsonEncode({ + 'client': 'Pyramid', + 'uploaded_at': DateTime.now().toIso8601String(), + 'entry_count': state.length, + 'entries': state.map((e) => e.toJson()).toList(), + })); + + final client = HttpClient(); + try { + final uri = Uri.parse('$serverUrl/api/e2ee-diagnostics'); + final request = await client.postUrl(uri); + request.headers.set('Content-Type', 'application/json; charset=utf-8'); + request.headers.set('Authorization', 'Bearer $token'); + request.headers.contentLength = payload.length; + request.add(payload); + final response = await request.close(); + await response.drain(); + if (response.statusCode == 200) { + final count = state.length; + clear(); + return '$count Einträge hochgeladen und lokal gelöscht.'; + } + return 'Server-Fehler: HTTP ${response.statusCode}'; + } on SocketException catch (e) { + return 'Netzwerkfehler: ${e.message}'; + } catch (e) { + return 'Fehler: $e'; + } finally { + client.close(); + } + } +} + +final e2eeDiagnosticsProvider = + NotifierProvider>( + E2eeDiagnosticsNotifier.new, +); diff --git a/lib/core/fcm_push_service.dart b/lib/core/fcm_push_service.dart new file mode 100644 index 0000000..89a4d2c --- /dev/null +++ b/lib/core/fcm_push_service.dart @@ -0,0 +1,183 @@ +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; +import 'package:flutter/foundation.dart'; +import 'package:matrix/matrix.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +// Self-hosted Sygnal instance on the Pi — must be configured with the +// Firebase service account for the 'chat-pyramid' Firebase project. +// push.element.io only supports Element's own apps and will actively reject +// chat.pyramid.pyramid pushkeys, causing the homeserver to auto-remove the pusher. +const _kGatewayUrl = 'https://push.steggi-matrix.work/_matrix/push/v1/notify'; +const _kAppId = 'chat.pyramid.pyramid'; + +// ── Foreground-Setup & Pusher-Registrierung ─────────────────────────────────── + +Future fcmDiagnostics(Client matrixClient) async { + if (!Platform.isAndroid) return 'Kein Android'; + final buf = StringBuffer(); + try { + await Firebase.initializeApp(); + buf.writeln('✓ Firebase initialisiert'); + } catch (e) { + buf.writeln('✗ Firebase-Init: $e'); + return buf.toString(); + } + try { + final settings = await FirebaseMessaging.instance.requestPermission(); + buf.writeln('✓ Berechtigung: ${settings.authorizationStatus.name}'); + } catch (e) { + buf.writeln('✗ Berechtigung: $e'); + } + try { + final token = await FirebaseMessaging.instance.getToken(); + if (token != null) { + buf.writeln('✓ FCM-Token: ${token.substring(0, 20)}…'); + } else { + buf.writeln('✗ FCM-Token: null'); + } + } catch (e) { + buf.writeln('✗ FCM-Token: $e'); + } + try { + final pushers = await matrixClient.getPushers() ?? []; + final fcmPushers = pushers.where((p) => p.appId == _kAppId).toList(); + if (fcmPushers.isEmpty) { + buf.writeln('✗ Pusher: keiner bei Synapse registriert!'); + } else { + buf.writeln('✓ Pusher: ${fcmPushers.length} registriert'); + } + } catch (e) { + buf.writeln('✗ Pusher-Abfrage: $e'); + } + return buf.toString(); +} + +Future initFcm(Client matrixClient) async { + if (!Platform.isAndroid) return; + + try { + await Firebase.initializeApp(); + } catch (_) { + // Bereits initialisiert (main.dart) oder google-services.json fehlt – weiter + } + + // Background messages are handled by handleBackgroundMessage (background_push.dart) + // via FlutterFirebaseMessagingService. It decrypts E2EE events using the Matrix + // SDK and shows notifications via flutter_local_notifications with + // showsUserInterface:false so no Activity opens when the user replies. + + // Notification-Berechtigung anfordern (Android 13+) + await FirebaseMessaging.instance.requestPermission(); + + // Foreground-Notifications unterdrücken — App zeigt selbst Nachrichten + await FirebaseMessaging.instance + .setForegroundNotificationPresentationOptions( + alert: false, + badge: false, + sound: false, + ); + + // Re-register pusher if token was refreshed while the app was killed. + final prefs = await SharedPreferences.getInstance(); + final pendingToken = prefs.getString('flutter.fcm_pending_token'); + if (pendingToken != null && matrixClient.isLogged()) { + await _registerPusher(matrixClient, pendingToken); + await prefs.remove('flutter.fcm_pending_token'); + } + + final token = pendingToken ?? await _getToken(); + if (token != null && matrixClient.isLogged()) { + await _registerPusher(matrixClient, token); + // Save homeserver + token for PushService.kt (Kotlin native notification handler) + await _saveNotifCredentials(matrixClient); + } + + // Bei Token-Refresh: Pusher + gespeicherte Credentials aktualisieren + FirebaseMessaging.instance.onTokenRefresh.listen((newToken) async { + if (matrixClient.isLogged()) { + await _registerPusher(matrixClient, newToken); + await _saveNotifCredentials(matrixClient); + } + }); +} + +Future _saveNotifCredentials(Client client) async { + try { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_homeserver', client.homeserver.toString()); + await prefs.setString('notif_access_token', client.accessToken ?? ''); + } catch (_) {} +} + +Future _getToken() async { + try { + return await FirebaseMessaging.instance.getToken(); + } catch (_) { + return null; + } +} + +Future _registerPusher(Client client, String fcmToken) async { + try { + await client.postPusher( + Pusher( + pushkey: fcmToken, + kind: 'http', + appId: _kAppId, + appDisplayName: 'Pyramid', + deviceDisplayName: client.deviceName ?? 'Android', + lang: 'de', + data: PusherData( + url: Uri.parse(_kGatewayUrl), + format: 'event_id_only', + ), + ), + append: true, + ); + } catch (e) { + debugPrint('[FCM] Pusher-Registrierung fehlgeschlagen: $e'); + } +} + +/// Tries to register the FCM pusher and returns a human-readable result string. +Future retryPusherRegistration(Client client) async { + if (!Platform.isAndroid) return 'Kein Android'; + final buf = StringBuffer(); + try { + String? token; + try { + token = await FirebaseMessaging.instance.getToken(); + } catch (e) { + return '✗ FCM-Token: $e'; + } + if (token == null) { + return '✗ FCM-Token: null (Google Play Services Problem?)'; + } + buf.writeln('✓ FCM-Token: ${token.substring(0, 20)}…'); + buf.writeln(' Gateway: $_kGatewayUrl'); + await client.postPusher( + Pusher( + pushkey: token, + kind: 'http', + appId: _kAppId, + appDisplayName: 'Pyramid', + deviceDisplayName: client.deviceName ?? 'Android', + lang: 'de', + data: PusherData( + url: Uri.parse(_kGatewayUrl), + format: 'event_id_only', + ), + ), + append: true, + ); + buf.writeln('✓ Pusher registriert'); + await _saveNotifCredentials(client); + buf.writeln('✓ Credentials gespeichert'); + } catch (e) { + buf.writeln('✗ Fehler: $e'); + } + return buf.toString().trim(); +} diff --git a/lib/core/ice_servers.dart b/lib/core/ice_servers.dart new file mode 100644 index 0000000..80020cb --- /dev/null +++ b/lib/core/ice_servers.dart @@ -0,0 +1,65 @@ +import 'dart:convert'; + +import 'package:http/http.dart' as http; + +/// Zentrale Quelle für ICE-Server (STUN/TURN), die in ALLE WebRTC-Verbindungen +/// injiziert werden (Matrix-1:1-Calls und LiveKit). +/// +/// Hintergrund: Der Heimserver hängt hinter CGNAT (keine Portfreigabe möglich). +/// Direkte Verbindungen brauchen deshalb ICE-Hole-Punching mit STUN auf beiden +/// Seiten; für harte Fälle (symmetrische Mobilfunk-NAT) können später +/// TURN-Server (z. B. Cloudflare TURN, 1 TB/Monat gratis) ergänzt werden — +/// dafür muss nur die ice.json auf dem Pi aktualisiert werden, ohne App-Update. +class IceServers { + /// Wird vom Pi ausgeliefert und kann dort per Cron mit frischen + /// TURN-Credentials befüllt werden (siehe /home/steggi/matrix/ice.json). + static const _remoteUrl = + 'https://steggi-matrix.work/.well-known/pyramid/ice.json'; + + /// Fallback, falls die ice.json nicht erreichbar ist. + static const List> _fallback = [ + { + 'urls': [ + 'stun:stun.l.google.com:19302', + 'stun:stun.cloudflare.com:3478', + ], + }, + ]; + + static List>? _cached; + static DateTime? _fetchedAt; + + /// Liefert die ICE-Server als WebRTC-`iceServers`-Maps + /// (`{'urls': [...], 'username': ..., 'credential': ...}`). + /// Ergebnis wird 30 Minuten gecached; TURN-Credentials in der ice.json + /// sollten deutlich länger gültig sein. + static Future>> get() async { + final cached = _cached; + if (cached != null && + _fetchedAt != null && + DateTime.now().difference(_fetchedAt!) < + const Duration(minutes: 30)) { + return cached; + } + try { + final resp = await http + .get(Uri.parse(_remoteUrl)) + .timeout(const Duration(seconds: 4)); + if (resp.statusCode == 200) { + final body = jsonDecode(resp.body); + final list = (body['ice_servers'] as List) + .whereType() + .map((e) => e.cast()) + .toList(); + if (list.isNotEmpty) { + _cached = list; + _fetchedAt = DateTime.now(); + return list; + } + } + } catch (_) { + // Offline/Endpoint fehlt — Fallback unten. + } + return _cached ?? _fallback; + } +} diff --git a/lib/core/livekit_call_manager.dart b/lib/core/livekit_call_manager.dart new file mode 100644 index 0000000..29e1119 --- /dev/null +++ b/lib/core/livekit_call_manager.dart @@ -0,0 +1,606 @@ +// ignore_for_file: avoid_print +import 'dart:async'; + +import 'package:flutter/foundation.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:livekit_client/livekit_client.dart'; +import 'package:matrix/matrix.dart' hide Room; +import 'package:pyramid/core/ice_servers.dart'; +import 'package:pyramid/core/livekit_token.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +const _kVoicePresenceType = 'io.pyramid.voice.presence'; + +class LiveKitCallManager with ChangeNotifier { + static final LiveKitCallManager instance = LiveKitCallManager._(); + LiveKitCallManager._(); + + // ── Publish quality presets (Streamer → Server) ────────────────────────── + static final Map qualityPresets = { + 'sd': VideoParametersPresets.h360_169, + 'hd': VideoParametersPresets.h720_169, + 'fhd': VideoParametersPresets.h1080_169, + '4k': VideoParametersPresets.h2160_169, + }; + + static const Map _screenShareEncodings = { + 'sd': VideoEncoding(maxBitrate: 500_000, maxFramerate: 10), + 'hd': VideoEncoding(maxBitrate: 1_500_000, maxFramerate: 15), + 'fhd': VideoEncoding(maxBitrate: 2_500_000, maxFramerate: 20), + '4k': VideoEncoding(maxBitrate: 4_000_000, maxFramerate: 30), + }; + + Room? _room; + EventsListener? _roomEventListener; + String _displayName = ''; + bool isConnecting = false; + String? error; + bool isMuted = false; + bool isCameraOff = false; + bool isScreenSharing = false; + String _localQualityKey = 'hd'; + String _subscribeQualityKey = 'auto'; // 'auto' | 'low' | 'medium' | 'high' + String? _currentScreenShareSourceId; + LocalVideoTrack? _screenShareTrack; + bool isDeafened = false; + bool _mutedBeforeDeafen = false; + bool isVoiceChannel = false; + String? _matrixRoomId; + Client? _matrixClient; + Timer? _presenceHeartbeat; + + Timer? _statsTimer; + + bool get isActive => _room != null || isConnecting; + Room? get room => _room; + String? get currentRoomId => _matrixRoomId; + String get displayName => _displayName; + bool get noiseSuppression => false; + String get currentQualityKey => _localQualityKey; + String get subscribeQualityKey => _subscribeQualityKey; + + VideoParameters get _currentQuality => + qualityPresets[_localQualityKey] ?? VideoParametersPresets.h720_169; + + void _onRoomChanged() => notifyListeners(); + + void _cleanUpAfterDisconnect() { + _stopStatsLogging(); + _presenceHeartbeat?.cancel(); + _presenceHeartbeat = null; + if (_matrixClient != null && _matrixRoomId != null) { + _writePresence(false).catchError((_) {}); + } + _roomEventListener?.dispose(); + _roomEventListener = null; + _room?.removeListener(_onRoomChanged); + _room = null; + _displayName = ''; + isConnecting = false; + error = null; + isMuted = false; + isCameraOff = false; + isScreenSharing = false; + isDeafened = false; + isVoiceChannel = false; + _mutedBeforeDeafen = false; + _screenShareTrack = null; + _currentScreenShareSourceId = null; + _matrixRoomId = null; + _matrixClient = null; + notifyListeners(); + } + + Future _writePresence(bool active) async { + final client = _matrixClient; + final roomId = _matrixRoomId; + final userId = client?.userID; + if (client == null || roomId == null || userId == null) return; + try { + Map content; + if (active) { + // Resolve display name + avatar from any joined room's member state + User? member; + for (final r in client.rooms) { + final participants = r.getParticipants(); + try { + member = participants.firstWhere((u) => u.id == userId); + if (member.displayName != null || member.avatarUrl != null) break; + } catch (_) {} + } + content = { + 'active': true, + 'joined_at': DateTime.now().millisecondsSinceEpoch, + 'display_name': member?.displayName ?? userId, + if (member?.avatarUrl != null) 'avatar_url': member!.avatarUrl.toString(), + }; + } else { + content = {'active': false}; + } + await client.setRoomStateWithKey(roomId, _kVoicePresenceType, userId, content); + } catch (e) { + print('[VoicePresence] $e'); + } + } + + Future startCall({ + required String roomName, + required String roomDisplayName, + required String identity, + bool audioOnly = false, + bool voiceChannel = false, + Client? matrixClient, + String? matrixRoomId, + }) async { + if (isActive) return; + + final url = 'wss://livekit.steggi-matrix.work'; + + isConnecting = true; + isVoiceChannel = voiceChannel; + error = null; + _displayName = roomDisplayName; + isCameraOff = audioOnly; + isMuted = false; + isScreenSharing = false; + isDeafened = false; + _mutedBeforeDeafen = false; + _localQualityKey = 'hd'; + _subscribeQualityKey = 'auto'; + _matrixClient = matrixClient; + _matrixRoomId = matrixRoomId; + notifyListeners(); + + try { + final token = LiveKitTokenGenerator.generate( + roomName: roomName, + identity: identity, + displayName: identity, + ttlSeconds: 21600, + ); + + final room = Room( + roomOptions: const RoomOptions( + adaptiveStream: false, // Matches FluffyChat fix + dynacast: true, + ), + ); + room.addListener(_onRoomChanged); + + // Eigene ICE-Server (STUN/TURN aus ice.json) mitgeben. Client-seitige + // iceServers ERSETZEN die vom LiveKit-Server gelieferten — die zeigten + // bisher auf einen hinter CGNAT unerreichbaren coturn. + RTCConfiguration rtcConfig = const RTCConfiguration(); + try { + final ice = await IceServers.get(); + rtcConfig = RTCConfiguration( + iceServers: ice + .map((m) => RTCIceServer( + urls: m['urls'] is List + ? List.from(m['urls'] as List) + : [m['urls'] as String], + username: m['username'] as String?, + credential: m['credential'] as String?, + )) + .toList(), + ); + } catch (e) { + print('[LiveKit] ICE server fetch error: $e'); + } + + await room.connect( + url, + token, + connectOptions: ConnectOptions(rtcConfiguration: rtcConfig), + ); + + _room = room; + isConnecting = false; + notifyListeners(); + + if (voiceChannel && matrixClient != null && matrixRoomId != null) { + await _writePresence(true); + _presenceHeartbeat = Timer.periodic(const Duration(seconds: 30), (_) { + _writePresence(true).catchError((_) {}); + }); + } + + _roomEventListener = room.createListener() + ..on((_) => notifyListeners()) + ..on((event) { + if (event.publication.source == TrackSource.screenShareVideo) { + isScreenSharing = false; + _currentScreenShareSourceId = null; + _screenShareTrack = null; + } + notifyListeners(); + }) + ..on((event) { + final pub = event.publication; + if (_subscribeQualityKey != 'auto' && pub.kind == TrackType.VIDEO) { + pub.setVideoQuality(_videoQualityFromKey(_subscribeQualityKey)); + } + // Ausgabelautstärke aus den Einstellungen auf neue Audio-Tracks. + if (pub.kind == TrackType.AUDIO) { + try { + rtc.Helper.setVolume( + _outputVolume.clamp(0.0, 2.0), event.track.mediaStreamTrack); + } catch (_) {} + } + notifyListeners(); + }) + ..on((_) => notifyListeners()) + ..on((_) => notifyListeners()) + ..on((_) => notifyListeners()) + ..on((_) => notifyListeners()) + ..on((_) => notifyListeners()) + ..on((_) { + _cleanUpAfterDisconnect(); + }); + + // In den Einstellungen gewählte Geräte anwenden (voice_*_device Prefs). + // Stale-IDs (abgestecktes Headset etc.) werden gegen die aktuell + // vorhandenen Geräte validiert und sonst ignoriert. + String? prefMic, prefSpeaker, prefCam; + var deviceIds = {}; + try { + final prefs = await SharedPreferences.getInstance(); + _outputVolume = prefs.getDouble('voice_output_volume') ?? 1.0; + prefMic = prefs.getString('voice_mic_device'); + prefSpeaker = prefs.getString('voice_speaker_device'); + prefCam = prefs.getString('voice_camera_device'); + final devices = await rtc.navigator.mediaDevices.enumerateDevices(); + deviceIds = devices.map((d) => d.deviceId).toSet(); + } catch (e) { + print('[LiveKit] Device prefs/enumerate error: $e'); + } + if (prefMic != null && !deviceIds.contains(prefMic)) prefMic = null; + if (prefSpeaker != null && !deviceIds.contains(prefSpeaker)) prefSpeaker = null; + if (prefCam != null && !deviceIds.contains(prefCam)) prefCam = null; + + await room.localParticipant?.setMicrophoneEnabled( + true, + audioCaptureOptions: + prefMic != null ? AudioCaptureOptions(deviceId: prefMic) : null, + ); + + if (prefSpeaker != null) { + try { + await rtc.Helper.selectAudioOutput(prefSpeaker); + } catch (e) { + print('[LiveKit] selectAudioOutput error: $e'); + } + } + + if (!audioOnly) { + try { + await room.localParticipant?.setCameraEnabled( + true, + cameraCaptureOptions: CameraCaptureOptions( + deviceId: prefCam, + params: _currentQuality, + ), + ); + } catch (e) { + print('[LiveKit] Failed to enable camera: $e'); + } + } + + _startStatsLogging(); + } catch (e) { + print('[VOIP] Start call error: $e'); + isConnecting = false; + error = e.toString(); + _cleanUpAfterDisconnect(); + } + } + + VideoQuality _videoQualityFromKey(String key) { + switch (key) { + case 'low': return VideoQuality.LOW; + case 'medium': return VideoQuality.MEDIUM; + case 'high': return VideoQuality.HIGH; + default: return VideoQuality.HIGH; // auto defaults to high + } + } + + // ── Ausgabelautstärke (Settings-Slider "voice_output_volume") ───────────── + double _outputVolume = 1.0; + + /// Live-Anwendung des Lautstärke-Sliders auf alle Remote-Audio-Tracks. + Future setOutputVolume(double v) async { + _outputVolume = v; + final room = _room; + if (room == null) return; + for (final p in room.remoteParticipants.values) { + for (final pub in p.audioTrackPublications) { + final t = pub.track; + if (t != null) { + try { + await rtc.Helper.setVolume(v.clamp(0.0, 2.0), t.mediaStreamTrack); + } catch (_) {} + } + } + } + } + + Future setSubscribeQuality(String key) async { + print('[LiveKit] Viewer changing subscribe quality to: $key'); + _subscribeQualityKey = key; + if (_room == null) { notifyListeners(); return; } + + final quality = _videoQualityFromKey(key); + for (final p in _room!.remoteParticipants.values) { + for (final pub in p.videoTrackPublications) { + if (pub.kind == TrackType.VIDEO) { + print('[LiveKit] Setting subscription quality for ${p.identity} to $quality'); + pub.setVideoQuality(quality); + } + } + } + notifyListeners(); + } + + Future toggleMute() async { + isMuted = !isMuted; + notifyListeners(); + await _room?.localParticipant?.setMicrophoneEnabled(!isMuted); + } + + Future toggleDeafen() async { + if (!isDeafened) { + _mutedBeforeDeafen = isMuted; + isDeafened = true; + if (!isMuted) { + await _room?.localParticipant?.setMicrophoneEnabled(false); + isMuted = true; + } + } else { + isDeafened = false; + if (!_mutedBeforeDeafen) { + await _room?.localParticipant?.setMicrophoneEnabled(true); + isMuted = false; + } + } + _applyDeafen(); + notifyListeners(); + } + + void _applyDeafen() { + if (_room == null) return; + for (final p in _room!.remoteParticipants.values) { + for (final trackPub in p.audioTrackPublications) { + final track = trackPub.track; + if (track != null) { + track.mediaStreamTrack.enabled = !isDeafened; + } + } + } + } + + Future toggleCamera() async { + if (isCameraOff) { + try { + await _room?.localParticipant?.setCameraEnabled( + true, + cameraCaptureOptions: CameraCaptureOptions(params: _currentQuality), + ); + isCameraOff = false; + } catch (e) { + print('[LiveKit] toggleCamera ON error: $e'); + } + } else { + try { + await _room?.localParticipant?.setCameraEnabled(false); + } catch (e) { + print('[LiveKit] toggleCamera OFF error: $e'); + } + isCameraOff = true; + } + notifyListeners(); + } + + Future toggleScreenShare() async { + if (isScreenSharing) { + await stopScreenShare(); + } else { + try { + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows) { + final sources = await rtc.desktopCapturer.getSources(types: [rtc.SourceType.Screen, rtc.SourceType.Window]); + if (sources.isNotEmpty) { + await startScreenShare(sources.first.id); + return; + } + } + + await _room?.localParticipant?.setScreenShareEnabled(true); + isScreenSharing = true; + notifyListeners(); + } catch (e) { + print('[ScreenShare] Toggle error: $e'); + } + } + } + + VideoEncoding _screenShareEncoding() { + return _screenShareEncodings[_localQualityKey] ?? + const VideoEncoding(maxBitrate: 1_500_000, maxFramerate: 15); + } + + Future startScreenShare(String sourceId) async { + if (isScreenSharing) return; + try { + final encoding = _screenShareEncoding(); + final track = await LocalVideoTrack.createScreenShareTrack( + ScreenShareCaptureOptions( + sourceId: sourceId, + maxFrameRate: encoding.maxFramerate.toDouble(), + ), + ); + + if (_room == null || _room!.localParticipant == null) return; + + await _room!.localParticipant!.publishVideoTrack( + track, + publishOptions: VideoPublishOptions( + simulcast: true, + degradationPreference: DegradationPreference.balanced, + screenShareEncoding: encoding, + ), + ); + + isScreenSharing = true; + _currentScreenShareSourceId = sourceId; + _screenShareTrack = track; + notifyListeners(); + unawaited(_applyFpsToAllSimulcastLayers(track)); + } catch (e) { + print('[ScreenShare] ERROR: $e'); + } + } + + Future _applyFpsToAllSimulcastLayers(LocalVideoTrack track) async { + final targetFps = _screenShareEncoding().maxFramerate; + for (var attempt = 1; attempt <= 5; attempt++) { + await Future.delayed(const Duration(milliseconds: 600)); + if (!isScreenSharing || _screenShareTrack != track) return; + final sender = track.transceiver?.sender; + if (sender == null) continue; + final params = sender.parameters; + final encodings = params.encodings; + if (encodings == null || encodings.isEmpty) continue; + var anyUpdated = false; + for (final enc in encodings) { + if ((enc.maxFramerate ?? 0) < targetFps) { + enc.maxFramerate = targetFps; + anyUpdated = true; + } + } + if (anyUpdated) await sender.setParameters(params); + return; + } + } + + Future stopScreenShare() async { + final local = _room?.localParticipant; + if (local != null) { + final toStop = []; + for (final pub in local.videoTrackPublications) { + if (pub.source == TrackSource.screenShareVideo) { + toStop.add(pub.sid); + await pub.track?.stop(); + } + } + for (final sid in toStop) { + try { await local.removePublishedTrack(sid); } catch (_) {} + } + } + try { await _room?.localParticipant?.setScreenShareEnabled(false); } catch (_) {} + isScreenSharing = false; + _currentScreenShareSourceId = null; + _screenShareTrack = null; + notifyListeners(); + } + + Future hangUp() async { + _stopStatsLogging(); + _presenceHeartbeat?.cancel(); + _presenceHeartbeat = null; + if (_matrixClient != null && _matrixRoomId != null) { + await _writePresence(false).catchError((_) {}); + } + _roomEventListener?.dispose(); + _roomEventListener = null; + _room?.removeListener(_onRoomChanged); + await _room?.disconnect(); + _room = null; + _displayName = ''; + isConnecting = false; + error = null; + isMuted = false; + isCameraOff = false; + isScreenSharing = false; + isDeafened = false; + isVoiceChannel = false; + _mutedBeforeDeafen = false; + _screenShareTrack = null; + _currentScreenShareSourceId = null; + _matrixRoomId = null; + _matrixClient = null; + notifyListeners(); + } + + Future changeQuality(String qualityKey) async { + print('[LiveKit] Streamer changing publish quality to: $qualityKey'); + _localQualityKey = qualityKey; + final params = qualityPresets[qualityKey]; + if (params == null) { notifyListeners(); return; } + if (_room == null) { notifyListeners(); return; } + + final local = _room!.localParticipant; + if (local == null) { notifyListeners(); return; } + + if (!isCameraOff) { + await local.setCameraEnabled(false); + await Future.delayed(const Duration(milliseconds: 400)); + try { + await local.setCameraEnabled( + true, + cameraCaptureOptions: CameraCaptureOptions(params: params), + ); + } catch (e) { + print('[LiveKit] Camera restart error: $e'); + isCameraOff = true; + } + } + + if (isScreenSharing && _currentScreenShareSourceId != null) { + final sid = _currentScreenShareSourceId!; + await stopScreenShare(); + await Future.delayed(const Duration(milliseconds: 400)); + await startScreenShare(sid); + } + notifyListeners(); + } + + Future changeAudioInput(String deviceId) async { + final participant = _room?.localParticipant; + if (participant == null) return; + try { + final track = await LocalAudioTrack.create(AudioCaptureOptions(deviceId: deviceId)); + for (final pub in List.of(participant.audioTrackPublications)) { + await participant.removePublishedTrack(pub.sid); + } + await participant.publishAudioTrack(track); + if (isMuted) await participant.setMicrophoneEnabled(false); + } catch (e) { print('[Audio] error: $e'); } + } + + void setRemoteVolume(double volume) { + if (_room == null) return; + final mute = volume < 0.05; + for (final p in _room!.remoteParticipants.values) { + for (final pub in p.audioTrackPublications) { + pub.track?.mediaStreamTrack.enabled = !mute; + } + } + } + + void _applyNoiseSuppression(bool enabled) {} + + void _startStatsLogging() { + _stopStatsLogging(); + _statsTimer = Timer.periodic(const Duration(seconds: 5), (_) => _logStats()); + } + + void _stopStatsLogging() { + _statsTimer?.cancel(); + _statsTimer = null; + } + + Future _logStats() async { + if (_room == null) return; + // Basic stats logging... + print('[Stats] SubQuality: $_subscribeQualityKey | PubQuality: $_localQualityKey'); + } +} diff --git a/lib/core/livekit_token.dart b/lib/core/livekit_token.dart new file mode 100644 index 0000000..aa5e257 --- /dev/null +++ b/lib/core/livekit_token.dart @@ -0,0 +1,37 @@ +import 'package:dart_jsonwebtoken/dart_jsonwebtoken.dart'; + +class LiveKitTokenGenerator { + // Your LiveKit Credentials + static const String apiKey = 'LKMatrixPi'; + static const String apiSecret = 'rYUT2PRaKLedp5VLQCQE83eZG7fjuBWtFPXGiveBmIE'; + + static String generate({ + required String roomName, + required String identity, + String? displayName, + int ttlSeconds = 3600, // Valid for 1 hour by default + }) { + final jwt = JWT( + { + 'video': { + 'roomJoin': true, + 'room': roomName, + 'canPublish': true, + 'canSubscribe': true, + 'canPublishData': true, + }, + 'metadata': displayName ?? identity, + }, + issuer: apiKey, + subject: identity, + ); + + // Sign the token with your secret + final token = jwt.sign( + SecretKey(apiSecret), + expiresIn: Duration(seconds: ttlSeconds), + ); + + return token; + } +} diff --git a/lib/core/matrix_client.dart b/lib/core/matrix_client.dart index 0a289eb..24402dc 100644 --- a/lib/core/matrix_client.dart +++ b/lib/core/matrix_client.dart @@ -3,25 +3,78 @@ import 'dart:io'; import 'package:flutter/foundation.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:flutter_secure_storage/flutter_secure_storage.dart'; +import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; +import 'package:matrix/encryption/utils/key_verification.dart'; import 'package:matrix/matrix.dart'; import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; +import 'package:sqflite/sqflite.dart' as sqflite_native; import 'package:sqflite_common_ffi/sqflite_ffi.dart'; +import 'package:pyramid/core/voip_manager.dart'; final matrixClientProvider = FutureProvider((ref) async { - if (!kIsWeb && (Platform.isWindows || Platform.isLinux)) { + final DatabaseFactory factory; + + if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) { + // Use the native sqflite plugin — Android/iOS have system SQLite built-in, + // no .so loading required. + factory = sqflite_native.databaseFactory; + } else if (!kIsWeb) { sqfliteFfiInit(); - databaseFactory = databaseFactoryFfi; + factory = databaseFactoryFfi; + } else { + throw UnsupportedError('Web not supported'); } final appDir = await getApplicationSupportDirectory(); final dbPath = p.join(appDir.path, 'pyramid.sqlite'); - final db = await databaseFactoryFfi.openDatabase(dbPath); + final db = await factory.openDatabase(dbPath); + + // Optimization for Windows/FFI to prevent "database is locked" errors + try { + await db.execute('PRAGMA journal_mode=WAL'); + await db.execute('PRAGMA busy_timeout = 5000'); + } catch (e) { + if (kDebugMode) print('Could not set PRAGMAs: $e'); + } + final sdkDb = await MatrixSdkDatabase.init('pyramid', database: db); - final client = Client('Pyramid', database: sdkDb); - await client.init(); + final client = Client( + 'Pyramid', + database: sdkDb, + // Custom State-Events, die beim App-Start mit aus der DB geladen werden + // müssen — sonst sind Space-Banner & Voice-Presence nach Neustart leer, + // bis der jeweilige Raum vollständig nachgeladen wird. + importantStateEvents: { + 'io.pyramid.space.banner', + 'io.pyramid.voice.presence', + }, + verificationMethods: { + KeyVerificationMethod.numbers, + KeyVerificationMethod.emoji, + KeyVerificationMethod.qrShow, + }, + logLevel: kReleaseMode ? Level.warning : Level.verbose, + nativeImplementations: NativeImplementationsIsolate( + compute, + vodozemacInit: () => vod.init(), + ), + ); + + await client.init( + waitForFirstSync: false, + waitUntilLoadCompletedLoaded: false, + ); + + // Re-use or create singleton instance + try { + PyramidVoipManager.instance.client; + } catch (_) { + PyramidVoipManager(client); + } + return client; }); diff --git a/lib/core/media_cache.dart b/lib/core/media_cache.dart new file mode 100644 index 0000000..384fcd8 --- /dev/null +++ b/lib/core/media_cache.dart @@ -0,0 +1,139 @@ +import 'dart:collection'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart'; +import 'package:path_provider/path_provider.dart'; + +/// Shared, bounded LRU cache for media bytes (chat images, document previews, +/// avatars). Eviction is driven by a total byte budget plus a hard entry cap, +/// so the most-recently-viewed media (i.e. your recent messages) stays instantly +/// available while older media is dropped and re-fetched on demand. +/// +/// In addition to the in-memory layer there is a small disk layer for +/// persistent entries (avatars, banners), so they appear instantly after an +/// app restart instead of popping in once re-downloaded. +class MediaCache { + MediaCache._(); + static final MediaCache instance = MediaCache._(); + + // ~256 MB in memory, capped at 300 entries — comfortably covers the last + // ~100 messages of media per active chat without unbounded growth. + static const int _maxBytes = 256 * 1024 * 1024; + static const int _maxEntries = 300; + // Don't cache very large single files (videos etc.) — they'd evict everything. + static const int _maxEntryBytes = 32 * 1024 * 1024; + + // Disk layer: only small entries (avatars, banners), bounded total size. + static const int _maxDiskEntryBytes = 1024 * 1024; // 1 MB pro Eintrag + static const int _maxDiskTotalBytes = 64 * 1024 * 1024; // 64 MB gesamt + + final LinkedHashMap _entries = LinkedHashMap(); + int _totalBytes = 0; + + Directory? _diskDir; + bool _pruneScheduled = false; + + Uint8List? get(String key) { + final v = _entries.remove(key); + if (v != null) _entries[key] = v; // move to most-recently-used position + return v; + } + + void put(String key, Uint8List bytes) { + if (bytes.lengthInBytes > _maxEntryBytes) return; + + final existing = _entries.remove(key); + if (existing != null) _totalBytes -= existing.lengthInBytes; + + _entries[key] = bytes; + _totalBytes += bytes.lengthInBytes; + + _evict(); + } + + /// Memory lookup first, then disk. Disk hits are promoted back into memory. + Future getPersistent(String key) async { + final mem = get(key); + if (mem != null) return mem; + try { + final file = await _diskFile(key); + if (await file.exists()) { + final bytes = await file.readAsBytes(); + if (bytes.isNotEmpty) { + put(key, bytes); + // Touch für LRU-Pruning nach mtime. + file.setLastModified(DateTime.now()).catchError((_) {}); + return bytes; + } + } + } catch (_) {} + return null; + } + + /// Stores in memory and (for small entries) on disk, surviving restarts. + Future putPersistent(String key, Uint8List bytes) async { + put(key, bytes); + if (bytes.lengthInBytes > _maxDiskEntryBytes) return; + try { + final file = await _diskFile(key); + await file.writeAsBytes(bytes); + } catch (_) {} + } + + Future _diskFile(String key) async { + final dir = _diskDir ??= await _initDiskDir(); + final name = sha1.convert(utf8.encode(key)).toString(); + return File('${dir.path}${Platform.pathSeparator}$name.bin'); + } + + Future _initDiskDir() async { + final support = await getApplicationSupportDirectory(); + final dir = Directory( + '${support.path}${Platform.pathSeparator}media_cache'); + await dir.create(recursive: true); + _schedulePrune(dir); + return dir; + } + + /// Once per session: drop the oldest disk entries when over budget. + void _schedulePrune(Directory dir) { + if (_pruneScheduled) return; + _pruneScheduled = true; + Future(() async { + try { + final files = {}; + var total = 0; + await for (final e in dir.list()) { + if (e is! File) continue; + final stat = await e.stat(); + files[e] = stat; + total += stat.size; + } + if (total <= _maxDiskTotalBytes) return; + final sorted = files.entries.toList() + ..sort((a, b) => a.value.modified.compareTo(b.value.modified)); + for (final entry in sorted) { + if (total <= _maxDiskTotalBytes) break; + total -= entry.value.size; + await entry.key.delete().catchError((_) => entry.key); + } + } catch (_) {} + }); + } + + void _evict() { + while ((_totalBytes > _maxBytes || _entries.length > _maxEntries) && + _entries.isNotEmpty) { + final oldestKey = _entries.keys.first; + final removed = _entries.remove(oldestKey); + if (removed != null) _totalBytes -= removed.lengthInBytes; + } + } + + void clear() { + _entries.clear(); + _totalBytes = 0; + } +} diff --git a/lib/core/notification_service.dart b/lib/core/notification_service.dart new file mode 100644 index 0000000..9173185 --- /dev/null +++ b/lib/core/notification_service.dart @@ -0,0 +1,660 @@ +import 'dart:io'; +import 'dart:isolate'; +import 'dart:ui'; + +import 'package:flutter/services.dart'; +import 'package:flutter_local_notifications/flutter_local_notifications.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:local_notifier/local_notifier.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/background_push.dart'; +import 'package:pyramid/core/fcm_push_service.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/settings_prefs.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:windows_taskbar/windows_taskbar.dart'; + +const _kInstallChannel = MethodChannel('chat.pyramid.pyramid/install'); + +// ─── Stable notification ID per room (same algorithm as PushService.kt) ────── +// Dart's String.hashCode is randomised per-process; this gives a deterministic +// integer that matches the Kotlin side so FCM and sync notifications collapse. +int _stableRoomId(String roomId) { + var h = 0; + for (final c in roomId.codeUnits) { + h = ((h * 31) + c) & 0x7FFFFFFF; + } + return h == 0 ? 1 : h; +} + +// ─── Android plugin ─────────────────────────────────────────────────────────── + +final _androidPlugin = FlutterLocalNotificationsPlugin(); +bool _androidInitialized = false; + +// ─── IsolateNameServer port ─────────────────────────────────────────────────── +// Registered on startup so background isolates can forward notification actions +// to the running main isolate instead of starting a new Flutter engine. +ReceivePort? _mainIsolatePort; + +// Room → active Windows notification (so we can close it on room-open). +final _windowsNotifs = {}; + +// ─── Notification tap payload → navigate to room ────────────────────────────── + +final notificationTapProvider = StateProvider((ref) => null); + +// ─── Permission state (Android) ─────────────────────────────────────────────── + +/// True when the user has permanently denied notification permission on Android. +final notificationsBlockedProvider = StateProvider((ref) => false); + +// ─── Init ───────────────────────────────────────────────────────────────────── + +Future initNotifications(WidgetRef ref) async { + if (Platform.isAndroid) { + await _initAndroid(ref); + } else if (Platform.isWindows) { + await _initWindows(); + } +} + +Future _initAndroid(WidgetRef ref) async { + if (_androidInitialized) return; + _androidInitialized = true; + + // Register the IsolateNameServer port so background isolates can forward + // notification actions to us instead of starting a new Flutter engine. + _mainIsolatePort?.close(); + _mainIsolatePort = ReceivePort(); + IsolateNameServer.removePortNameMapping(kMainIsolateName); + IsolateNameServer.registerPortWithName( + _mainIsolatePort!.sendPort, kMainIsolateName); + _mainIsolatePort!.listen((msg) => _onIsolateMessage(msg, ref)); + print('[NOTIF] IsolateNameServer port registered: $kMainIsolateName'); + + await _androidPlugin.initialize( + const InitializationSettings( + android: AndroidInitializationSettings('@drawable/ic_notification'), + ), + onDidReceiveNotificationResponse: (details) { + print('[NOTIF-FG] onDidReceiveNotificationResponse fired'); + print('[NOTIF-FG] actionId=${details.actionId} payload=${details.payload} input=${details.input}'); + if (details.actionId == 'reply') { + final text = details.input?.trim() ?? ''; + final roomId = details.payload; + print('[NOTIF-FG] reply: text="$text" roomId=$roomId'); + if (text.isNotEmpty && roomId != null && roomId.isNotEmpty) { + _androidPlugin.cancel(_stableRoomId(roomId)); + ref.read(matrixClientProvider.future).then((client) async { + final room = client.getRoomById(roomId); + print('[NOTIF-FG] getRoomById → ${room != null ? 'found' : 'null'}'); + if (room != null) { + try { + await room.sendTextEvent(text); + print('[NOTIF-FG] sendTextEvent OK'); + } catch (e) { + print('[NOTIF-FG] sendTextEvent failed: $e — storing in prefs'); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + } + } else { + print('[NOTIF-FG] room null — storing in prefs, waiting for sync'); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + try { + await client.onSync.stream.first; + print('[NOTIF-FG] sync arrived — retrying _sendPendingReply'); + await _sendPendingReply(ref); + } catch (e) { + print('[NOTIF-FG] sync/send error: $e'); + } + } + }); + } else { + print('[NOTIF-FG] reply skipped: text empty or roomId null'); + } + return; + } + if (details.actionId == 'read') { + final roomId = details.payload; + if (roomId != null) _androidPlugin.cancel(_stableRoomId(roomId)); + print('[NOTIF-FG] read action — dismissed'); + return; + } + final roomId = details.payload; + print('[NOTIF-FG] tap → opening room $roomId'); + if (roomId != null && roomId.isNotEmpty) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + } + }, + // Registers the background action handler so flutter_local_notifications + // can invoke it in a fresh isolate when the app is killed and the user + // presses Reply or Gelesen on a background notification. + onDidReceiveBackgroundNotificationResponse: + handleBackgroundNotificationResponse, + ); + + // Handle notification taps from PushService.kt (native FCM notifications). + // "openRoom" arrives when app is already running and user taps a notification. + _kInstallChannel.setMethodCallHandler((call) async { + final args = call.arguments; + if (call.method == 'openRoom') { + final roomId = (args is Map ? args['room_id'] : null) as String?; + print('[NOTIF-FG] openRoom: $roomId'); + if (roomId != null && roomId.isNotEmpty) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + } + await _sendPendingReply(ref); + } else if (call.method == 'replyFromNotification') { + // Native Android path: ReplyReceiver forwarded the inline reply text via + // MethodChannel — no Activity was opened. + final roomId = (args is Map ? args['room_id'] : null) as String?; + final text = (args is Map ? args['text'] : null) as String?; + print('[NOTIF-FG] replyFromNotification: room=$roomId text=$text'); + if (roomId != null && roomId.isNotEmpty && text != null && text.isNotEmpty) { + _androidPlugin.cancel(_stableRoomId(roomId)); + Future storePending() async { + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + } + + try { + final client = await ref.read(matrixClientProvider.future); + final room = client.getRoomById(roomId); + if (room != null) { + await room.sendTextEvent(text); + print('[NOTIF-FG] replyFromNotification: sent OK'); + } else { + print('[NOTIF-FG] replyFromNotification: room null, storing in prefs'); + await storePending(); + // Retry on the next sync — room list is populated after first sync. + client.onSync.stream.first + .then((_) => _sendPendingReply(ref)) + .catchError((_) {}); + } + } catch (e) { + print('[NOTIF-FG] replyFromNotification error: $e — storing in prefs'); + await storePending(); + // Resume-based retry (checkPendingReply in app.dart) will pick this up. + } + } + } else if (call.method == 'sharedContent') { + // "Teilen nach Pyramid" während die App läuft — AppShell zeigt den Picker. + final text = (args is Map ? args['text'] : null) as String?; + final paths = (args is Map ? args['paths'] : null); + final share = PendingShare( + text: text, + paths: paths is List ? paths.whereType().toList() : const [], + ); + if (!share.isEmpty) { + ref.read(pendingShareProvider.notifier).state = share; + } + } else if (call.method == 'decryptAndUpdateNotification') { + // Called by PushService.kt after showing a "Neue Nachricht" placeholder. + // We decrypt the event here (the Matrix client has the keys) and overwrite + // the notification with the real sender name and message body. + final roomId = (args is Map ? args['room_id'] : null) as String?; + final eventId = (args is Map ? args['event_id'] : null) as String?; + final notifId = (args is Map ? args['notif_id'] : null) as int?; + if (roomId != null && roomId.isNotEmpty) { + _decryptAndUpdateNotification(ref, roomId, eventId, notifId).catchError((_) {}); + } + } + }); + + // Cold-start tap: app was killed, user tapped notification → check launch intent. + try { + final roomId = await _kInstallChannel.invokeMethod('getInitialRoomId'); + if (roomId != null && roomId.isNotEmpty) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + } + } catch (_) {} + + // Cold-start reply: app was killed, user pressed Reply → reply text is in the + // launch intent (onCreate fires instead of onNewIntent when app is killed). + try { + final reply = await _kInstallChannel.invokeMethod('getInitialReply'); + if (reply is Map) { + final roomId = reply['room_id'] as String?; + final text = reply['text'] as String?; + print('[NOTIF-REPLY] getInitialReply: roomId=$roomId text=$text'); + if (roomId != null && roomId.isNotEmpty && text != null && text.isNotEmpty) { + // Persist so _sendPendingReply sends it after the first sync. + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + // Send the app back to background immediately — the user replied from + // the notification and doesn't want the full UI to appear. + try { + await _kInstallChannel.invokeMethod('minimizeApp'); + } catch (_) {} + } + } + } catch (_) {} + + // Cold-start share: app was launched via "Teilen nach Pyramid". + try { + final share = await _kInstallChannel.invokeMethod('getInitialShare'); + if (share is Map) { + final text = share['text'] as String?; + final paths = share['paths']; + final pending = PendingShare( + text: text, + paths: paths is List ? paths.whereType().toList() : const [], + ); + if (!pending.isEmpty) { + ref.read(pendingShareProvider.notifier).state = pending; + } + } + } catch (_) {} + + final androidPlugin = _androidPlugin + .resolvePlatformSpecificImplementation< + AndroidFlutterLocalNotificationsPlugin>(); + + // Pre-create channel so it exists before the FCM background isolate runs. + await androidPlugin?.createNotificationChannel( + const AndroidNotificationChannel( + 'pyramid_messages', + 'Nachrichten', + description: 'Neue Nachrichten', + importance: Importance.high, + enableVibration: true, + playSound: true, + ), + ); + + final granted = await androidPlugin?.requestNotificationsPermission(); + if (granted == false) { + ref.read(notificationsBlockedProvider.notifier).state = true; + } + + // FCM: Firebase initialisieren + Pusher beim Homeserver registrieren. + // Use .future so we wait for the Matrix client to be fully ready + // rather than potentially getting null from .value during startup. + try { + final client = await ref.read(matrixClientProvider.future); + await initFcm(client); + // Rooms are only reliably in memory after the first sync completes. + // Send any reply that was stored while the app was killed. + client.onSync.stream.first + .then((_) => _sendPendingReply(ref)) + .catchError((_) {}); + } catch (_) {} +} + +// ─── IsolateNameServer message handler ─────────────────────────────────────── +// Called when a background isolate (handleBackgroundNotificationResponse) +// forwards a notification action to the running main isolate. + +void _onIsolateMessage(dynamic message, WidgetRef ref) { + if (message is! Map) return; + final actionId = message['actionId'] as String?; + final payload = message['payload'] as String?; + final input = message['input'] as String?; + final id = message['id'] as int?; + + print('[NOTIF-ISOLATE] action=$actionId payload=$payload input=$input'); + + switch (actionId) { + case 'reply': + final roomId = payload; + final text = (input ?? '').trim(); + if (roomId == null || roomId.isEmpty || text.isEmpty) return; + _androidPlugin.cancel(id ?? _stableRoomId(roomId)); + ref.read(matrixClientProvider.future).then((client) async { + final room = client.getRoomById(roomId); + if (room != null) { + try { + await room.sendTextEvent(text); + print('[NOTIF-ISOLATE] reply sent OK'); + } catch (e) { + print('[NOTIF-ISOLATE] sendTextEvent failed: $e — storing in prefs'); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + client.onSync.stream.first + .then((_) => _sendPendingReply(ref)) + .catchError((_) {}); + } + } else { + print('[NOTIF-ISOLATE] room not in memory — storing in prefs'); + final prefs = await SharedPreferences.getInstance(); + await prefs.setString('notif_pending_reply_room', roomId); + await prefs.setString('notif_pending_reply_text', text); + client.onSync.stream.first + .then((_) => _sendPendingReply(ref)) + .catchError((_) {}); + } + }); + + case 'read': + if (payload != null) { + _androidPlugin.cancel(_stableRoomId(payload)); + } else if (id != null) { + _androidPlugin.cancel(id); + } + print('[NOTIF-ISOLATE] read → notification dismissed'); + + default: + // Plain notification tap → navigate to room. + if (payload != null && payload.isNotEmpty) { + ref.read(activeRoomIdProvider.notifier).state = payload; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + print('[NOTIF-ISOLATE] tap → navigated to $payload'); + } + } +} + +/// Sends a reply stored by the background notification handler. +/// Called on cold start and on every app resume so no reply is ever lost. +Future _sendPendingReply(WidgetRef ref) async { + try { + final prefs = await SharedPreferences.getInstance(); + final roomId = prefs.getString('notif_pending_reply_room'); + final text = prefs.getString('notif_pending_reply_text'); + print('[NOTIF-REPLY] _sendPendingReply: roomId=$roomId text=$text'); + if (roomId == null || text == null || text.isEmpty) return; + + final client = await ref.read(matrixClientProvider.future); + print('[NOTIF-REPLY] client ready, rooms=${client.rooms.length}'); + + final room = client.getRoomById(roomId); + print('[NOTIF-REPLY] getRoomById → ${room != null ? 'found' : 'null'}'); + if (room == null) { + print('[NOTIF-REPLY] room not in memory yet, retrying after next sync'); + client.onSync.stream.first + .then((_) => _sendPendingReply(ref)) + .catchError((_) {}); + return; + } + + await room.sendTextEvent(text); + print('[NOTIF-REPLY] sendTextEvent OK, clearing prefs'); + await prefs.remove('notif_pending_reply_room'); + await prefs.remove('notif_pending_reply_text'); + } catch (e) { + print('[NOTIF-REPLY] error: $e — prefs kept for retry'); + } +} + +/// Opens the OS notification-settings screen for this app (Android only). +Future openNotificationSettings() async { + if (!Platform.isAndroid) return; + await _kInstallChannel.invokeMethod('openNotificationSettings'); +} + +/// Opens the system battery optimisation dialog for Pyramid (Android only). +/// Samsung and other OEMs kill FCM background processes unless this is set +/// to "Unrestricted". +Future openBatteryOptimizationSettings() async { + if (!Platform.isAndroid) return; + await _kInstallChannel.invokeMethod('openBatterySettings'); +} + +Future _initWindows() async { + await localNotifier.setup(appName: 'Pyramid'); +} + +// ─── Heartbeat — tells the FCM background handler the app is running ────────── + +bool _appInForeground = true; + +/// Call from the app lifecycle observer in app.dart. +void setAppForeground(bool value) { + _appInForeground = value; + if (!value && Platform.isAndroid) { + // Clear immediately so the FCM background handler runs as soon as the app + // is no longer in the foreground / is killed. + SharedPreferences.getInstance() + .then((p) => p.setInt('notif_app_heartbeat', 0)); + } +} + +void _pingHeartbeat() { + if (!Platform.isAndroid || !_appInForeground) return; + SharedPreferences.getInstance().then( + (p) => p.setInt('notif_app_heartbeat', DateTime.now().millisecondsSinceEpoch), + ); +} + +// ─── Reset notification timestamp on app resume ─────────────────────────────── +// Events that arrived while the app was backgrounded were already notified by +// the FCM background handler. Update _watchStartTime so the notification +// watcher skips those catch-up events when the app comes back to foreground. + +void resetNotificationStartTime() { + _watchStartTime = DateTime.now(); +} + +// ─── Cancel notification for a room (call when the chat is opened) ──────────── + +Future cancelNotificationForRoom(String roomId) async { + if (Platform.isAndroid && _androidInitialized) { + await _androidPlugin.cancel(_stableRoomId(roomId)); + } else if (Platform.isWindows) { + final notif = _windowsNotifs.remove(roomId); + notif?.close(); + } +} + +// ─── Decrypt & update notification (called by PushService via MethodChannel) ── +// PushService shows a "Neue Nachricht" placeholder immediately. This function +// is called while the app is backgrounded — the Matrix client has the E2EE keys +// so it can decrypt the event and overwrite the placeholder with real content. + +Future _decryptAndUpdateNotification( + WidgetRef ref, String roomId, String? eventId, int? notifId) async { + try { + final client = await ref + .read(matrixClientProvider.future) + .timeout(const Duration(seconds: 5)); + var room = client.getRoomById(roomId); + if (room == null) { + print('[NOTIF] decryptAndUpdate: room $roomId not found'); + return; + } + + // The event might not have synced yet — wait for the next sync (max 12 s). + // We use lastEvent as a proxy: after sync it will be the event we want. + Event? event = room.lastEvent; + final bool alreadyHave = + eventId == null || event?.eventId == eventId; + if (!alreadyHave || event == null) { + print('[NOTIF] decryptAndUpdate: waiting for sync to deliver $eventId'); + await client.onSync.stream.first.timeout(const Duration(seconds: 12)); + room = client.getRoomById(roomId); + if (room == null) return; + event = room.lastEvent; + } + + if (event == null) { + print('[NOTIF] decryptAndUpdate: event still null after sync'); + return; + } + if (event.type != EventTypes.Message) return; + if (event.senderId == client.userID) return; + + final rawBody = event.body; + // If decryption failed the body starts with "** Unable to decrypt" + if (rawBody.isEmpty || rawBody.startsWith('**')) { + print('[NOTIF] decryptAndUpdate: decryption failed, keeping placeholder'); + return; + } + + final notifBody = + rawBody.length > 100 ? '${rawBody.substring(0, 100)}…' : rawBody; + final sender = room.unsafeGetUserFromMemoryOrFallback(event.senderId); + final displayName = sender.displayName ?? + event.senderId.split(':').first.replaceFirst('@', ''); + final title = room.isDirectChat + ? displayName + : '$displayName · ${room.getLocalizedDisplayname()}'; + + // Overwrite the "Neue Nachricht" placeholder — same notifId so Android + // replaces the existing notification rather than stacking a new one. + await _kInstallChannel.invokeMethod('showNativeNotification', { + 'title': title, + 'body': notifBody, + 'roomId': roomId, + 'notifId': notifId ?? _stableRoomId(roomId), + }); + print('[NOTIF] decryptAndUpdate: updated notification → "$title: $notifBody"'); + } catch (e) { + print('[NOTIF] decryptAndUpdate error: $e'); + } +} + +// ─── Show notification ──────────────────────────────────────────────────────── + +Future showMessageNotification({ + required String roomId, + String? roomName, + required String senderName, + required String body, +}) async { + final title = roomName != null ? '$senderName · $roomName' : senderName; + if (Platform.isAndroid && _androidInitialized) { + // Use native Kotlin notification so the reply PendingIntent targets + // ReplyReceiver directly — the app never opens when the user replies. + try { + await _kInstallChannel.invokeMethod('showNativeNotification', { + 'title': title, + 'body': body, + 'roomId': roomId, + 'notifId': _stableRoomId(roomId), + }); + } catch (e) { + print('[NOTIF] showNativeNotification failed: $e'); + } + } else if (Platform.isWindows) { + // Close the previous notification for this room before showing a new one. + _windowsNotifs.remove(roomId)?.close(); + + final notif = LocalNotification( + identifier: 'msg_$roomId', + title: title, + body: body, + ); + notif.onShow = () {}; + _windowsNotifs[roomId] = notif; + await localNotifier.notify(notif); + + // Also flash the taskbar button + WindowsTaskbar.setFlashTaskbarAppIcon(); + } +} + +// ─── Taskbar badge (Windows) ────────────────────────────────────────────────── + +bool _badgeVisible = false; + +Future _updateTaskbar(int unreadCount) async { + if (!Platform.isWindows) return; + try { + if (unreadCount > 0 && !_badgeVisible) { + _badgeVisible = true; + await WindowsTaskbar.setProgressMode(TaskbarProgressMode.error); + } else if (unreadCount == 0 && _badgeVisible) { + _badgeVisible = false; + await WindowsTaskbar.setProgressMode(TaskbarProgressMode.noProgress); + } + } catch (_) {} +} + +// Exported so AppShell can call it when the app resumes from background. +Future checkPendingReply(WidgetRef ref) => _sendPendingReply(ref); + +// ─── Watcher provider ───────────────────────────────────────────────────────── + +final notificationWatcherProvider = Provider((ref) { + ref.watch(matrixClientProvider).whenData((client) { + _watchEvents(ref, client); + _watchBadge(client); + }); +}); + +// Set once on first _watchEvents call so we can skip catchup events from the +// initial SDK sync (they were already shown by the FCM background handler). +DateTime? _watchStartTime; + +void _watchEvents(Ref ref, Client client) { + _watchStartTime ??= DateTime.now(); + client.onNotification.stream.listen((Event event) { + if (event.type != EventTypes.Message) return; + if (event.senderId == client.userID) return; + + // Skip events that predate this app session — the FCM background handler + // already showed a notification for them while the app was killed. + if (event.originServerTs.isBefore(_watchStartTime!)) return; + + // ── Master notification toggle (desktop/Windows setting) ────────────── + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + if (!ref.read(notifDesktopProvider)) return; + } + + final roomId = event.room.id; + // Suppress only when the window is focused AND the room is currently open. + // If the window is minimized or in the background, always show the notification. + final windowFocused = ref.read(windowFocusedProvider); + if (windowFocused && roomId == ref.read(activeRoomIdProvider)) return; + + final room = event.room; + if (room.membership != Membership.join) return; + + // ── Mention-only filter ─────────────────────────────────────────────── + if (ref.read(notifMentionOnlyDmProvider)) { + final myId = client.userID ?? ''; + // Check MSC3952 m.mentions field first, then fall back to body scan. + final mentionedIds = (event.content + .tryGetMap('m.mentions') + ?.tryGetList('user_ids')) ?? + []; + final bodyMentionsUs = event.body.contains(myId) || + event.body.contains('@${myId.split(':').first.replaceFirst('@', '')}'); + if (!mentionedIds.contains(myId) && !bodyMentionsUs) return; + } + + // ── Build notification body ─────────────────────────────────────────── + final rawBody = event.body; + final showPreview = ref.read(notifPreviewProvider); + final notifBody = showPreview + ? (rawBody.length > 100 ? '${rawBody.substring(0, 100)}…' : rawBody) + : 'Neue Nachricht'; + + final sender = room.unsafeGetUserFromMemoryOrFallback(event.senderId); + final displayName = sender.displayName ?? + event.senderId.split(':').first.replaceFirst('@', ''); + + showMessageNotification( + roomId: roomId, + roomName: room.isDirectChat ? null : room.getLocalizedDisplayname(), + senderName: displayName, + body: notifBody, + ); + }); +} + +void _watchBadge(Client client) { + client.onSync.stream.listen( + (_) { + try { + final total = client.rooms + .where((r) => r.membership == Membership.join) + .fold(0, (sum, r) => sum + r.notificationCount); + _updateTaskbar(total); + _pingHeartbeat(); // keep PushService.kt from double-notifying + } catch (_) {} + }, + onError: (_) {}, + cancelOnError: false, + ); +} diff --git a/lib/core/router.dart b/lib/core/router.dart index 58f4872..d887390 100644 --- a/lib/core/router.dart +++ b/lib/core/router.dart @@ -3,17 +3,14 @@ import 'package:go_router/go_router.dart'; import 'package:pyramid/features/auth/login_notifier.dart'; import 'package:pyramid/features/auth/login_page.dart'; import 'package:pyramid/features/auth/server_page.dart'; -import 'package:pyramid/features/chat/chat_page.dart'; -import 'package:pyramid/features/rooms/rooms_page.dart'; -import 'package:pyramid/features/settings/settings_page.dart'; -import 'package:pyramid/layout/shell_page.dart'; +import 'package:pyramid/layout/app_shell.dart'; final routerProvider = Provider((ref) { final isLoggedIn = ref.watch(isLoggedInProvider).valueOrNull ?? false; final hasServer = ref.watch(homeserverProvider) != null; return GoRouter( - initialLocation: '/rooms', + initialLocation: '/app', redirect: (context, state) { final loc = state.matchedLocation; final onAuth = loc == '/login' || loc == '/server'; @@ -24,7 +21,7 @@ final routerProvider = Provider((ref) { return null; } - if (isLoggedIn && onAuth) return '/rooms'; + if (isLoggedIn && onAuth) return '/app'; return null; }, routes: [ @@ -36,23 +33,9 @@ final routerProvider = Provider((ref) { path: '/login', builder: (context, state) => const LoginPage(), ), - ShellRoute( - builder: (context, state, child) => ShellPage(child: child), - routes: [ - GoRoute( - path: '/rooms', - builder: (context, state) => const RoomsPage(), - ), - GoRoute( - path: '/chat/:roomId', - builder: (context, state) => - ChatPage(roomId: state.pathParameters['roomId']!), - ), - GoRoute( - path: '/settings', - builder: (context, state) => const SettingsPage(), - ), - ], + GoRoute( + path: '/app', + builder: (context, state) => const AppShell(), ), ], ); diff --git a/lib/core/settings_prefs.dart b/lib/core/settings_prefs.dart new file mode 100644 index 0000000..7fd2ae4 --- /dev/null +++ b/lib/core/settings_prefs.dart @@ -0,0 +1,136 @@ +import 'dart:convert'; + +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +// ── Generic SharedPreferences-backed bool notifier ────────────────────────── + +class BoolPref extends StateNotifier { + final String _key; + + BoolPref(this._key, bool defaultValue) : super(defaultValue) { + _load(defaultValue); + } + + Future _load(bool def) async { + final p = await SharedPreferences.getInstance(); + if (mounted) state = p.getBool(_key) ?? def; + } + + Future set(bool v) async { + state = v; + final p = await SharedPreferences.getInstance(); + await p.setBool(_key, v); + } + + void toggle() => set(!state); +} + +// ── Generic SharedPreferences-backed String-Set notifier ─────────────────── + +class StringSetPref extends StateNotifier> { + final String _key; + + StringSetPref(this._key) : super({}) { + _load(); + } + + Future _load() async { + final p = await SharedPreferences.getInstance(); + final list = p.getStringList(_key); + if (mounted && list != null) state = list.toSet(); + } + + Future add(String v) async { + if (state.contains(v)) return; + state = {...state, v}; + final p = await SharedPreferences.getInstance(); + await p.setStringList(_key, state.toList()); + } + + Future remove(String v) async { + if (!state.contains(v)) return; + state = {...state}..remove(v); + final p = await SharedPreferences.getInstance(); + await p.setStringList(_key, state.toList()); + } +} + +// ── Notification preferences ───────────────────────────────────────────────── + +final notifDesktopProvider = + StateNotifierProvider((ref) => BoolPref('notif_desktop', true)); + +final notifSoundProvider = + StateNotifierProvider((ref) => BoolPref('notif_sound', true)); + +final notifPreviewProvider = + StateNotifierProvider((ref) => BoolPref('notif_preview', true)); + +final notifMentionOnlyDmProvider = + StateNotifierProvider((ref) => BoolPref('notif_mention_dm', false)); + +// ── Privacy preferences ────────────────────────────────────────────────────── + +final privacyPresenceProvider = + StateNotifierProvider((ref) => BoolPref('privacy_presence', true)); + +final privacyReadReceiptsProvider = + StateNotifierProvider((ref) => BoolPref('privacy_read_receipts', true)); + +final privacyTypingProvider = + StateNotifierProvider((ref) => BoolPref('privacy_typing', true)); + +// ── Theme persistence helpers ──────────────────────────────────────────────── + +Future saveThemePrefs({ + bool? isDark, + int? accentIdx, + double? radius, + double? motion, +}) async { + final p = await SharedPreferences.getInstance(); + if (isDark != null) await p.setBool('theme_dark', isDark); + if (accentIdx != null) await p.setInt('theme_accent', accentIdx); + if (radius != null) await p.setDouble('theme_radius', radius); + if (motion != null) await p.setDouble('theme_motion', motion); +} + +Future<({bool isDark, int accentIdx, double radius, double motion})> + loadThemePrefs() async { + final p = await SharedPreferences.getInstance(); + return ( + isDark: p.getBool('theme_dark') ?? true, + accentIdx: p.getInt('theme_accent') ?? 0, + radius: p.getDouble('theme_radius') ?? 12.0, + motion: p.getDouble('theme_motion') ?? 1.0, + ); +} + +// ── Server banner persistence ───────────────────────────────────────────────── +// Stored as a single JSON map under 'server_banners': homeserverUrl → mxcUri + +const _kServerBannersKey = 'server_banners'; + +Future> loadAllServerBanners() async { + final p = await SharedPreferences.getInstance(); + final raw = p.getString(_kServerBannersKey); + if (raw == null) return {}; + try { + final decoded = jsonDecode(raw) as Map; + return decoded.map((k, v) => MapEntry(k, v as String)); + } catch (_) { + return {}; + } +} + +Future saveServerBanner(String homeserverUrl, String? mxcUri) async { + final p = await SharedPreferences.getInstance(); + final current = await loadAllServerBanners(); + if (mxcUri == null || mxcUri.isEmpty) { + current.remove(homeserverUrl); + } else { + current[homeserverUrl] = mxcUri; + } + await p.setString(_kServerBannersKey, jsonEncode(current)); +} diff --git a/lib/core/theme.dart b/lib/core/theme.dart index 60f07d1..b7d1574 100644 --- a/lib/core/theme.dart +++ b/lib/core/theme.dart @@ -1,24 +1,151 @@ import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -final colorSchemeProvider = Provider((ref) { - return ColorScheme.fromSeed( - seedColor: const Color(0xFF6B4FA0), - brightness: Brightness.light, - ); -}); +// Pyramid design tokens — matching mockup CSS variables exactly +class PyramidColors { + const PyramidColors._(); -ThemeData buildTheme(ColorScheme colorScheme, Brightness brightness) { - final scheme = brightness == Brightness.dark - ? ColorScheme.fromSeed( - seedColor: const Color(0xFF6B4FA0), - brightness: Brightness.dark, - ) - : colorScheme; + // Dark theme + static const bg0 = Color(0xFF0A0A0C); + static const bg1 = Color(0xFF111114); + static const bg2 = Color(0xFF17171C); + static const bg3 = Color(0xFF1E1E25); + static const bgHover = Color(0xFF232330); + static const bgActive = Color(0xFF2A2A38); + static const border = Color(0xFF25252E); + static const borderStrong = Color(0xFF32323D); + static const fg = Color(0xFFECECF0); + static const fgMuted = Color(0xFFA4A4B0); + static const fgDim = Color(0xFF6F6F7D); + + // Light theme + static const bg0Light = Color(0xFFF5F4F0); + static const bg1Light = Color(0xFFFFFFFF); + static const bg2Light = Color(0xFFFAF9F5); + static const bg3Light = Color(0xFFF0EEEA); + static const bgHoverLight = Color(0xFFE9E7E1); + static const bgActiveLight = Color(0xFFDFDCD3); + static const borderLight = Color(0xFFE5E2DC); + static const borderStrongLight = Color(0xFFD3CFC6); + static const fgLight = Color(0xFF1A1A1F); + static const fgMutedLight = Color(0xFF54545E); + static const fgDimLight = Color(0xFF8A8A92); + + // Semantic colors (same in both themes) + static const danger = Color(0xFFE5484D); + static const success = Color(0xFF30A46C); + static const online = Color(0xFF4ADE80); + static const away = Color(0xFFFACC15); + static const busy = Color(0xFFF87171); + + // Accent presets — default: amber hsl(42 95% 58%) + static const accentAmber = Color(0xFFF5A614); + static const accentCoral = Color(0xFFED6951); + static const accentMint = Color(0xFF3DB88A); + static const accentViolet = Color(0xFFB67EEA); + static const accentCobalt = Color(0xFF5BA3F5); + static const accentLime = Color(0xFF8EC63F); + + static const accentFg = Color(0xFF0B0B0D); +} + +class PyramidTheme extends InheritedWidget { + final bool isDark; + final Color accent; + final double radius; + final double density; + final double motion; + + const PyramidTheme({ + super.key, + required super.child, + this.isDark = true, + this.accent = PyramidColors.accentAmber, + this.radius = 12, + this.density = 1, + this.motion = 1, + }); + + static PyramidTheme of(BuildContext context) { + return context.dependOnInheritedWidgetOfExactType()!; + } + + Color get bg0 => isDark ? PyramidColors.bg0 : PyramidColors.bg0Light; + Color get bg1 => isDark ? PyramidColors.bg1 : PyramidColors.bg1Light; + Color get bg2 => isDark ? PyramidColors.bg2 : PyramidColors.bg2Light; + Color get bg3 => isDark ? PyramidColors.bg3 : PyramidColors.bg3Light; + Color get bgHover => isDark ? PyramidColors.bgHover : PyramidColors.bgHoverLight; + Color get bgActive => isDark ? PyramidColors.bgActive : PyramidColors.bgActiveLight; + Color get border => isDark ? PyramidColors.border : PyramidColors.borderLight; + Color get borderStrong => isDark ? PyramidColors.borderStrong : PyramidColors.borderStrongLight; + Color get fg => isDark ? PyramidColors.fg : PyramidColors.fgLight; + Color get fgMuted => isDark ? PyramidColors.fgMuted : PyramidColors.fgMutedLight; + Color get fgDim => isDark ? PyramidColors.fgDim : PyramidColors.fgDimLight; + Color get danger => PyramidColors.danger; + Color get online => PyramidColors.online; + Color get away => PyramidColors.away; + Color get busy => PyramidColors.busy; + Color get accentSoft => accent.withAlpha(36); // ~14% + Color get accentGlow => accent.withAlpha(89); // ~35% + Color get accentFg => PyramidColors.accentFg; + + double get rSm => radius * 0.6; + double get rBase => radius; + double get rLg => radius * 1.5; + double get rXl => radius * 2; + + double get rowPadY => 10 * density; + double get rowPadX => 12 * density; + double get msgGap => 16 * density; + + Duration get durationFast => const Duration(milliseconds: 150); + Duration get durationNormal => const Duration(milliseconds: 220); + Curve get springBounce => Curves.easeOutBack; + Curve get springSoft => Curves.easeOutCubic; + + @override + bool updateShouldNotify(PyramidTheme oldWidget) => + isDark != oldWidget.isDark || + accent != oldWidget.accent || + radius != oldWidget.radius || + density != oldWidget.density || + motion != oldWidget.motion; +} + +// Inter ist als Asset gebündelt (pubspec `fonts:`) — kein Laufzeit-Download. +TextStyle _base(Color color) => TextStyle(fontFamily: 'Inter', color: color); + +ThemeData buildPyramidThemeData(bool isDark) { + final fg = isDark ? PyramidColors.fg : PyramidColors.fgLight; + final bg1 = isDark ? PyramidColors.bg1 : PyramidColors.bg1Light; + final accent = PyramidColors.accentAmber; return ThemeData( - colorScheme: scheme, useMaterial3: true, - dividerTheme: const DividerThemeData(space: 1, thickness: 1), + fontFamily: 'Inter', + brightness: isDark ? Brightness.dark : Brightness.light, + scaffoldBackgroundColor: bg1, + colorScheme: ColorScheme( + brightness: isDark ? Brightness.dark : Brightness.light, + primary: accent, + onPrimary: PyramidColors.accentFg, + secondary: accent, + onSecondary: PyramidColors.accentFg, + error: PyramidColors.danger, + onError: Colors.white, + surface: bg1, + onSurface: fg, + ), + textTheme: TextTheme( + bodyMedium: _base(fg).copyWith(fontSize: 14), + bodySmall: _base(fg).copyWith(fontSize: 12, color: isDark ? PyramidColors.fgMuted : PyramidColors.fgMutedLight), + labelSmall: _base(fg).copyWith(fontSize: 11, color: isDark ? PyramidColors.fgDim : PyramidColors.fgDimLight), + ), + dividerTheme: DividerThemeData( + color: isDark ? PyramidColors.border : PyramidColors.borderLight, + thickness: 1, + space: 1, + ), + splashFactory: NoSplash.splashFactory, + highlightColor: Colors.transparent, ); } diff --git a/lib/core/update_checker.dart b/lib/core/update_checker.dart index f48ac27..8883284 100644 --- a/lib/core/update_checker.dart +++ b/lib/core/update_checker.dart @@ -1,6 +1,7 @@ import 'dart:convert'; import 'dart:io'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:http/http.dart' as http; import 'package:package_info_plus/package_info_plus.dart'; @@ -55,7 +56,27 @@ bool _isNewer((int, int, int) remote, (int, int, int) local) { return remote.$3 > local.$3; } -String? _findDownloadUrl(List assets) { +// Rewrite the host in a Gitea asset URL to always use the configured base, +// so downloads work from outside the home network once nginx is set up. +String? _rewriteHost(String? url) { + if (url == null) return null; + return url.replaceFirst(RegExp(r'https?://[^/]+'), _kGiteaBase); +} + +// Device ABIs in preference order (e.g. [arm64-v8a, armeabi-v7a, armeabi]), +// fetched once from the platform. Used to pick the matching split APK. +Future> _deviceAbis() async { + if (!Platform.isAndroid) return const []; + try { + final abis = await const MethodChannel('chat.pyramid.pyramid/install') + .invokeListMethod('getAbis'); + return abis?.map((a) => a.toLowerCase()).toList() ?? const []; + } catch (_) { + return const []; + } +} + +String? _findDownloadUrl(List assets, List abis) { if (assets.isEmpty) return null; final list = assets.cast>(); @@ -71,6 +92,12 @@ String? _findDownloadUrl(List assets) { return pick((n) => n.endsWith('.exe')) ?? pick((n) => n.endsWith('.msix')); } if (Platform.isAndroid) { + // Prefer the split APK matching the device's best ABI, then weaker ABIs. + // Fall back to any APK so fat-APK releases (pre-split) keep working. + for (final abi in abis) { + final url = pick((n) => n.endsWith('.apk') && n.contains(abi)); + if (url != null) return url; + } return pick((n) => n.endsWith('.apk')); } return null; @@ -78,38 +105,53 @@ String? _findDownloadUrl(List assets) { // ─── Fetch ──────────────────────────────────────────────────────────────────── -Future _fetchLatestRelease() async { +Future _fetchLatestRelease(List abis) async { + // Fetch enough releases to find the highest version even if they were + // created out of chronological order (Gitea sorts by created_at, not semver). + final uri = Uri.parse( + '$_kGiteaBase/api/v1/repos/$_kGiteaRepo/releases?limit=20', + ); + // Let network/timeout exceptions propagate so the provider shows an error + // state instead of silently appearing as "up to date". + final response = await http + .get(uri, headers: {'Accept': 'application/json'}) + .timeout(const Duration(seconds: 10)); + + if (response.statusCode != 200) { + throw Exception('Gitea antwortete mit ${response.statusCode}'); + } + try { - final uri = Uri.parse( - '$_kGiteaBase/api/v1/repos/$_kGiteaRepo/releases?limit=1', - ); - final response = await http - .get(uri, headers: {'Accept': 'application/json'}) - .timeout(const Duration(seconds: 10)); - - if (response.statusCode != 200) return null; - final list = json.decode(response.body) as List; if (list.isEmpty) return null; - final data = list.first as Map; - final tagName = data['tag_name'] as String? ?? ''; - if (tagName.isEmpty) return null; + // Find the release with the highest version number, ignoring drafts and + // pre-releases. This is robust even when releases are created out of order. + UpdateInfo? best; + for (final item in list) { + final data = item as Map; + if (data['draft'] == true || data['prerelease'] == true) continue; - final remoteVer = _parseVersion(tagName); - if (remoteVer == null) return null; + final tagName = data['tag_name'] as String? ?? ''; + if (tagName.isEmpty) continue; - final assets = (data['assets'] as List?) ?? []; - final downloadUrl = _findDownloadUrl(assets); + final remoteVer = _parseVersion(tagName); + if (remoteVer == null) continue; - return UpdateInfo( - tagName: tagName, - releaseName: data['name'] as String? ?? tagName, - body: data['body'] as String? ?? '', - htmlUrl: '$_kGiteaBase/$_kGiteaRepo/releases/tag/$tagName', - remoteVersion: remoteVer, - downloadUrl: downloadUrl, - ); + if (best == null || _isNewer(remoteVer, best.remoteVersion)) { + final assets = (data['assets'] as List?) ?? []; + final downloadUrl = _rewriteHost(_findDownloadUrl(assets, abis)); + best = UpdateInfo( + tagName: tagName, + releaseName: data['name'] as String? ?? tagName, + body: data['body'] as String? ?? '', + htmlUrl: '$_kGiteaBase/$_kGiteaRepo/releases/tag/$tagName', + remoteVersion: remoteVer, + downloadUrl: downloadUrl, + ); + } + } + return best; } catch (_) { return null; } @@ -128,7 +170,7 @@ final updateInfoProvider = FutureProvider((ref) async { await prefs.setInt(_kPrefLastCheck, DateTime.now().millisecondsSinceEpoch); - final remote = await _fetchLatestRelease(); + final remote = await _fetchLatestRelease(await _deviceAbis()); if (remote == null) return null; final info = await PackageInfo.fromPlatform(); diff --git a/lib/core/voip_manager.dart b/lib/core/voip_manager.dart new file mode 100644 index 0000000..826bd19 --- /dev/null +++ b/lib/core/voip_manager.dart @@ -0,0 +1,536 @@ +import 'dart:async'; +import 'package:flutter/foundation.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:matrix/matrix.dart'; +import 'package:shared_preferences/shared_preferences.dart'; +import 'package:webrtc_interface/webrtc_interface.dart'; +import 'package:pyramid/core/ice_servers.dart'; +import 'package:pyramid/widgets/screen_share_picker.dart'; + +class PyramidVoipManager extends ChangeNotifier implements WebRTCDelegate { + static PyramidVoipManager? _instance; + static PyramidVoipManager get instance => _instance!; + + final Client client; + late final VoIP voip; + CallSession? currentCall; + + final rtc.RTCVideoRenderer localRenderer = rtc.RTCVideoRenderer(); + final rtc.RTCVideoRenderer remoteRenderer = rtc.RTCVideoRenderer(); + bool _renderersInitialized = false; + + bool _isMicMuted = false; + bool _isCameraMuted = true; + bool _isScreensharing = false; + bool _isRemoteScreensharing = false; + bool _isDeafened = false; + bool _isUpdating = false; + String? _selectedSourceId; + String _currentQualityKey = 'hd'; + + bool get isMicMuted => _isMicMuted; + bool get isCameraMuted => _isCameraMuted; + bool get isScreensharing => _isScreensharing; + bool get isRemoteScreensharing => _isRemoteScreensharing; + bool get isDeafened => _isDeafened; + String get currentQualityKey => _currentQualityKey; + + PyramidVoipManager(this.client) { + _instance = this; + voip = VoIP(client, this); + // Suppress speakerphone call — not supported on Windows/Desktop + try { + (voip as dynamic).onConfigSpeakerphone = (bool _) async {}; + } catch (_) {} + _ensureRenderers(); + } + + Future _ensureRenderers() async { + if (_renderersInitialized) return; + try { + await localRenderer.initialize(); + await remoteRenderer.initialize(); + _renderersInitialized = true; + } catch (e) { + print('[VOIP] Renderer init error: $e'); + } + } + + @override + MediaDevices get mediaDevices => MediaDevicesWrapper(rtc.navigator.mediaDevices, this); + + @override + bool get isWeb => kIsWeb; + + @override + Future createPeerConnection( + Map configuration, [ + Map constraints = const {}, + ]) async { + // Zusätzliche ICE-Server (STUN/TURN aus ice.json) zu den vom Homeserver + // gelieferten mergen — ohne STUN scheitern Calls außerhalb des LANs, + // weil der Server hinter CGNAT hängt. + try { + final extra = await IceServers.get(); + final merged = Map.from(configuration); + final existing = + (merged['iceServers'] as List?)?.cast>() ?? []; + merged['iceServers'] = [...existing, ...extra]; + configuration = merged; + } catch (e) { + print('[VOIP] ICE server merge error: $e'); + } + return rtc.createPeerConnection(configuration, constraints); + } + + @override + Future handleNewCall(CallSession call) async { + print('[VOIP] Incoming call ${call.callId} (type: ${call.type})'); + await _ensureRenderers(); + currentCall = call; + _isCameraMuted = call.type == CallType.kVoice; + _setupCallListeners(call); + _updateInternalStates(); + notifyListeners(); + } + + Timer? _renderRefreshTimer; + void _setupCallListeners(CallSession call) { + call.onCallStateChanged.stream.listen((state) { + print('[VOIP] State: $state'); + _updateInternalStates(); + + if (state == CallState.kConnected) { + if (!_isCameraMuted) { + print('[VOIP] Ensuring camera is unmuted on connect'); + call.setLocalVideoMuted(false); + } + } + _updateRenderers(); + }); + + _renderRefreshTimer?.cancel(); + _renderRefreshTimer = Timer.periodic( + const Duration(milliseconds: 1000), // Faster polling to catch feeds + (_) => _updateRenderers(), + ); + + _updateRenderers(); + } + + void _updateInternalStates() { + if (currentCall == null) return; + final dynamic c = currentCall; + try { + _isMicMuted = c.isMicrophoneMuted == true; + _isCameraMuted = c.isLocalVideoMuted == true; + } catch (_) {} + notifyListeners(); + } + + Future _updateRenderers() async { + if (currentCall == null || _isUpdating) return; + _isUpdating = true; + + try { + await _ensureRenderers(); + final dynamic c = currentCall; + rtc.MediaStream? remote; + rtc.MediaStream? local; + + rtc.MediaStream? extract(dynamic obj) { + if (obj == null) return null; + if (obj is rtc.MediaStream) return obj; + try { return obj.stream as rtc.MediaStream?; } catch (_) {} + return null; + } + + final List feeds = []; + try { + final dynamic sdkFeeds = c.getFeeds(); + if (sdkFeeds is Iterable) feeds.addAll(sdkFeeds.toList()); + } catch (_) {} + + bool remoteScreenFound = false; + bool localScreenFound = false; + + for (final dynamic f in feeds) { + final s = extract(f); + if (s == null) continue; + + bool isLocal = false; + try { isLocal = f.isLocal == true || f.userId == client.userID; } catch (_) {} + + String purpose = 'm.usermedia'; + try { purpose = f.purpose ?? 'm.usermedia'; } catch (_) {} + + if (isLocal) { + if (local == null || purpose == 'm.screenshare') { + local = s; + if (purpose == 'm.screenshare') localScreenFound = true; + } + } else { + if (remote == null || purpose == 'm.screenshare') { + remote = s; + if (purpose == 'm.screenshare') remoteScreenFound = true; + } + } + } + + _isScreensharing = localScreenFound; + _isRemoteScreensharing = remoteScreenFound; + + if (remote == null) { + try { remote = extract(c.remoteUserMediaStream); } catch (_) {} + } + if (remote == null) { + try { remote = extract(c.remoteStream); } catch (_) {} + } + if (local == null) { + try { local = extract(c.localUserMediaStream); } catch (_) {} + } + + // Ausgabelautstärke (Settings-Slider) auf den Remote-Stream anwenden — + // nur einmal pro Stream, _updateRenderers läuft auch per Timer. + if (remote != null && remote.id != _volumeAppliedStreamId) { + _volumeAppliedStreamId = remote.id; + _remoteAudioStream = remote; + applyOutputVolume(); + } + + // Final check for tracks before assigning + bool changed = false; + if (remote != null && remote.getVideoTracks().isNotEmpty) { + if (remoteRenderer.srcObject?.id != remote.id) { + print('[VOIP] Assigning Remote Renderer: ${remote.id} (${remote.getVideoTracks().length} video tracks)'); + remoteRenderer.srcObject = remote; + changed = true; + } + } else if (remoteRenderer.srcObject != null) { + remoteRenderer.srcObject = null; + changed = true; + } + + if (local != null && local.getVideoTracks().isNotEmpty) { + if (localRenderer.srcObject?.id != local.id) { + print('[VOIP] Assigning Local Renderer: ${local.id} (${local.getVideoTracks().length} video tracks)'); + localRenderer.srcObject = local; + changed = true; + } + } else if (localRenderer.srcObject != null) { + localRenderer.srcObject = null; + changed = true; + } + + if (changed) notifyListeners(); + } catch (e) { + print('[VOIP] Error in _updateRenderers: $e'); + } finally { + _isUpdating = false; + } + } + + @override + Future handleCallEnded(CallSession session) async { + if (currentCall?.callId == session.callId) { + _renderRefreshTimer?.cancel(); + _renderRefreshTimer = null; + localRenderer.srcObject = null; + remoteRenderer.srcObject = null; + _remoteAudioStream = null; + _volumeAppliedStreamId = null; + currentCall = null; + _isScreensharing = false; + _isRemoteScreensharing = false; + notifyListeners(); + } + } + + // ── Ausgabelautstärke (Settings-Slider "voice_output_volume") ───────────── + rtc.MediaStream? _remoteAudioStream; + String? _volumeAppliedStreamId; + + /// Wendet die in den Einstellungen gewählte Ausgabelautstärke auf den + /// Remote-Audio-Stream an. Ohne [value] wird der Pref-Wert gelesen. + Future applyOutputVolume([double? value]) async { + var v = value; + if (v == null) { + try { + final prefs = await SharedPreferences.getInstance(); + v = prefs.getDouble('voice_output_volume') ?? 1.0; + } catch (_) { + v = 1.0; + } + } + final stream = _remoteAudioStream; + if (stream == null) return; + for (final track in stream.getAudioTracks()) { + try { + await rtc.Helper.setVolume(v.clamp(0.0, 2.0), track); + } catch (_) {} + } + } + + @override + Future handleMissedCall(CallSession session) async { + if (currentCall?.callId == session.callId) { + currentCall = null; + notifyListeners(); + } + } + + @override + Future handleNewGroupCall(GroupCallSession groupCall) async {} + @override + Future handleGroupCallEnded(GroupCallSession groupCall) async {} + @override + bool get canHandleNewCall => currentCall == null; + @override + Future playRingtone() async {} + @override + Future stopRingtone() async {} + @override + EncryptionKeyProvider? get keyProvider => null; + @override + Future registerListeners(CallSession session) async {} + + Future safeAction(Future Function() action) async { + try { + await action(); + await Future.delayed(const Duration(milliseconds: 1000)); + } catch (e) { + print('[VOIP] Action error: $e'); + } + _updateInternalStates(); + _updateRenderers(); + } + + Future toggleMic() async { + if (currentCall == null) return; + _isMicMuted = !_isMicMuted; + notifyListeners(); + try { + await currentCall!.setMicrophoneMuted(_isMicMuted); + } catch (e) { + _isMicMuted = !_isMicMuted; + notifyListeners(); + } + } + + Future toggleCamera() async { + if (currentCall == null) return; + _isCameraMuted = !_isCameraMuted; + notifyListeners(); + try { + await currentCall!.setLocalVideoMuted(_isCameraMuted); + for (var i = 0; i < 5; i++) { + await Future.delayed(Duration(milliseconds: 300 + (i * 200))); + await _updateRenderers(); + } + } catch (e) { + print('[VOIP] toggleCamera error: $e'); + _isCameraMuted = !_isCameraMuted; + notifyListeners(); + } + _updateInternalStates(); + await _updateRenderers(); + } + + Future toggleScreenSharing([BuildContext? context]) async { + if (currentCall == null) return; + final call = currentCall!; + + if (_isScreensharing) { + await safeAction(() => call.setScreensharingEnabled(false)); + return; + } + + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows && context != null) { + final selectedSource = await ScreenSharePicker.show(context); + if (selectedSource == null) return; + _selectedSourceId = selectedSource.id; + } else { + _selectedSourceId = null; + } + + await safeAction(() async { + await call.setScreensharingEnabled(true); + }); + } + + Future toggleDeafen() async { + _isDeafened = !_isDeafened; + notifyListeners(); + } + + Future hangup() async { + if (currentCall == null) return; + await safeAction(() async { + await currentCall!.hangup(reason: CallErrorCode.userHangup); + currentCall = null; + }); + } + + Future startCall(String roomId, {bool video = false}) async { + final room = client.getRoomById(roomId); + if (room == null) return; + await _ensureRenderers(); + _isCameraMuted = !video; + + print('[VOIP] Starting call in room $roomId (video=$video)'); + final call = await voip.inviteToCall(room, video ? CallType.kVideo : CallType.kVoice); + currentCall = call; + + _setupCallListeners(call); + + if (video) { + await Future.delayed(const Duration(milliseconds: 800)); + await call.setLocalVideoMuted(false); + await _updateRenderers(); + } + + _updateInternalStates(); + notifyListeners(); + } + + Future changeQuality(String key) async { + _currentQualityKey = key; + if (currentCall == null) { + notifyListeners(); + return; + } + + if (!_isCameraMuted) { + await toggleCamera(); + await Future.delayed(const Duration(milliseconds: 300)); + await toggleCamera(); + } + + if (_isScreensharing) { + final String? oldSource = _selectedSourceId; + await safeAction(() => currentCall!.setScreensharingEnabled(false)); + await Future.delayed(const Duration(milliseconds: 300)); + _selectedSourceId = oldSource; + await safeAction(() => currentCall!.setScreensharingEnabled(true)); + } + + notifyListeners(); + } +} + +class MediaDevicesWrapper extends MediaDevices { + final MediaDevices _delegate; + final PyramidVoipManager _manager; + MediaDevicesWrapper(this._delegate, this._manager); + + @override + Future getUserMedia(Map constraints) async { + final Map improvedConstraints = Map.from(constraints); + + final String? sourceId = _manager._selectedSourceId; + if (sourceId != null) { + if (improvedConstraints['video'] is! Map) { + improvedConstraints['video'] = {}; + } + + final v = Map.from(improvedConstraints['video']); + v['mandatory'] ??= {}; + v['mandatory']['chromeMediaSource'] = 'desktop'; + v['mandatory']['chromeMediaSourceId'] = sourceId; + improvedConstraints['video'] = v; + } + + // In den Einstellungen gewählte Geräte (voice_*_device Prefs) anwenden — + // nur wenn kein Screenshare-Source gesetzt ist (sonst nicht anfassen). + try { + final prefs = await SharedPreferences.getInstance(); + final mic = prefs.getString('voice_mic_device'); + final cam = prefs.getString('voice_camera_device'); + final speaker = prefs.getString('voice_speaker_device'); + if (mic != null && + improvedConstraints['audio'] != null && + improvedConstraints['audio'] != false) { + final a = improvedConstraints['audio'] is Map + ? Map.from(improvedConstraints['audio']) + : {}; + a['deviceId'] = mic; + a['optional'] = [ + ...?(a['optional'] as List?), + {'sourceId': mic}, + ]; + improvedConstraints['audio'] = a; + } + if (cam != null && + sourceId == null && + improvedConstraints['video'] != null && + improvedConstraints['video'] != false) { + final v = improvedConstraints['video'] is Map + ? Map.from(improvedConstraints['video']) + : {}; + v['deviceId'] = cam; + improvedConstraints['video'] = v; + } + if (speaker != null) { + rtc.Helper.selectAudioOutput(speaker).catchError((_) {}); + } + } catch (_) {} + + if (improvedConstraints['video'] != null && improvedConstraints['video'] != false) { + final String q = _manager.currentQualityKey; + int width = 1280; + int height = 720; + + if (q == 'sd') { width = 640; height = 360; } + else if (q == 'fhd') { width = 1920; height = 1080; } + else if (q == '4k') { width = 3840; height = 2160; } + + if (improvedConstraints['video'] is bool) { + improvedConstraints['video'] = { + 'width': {'ideal': width}, + 'height': {'ideal': height}, + 'frameRate': {'ideal': 30}, + }; + } else if (improvedConstraints['video'] is Map) { + final v = Map.from(improvedConstraints['video']); + v['width'] = {'ideal': width}; + v['height'] = {'ideal': height}; + improvedConstraints['video'] = v; + } + } + return _delegate.getUserMedia(improvedConstraints); + } + + @override + Future getDisplayMedia(Map constraints) async { + final String? sourceId = _manager._selectedSourceId; + if (!kIsWeb && defaultTargetPlatform == TargetPlatform.windows && sourceId != null) { + final desktopConstraints = { + 'video': { + 'mandatory': { + 'chromeMediaSource': 'desktop', + 'chromeMediaSourceId': sourceId, + }, + 'optional': [], + }, + 'audio': false, + }; + return _delegate.getDisplayMedia(desktopConstraints); + } + return _delegate.getDisplayMedia(constraints); + } + + @override + Future> enumerateDevices() => _delegate.enumerateDevices(); + @override + MediaTrackSupportedConstraints getSupportedConstraints() => _delegate.getSupportedConstraints(); + @override + set ondevicechange(Function(dynamic event)? callback) => _delegate.ondevicechange = callback; + @override + Function(dynamic event)? get ondevicechange => _delegate.ondevicechange; + @override + Future> getSources() => _delegate.getSources(); + @override + Future selectAudioOutput([AudioOutputOptions? options]) => _delegate.selectAudioOutput(options); +} diff --git a/lib/features/auth/bootstrap_dialog.dart b/lib/features/auth/bootstrap_dialog.dart new file mode 100644 index 0000000..ce08ae7 --- /dev/null +++ b/lib/features/auth/bootstrap_dialog.dart @@ -0,0 +1,534 @@ +import 'package:flutter/material.dart'; +import 'package:matrix/encryption.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/theme.dart'; + +Future showBootstrapDialog( + BuildContext context, + Client client, { + bool force = false, +}) async { + if (client.encryption == null) return; + if (!force) { + final enc = client.encryption!; + final cached = await enc.keyManager.isCached().catchError((_) => false); + if (cached && enc.crossSigning.enabled) return; + } + if (!context.mounted) return; + await showDialog( + context: context, + barrierDismissible: false, + builder: (_) => _BootstrapDialog(client: client), + ); +} + +class _BootstrapDialog extends StatefulWidget { + final Client client; + const _BootstrapDialog({required this.client}); + + @override + State<_BootstrapDialog> createState() => _BootstrapDialogState(); +} + +class _BootstrapDialogState extends State<_BootstrapDialog> { + Bootstrap? _bootstrap; + final _keyCtrl = TextEditingController(); + bool _keyLoading = false; + String? _keyError; + bool _wipe = false; + + @override + void initState() { + super.initState(); + _start(); + } + + @override + void dispose() { + _keyCtrl.dispose(); + super.dispose(); + } + + Future _start() async { + final client = widget.client; + await client.roomsLoading; + await client.accountDataLoading; + await client.userDeviceKeysLoading; + while (client.prevBatch == null) { + await client.onSyncStatus.stream.first; + } + if (!mounted) return; + setState(() { + _bootstrap = client.encryption!.bootstrap( + onUpdate: (_) { + if (mounted) setState(() {}); + }, + ); + }); + } + + void _autoAdvance(Bootstrap bs) { + switch (bs.state) { + case BootstrapState.askWipeSsss: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.wipeSsss(_wipe)); + case BootstrapState.askBadSsss: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.ignoreBadSecrets(true)); + case BootstrapState.askUseExistingSsss: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.useExistingSsss(!_wipe)); + case BootstrapState.askUnlockSsss: + // Handled by UI if oldSsssKeys exist, otherwise skip + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.unlockedSsss()); + case BootstrapState.askNewSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.newSsss()); + case BootstrapState.askWipeCrossSigning: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.wipeCrossSigning(_wipe)); + case BootstrapState.askSetupCrossSigning: + WidgetsBinding.instance.addPostFrameCallback( + (_) => bs.askSetupCrossSigning( + setupMasterKey: true, + setupSelfSigningKey: true, + setupUserSigningKey: true, + ), + ); + case BootstrapState.askWipeOnlineKeyBackup: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.wipeOnlineKeyBackup(_wipe)); + case BootstrapState.askSetupOnlineKeyBackup: + WidgetsBinding.instance + .addPostFrameCallback((_) => bs.askSetupOnlineKeyBackup(true)); + default: + break; + } + } + + Future _unlock() async { + final bs = _bootstrap; + if (bs == null || bs.newSsssKey == null) return; + final key = _keyCtrl.text.trim(); + if (key.isEmpty) { + setState(() => _keyError = 'Bitte Wiederherstellungsschlüssel eingeben.'); + return; + } + setState(() { + _keyLoading = true; + _keyError = null; + }); + try { + await bs.newSsssKey!.unlock(keyOrPassphrase: key); + Logs().d('[Bootstrap] SSSS key unlocked'); + await bs.openExistingSsss(); + Logs().d('[Bootstrap] SSSS opened, secrets cached'); + if (bs.encryption.crossSigning.enabled) { + await widget.client.encryption!.crossSigning.selfSign(recoveryKey: key); + Logs().d('[Bootstrap] Cross-signing self-signed'); + } + } on InvalidPassphraseException catch (_) { + setState( + () => _keyError = 'Falscher Schlüssel. Bitte nochmal prüfen.', + ); + } on FormatException catch (_) { + setState(() => _keyError = 'Ungültiges Format. Prüfe deinen Schlüssel.'); + } catch (e) { + setState(() => _keyError = e.toString().split('\n').first); + } finally { + if (mounted) setState(() => _keyLoading = false); + } + } + + Future _close({required bool success}) async { + if (success) { + // Download all megolm session keys from backup — bypasses + // _requestedSessionIds deduplication so previously failed decryptions + // get a second chance. + widget.client.encryption?.keyManager + .loadAllKeys() + .catchError((e) => Logs().e('[Bootstrap] loadAllKeys failed', e)); + } + if (mounted) Navigator.of(context).pop(success); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final bs = _bootstrap; + + // Waiting for bootstrap to initialise + if (bs == null || bs.state == BootstrapState.loading) { + return _Shell( + pt: pt, + title: 'Verschlüsselung einrichten', + onClose: () => _close(success: false), + child: const Center( + child: Padding( + padding: EdgeInsets.all(32), + child: CircularProgressIndicator.adaptive(), + ), + ), + ); + } + + // User must enter recovery key + if (bs.state == BootstrapState.openExistingSsss) { + return _Shell( + pt: pt, + title: 'Nachrichten entschlüsseln', + onClose: () => _close(success: false), + child: _KeyInputBody( + pt: pt, + ctrl: _keyCtrl, + loading: _keyLoading, + error: _keyError, + onUnlock: _unlock, + onWipe: () { + setState(() { + _wipe = true; + _start(); + }); + }, + ), + ); + } + + // Success — all done + if (bs.state == BootstrapState.done) { + return _Shell( + pt: pt, + title: 'Einrichtung abgeschlossen', + onClose: null, + child: _DoneBody( + pt: pt, + onClose: () => _close(success: true), + ), + ); + } + + // Error + if (bs.state == BootstrapState.error) { + return _Shell( + pt: pt, + title: 'Fehler', + onClose: () => _close(success: false), + child: _ErrorBody( + pt: pt, + onClose: () => _close(success: false), + ), + ); + } + + // Auto-advance all other (non-interactive) states + _autoAdvance(bs); + return _Shell( + pt: pt, + title: 'Verschlüsselung einrichten…', + onClose: () => _close(success: false), + child: const Center( + child: Padding( + padding: EdgeInsets.all(32), + child: CircularProgressIndicator.adaptive(), + ), + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Sub-widgets +// ───────────────────────────────────────────────────────────────────────────── + +class _Shell extends StatelessWidget { + final PyramidTheme pt; + final String title; + final VoidCallback? onClose; + final Widget child; + + const _Shell({ + required this.pt, + required this.title, + required this.onClose, + required this.child, + }); + + @override + Widget build(BuildContext context) { + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase + 4), + ), + child: ConstrainedBox( + constraints: const BoxConstraints( + maxWidth: 460, + minWidth: 320, + minHeight: 120, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Header + Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 12, 12), + child: Row( + children: [ + Icon(Icons.shield_outlined, size: 18, color: pt.accent), + const SizedBox(width: 8), + Expanded( + child: Text( + title, + style: TextStyle( + color: pt.fg, + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + ), + if (onClose != null) + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: onClose, + tooltip: 'Überspringen', + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ], + ), + ), + Divider(color: pt.border, height: 1), + child, + ], + ), + ), + ); + } +} + +class _KeyInputBody extends StatelessWidget { + final PyramidTheme pt; + final TextEditingController ctrl; + final bool loading; + final String? error; + final VoidCallback onUnlock; + final VoidCallback onWipe; + + const _KeyInputBody({ + required this.pt, + required this.ctrl, + required this.loading, + required this.error, + required this.onUnlock, + required this.onWipe, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 20, 20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Gib deinen Wiederherstellungsschlüssel ein, um deine verschlüsselten Nachrichten lesbar zu machen.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + const SizedBox(height: 16), + TextField( + controller: ctrl, + readOnly: loading, + autofocus: true, + autocorrect: false, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontFamily: 'monospace', + ), + decoration: InputDecoration( + hintText: 'EsXX XXXX XXXX XXXX XXXX XXXX XXXX XXXX', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 12), + labelText: 'Wiederherstellungsschlüssel', + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + errorText: error, + errorMaxLines: 2, + filled: true, + fillColor: pt.bg2, + prefixIcon: Icon(Icons.vpn_key_outlined, color: pt.fgDim, size: 18), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.accent), + ), + isDense: true, + contentPadding: const EdgeInsets.symmetric( + horizontal: 12, + vertical: 12, + ), + ), + cursorColor: pt.accent, + onSubmitted: (_) => onUnlock(), + ), + const SizedBox(height: 16), + SizedBox( + width: double.infinity, + child: ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + elevation: 0, + ), + onPressed: loading ? null : onUnlock, + icon: loading + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + color: pt.accentFg, + strokeWidth: 2, + ), + ) + : const Icon(Icons.lock_open_outlined, size: 18), + label: Text( + loading ? 'Entschlüssele…' : 'Nachrichten entschlüsseln', + ), + ), + ), + const SizedBox(height: 12), + // Divider + lost key option + Row( + children: [ + Expanded(child: Divider(color: pt.border)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Text('oder', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ), + Expanded(child: Divider(color: pt.border)), + ], + ), + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: OutlinedButton.icon( + style: OutlinedButton.styleFrom( + foregroundColor: PyramidColors.danger, + side: BorderSide(color: PyramidColors.danger.withAlpha(100)), + padding: const EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8), + ), + ), + onPressed: loading ? null : onWipe, + icon: const Icon(Icons.delete_outlined, size: 16), + label: const Text('Schlüssel verloren — neu einrichten', style: TextStyle(fontSize: 13)), + ), + ), + ], + ), + ); + } +} + +class _DoneBody extends StatelessWidget { + final PyramidTheme pt; + final VoidCallback onClose; + + const _DoneBody({required this.pt, required this.onClose}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon( + Icons.check_circle_outline_rounded, + color: PyramidColors.success, + size: 56, + ), + const SizedBox(height: 12), + Text( + 'Alle Schlüssel wurden erfolgreich importiert.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 6), + Text( + 'Deine verschlüsselten Nachrichten werden jetzt im Hintergrund entschlüsselt.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + elevation: 0, + ), + onPressed: onClose, + child: const Text('Fertig'), + ), + ), + ], + ), + ); + } +} + +class _ErrorBody extends StatelessWidget { + final PyramidTheme pt; + final VoidCallback onClose; + + const _ErrorBody({required this.pt, required this.onClose}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 20), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline_rounded, color: PyramidColors.danger, size: 48), + const SizedBox(height: 12), + Text( + 'Etwas ist schiefgelaufen. Versuche es erneut.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: pt.fg, + side: BorderSide(color: pt.border), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: onClose, + child: const Text('Schließen'), + ), + ), + ], + ), + ); + } +} diff --git a/lib/features/auth/login_notifier.dart b/lib/features/auth/login_notifier.dart index 6696c71..1b778ff 100644 --- a/lib/features/auth/login_notifier.dart +++ b/lib/features/auth/login_notifier.dart @@ -1,5 +1,9 @@ +import 'dart:async'; +import 'dart:io'; + import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:matrix/matrix.dart' as mx; +import 'package:pyramid/core/fcm_push_service.dart'; import 'package:pyramid/core/matrix_client.dart'; import 'package:shared_preferences/shared_preferences.dart'; @@ -74,6 +78,8 @@ class LoginNotifier extends StateNotifier { initialDeviceDisplayName: deviceName ?? 'Pyramid', ); + if (Platform.isAndroid) unawaited(initFcm(client)); + state = state.copyWith(status: LoginStatus.idle); } on mx.MatrixException catch (e) { state = state.copyWith( diff --git a/lib/features/call/mini_call_widget.dart b/lib/features/call/mini_call_widget.dart new file mode 100644 index 0000000..a3e5114 --- /dev/null +++ b/lib/features/call/mini_call_widget.dart @@ -0,0 +1,470 @@ +import 'dart:async'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/core/livekit_call_manager.dart'; +import 'package:pyramid/core/voip_manager.dart'; +import 'package:pyramid/widgets/screen_share_picker.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:livekit_client/livekit_client.dart'; + +class MiniCallWidget extends ConsumerStatefulWidget { + final dynamic call; // Can be LiveKitCallManager or PyramidVoipManager + const MiniCallWidget({super.key, required this.call}); + + @override + ConsumerState createState() => _MiniCallWidgetState(); +} + +class _MiniCallWidgetState extends ConsumerState { + int _elapsed = 0; + Timer? _timer; + bool _streamCollapsed = false; + + @override + void initState() { + super.initState(); + _timer = Timer.periodic(const Duration(seconds: 1), (_) { + if (mounted) setState(() => _elapsed++); + }); + } + + @override + void dispose() { + _timer?.cancel(); + super.dispose(); + } + + String _fmt(int s) { + final m = s ~/ 60; + final sec = s % 60; + return '${m.toString().padLeft(2, '0')}:${sec.toString().padLeft(2, '0')}'; + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final isVoip = widget.call is PyramidVoipManager; + final call = widget.call; + + final String displayName = isVoip + ? (call.currentCall?.room.getLocalizedDisplayname() ?? 'Unknown') + : call.displayName; + + final bool isConnecting = isVoip ? false : call.isConnecting; + final bool isMuted = isVoip ? call.isMicMuted : call.isMuted; + final bool isCameraOff = isVoip ? call.isCameraMuted : call.isCameraOff; + final bool isDeafened = isVoip ? call.isDeafened : call.isDeafened; + final bool isStreaming = isVoip ? call.isScreensharing : call.isScreenSharing; + + // Show stream preview if camera is on or screensharing + final showPreview = !isCameraOff || isStreaming; + // Im Querformat auf Mobilgeräten ist die Höhe knapp — Vorschau kompakter. + final compact = MediaQuery.sizeOf(context).height < 500; + final previewHeight = _streamCollapsed ? 28.0 : (compact ? 84.0 : 140.0); + + return Container( + decoration: BoxDecoration( + color: pt.bg2, + border: Border(top: BorderSide(color: pt.border)), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Stream Mini Preview (Mockup style) + if (showPreview) + AnimatedContainer( + duration: const Duration(milliseconds: 220), + curve: Curves.easeOutCubic, + height: previewHeight, + width: double.infinity, + decoration: const BoxDecoration( + color: Colors.black, + border: Border(bottom: BorderSide(color: Colors.black26)), + ), + child: Stack( + children: [ + // Stream Content + if (!_streamCollapsed) + Positioned.fill( + child: isVoip + ? rtc.RTCVideoView( + // When we're screensharing show our local stream, + // otherwise show the remote participant's stream + isStreaming ? call.localRenderer : call.remoteRenderer, + objectFit: rtc.RTCVideoViewObjectFit.RTCVideoViewObjectFitCover, + ) + : _LiveKitPreview(manager: call as LiveKitCallManager), + ), + + // Top bar of preview + Container( + height: 28, + padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.black.withAlpha(200), Colors.transparent], + ), + ), + child: Row( + children: [ + const _LiveDot(), + const SizedBox(width: 6), + Expanded( + child: Text( + isStreaming ? 'STREAMING' : 'CAMERA ON', + style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.w700, letterSpacing: 0.5), + ), + ), + GestureDetector( + onTap: () => setState(() => _streamCollapsed = !_streamCollapsed), + child: Icon( + _streamCollapsed ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded, + size: 16, + color: Colors.white70, + ), + ), + ], + ), + ), + ], + ), + ), + + // Connected info row + GestureDetector( + onTap: () => ref.read(viewModeProvider.notifier).state = ViewMode.voice, + child: Container( + padding: const EdgeInsets.fromLTRB(12, 10, 12, 10), + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + pt.online.withAlpha(46), + Colors.transparent, + ], + end: Alignment.centerRight, + ), + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + const _LiveDot(), + const SizedBox(width: 6), + Text( + isConnecting ? 'CONNECTING...' : 'VOICE CONNECTED', + style: TextStyle( + color: pt.online, + fontSize: 10, + fontWeight: FontWeight.w800, + letterSpacing: 0.8, + ), + ), + ], + ), + const SizedBox(height: 2), + Text( + displayName, + style: TextStyle( + color: pt.fg, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + overflow: TextOverflow.ellipsis, + ), + Text( + _fmt(_elapsed), + style: TextStyle( + color: pt.fgDim, + fontSize: 10, + fontFamily: 'monospace', + ), + ), + ], + ), + ), + Row( + mainAxisSize: MainAxisSize.min, + children: [ + _ActionIcon( + icon: Icons.open_in_new_rounded, + pt: pt, + onTap: () => ref.read(viewModeProvider.notifier).state = ViewMode.voice, + ), + _ActionIcon( + icon: Icons.call_end_rounded, + pt: pt, + danger: true, + onTap: () { + if (isVoip) { + call.hangup(); + } else { + call.hangUp(); + } + ref.read(activeVoiceRoomIdProvider.notifier).state = null; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + }, + ), + ], + ), + ], + ), + ), + ), + // Controls + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + child: Row( + children: [ + _ControlBtn( + icon: isMuted ? Icons.mic_off_rounded : Icons.mic_none_rounded, + active: !isMuted, + danger: isMuted, + pt: pt, + onTap: () { + if (isVoip) { + call.toggleMic(); + } else { + call.toggleMute(); + } + }, + ), + const SizedBox(width: 4), + _ControlBtn( + icon: isDeafened ? Icons.headset_off_rounded : Icons.headphones_rounded, + active: !isDeafened, + danger: isDeafened, + pt: pt, + onTap: () => call.toggleDeafen(), + ), + const SizedBox(width: 4), + _ControlBtn( + icon: isCameraOff ? Icons.videocam_off_rounded : Icons.videocam_rounded, + active: !isCameraOff, + pt: pt, + onTap: () => call.toggleCamera(), + ), + const SizedBox(width: 4), + _ControlBtn( + icon: Icons.screen_share_rounded, + active: isStreaming, + pt: pt, + onTap: () async { + if (isVoip) { + (call as PyramidVoipManager).toggleScreenSharing(context); + } else { + final lk = call as LiveKitCallManager; + if (lk.isScreenSharing) { + await lk.stopScreenShare(); + } else { + final source = await ScreenSharePicker.show(context); + if (source != null) { + await lk.startScreenShare(source.id); + } + } + } + }, + ), + ], + ), + ), + ], + ), + ); + } +} + +class _ActionIcon extends StatelessWidget { + final IconData icon; + final PyramidTheme pt; + final VoidCallback onTap; + final bool danger; + + const _ActionIcon({required this.icon, required this.pt, required this.onTap, this.danger = false}); + + @override + Widget build(BuildContext context) { + return IconButton( + icon: Icon(icon, size: 18), + onPressed: onTap, + color: danger ? pt.danger : pt.fgDim, + visualDensity: VisualDensity.compact, + style: danger ? IconButton.styleFrom( + hoverColor: pt.danger.withAlpha(30), + ) : null, + ); + } +} + +class _ControlBtn extends StatefulWidget { + final IconData icon; + final bool active; + final bool danger; + final PyramidTheme pt; + final VoidCallback onTap; + + const _ControlBtn({required this.icon, required this.active, required this.pt, required this.onTap, this.danger = false}); + + @override + State<_ControlBtn> createState() => _ControlBtnState(); +} + +class _ControlBtnState extends State<_ControlBtn> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Expanded( + child: MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: pt.durationFast, + height: 32, + decoration: BoxDecoration( + color: widget.active ? (widget.danger ? pt.danger : pt.accent) : pt.bg3, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Icon( + widget.icon, + size: 16, + color: widget.active ? (widget.danger ? Colors.white : pt.accentFg) : pt.fg, + ), + ), + ), + ), + ); + } +} + +class _LiveKitPreview extends StatelessWidget { + final LiveKitCallManager manager; + const _LiveKitPreview({required this.manager}); + + @override + Widget build(BuildContext context) { + final room = manager.room; + if (room == null) return const SizedBox(); + + // Find first available video track (screenshare preferred) + VideoTrack? bestTrack; + + // Check remote participants + for (final p in room.remoteParticipants.values) { + for (final pub in p.videoTrackPublications) { + if (pub.source == TrackSource.screenShareVideo) { + final t = pub.track; + if (t is VideoTrack) { + bestTrack = t; + break; + } + } + } + if (bestTrack != null) break; + } + + // Fallback to camera if no screen share + if (bestTrack == null) { + for (final p in room.remoteParticipants.values) { + for (final pub in p.videoTrackPublications) { + if (pub.source == TrackSource.camera) { + final t = pub.track; + if (t is VideoTrack) { + bestTrack = t; + break; + } + } + } + if (bestTrack != null) break; + } + } + + // Fallback to local if still nothing + if (bestTrack == null && room.localParticipant != null) { + for (final pub in room.localParticipant!.videoTrackPublications) { + final t = pub.track; + if (t is VideoTrack) { + bestTrack = t; + break; + } + } + } + + if (bestTrack == null) { + return Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [Colors.indigo.shade900, Colors.blue.shade900], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + child: const Center( + child: Icon(Icons.podcasts_rounded, color: Colors.white24, size: 40), + ), + ); + } + + return VideoTrackRenderer( + bestTrack, + fit: VideoViewFit.cover, + ); + } +} + +class _LiveDot extends StatefulWidget { + const _LiveDot(); + + @override + State<_LiveDot> createState() => _LiveDotState(); +} + +class _LiveDotState extends State<_LiveDot> with SingleTickerProviderStateMixin { + late AnimationController _ctrl; + + @override + void initState() { + super.initState(); + _ctrl = AnimationController(vsync: this, duration: const Duration(seconds: 2))..repeat(reverse: true); + } + + @override + void dispose() { + _ctrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return AnimatedBuilder( + animation: _ctrl, + builder: (context, _) => Container( + width: 6, + height: 6, + decoration: BoxDecoration( + color: pt.online, + shape: BoxShape.circle, + boxShadow: [ + BoxShadow( + color: pt.online.withAlpha((_ctrl.value * 150).toInt()), + blurRadius: 4 * _ctrl.value, + spreadRadius: 2 * _ctrl.value, + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/call/voice_channel.dart b/lib/features/call/voice_channel.dart new file mode 100644 index 0000000..4ffe4d1 --- /dev/null +++ b/lib/features/call/voice_channel.dart @@ -0,0 +1,1123 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:livekit_client/livekit_client.dart'; +import 'package:collection/collection.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/widgets/screen_share_picker.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/core/livekit_call_manager.dart'; +import 'package:pyramid/core/voip_manager.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart' as rtc; +import 'package:pyramid/widgets/hover_region.dart'; +import 'package:pyramid/widgets/pyramid_loader.dart'; + +// Unified participant data to handle both LiveKit and VoIP +class _ParticipantData { + final String id; + final String name; + final Widget? videoWidget; + final bool isSpeaking; + final bool isMuted; + final bool hasVideo; + final bool isScreenShare; + final Color avatarColor; + final dynamic originalParticipant; + final double aspectRatio; + + const _ParticipantData({ + required this.id, + required this.name, + this.videoWidget, + this.isSpeaking = false, + this.isMuted = false, + this.hasVideo = false, + this.isScreenShare = false, + this.avatarColor = Colors.grey, + this.originalParticipant, + this.aspectRatio = 16.0 / 9.0, + }); +} + +class VoiceChannelView extends ConsumerWidget { + const VoiceChannelView({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + final call = ref.watch(callStateProvider); + final voip = ref.watch(voipStateProvider); + + if (voip.currentCall != null && voip.currentCall!.state != CallState.kEnded) { + return _UnifiedCallView( + participants: _getVoipParticipants(voip), + isLiveKit: false, + displayName: voip.currentCall!.room.getLocalizedDisplayname(), + isConnecting: false, + onHangUp: () { + voip.hangup(); + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + }, + onMinimize: () => + ref.read(viewModeProvider.notifier).state = ViewMode.chat, + onToggleMic: voip.toggleMic, + onToggleDeafen: voip.toggleDeafen, + onToggleCam: voip.toggleCamera, + onToggleScreen: () => voip.toggleScreenSharing(context), + isMuted: voip.isMicMuted, + isDeafened: voip.isDeafened, + isCameraOff: voip.isCameraMuted, + isScreenSharing: voip.isScreensharing, + onQualityMenu: (pos) => _showVoipQualityMenu(context, voip, pos), + pt: pt, + ); + } + + if (!call.isActive) { + return _NoCall(pt: pt, ref: ref); + } + + return _UnifiedCallView( + participants: _getLiveKitParticipants(call), + isLiveKit: true, + displayName: call.displayName, + isConnecting: call.isConnecting, + onHangUp: () { + call.hangUp(); + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + }, + onMinimize: () => + ref.read(viewModeProvider.notifier).state = ViewMode.chat, + onToggleMic: call.toggleMute, + onToggleDeafen: call.toggleDeafen, + onToggleCam: call.toggleCamera, + onToggleScreen: () => _handleLiveKitScreenShare(context, call), + isMuted: call.isMuted, + isDeafened: call.isDeafened, + isCameraOff: call.isCameraOff, + isScreenSharing: call.isScreenSharing, + onQualityMenu: (pos) => _showLiveKitQualityMenu(context, call, pos), + pt: pt, + ); + } + + List<_ParticipantData> _getLiveKitParticipants(LiveKitCallManager call) { + final room = call.room; + if (room == null) return []; + final all = [ + if (room.localParticipant != null) room.localParticipant!, + ...room.remoteParticipants.values, + ]; + + return all.mapIndexed((i, p) { + final screenPub = p.videoTrackPublications.firstWhereOrNull((v) => v.source == TrackSource.screenShareVideo); + final camPub = p.videoTrackPublications.firstWhereOrNull((v) => v.source == TrackSource.camera); + final videoTrack = (screenPub?.track ?? camPub?.track) as VideoTrack?; + final isScreen = screenPub != null; + + double ar = 16.0 / 9.0; + if (videoTrack != null) { + try { + final dim = (videoTrack as dynamic).currentDimensions ?? (videoTrack as dynamic).dimensions; + if (dim != null) { + final w = (dim.width as num?)?.toDouble() ?? 0; + final h = (dim.height as num?)?.toDouble() ?? 0; + if (w > 0 && h > 0) ar = w / h; + } + } catch (_) {} + } + + return _ParticipantData( + id: p.identity, + name: p.identity == room.localParticipant?.identity ? 'Du' : p.identity, + videoWidget: videoTrack != null ? VideoTrackRenderer(videoTrack, fit: VideoViewFit.contain) : null, + isSpeaking: p.isSpeaking, + isMuted: !p.isMicrophoneEnabled(), + hasVideo: videoTrack != null, + isScreenShare: isScreen, + avatarColor: _avatarColors[i % _avatarColors.length], + originalParticipant: p, + aspectRatio: ar, + ); + }).toList(); + } + + List<_ParticipantData> _getVoipParticipants(PyramidVoipManager voip) { + final participants = <_ParticipantData>[]; + + double _ar(rtc.RTCVideoRenderer r) { + final w = r.videoWidth.toDouble(); + final h = r.videoHeight.toDouble(); + return (w > 0 && h > 0) ? w / h : 16.0 / 9.0; + } + + // Remote + final isRemoteScreen = voip.isRemoteScreensharing; + final hasRemoteVideo = voip.remoteRenderer.srcObject != null && voip.remoteRenderer.srcObject!.getVideoTracks().isNotEmpty; + participants.add(_ParticipantData( + id: 'remote', + name: voip.currentCall?.room.getLocalizedDisplayname() ?? 'Remote', + videoWidget: hasRemoteVideo ? rtc.RTCVideoView(voip.remoteRenderer, objectFit: rtc.RTCVideoViewObjectFit.RTCVideoViewObjectFitContain) : null, + isMuted: false, + hasVideo: hasRemoteVideo, + isScreenShare: isRemoteScreen, + avatarColor: _avatarColors[1], + aspectRatio: hasRemoteVideo ? _ar(voip.remoteRenderer) : 16.0 / 9.0, + )); + + // Local + final isLocalScreen = voip.isScreensharing; + final hasLocalVideo = voip.localRenderer.srcObject != null && voip.localRenderer.srcObject!.getVideoTracks().isNotEmpty; + participants.add(_ParticipantData( + id: 'local', + name: 'Du', + videoWidget: hasLocalVideo ? rtc.RTCVideoView(voip.localRenderer, objectFit: rtc.RTCVideoViewObjectFit.RTCVideoViewObjectFitContain) : null, + isMuted: voip.isMicMuted, + hasVideo: hasLocalVideo, + isScreenShare: isLocalScreen, + avatarColor: _avatarColors[0], + aspectRatio: hasLocalVideo ? _ar(voip.localRenderer) : 16.0 / 9.0, + )); + + return participants; + } + + static const _avatarColors = [ + Color(0xFFFF6B9D), Color(0xFF06B6D4), Color(0xFFA855F7), + Color(0xFF10B981), Color(0xFFF59E0B), Color(0xFFEF4444), + Color(0xFF3B82F6), Color(0xFF84CC16), + ]; +} + +class _UnifiedCallView extends StatefulWidget { + final List<_ParticipantData> participants; + final bool isLiveKit; + final String displayName; + final bool isConnecting; + final VoidCallback onHangUp; + final VoidCallback onMinimize; + final VoidCallback onToggleMic; + final VoidCallback onToggleDeafen; + final VoidCallback onToggleCam; + final VoidCallback onToggleScreen; + final bool isMuted; + final bool isDeafened; + final bool isCameraOff; + final bool isScreenSharing; + final Function(Offset)? onQualityMenu; + final PyramidTheme pt; + + const _UnifiedCallView({ + required this.participants, + required this.isLiveKit, + required this.displayName, + required this.isConnecting, + required this.onHangUp, + required this.onMinimize, + required this.onToggleMic, + required this.onToggleDeafen, + required this.onToggleCam, + required this.onToggleScreen, + required this.isMuted, + required this.isDeafened, + required this.isCameraOff, + required this.isScreenSharing, + this.onQualityMenu, + required this.pt, + }); + + @override + State<_UnifiedCallView> createState() => _UnifiedCallViewState(); +} + +class _UnifiedCallViewState extends State<_UnifiedCallView> { + String? _heroId; + bool _isGridView = false; + bool _stripCollapsed = false; + + @override + void initState() { + super.initState(); + _autoSelectHero(); + } + + @override + void didUpdateWidget(_UnifiedCallView oldWidget) { + super.didUpdateWidget(oldWidget); + _autoSelectHero(); + } + + void _autoSelectHero() { + if (_isGridView) return; + final screenshare = widget.participants.firstWhereOrNull((p) => p.isScreenShare); + if (screenshare != null && (_heroId == null || !widget.participants.any((p) => p.id == _heroId && p.hasVideo))) { + _heroId = screenshare.id; + } else if (_heroId == null && widget.participants.isNotEmpty) { + final firstVideo = widget.participants.firstWhereOrNull((p) => p.hasVideo); + if (firstVideo != null) _heroId = firstVideo.id; + } + } + + List<_ParticipantData> _sorted(List<_ParticipantData> all) { + int rank(_ParticipantData p) { + if (p.isScreenShare) return 0; + if (p.hasVideo) return 1; + if (p.isSpeaking) return 2; + return 3; + } + return [...all]..sort((a, b) => rank(a).compareTo(rank(b))); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final all = _sorted(widget.participants); + final hero = all.firstWhereOrNull((p) => p.id == _heroId) ?? (all.isNotEmpty ? all.first : null); + + if (widget.isConnecting) { + return Scaffold( + backgroundColor: pt.bg1, + body: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const PyramidLoader(size: 80), + const SizedBox(height: 20), + Text('Verbinde…', + style: TextStyle(color: pt.fgMuted, fontSize: 14)), + const SizedBox(height: 16), + TextButton.icon( + style: TextButton.styleFrom(foregroundColor: pt.danger), + onPressed: widget.onHangUp, + icon: const Icon(Icons.call_end_rounded, size: 16), + label: const Text('Abbrechen'), + ), + ], + ), + ), + ); + } + + return Scaffold( + backgroundColor: pt.bg1, + body: Column( + children: [ + _CallHeader( + displayName: widget.displayName, + isGridView: _isGridView, + onToggleView: () => setState(() => _isGridView = !_isGridView), + onMinimize: widget.onMinimize, + pt: pt, + ), + Expanded( + child: AnimatedSwitcher( + duration: const Duration(milliseconds: 300), + child: _isGridView || hero == null + ? _ParticipantGrid(participants: all, pt: pt, onSelect: (p) => setState(() { _heroId = p.id; _isGridView = false; })) + : _HeroLayout( + hero: hero, + others: all.where((p) => p.id != hero.id).toList(), + stripCollapsed: _stripCollapsed, + onToggleStrip: () => setState(() => _stripCollapsed = !_stripCollapsed), + onSetStripCollapsed: (v) => setState(() => _stripCollapsed = v), + onSelectOther: (p) => setState(() => _heroId = p.id), + onQualityMenu: widget.onQualityMenu, + pt: pt, + ), + ), + ), + _CallControls( + isMuted: widget.isMuted, + isDeafened: widget.isDeafened, + isCameraOff: widget.isCameraOff, + isScreenSharing: widget.isScreenSharing, + onToggleMic: widget.onToggleMic, + onToggleDeafen: widget.onToggleDeafen, + onToggleCam: widget.onToggleCam, + onToggleScreen: widget.onToggleScreen, + onHangUp: widget.onHangUp, + pt: pt, + ), + ], + ), + ); + } +} + +class _CallHeader extends StatelessWidget { + final String displayName; + final bool isGridView; + final VoidCallback onToggleView; + final VoidCallback onMinimize; + final PyramidTheme pt; + + const _CallHeader({required this.displayName, required this.isGridView, required this.onToggleView, required this.onMinimize, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: pt.border))), + child: Row( + children: [ + Icon(Icons.headphones_rounded, size: 16, color: pt.fgMuted), + const SizedBox(width: 8), + Text(displayName, style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600)), + const SizedBox(width: 8), + _LiveBadge(pt: pt), + const Spacer(), + PyrIconBtn( + icon: Icon(isGridView ? Icons.grid_view_rounded : Icons.featured_video_rounded, color: isGridView ? pt.accent : pt.fg), + tooltip: isGridView ? 'Hero mode' : 'Grid mode', + onPressed: onToggleView, + ), + const SizedBox(width: 4), + PyrIconBtn( + icon: Icon(Icons.close_fullscreen_rounded, color: pt.fg), + tooltip: 'Minimieren', + onPressed: onMinimize, + ), + ], + ), + ); + } +} + +class _LiveBadge extends StatelessWidget { + final PyramidTheme pt; + const _LiveBadge({required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration(borderRadius: BorderRadius.circular(999), color: pt.online.withAlpha(30)), + child: Row(children: [ + Container(width: 6, height: 6, decoration: BoxDecoration(color: pt.online, shape: BoxShape.circle)), + const SizedBox(width: 4), + Text('Live', style: TextStyle(color: pt.online, fontSize: 11, fontWeight: FontWeight.w600)), + ]), + ); + } +} + +class _ParticipantGrid extends StatelessWidget { + final List<_ParticipantData> participants; + final PyramidTheme pt; + final Function(_ParticipantData) onSelect; + + const _ParticipantGrid({required this.participants, required this.pt, required this.onSelect}); + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, box) { + final cols = box.maxWidth > 900 ? 4 : (box.maxWidth > 600 ? 3 : 2); + const spacing = 12.0; + final tileWidth = (box.maxWidth - spacing * (cols - 1) - 24) / cols; + + return SingleChildScrollView( + padding: const EdgeInsets.all(12), + child: Wrap( + spacing: spacing, + runSpacing: spacing, + children: participants.map((p) => SizedBox( + width: tileWidth, + height: tileWidth / p.aspectRatio, + child: _ParticipantTile(data: p, pt: pt, onTap: () => onSelect(p)), + )).toList(), + ), + ); + }); + } +} + +class _HeroLayout extends StatelessWidget { + final _ParticipantData hero; + final List<_ParticipantData> others; + final bool stripCollapsed; + final VoidCallback onToggleStrip; + final Function(bool) onSetStripCollapsed; + final Function(_ParticipantData) onSelectOther; + final Function(Offset)? onQualityMenu; + final PyramidTheme pt; + + const _HeroLayout({ + required this.hero, + required this.others, + required this.stripCollapsed, + required this.onToggleStrip, + required this.onSetStripCollapsed, + required this.onSelectOther, + this.onQualityMenu, + required this.pt, + }); + + @override + Widget build(BuildContext context) { + return LayoutBuilder(builder: (context, box) { + final isLandscape = box.maxWidth > box.maxHeight && box.maxWidth > 600; + + final heroView = _HeroSection( + data: hero, + onQualityMenu: onQualityMenu, + pt: pt, + ); + + final strip = _ParticipantStrip( + participants: others, + isVertical: isLandscape, + onSelect: onSelectOther, + pt: pt, + ); + + if (isLandscape) { + return Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(12), + child: GestureDetector( + onHorizontalDragEnd: (details) { + if (details.primaryVelocity! < -300) onSetStripCollapsed(false); + if (details.primaryVelocity! > 300) onSetStripCollapsed(true); + }, + child: heroView, + ), + ), + ), + if (!stripCollapsed) + SizedBox(width: 200, child: Padding(padding: const EdgeInsets.only(right: 12, top: 12, bottom: 12), child: strip)), + _CollapseHandle(isVertical: true, collapsed: stripCollapsed, onToggle: onToggleStrip, pt: pt), + ], + ); + } else { + return Column( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.all(12), + child: GestureDetector( + onVerticalDragEnd: (details) { + if (details.primaryVelocity! < -300) onSetStripCollapsed(false); + if (details.primaryVelocity! > 300) onSetStripCollapsed(true); + }, + child: heroView, + ), + ), + ), + _CollapseHandle(isVertical: false, collapsed: stripCollapsed, onToggle: onToggleStrip, pt: pt), + if (!stripCollapsed) + SizedBox(height: 120, child: Padding(padding: const EdgeInsets.only(bottom: 12, left: 12, right: 12), child: strip)), + ], + ); + } + }); + } +} + +class _HeroSection extends StatefulWidget { + final _ParticipantData data; + final Function(Offset)? onQualityMenu; + final PyramidTheme pt; + + const _HeroSection({required this.data, this.onQualityMenu, required this.pt}); + + @override + State<_HeroSection> createState() => _HeroSectionState(); +} + +class _HeroSectionState extends State<_HeroSection> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: () => setState(() => _hovered = !_hovered), + child: Center( + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rLg), + child: Container( + color: Colors.black, + child: Stack( + children: [ + Positioned.fill( + child: widget.data.videoWidget != null + ? _MirrorWrapper( + isLocal: widget.data.id == 'local' || (widget.data.originalParticipant is LocalParticipant), + isScreenShare: widget.data.isScreenShare, + child: widget.data.videoWidget!, + ) + : _BigAvatar(data: widget.data, pt: pt), + ), + + AnimatedPositioned( + duration: const Duration(milliseconds: 200), + top: _hovered ? 0 : -60, left: 0, right: 0, + child: _HeroTopBar(data: widget.data, pt: pt), + ), + + AnimatedPositioned( + duration: const Duration(milliseconds: 200), + bottom: _hovered ? 0 : -60, left: 0, right: 0, + child: _HeroBottomBar( + data: widget.data, + onQualityMenu: widget.onQualityMenu, + pt: pt, + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} + +class _HeroTopBar extends StatelessWidget { + final _ParticipantData data; + final PyramidTheme pt; + const _HeroTopBar({required this.data, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + decoration: const BoxDecoration( + gradient: LinearGradient(begin: Alignment.topCenter, end: Alignment.bottomCenter, colors: [Colors.black54, Colors.transparent]), + ), + child: Row( + children: [ + if (data.isScreenShare) _LivePill(pt: pt), + const SizedBox(width: 8), + Text( + data.isScreenShare ? "${data.name} präsentiert" : data.name, + style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600, fontSize: 14), + ), + ], + ), + ); + } +} + +class _HeroBottomBar extends StatelessWidget { + final _ParticipantData data; + final Function(Offset)? onQualityMenu; + final PyramidTheme pt; + const _HeroBottomBar({required this.data, this.onQualityMenu, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + decoration: const BoxDecoration( + gradient: LinearGradient(begin: Alignment.bottomCenter, end: Alignment.topCenter, colors: [Colors.black54, Colors.transparent]), + ), + child: Row( + children: [ + const Spacer(), + if (onQualityMenu != null) + _HeroActionBtn(icon: Icons.settings_rounded, onTapDown: (d) => onQualityMenu!(d.globalPosition)), + const SizedBox(width: 8), + _HeroActionBtn( + icon: Icons.fullscreen_rounded, + onTap: () => Navigator.of(context).push(MaterialPageRoute( + fullscreenDialog: true, + builder: (_) => _FullscreenVideoPage(data: data), + )), + ), + ], + ), + ); + } +} + +class _HeroActionBtn extends StatelessWidget { + final IconData icon; + final VoidCallback? onTap; + final Function(TapDownDetails)? onTapDown; + const _HeroActionBtn({required this.icon, this.onTap, this.onTapDown}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + onTapDown: onTapDown, + child: Container( + width: 36, height: 36, + decoration: BoxDecoration(color: Colors.white24, borderRadius: BorderRadius.circular(8)), + child: Icon(icon, color: Colors.white, size: 20), + ), + ); + } +} + +class _LivePill extends StatelessWidget { + final PyramidTheme pt; + const _LivePill({required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration(color: const Color(0xFFEF4444), borderRadius: BorderRadius.circular(4)), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Container(width: 4, height: 4, decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle)), + const SizedBox(width: 4), + const Text('LIVE', style: TextStyle(color: Colors.white, fontSize: 9, fontWeight: FontWeight.w800, letterSpacing: 0.5)), + ]), + ); + } +} + +class _ParticipantStrip extends StatelessWidget { + final List<_ParticipantData> participants; + final bool isVertical; + final Function(_ParticipantData) onSelect; + final PyramidTheme pt; + + const _ParticipantStrip({required this.participants, required this.isVertical, required this.onSelect, required this.pt}); + + @override + Widget build(BuildContext context) { + return ListView.separated( + scrollDirection: isVertical ? Axis.vertical : Axis.horizontal, + itemCount: participants.length, + separatorBuilder: (_, __) => const SizedBox(width: 12, height: 12), + itemBuilder: (context, i) => SizedBox( + width: isVertical ? double.infinity : 101 * participants[i].aspectRatio, + height: 101, + child: _ParticipantTile(data: participants[i], pt: pt, onTap: () => onSelect(participants[i])), + ), + ); + } +} + +class _ParticipantTile extends StatefulWidget { + final _ParticipantData data; + final PyramidTheme pt; + final VoidCallback onTap; + + const _ParticipantTile({required this.data, required this.pt, required this.onTap}); + + @override + State<_ParticipantTile> createState() => _ParticipantTileState(); +} + +class _ParticipantTileState extends State<_ParticipantTile> with SingleTickerProviderStateMixin { + late AnimationController _speakingCtrl; + + @override + void initState() { + super.initState(); + _speakingCtrl = AnimationController(vsync: this, duration: const Duration(milliseconds: 800))..repeat(reverse: true); + } + + @override + void dispose() { + _speakingCtrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final data = widget.data; + + return GestureDetector( + onTap: widget.onTap, + child: AnimatedBuilder( + animation: _speakingCtrl, + builder: (context, _) { + final isSpeaking = data.isSpeaking; + final pulse = isSpeaking ? _speakingCtrl.value : 0.0; + + return AnimatedContainer( + duration: const Duration(milliseconds: 200), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all( + color: isSpeaking + ? pt.accent.withAlpha((150 + pulse * 105).toInt()) + : pt.border, + width: isSpeaking ? 2 : 1, + ), + boxShadow: isSpeaking + ? [BoxShadow(color: pt.accent.withAlpha((20 + pulse * 40).toInt()), blurRadius: 4 + pulse * 8, spreadRadius: pulse * 2)] + : null, + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rBase - 1), + child: Stack( + children: [ + Positioned.fill( + child: data.videoWidget != null + ? _MirrorWrapper( + isLocal: data.id == 'local' || (data.originalParticipant is LocalParticipant), + isScreenShare: data.isScreenShare, + child: data.videoWidget!, + ) + : _SmallAvatar(data: data, pt: pt), + ), + + Positioned( + left: 6, bottom: 6, right: 6, + child: Row( + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration(color: Colors.black54, borderRadius: BorderRadius.circular(4)), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (data.isMuted) ...[Icon(Icons.mic_off_rounded, size: 10, color: pt.danger), const SizedBox(width: 4)], + Flexible(child: Text(data.name, style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis)), + ], + ), + ), + ], + ), + ), + if (data.isScreenShare) Positioned(top: 6, left: 6, child: _LivePill(pt: pt)), + ], + ), + ), + ); + }, + ), + ); + } +} + +class _CollapseHandle extends StatelessWidget { + final bool isVertical; + final bool collapsed; + final VoidCallback onToggle; + final PyramidTheme pt; + + const _CollapseHandle({required this.isVertical, required this.collapsed, required this.onToggle, required this.pt}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onToggle, + child: Container( + width: isVertical ? 24 : double.infinity, + height: isVertical ? double.infinity : 24, + color: Colors.transparent, + child: Center( + child: Icon( + isVertical + ? (collapsed ? Icons.chevron_left_rounded : Icons.chevron_right_rounded) + : (collapsed ? Icons.keyboard_arrow_up_rounded : Icons.keyboard_arrow_down_rounded), + color: pt.fgDim, size: 20, + ), + ), + ), + ); + } +} + +class _BigAvatar extends StatelessWidget { + final _ParticipantData data; + final PyramidTheme pt; + const _BigAvatar({required this.data, required this.pt}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 100, height: 100, + decoration: BoxDecoration( + gradient: LinearGradient(colors: [data.avatarColor, data.avatarColor.withAlpha(150)], begin: Alignment.topLeft, end: Alignment.bottomRight), + shape: BoxShape.circle, + ), + child: Center(child: Text(data.name.isNotEmpty ? data.name[0].toUpperCase() : '?', style: const TextStyle(color: Colors.white, fontSize: 40, fontWeight: FontWeight.bold))), + ), + ); + } +} + +class _SmallAvatar extends StatelessWidget { + final _ParticipantData data; + final PyramidTheme pt; + const _SmallAvatar({required this.data, required this.pt}); + + @override + Widget build(BuildContext context) { + return Center( + child: Container( + width: 44, height: 44, + decoration: BoxDecoration( + gradient: LinearGradient(colors: [data.avatarColor, data.avatarColor.withAlpha(150)], begin: Alignment.topLeft, end: Alignment.bottomRight), + shape: BoxShape.circle, + ), + child: Center(child: Text(data.name.isNotEmpty ? data.name[0].toUpperCase() : '?', style: const TextStyle(color: Colors.white, fontSize: 18, fontWeight: FontWeight.bold))), + ), + ); + } +} + +class _CallControls extends StatelessWidget { + final bool isMuted; + final bool isDeafened; + final bool isCameraOff; + final bool isScreenSharing; + final VoidCallback onToggleMic; + final VoidCallback onToggleDeafen; + final VoidCallback onToggleCam; + final VoidCallback onToggleScreen; + final VoidCallback onHangUp; + final PyramidTheme pt; + + const _CallControls({ + required this.isMuted, + required this.isDeafened, + required this.isCameraOff, + required this.isScreenSharing, + required this.onToggleMic, + required this.onToggleDeafen, + required this.onToggleCam, + required this.onToggleScreen, + required this.onHangUp, + required this.pt, + }); + + @override + Widget build(BuildContext context) { + return SafeArea( + top: false, + child: Container( + padding: const EdgeInsets.symmetric(vertical: 16, horizontal: 20), + decoration: BoxDecoration(color: pt.bg1, border: Border(top: BorderSide(color: pt.border))), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + _VoiceCtrlBtn(icon: isMuted ? Icons.mic_off_rounded : Icons.mic_rounded, danger: isMuted, pt: pt, onTap: onToggleMic), + const SizedBox(width: 16), + _VoiceCtrlBtn(icon: isDeafened ? Icons.headset_off_rounded : Icons.headphones_rounded, danger: isDeafened, pt: pt, onTap: onToggleDeafen), + const SizedBox(width: 16), + _VoiceCtrlBtn(icon: isCameraOff ? Icons.videocam_off_rounded : Icons.videocam_rounded, active: !isCameraOff, pt: pt, onTap: onToggleCam), + const SizedBox(width: 16), + _VoiceCtrlBtn(icon: Icons.screen_share_rounded, active: isScreenSharing, pt: pt, onTap: onToggleScreen), + const SizedBox(width: 24), + Container(width: 1, height: 32, color: pt.border), + const SizedBox(width: 24), + _VoiceCtrlBtn(icon: Icons.call_end_rounded, isDanger: true, pt: pt, onTap: onHangUp), + ], + ), + ), + ); + } +} + +class _NoCall extends StatelessWidget { + final PyramidTheme pt; + final WidgetRef ref; + const _NoCall({required this.pt, required this.ref}); + + @override + Widget build(BuildContext context) { + return Container( + color: pt.bg1, + child: Column( + children: [ + Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: pt.border))), + child: Row( + children: [ + PyrIconBtn( + icon: const Icon(Icons.menu_rounded), + tooltip: 'Toggle sidebar', + onPressed: () => ref.read(railCollapsedProvider.notifier).update((s) => !s), + ), + const SizedBox(width: 8), + Icon(Icons.headphones_rounded, size: 16, color: pt.fgMuted), + const SizedBox(width: 8), + Text('No active call', style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600)), + ], + ), + ), + Expanded( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text('𐃏', style: TextStyle(fontSize: 48, color: pt.fgDim.withAlpha(100))), + const SizedBox(height: 12), + Text('Join a voice room to start a call', style: TextStyle(color: pt.fgMuted, fontSize: 14)), + ], + ), + ), + ), + ], + ), + ); + } +} + +class _FullscreenVideoPage extends StatelessWidget { + final _ParticipantData data; + const _FullscreenVideoPage({required this.data}); + + @override + Widget build(BuildContext context) { + return Scaffold( + backgroundColor: Colors.black, + body: Stack(children: [ + Positioned.fill( + child: data.videoWidget != null + ? _MirrorWrapper( + isLocal: data.id == 'local' || (data.originalParticipant is LocalParticipant), + isScreenShare: data.isScreenShare, + child: data.videoWidget!, + ) + : _BigAvatar(data: data, pt: PyramidTheme.of(context)), + ), + Positioned( + top: 0, right: 0, + child: SafeArea( + child: IconButton( + icon: const Icon(Icons.fullscreen_exit_rounded, color: Colors.white, size: 28), + onPressed: () => Navigator.of(context).pop(), + ), + ), + ), + ]), + ); + } +} + +void _handleLiveKitScreenShare(BuildContext context, LiveKitCallManager call) async { + if (call.isScreenSharing) { + await call.stopScreenShare(); + } else { + final source = await ScreenSharePicker.show(context); + if (source != null) await call.startScreenShare(source.id); + } +} + +void _showLiveKitQualityMenu(BuildContext context, LiveKitCallManager call, Offset pos) { + final pt = PyramidTheme.of(context); + showMenu( + context: context, + position: RelativeRect.fromLTRB(pos.dx - 210, pos.dy - 350, pos.dx, pos.dy), + color: pt.bg2, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(pt.rBase)), + items: [ + const PopupMenuItem(enabled: false, height: 28, child: Text('SENDEN', style: TextStyle(fontSize: 10, fontWeight: FontWeight.w700, color: Colors.grey))), + for (final q in [('sd', 'SD', '360p'), ('hd', 'HD', '720p'), ('fhd', 'Full HD', '1080p'), ('4k', '4K', '2160p')]) + PopupMenuItem(onTap: () => call.changeQuality(q.$1), child: _QualityItem(label: q.$2, hint: q.$3, active: call.currentQualityKey == q.$1, pt: pt)), + const PopupMenuDivider(), + const PopupMenuItem(enabled: false, height: 28, child: Text('EMPFANGEN', style: TextStyle(fontSize: 10, fontWeight: FontWeight.w700, color: Colors.grey))), + for (final q in [('auto', 'Auto', ''), ('high', 'Hoch', 'FHD'), ('medium', 'Mittel', 'HD'), ('low', 'Niedrig', 'SD')]) + PopupMenuItem(onTap: () => call.setSubscribeQuality(q.$1), child: _QualityItem(label: q.$2, hint: q.$3, active: call.subscribeQualityKey == q.$1, pt: pt)), + ], + ); +} + +void _showVoipQualityMenu(BuildContext context, PyramidVoipManager voip, Offset pos) { + final pt = PyramidTheme.of(context); + showMenu( + context: context, + position: RelativeRect.fromLTRB(pos.dx - 210, pos.dy - 200, pos.dx, pos.dy), + color: pt.bg2, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(pt.rBase)), + items: [ + const PopupMenuItem(enabled: false, height: 28, child: Text('SENDEN', style: TextStyle(fontSize: 10, fontWeight: FontWeight.w700, color: Colors.grey))), + for (final q in [('sd', 'SD', '360p'), ('hd', 'HD', '720p'), ('fhd', 'Full HD', '1080p'), ('4k', '4K', '2160p')]) + PopupMenuItem(onTap: () => voip.changeQuality(q.$1), child: _QualityItem(label: q.$2, hint: q.$3, active: voip.currentQualityKey == q.$1, pt: pt)), + ], + ); +} + +class _QualityItem extends StatelessWidget { + final String label; + final String? hint; + final bool active; + final PyramidTheme pt; + const _QualityItem({required this.label, required this.active, required this.pt, this.hint}); + + @override + Widget build(BuildContext context) { + return Row(children: [ + if (active) Icon(Icons.check_rounded, size: 16, color: pt.accent) else const SizedBox(width: 16), + const SizedBox(width: 8), + Text(label, style: TextStyle(color: active ? pt.accent : pt.fg, fontSize: 13, fontWeight: active ? FontWeight.bold : FontWeight.normal)), + if (hint != null && hint!.isNotEmpty) ...[const Spacer(), Text(hint!, style: TextStyle(color: pt.fgMuted, fontSize: 11))], + ]); + } +} + +class _VoiceCtrlBtn extends StatefulWidget { + final IconData icon; + final PyramidTheme pt; + final bool active; + final bool danger; + final bool isDanger; + final VoidCallback? onTap; + + const _VoiceCtrlBtn({required this.icon, required this.pt, this.onTap, this.active = false, this.danger = false, this.isDanger = false}); + + @override + State<_VoiceCtrlBtn> createState() => _VoiceCtrlBtnState(); +} + +class _VoiceCtrlBtnState extends State<_VoiceCtrlBtn> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + Color bg; + Color iconColor; + if (widget.isDanger) { bg = pt.danger; iconColor = Colors.white; } + else if (widget.danger) { bg = pt.danger.withAlpha(30); iconColor = pt.danger; } + else if (widget.active) { bg = pt.accent.withAlpha(30); iconColor = pt.accent; } + else { bg = _hovered ? pt.bgHover : pt.bg3; iconColor = pt.fg; } + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: 52, height: 52, + decoration: BoxDecoration(color: bg, borderRadius: BorderRadius.circular(26)), + child: Center(child: Icon(widget.icon, size: 20, color: iconColor)), + ), + ), + ); + } +} + +class _MirrorWrapper extends StatelessWidget { + final Widget child; + final bool isLocal; + final bool isScreenShare; + + const _MirrorWrapper({required this.child, required this.isLocal, required this.isScreenShare}); + + @override + Widget build(BuildContext context) { + if (isLocal && !isScreenShare) { + return Transform( + alignment: Alignment.center, + transform: Matrix4.identity()..rotateY(3.14159), + child: child, + ); + } + return child; + } +} diff --git a/lib/features/chat/attachment_dialog.dart b/lib/features/chat/attachment_dialog.dart new file mode 100644 index 0000000..cfa052f --- /dev/null +++ b/lib/features/chat/attachment_dialog.dart @@ -0,0 +1,328 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:mime/mime.dart'; +import 'package:pyramid/core/theme.dart'; + +class AttachmentDialog extends StatefulWidget { + final List files; + final Room room; + final Event? replyTo; + + const AttachmentDialog({ + super.key, + required this.files, + required this.room, + this.replyTo, + }); + + static Future show( + BuildContext context, + List files, + Room room, { + Event? replyTo, + }) async { + // Snappy Scale+Fade-Eingangsanimation statt Standard-Einblendung. + return await showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: 'Anhang', + barrierColor: Colors.black54, + transitionDuration: const Duration(milliseconds: 180), + pageBuilder: (_, __, ___) => + AttachmentDialog(files: files, room: room, replyTo: replyTo), + transitionBuilder: (_, anim, __, child) { + final curved = + CurvedAnimation(parent: anim, curve: Curves.easeOutBack); + return FadeTransition( + opacity: anim, + child: ScaleTransition(scale: Tween(begin: 0.92, end: 1.0).animate(curved), child: child), + ); + }, + ) ?? + false; + } + + @override + State createState() => _AttachmentDialogState(); +} + +class _AttachmentDialogState extends State { + final _msgCtrl = TextEditingController(); + bool _sending = false; + String? _error; + bool _compress = false; + + bool get _hasImages => widget.files.any((f) { + final mime = lookupMimeType(f.path.split(Platform.pathSeparator).last) ?? ''; + return mime.startsWith('image/'); + }); + + @override + void dispose() { + _msgCtrl.dispose(); + super.dispose(); + } + + Future _send() async { + setState(() { _sending = true; _error = null; }); + try { + for (final file in widget.files) { + final bytes = await file.readAsBytes(); + final filename = file.path.split(Platform.pathSeparator).last; + final mimeType = lookupMimeType(filename) ?? 'application/octet-stream'; + final matrixFile = MatrixFile(bytes: bytes, name: filename, mimeType: mimeType); + final isImage = mimeType.startsWith('image/'); + await widget.room.sendFileEvent( + matrixFile, + inReplyTo: widget.replyTo, + shrinkImageMaxDimension: (_compress && isImage) ? 1600 : null, + ); + } + if (_msgCtrl.text.trim().isNotEmpty) { + await widget.room.sendTextEvent( + _msgCtrl.text.trim(), + inReplyTo: widget.replyTo, + ); + } + if (mounted) Navigator.of(context).pop(true); + } catch (e) { + setState(() { _sending = false; _error = e.toString().split('\n').first; }); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rLg), + side: BorderSide(color: pt.border), + ), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 480, minWidth: 320), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Title + Row( + children: [ + Icon(Icons.attach_file_rounded, size: 18, color: pt.accent), + const SizedBox(width: 8), + Text( + '${widget.files.length} Datei${widget.files.length == 1 ? '' : 'en'} senden', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w600), + ), + const Spacer(), + GestureDetector( + onTap: () => Navigator.of(context).pop(false), + child: Icon(Icons.close_rounded, size: 18, color: pt.fgDim), + ), + ], + ), + const SizedBox(height: 16), + // File list + ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 160), + child: ListView.builder( + shrinkWrap: true, + itemCount: widget.files.length, + itemBuilder: (ctx, i) => _FilePreview(file: widget.files[i], pt: pt), + ), + ), + const SizedBox(height: 16), + // Caption field + TextField( + controller: _msgCtrl, + style: TextStyle(color: pt.fg, fontSize: 14), + cursorColor: pt.accent, + maxLines: 3, + minLines: 1, + decoration: InputDecoration( + hintText: 'Nachricht hinzufügen (optional)', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 14), + filled: true, + fillColor: pt.bg2, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.accent), + ), + contentPadding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + isDense: true, + ), + ), + // Image quality toggle + if (_hasImages) ...[ + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Icon(Icons.high_quality_outlined, size: 16, color: pt.fgMuted), + const SizedBox(width: 8), + Text('Hohe Qualität', style: TextStyle(color: pt.fg, fontSize: 13)), + const Spacer(), + Switch.adaptive( + value: !_compress, + onChanged: (v) => setState(() => _compress = !v), + activeColor: pt.accent, + ), + ], + ), + ), + ], + if (_error != null) ...[ + const SizedBox(height: 8), + Text(_error!, style: TextStyle(color: pt.danger, fontSize: 12)), + ], + const SizedBox(height: 16), + // Actions + Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: _sending ? null : () => Navigator.of(context).pop(false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + const SizedBox(width: 8), + FilledButton.icon( + onPressed: _sending ? null : _send, + style: FilledButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase), + ), + ), + icon: _sending + ? SizedBox( + width: 14, + height: 14, + child: CircularProgressIndicator( + strokeWidth: 2, + color: pt.accentFg, + ), + ) + : const Icon(Icons.send_rounded, size: 14), + label: const Text('Senden'), + ), + ], + ), + ], + ), + ), + ), + ); + } +} + +class _FilePreview extends StatefulWidget { + final File file; + final PyramidTheme pt; + + const _FilePreview({required this.file, required this.pt}); + + @override + State<_FilePreview> createState() => _FilePreviewState(); +} + +class _FilePreviewState extends State<_FilePreview> { + int? _bytes; + + @override + void initState() { + super.initState(); + widget.file.length().then((b) { if (mounted) setState(() => _bytes = b); }); + } + + @override + Widget build(BuildContext context) { + final filename = widget.file.path.split(Platform.pathSeparator).last; + final mime = lookupMimeType(filename) ?? 'application/octet-stream'; + final isImage = mime.startsWith('image/'); + + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: widget.pt.bg2, + borderRadius: BorderRadius.circular(widget.pt.rBase), + border: Border.all(color: widget.pt.border), + ), + child: Row( + children: [ + if (isImage) + ClipRRect( + borderRadius: BorderRadius.circular(6), + child: Image.file(widget.file, width: 40, height: 40, fit: BoxFit.cover), + ) + else + Container( + width: 40, + height: 40, + decoration: BoxDecoration( + color: widget.pt.bg3, + borderRadius: BorderRadius.circular(6), + ), + child: Center( + child: Icon(_mimeIcon(mime), size: 20, color: widget.pt.fgDim), + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + filename, + style: TextStyle(color: widget.pt.fg, fontSize: 13), + overflow: TextOverflow.ellipsis, + ), + if (_bytes != null) + Text( + _formatSize(_bytes!), + style: TextStyle(color: widget.pt.fgDim, fontSize: 11), + ), + ], + ), + ), + ], + ), + ); + } + + IconData _mimeIcon(String mime) { + if (mime.startsWith('video/')) return Icons.videocam_outlined; + if (mime.startsWith('audio/')) return Icons.audio_file_outlined; + if (mime.contains('pdf')) return Icons.picture_as_pdf_outlined; + if (mime.contains('zip') || mime.contains('tar') || mime.contains('gz')) { + return Icons.folder_zip_outlined; + } + return Icons.insert_drive_file_outlined; + } + + String _formatSize(int bytes) { + if (bytes < 1024) return '${bytes} B'; + if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(1)} KB'; + return '${(bytes / (1024 * 1024)).toStringAsFixed(1)} MB'; + } +} diff --git a/lib/features/chat/chat_composer.dart b/lib/features/chat/chat_composer.dart new file mode 100644 index 0000000..b65bcee --- /dev/null +++ b/lib/features/chat/chat_composer.dart @@ -0,0 +1,630 @@ +import 'dart:async'; +import 'dart:io'; +import 'dart:typed_data'; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pyramid/core/settings_prefs.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/attachment_dialog.dart'; +import 'package:pyramid/features/chat/emoji_picker.dart'; +import 'package:pyramid/features/chat/gif_sticker_picker.dart'; +import 'package:pyramid/utils/clipboard_image.dart'; + +class ChatComposer extends ConsumerStatefulWidget { + final Room room; + final Event? replyTo; + final VoidCallback? onClearReply; + final VoidCallback? onOpenEmoji; + + const ChatComposer({ + super.key, + required this.room, + this.replyTo, + this.onClearReply, + this.onOpenEmoji, + }); + + @override + ConsumerState createState() => _ChatComposerState(); +} + +class _ChatComposerState extends ConsumerState { + final _ctrl = TextEditingController(); + late final FocusNode _focus; + bool _canSend = false; + OverlayEntry? _gifOverlay; + OverlayEntry? _emojiOverlay; + Timer? _typingTimer; + bool _isTyping = false; + + @override + void initState() { + super.initState(); + _focus = FocusNode(onKeyEvent: _handleKeyEvent); + _ctrl.addListener(_onTextChanged); + } + + KeyEventResult _handleKeyEvent(FocusNode node, KeyEvent event) { + if (event is KeyDownEvent && + event.logicalKey == LogicalKeyboardKey.keyV && + HardwareKeyboard.instance.isControlPressed) { + final bytes = getClipboardImageBytes(); + if (bytes != null) { + _pasteClipboardImage(bytes); + return KeyEventResult.handled; + } + } + return KeyEventResult.ignored; + } + + Future _pasteClipboardImage(Uint8List bytes) async { + final dir = await getTemporaryDirectory(); + final file = File('${dir.path}/paste_${DateTime.now().millisecondsSinceEpoch}.png'); + await file.writeAsBytes(bytes); + if (!mounted) return; + await AttachmentDialog.show(context, [file], widget.room, replyTo: widget.replyTo); + widget.onClearReply?.call(); + file.delete().catchError((_) => file); + } + + /// Bilder, die die Android-Tastatur einfügt (Gboard-Clipboard-Chip, + /// GIF-Auswahl der Tastatur etc.) — landen im Anhang-Dialog mit Vorschau. + Future _handleInsertedContent(KeyboardInsertedContent content) async { + final bytes = content.data; + if (bytes == null || bytes.isEmpty) return; + final ext = content.mimeType.contains('/') + ? content.mimeType.split('/').last + : 'png'; + final dir = await getTemporaryDirectory(); + final file = File( + '${dir.path}/keyboard_${DateTime.now().millisecondsSinceEpoch}.$ext'); + await file.writeAsBytes(bytes); + if (!mounted) return; + await AttachmentDialog.show(context, [file], widget.room, replyTo: widget.replyTo); + widget.onClearReply?.call(); + file.delete().catchError((_) => file); + } + + void _onTextChanged() { + final has = _ctrl.text.trim().isNotEmpty; + if (has != _canSend) setState(() => _canSend = has); + _updateTyping(has); + } + + void _updateTyping(bool typing) { + final sendTyping = ref.read(privacyTypingProvider); + if (!sendTyping) return; + + if (typing) { + // Reset the auto-stop timer on every keystroke. + _typingTimer?.cancel(); + _typingTimer = Timer(const Duration(seconds: 7), () => _sendTyping(false)); + if (!_isTyping) _sendTyping(true); + } else { + _typingTimer?.cancel(); + if (_isTyping) _sendTyping(false); + } + } + + void _sendTyping(bool typing) { + _isTyping = typing; + widget.room + .setTyping(typing, timeout: typing ? 10000 : null) + .catchError((_) {}); + } + + @override + void dispose() { + _typingTimer?.cancel(); + if (_isTyping) widget.room.setTyping(false).catchError((_) {}); + _gifOverlay?.remove(); + _emojiOverlay?.remove(); + _ctrl.dispose(); + _focus.dispose(); + super.dispose(); + } + + void _toggleGifPicker() { + if (_gifOverlay != null) { + _gifOverlay!.remove(); + _gifOverlay = null; + return; + } + + final platform = Theme.of(context).platform; + final isMobile = platform == TargetPlatform.android || platform == TargetPlatform.iOS; + + if (isMobile) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: (ctx) => Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.viewInsetsOf(ctx).bottom, + top: 40, + ), + child: GifStickerPicker( + room: widget.room, + onClose: () => Navigator.of(ctx).pop(), + ), + ), + ); + return; + } + + final box = context.findRenderObject() as RenderBox?; + final offset = box?.localToGlobal(Offset.zero) ?? Offset.zero; + final size = box?.size ?? Size.zero; + + _gifOverlay = OverlayEntry(builder: (ctx) { + final screenSize = MediaQuery.sizeOf(ctx); + const pickerW = 380.0; + const pickerH = 460.0; + final left = (offset.dx + size.width - pickerW).clamp(8.0, screenSize.width - pickerW - 8); + final top = (offset.dy - pickerH - 8).clamp(8.0, screenSize.height - pickerH - 8); + return Material( + type: MaterialType.transparency, + child: Stack(children: [ + GestureDetector( + onTap: () { _gifOverlay?.remove(); _gifOverlay = null; }, + behavior: HitTestBehavior.translucent, + child: const SizedBox.expand(), + ), + Positioned( + left: left, + top: top, + child: GifStickerPicker( + room: widget.room, + onClose: () { _gifOverlay?.remove(); _gifOverlay = null; }, + ), + ), + ]), + ); + }); + Overlay.of(context).insert(_gifOverlay!); + } + + void _toggleEmojiPicker() { + if (_emojiOverlay != null) { + _emojiOverlay!.remove(); + _emojiOverlay = null; + return; + } + + final platform = Theme.of(context).platform; + final isMobile = platform == TargetPlatform.android || platform == TargetPlatform.iOS; + + void onEmojiSelected(String emoji, BuildContext? ctx) { + final pos = _ctrl.selection.baseOffset; + final text = _ctrl.text; + final before = pos < 0 ? text : text.substring(0, pos); + final after = pos < 0 ? '' : text.substring(pos); + _ctrl.value = TextEditingValue( + text: '$before$emoji$after', + selection: TextSelection.collapsed( + offset: before.length + emoji.length, + ), + ); + if (isMobile && ctx != null) { + Navigator.of(ctx).pop(); + } else { + _emojiOverlay?.remove(); + _emojiOverlay = null; + } + _focus.requestFocus(); + } + + if (isMobile) { + showModalBottomSheet( + context: context, + backgroundColor: Colors.transparent, + isScrollControlled: true, + builder: (ctx) => Padding( + padding: EdgeInsets.only( + bottom: MediaQuery.viewInsetsOf(ctx).bottom, + top: 40, + ), + child: EmojiPicker( + onEmojiSelected: (emoji) => onEmojiSelected(emoji, ctx), + onClose: () => Navigator.of(ctx).pop(), + ), + ), + ); + return; + } + + final box = context.findRenderObject() as RenderBox?; + final offset = box?.localToGlobal(Offset.zero) ?? Offset.zero; + final size = box?.size ?? Size.zero; + + _emojiOverlay = OverlayEntry(builder: (ctx) { + final screenSize = MediaQuery.sizeOf(ctx); + const pickerW = 340.0; + const pickerH = 380.0; + final left = (offset.dx + size.width - pickerW).clamp(8.0, screenSize.width - pickerW - 8); + final top = (offset.dy - pickerH - 8).clamp(8.0, screenSize.height - pickerH - 8); + return Material( + type: MaterialType.transparency, + child: Stack(children: [ + GestureDetector( + onTap: () { _emojiOverlay?.remove(); _emojiOverlay = null; }, + behavior: HitTestBehavior.translucent, + child: const SizedBox.expand(), + ), + Positioned( + left: left, + top: top, + child: EmojiPicker( + onEmojiSelected: (emoji) => onEmojiSelected(emoji, null), + onClose: () { _emojiOverlay?.remove(); _emojiOverlay = null; }, + ), + ), + ]), + ); + }); + Overlay.of(context).insert(_emojiOverlay!); + } + + Future _pickAttachment() async { + final result = await FilePicker.platform.pickFiles(allowMultiple: true); + if (result == null || result.files.isEmpty) return; + if (!mounted) return; + final files = result.files + .where((f) => f.path != null) + .map((f) => File(f.path!)) + .toList(); + if (files.isEmpty) return; + await AttachmentDialog.show(context, files, widget.room, replyTo: widget.replyTo); + widget.onClearReply?.call(); + } + + Future _send() async { + final text = _ctrl.text.trim(); + if (text.isEmpty) return; + _ctrl.clear(); + setState(() => _canSend = false); + // Stop typing indicator immediately before sending. + _typingTimer?.cancel(); + if (_isTyping) _sendTyping(false); + await widget.room.sendTextEvent(text, inReplyTo: widget.replyTo); + widget.onClearReply?.call(); + _focus.requestFocus(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final size = MediaQuery.sizeOf(context); + final isSmall = size.width < 400; + + final roomName = widget.room.getLocalizedDisplayname(); + final placeholder = widget.room.isDirectChat + ? 'Message…' + : 'Message #$roomName'; + + return SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (widget.replyTo != null) + _ReplyBar( + event: widget.replyTo!, + onClear: widget.onClearReply ?? () {}, + pt: pt, + ), + Padding( + // Bottom inset matches the profile block in the rooms list (8px) so + // the composer sits flush with it. + padding: EdgeInsets.fromLTRB(isSmall ? 8 : 16, 0, isSmall ? 8 : 16, 8), + child: AnimatedContainer( + duration: const Duration(milliseconds: 180), + curve: Curves.easeOutCubic, + // Tuned so the single-line composer is flush with the profile + // block in the rooms list (~89px on the user's display). Grows for + // multiline. + constraints: const BoxConstraints(minHeight: 53), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase + 4), + border: Border.all( + color: _focus.hasFocus ? pt.accent : pt.border, + ), + boxShadow: _focus.hasFocus + ? [BoxShadow(color: pt.accentSoft, blurRadius: 0, spreadRadius: 3)] + : null, + ), + child: Focus( + onFocusChange: (_) => setState(() {}), + child: Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + // Attach button + _ComposerIconBtn( + icon: Icons.add_rounded, + tooltip: 'Datei anhängen', + pt: pt, + size: size.width < 600 ? 24 : 30, + onTap: _pickAttachment, + ), + // Text input + Expanded( + child: TextField( + controller: _ctrl, + focusNode: _focus, + minLines: 1, + maxLines: 8, + style: TextStyle(color: pt.fg, fontSize: 14), + cursorColor: pt.accent, + decoration: InputDecoration( + hintText: placeholder, + hintStyle: TextStyle(color: pt.fgDim, fontSize: 14), + border: InputBorder.none, + contentPadding: EdgeInsets.symmetric( + horizontal: size.width < 600 ? 4 : 8, + vertical: 10, + ), + isDense: true, + ), + inputFormatters: [ + if (!(Platform.isAndroid || Platform.isIOS)) + _SendOnEnterFormatter(onSend: _send), + ], + // Meldet der Android-Tastatur, dass dieses Feld Bilder + // annimmt — dadurch bietet z.B. Gboard frisch kopierte + // Bilder direkt in der Vorschlagsleiste an. + contentInsertionConfiguration: Platform.isAndroid + ? ContentInsertionConfiguration( + allowedMimeTypes: const [ + 'image/gif', + 'image/png', + 'image/jpeg', + 'image/webp', + ], + onContentInserted: _handleInsertedContent, + ) + : null, + ), + ), + // Inline tools + Row( + mainAxisSize: MainAxisSize.min, + children: [ + _ComposerIconBtn( + icon: Icons.gif_box_outlined, + tooltip: 'GIF', + pt: pt, + size: size.width < 600 ? 22 : 26, + onTap: _toggleGifPicker, + ), + _ComposerIconBtn( + icon: Icons.tag_faces_rounded, + tooltip: 'Emoji', + pt: pt, + size: size.width < 600 ? 22 : 26, + onTap: _toggleEmojiPicker, + ), + if (size.width > 600) + _ComposerIconBtn( + icon: Icons.alternate_email_rounded, + tooltip: 'Mention', + pt: pt, + size: 26, + ), + ], + ), + // Send button — only on mobile + if (Platform.isAndroid || Platform.isIOS) + Padding( + padding: const EdgeInsets.fromLTRB(4, 4, 8, 4), + child: _SendButton( + canSend: _canSend, + pt: pt, + onTap: _send, + ), + ), + ], + ), + ), + ), + ), + ], + ), + ); + } +} + +class _ComposerIconBtn extends StatefulWidget { + final IconData icon; + final String tooltip; + final PyramidTheme pt; + final double size; + final VoidCallback? onTap; + + const _ComposerIconBtn({ + required this.icon, + required this.tooltip, + required this.pt, + required this.size, + this.onTap, + }); + + @override + State<_ComposerIconBtn> createState() => _ComposerIconBtnState(); +} + +class _ComposerIconBtnState extends State<_ComposerIconBtn> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final platform = Theme.of(context).platform; + final isMobile = + platform == TargetPlatform.android || platform == TargetPlatform.iOS; + final touchSize = isMobile ? 44.0 : widget.size; + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: Tooltip( + message: widget.tooltip, + waitDuration: const Duration(milliseconds: 500), + child: SizedBox( + width: touchSize, + height: touchSize, + child: Center( + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: widget.size, + height: widget.size, + decoration: BoxDecoration( + color: _hovered ? widget.pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(6), + ), + child: Center( + child: Icon( + widget.icon, + size: widget.size * 0.55, + color: _hovered ? widget.pt.fg : widget.pt.fgMuted, + ), + ), + ), + ), + ), + ), + ), + ); + } +} + +class _SendButton extends StatefulWidget { + final bool canSend; + final PyramidTheme pt; + final VoidCallback onTap; + + const _SendButton({required this.canSend, required this.pt, required this.onTap}); + + @override + State<_SendButton> createState() => _SendButtonState(); +} + +class _SendButtonState extends State<_SendButton> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final active = widget.canSend; + + return MouseRegion( + cursor: active ? SystemMouseCursors.click : MouseCursor.defer, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: active ? widget.onTap : null, + child: AnimatedContainer( + duration: const Duration(milliseconds: 180), + curve: Curves.easeOutBack, + width: 36, + height: 36, + decoration: BoxDecoration( + color: active ? pt.accent : pt.bg3, + borderRadius: BorderRadius.circular(pt.rSm), + boxShadow: active && _hovered + ? [BoxShadow(color: pt.accentGlow, blurRadius: 12, offset: const Offset(0, 4))] + : null, + ), + transform: active + ? (_hovered + ? (Matrix4.diagonal3Values(1.1, 1.1, 1.0)..rotateZ(-0.26)) + : Matrix4.diagonal3Values(1.05, 1.05, 1.0)) + : Matrix4.identity(), + transformAlignment: Alignment.center, + child: Center( + child: Icon( + Icons.send_rounded, + size: 16, + color: active ? pt.accentFg : pt.fgDim, + ), + ), + ), + ), + ); + } +} + +class _ReplyBar extends StatelessWidget { + final Event event; + final VoidCallback onClear; + final PyramidTheme pt; + + const _ReplyBar({required this.event, required this.onClear, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.fromLTRB(16, 8, 8, 4), + decoration: BoxDecoration( + border: Border( + top: BorderSide(color: pt.border), + left: BorderSide(color: pt.accent, width: 3), + ), + ), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + event.senderFromMemoryOrFallback.calcDisplayname(), + style: TextStyle( + color: pt.accent, + fontSize: 12, + fontWeight: FontWeight.w600, + ), + ), + Text( + event.body, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle(color: pt.fgMuted, fontSize: 12), + ), + ], + ), + ), + GestureDetector( + onTap: onClear, + child: Icon(Icons.close_rounded, size: 16, color: pt.fgDim), + ), + ], + ), + ); + } +} + +class _SendOnEnterFormatter extends TextInputFormatter { + final VoidCallback onSend; + _SendOnEnterFormatter({required this.onSend}); + + @override + TextEditingValue formatEditUpdate( + TextEditingValue oldValue, + TextEditingValue newValue, + ) { + if (newValue.text.endsWith('\n') && !oldValue.text.endsWith('\n')) { + // Check if shift is pressed (can't detect here, just send on enter) + // For multiline we'd need keyboard shortcuts + WidgetsBinding.instance.addPostFrameCallback((_) => onSend()); + return oldValue; + } + return newValue; + } +} diff --git a/lib/features/chat/chat_input.dart b/lib/features/chat/chat_input.dart deleted file mode 100644 index e88b3af..0000000 --- a/lib/features/chat/chat_input.dart +++ /dev/null @@ -1,211 +0,0 @@ -import 'package:flutter/foundation.dart'; -import 'package:flutter/material.dart'; -import 'package:flutter/services.dart'; -import 'package:matrix/matrix.dart'; - -class ChatInput extends StatefulWidget { - final Room room; - final Event? replyTo; - final VoidCallback? onClearReply; - - const ChatInput({ - super.key, - required this.room, - this.replyTo, - this.onClearReply, - }); - - @override - State createState() => _ChatInputState(); -} - -class _ChatInputState extends State { - final _ctrl = TextEditingController(); - bool _canSend = false; - - @override - void initState() { - super.initState(); - _ctrl.addListener(() { - final hasText = _ctrl.text.trim().isNotEmpty; - if (hasText != _canSend) setState(() => _canSend = hasText); - }); - } - - @override - void dispose() { - _ctrl.dispose(); - super.dispose(); - } - - Future _send() async { - final text = _ctrl.text.trim(); - if (text.isEmpty) return; - _ctrl.clear(); - setState(() => _canSend = false); - await widget.room.sendTextEvent(text, inReplyTo: widget.replyTo); - widget.onClearReply?.call(); - } - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - final isDesktop = !kIsWeb && - (defaultTargetPlatform == TargetPlatform.windows || - defaultTargetPlatform == TargetPlatform.linux || - defaultTargetPlatform == TargetPlatform.macOS); - - // Desktop: taller bar, 4px square corners, bigger button - // Mobile: compact bar, pill shape, smaller button - final fieldRadius = isDesktop ? 4.0 : 20.0; - final btnSize = isDesktop ? 56.0 : 44.0; - final btnRadius = isDesktop ? 6.0 : 12.0; - final iconSize = isDesktop ? 24.0 : 20.0; - final fontSize = isDesktop ? 15.0 : 14.0; - final vPad = isDesktop ? 18.0 : 10.0; - final hPad = isDesktop ? 16.0 : 14.0; - final outerPad = isDesktop - ? const EdgeInsets.fromLTRB(12, 10, 12, 12) - : const EdgeInsets.fromLTRB(8, 4, 8, 8); - - return SafeArea( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - if (widget.replyTo != null) - _ReplyBar( - event: widget.replyTo!, - onClear: widget.onClearReply ?? () {}, - ), - Padding( - padding: outerPad, - child: Row( - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - Expanded( - child: TextField( - controller: _ctrl, - minLines: 1, - maxLines: 6, - textCapitalization: TextCapitalization.sentences, - style: TextStyle(fontSize: fontSize), - decoration: InputDecoration( - hintText: 'Nachricht...', - hintStyle: TextStyle(fontSize: fontSize), - contentPadding: EdgeInsets.symmetric( - horizontal: hPad, - vertical: vPad, - ), - border: OutlineInputBorder( - borderRadius: BorderRadius.circular(fieldRadius), - borderSide: BorderSide.none, - ), - enabledBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(fieldRadius), - borderSide: BorderSide.none, - ), - focusedBorder: OutlineInputBorder( - borderRadius: BorderRadius.circular(fieldRadius), - borderSide: BorderSide.none, - ), - filled: true, - fillColor: theme.colorScheme.surfaceContainerHigh, - ), - onSubmitted: (_) => _send(), - keyboardType: TextInputType.multiline, - inputFormatters: [ - _SendOnEnterFormatter(onSend: _send), - ], - ), - ), - SizedBox(width: isDesktop ? 10 : 8), - GestureDetector( - onTap: _canSend ? _send : null, - child: AnimatedContainer( - duration: const Duration(milliseconds: 150), - width: btnSize, - height: btnSize, - decoration: BoxDecoration( - color: _canSend - ? theme.colorScheme.primary - : theme.colorScheme.primary.withAlpha(70), - borderRadius: BorderRadius.circular(btnRadius), - ), - child: Center( - child: Icon( - Icons.send_rounded, - size: iconSize, - color: Colors.white, - ), - ), - ), - ), - ], - ), - ), - ], - ), - ); - } -} - -class _ReplyBar extends StatelessWidget { - final Event event; - final VoidCallback onClear; - const _ReplyBar({required this.event, required this.onClear}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Container( - padding: const EdgeInsets.fromLTRB(16, 8, 8, 4), - decoration: BoxDecoration( - border: Border( - top: BorderSide(color: theme.dividerColor), - left: BorderSide(color: theme.colorScheme.primary, width: 3), - ), - ), - child: Row( - children: [ - Expanded( - child: Column( - crossAxisAlignment: CrossAxisAlignment.start, - children: [ - Text( - event.senderFromMemoryOrFallback.calcDisplayname(), - style: theme.textTheme.labelSmall?.copyWith( - color: theme.colorScheme.primary, - fontWeight: FontWeight.bold, - ), - ), - Text( - event.body, - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall, - ), - ], - ), - ), - IconButton( - icon: const Icon(Icons.close, size: 18), - onPressed: onClear, - ), - ], - ), - ); - } -} - -class _SendOnEnterFormatter extends TextInputFormatter { - final VoidCallback onSend; - _SendOnEnterFormatter({required this.onSend}); - - @override - TextEditingValue formatEditUpdate( - TextEditingValue oldValue, - TextEditingValue newValue, - ) { - return newValue; - } -} diff --git a/lib/features/chat/chat_page.dart b/lib/features/chat/chat_page.dart deleted file mode 100644 index d69e972..0000000 --- a/lib/features/chat/chat_page.dart +++ /dev/null @@ -1,156 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:matrix/matrix.dart'; -import 'package:pyramid/features/chat/chat_input.dart'; -import 'package:pyramid/features/chat/chat_provider.dart'; -import 'package:pyramid/features/chat/message_bubble.dart'; - -class ChatPage extends ConsumerStatefulWidget { - final String roomId; - const ChatPage({super.key, required this.roomId}); - - @override - ConsumerState createState() => _ChatPageState(); -} - -class _ChatPageState extends ConsumerState { - final _scrollCtrl = ScrollController(); - Event? _replyTo; - - String get _roomId => Uri.decodeComponent(widget.roomId); - - @override - void initState() { - super.initState(); - _scrollCtrl.addListener(_onScroll); - } - - @override - void dispose() { - _scrollCtrl.dispose(); - super.dispose(); - } - - void _onScroll() { - if (_scrollCtrl.position.pixels >= - _scrollCtrl.position.maxScrollExtent - 300) { - final timeline = ref.read(timelineProvider(_roomId)).valueOrNull; - timeline?.requestHistory(); - } - } - - @override - Widget build(BuildContext context) { - final room = ref.watch(roomProvider(_roomId)); - final timelineAsync = ref.watch(timelineProvider(_roomId)); - - return Scaffold( - appBar: AppBar( - leading: IconButton( - icon: const Icon(Icons.arrow_back), - onPressed: () => context.go('/rooms'), - ), - title: Text(room?.getLocalizedDisplayname() ?? _roomId), - actions: [ - IconButton( - icon: const Icon(Icons.info_outline), - onPressed: () {}, - ), - ], - ), - body: Column( - children: [ - Expanded( - child: timelineAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (e, _) => Center(child: Text('Fehler: $e')), - data: (timeline) => _MessageList( - timeline: timeline, - scrollCtrl: _scrollCtrl, - currentUserId: room?.client.userID ?? '', - onReply: (event) => setState(() => _replyTo = event), - ), - ), - ), - if (room != null) - ChatInput( - room: room, - replyTo: _replyTo, - onClearReply: () => setState(() => _replyTo = null), - ), - ], - ), - ); - } -} - -class _MessageList extends StatelessWidget { - final Timeline timeline; - final ScrollController scrollCtrl; - final String currentUserId; - final ValueChanged onReply; - - const _MessageList({ - required this.timeline, - required this.scrollCtrl, - required this.currentUserId, - required this.onReply, - }); - - @override - Widget build(BuildContext context) { - final events = timeline.events - .where((e) => - e.type == EventTypes.Message && - e.status != EventStatus.error) - .toList(); - - if (events.isEmpty) { - return const Center(child: Text('Noch keine Nachrichten')); - } - - return ListView.builder( - controller: scrollCtrl, - reverse: true, - padding: const EdgeInsets.symmetric(vertical: 8), - itemCount: events.length, - itemBuilder: (context, i) { - final event = events[i]; - final isOwn = event.senderId == currentUserId; - - final showDate = i == events.length - 1 || - !_sameDay(event.originServerTs, events[i + 1].originServerTs); - - final replyEventId = - event.content.tryGetMap('m.relates_to') - ?['m.in_reply_to']?['event_id'] as String?; - final replyEvent = replyEventId != null - ? timeline.events.firstWhere( - (e) => e.eventId == replyEventId, - orElse: () => event, - ) - : null; - - return Column( - children: [ - if (showDate) - DateSeparator(date: event.originServerTs), - GestureDetector( - onLongPress: () => onReply(event), - child: MessageBubble( - event: event, - isOwn: isOwn, - replyEvent: - replyEvent?.eventId != event.eventId ? replyEvent : null, - ), - ), - ], - ); - }, - ); - } - - bool _sameDay(DateTime a, DateTime b) => - a.year == b.year && a.month == b.month && a.day == b.day; -} diff --git a/lib/features/chat/chat_provider.dart b/lib/features/chat/chat_provider.dart index 8f10bbe..7d53d92 100644 --- a/lib/features/chat/chat_provider.dart +++ b/lib/features/chat/chat_provider.dart @@ -1,20 +1,145 @@ +import 'dart:async'; + import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/e2ee_diagnostics.dart'; import 'package:pyramid/core/matrix_client.dart'; +// AsyncNotifier so onUpdate can refresh state in-place without recreating the +// timeline (which would reset the loaded event window back to the default 30). +class TimelineNotifier extends FamilyAsyncNotifier { + Timeline? _timeline; + StreamSubscription? _roomUpdateSub; + Timer? _redecryptTimer; + + @override + Future build(String arg) async { + final roomId = arg; + final client = await ref.watch(matrixClientProvider.future); + final room = client.getRoomById(roomId); + if (room == null) throw Exception('Raum nicht gefunden: $roomId'); + + _timeline?.cancelSubscriptions(); + _roomUpdateSub?.cancel(); + _redecryptTimer?.cancel(); + + final diag = ref.read(e2eeDiagnosticsProvider.notifier); + + final timeline = await room.getTimeline( + onUpdate: _onUpdate, + ); + _timeline = timeline; + + if (timeline.events.length < 20) { + await timeline.requestHistory(historyCount: 60); + } + + timeline.requestKeys(onlineKeyBackupOnly: false); + unawaited(_decryptLegacyEvents(client, timeline, roomId, diag)); + + // Re-decrypt whenever the room updates (e.g. after new keys arrive from + // key requests). Debounced to avoid redundant passes on rapid updates. + _roomUpdateSub = room.onUpdate.stream.listen((_) { + _redecryptTimer?.cancel(); + _redecryptTimer = Timer(const Duration(milliseconds: 800), () { + final t = _timeline; + if (t != null) { + unawaited(_decryptLegacyEvents(client, t, roomId, diag)); + } + }); + }); + + // Ensure device keys are downloaded for all room members so outbound + // Megolm session key sharing works on the first send. + if (room.encrypted && client.encryptionEnabled) { + unawaited(_preloadDeviceKeys(client, room)); + } + + ref.onDispose(() { + _roomUpdateSub?.cancel(); + _redecryptTimer?.cancel(); + _timeline?.cancelSubscriptions(); + _timeline = null; + }); + return timeline; + } + + void _onUpdate() { + final t = _timeline; + if (t != null) state = AsyncData(t); + } +} + final timelineProvider = - FutureProvider.family((ref, roomId) async { - final client = await ref.watch(matrixClientProvider.future); - final room = client.getRoomById(roomId); - if (room == null) throw Exception('Raum nicht gefunden: $roomId'); + AsyncNotifierProvider.family( + TimelineNotifier.new, +); - final timeline = await room.getTimeline( - onUpdate: () => ref.invalidateSelf(), - ); +Future _decryptLegacyEvents( + Client client, + Timeline timeline, + String roomId, + E2eeDiagnosticsNotifier diag, +) async { + final enc = client.encryption; + if (enc == null) return; - ref.onDispose(timeline.cancelSubscriptions); - return timeline; -}); + try { + await enc.keyManager.loadAllKeysFromRoom(roomId); + } catch (e) { + Logs().e('[ChatProvider] loadAllKeysFromRoom failed', e); + } + + if (!enc.enabled) return; + + var changed = false; + for (var i = 0; i < timeline.events.length; i++) { + final event = timeline.events[i]; + if (event.type != EventTypes.Encrypted) continue; + try { + final decrypted = await enc.decryptRoomEvent( + event, + store: true, + updateType: EventUpdateType.history, + ); + if (decrypted.type != EventTypes.Encrypted) { + timeline.events[i] = decrypted; + changed = true; + } else { + // Still encrypted — log for diagnostics + final sessionId = event.content.tryGet('session_id') ?? ''; + diag.add(E2eeDiagEntry( + timestamp: DateTime.now(), + roomId: roomId, + eventId: event.eventId, + sessionId: sessionId, + error: decrypted.content.tryGet('body') ?? 'unknown', + )); + } + } catch (e) { + final sessionId = event.content.tryGet('session_id') ?? ''; + diag.add(E2eeDiagEntry( + timestamp: DateTime.now(), + roomId: roomId, + eventId: event.eventId, + sessionId: sessionId, + error: e.toString(), + )); + } + } + // Notify UI of in-place changes only when something actually decrypted + if (changed) timeline.onUpdate?.call(); +} + +Future _preloadDeviceKeys(Client client, Room room) async { + try { + final members = await room.requestParticipants([Membership.join, Membership.invite]); + final userIds = members.map((m) => m.id).toSet(); + await client.updateUserDeviceKeys(additionalUsers: userIds); + } catch (e) { + Logs().w('[ChatProvider] Device key preload failed: $e'); + } +} final roomProvider = Provider.family((ref, roomId) { final client = ref.watch(matrixClientProvider).valueOrNull; diff --git a/lib/features/chat/chat_view.dart b/lib/features/chat/chat_view.dart new file mode 100644 index 0000000..e96d4ff --- /dev/null +++ b/lib/features/chat/chat_view.dart @@ -0,0 +1,2115 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; + +import 'package:flutter/services.dart' show Clipboard, ClipboardData; + +import 'package:desktop_drop/desktop_drop.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/settings_prefs.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/attachment_dialog.dart'; +import 'package:pyramid/features/chat/chat_composer.dart'; +import 'package:pyramid/features/chat/chat_provider.dart'; +import 'package:pyramid/features/chat/message_group.dart'; +import 'package:pyramid/features/chat/pinned_messages_panel.dart'; +import 'package:pyramid/widgets/hover_region.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +import 'package:pyramid/core/notification_service.dart'; +import 'package:pyramid/core/voip_manager.dart'; + +class ChatView extends ConsumerStatefulWidget { + final String roomId; + const ChatView({super.key, required this.roomId}); + + @override + ConsumerState createState() => _ChatViewState(); +} + +class _ChatViewState extends ConsumerState { + final _scrollCtrl = ScrollController(); + Event? _replyTo; + bool _loadingHistory = false; + bool _historyExhausted = false; + bool _draggingOver = false; + bool _pinnedOpen = false; + bool _profileExpanded = false; + bool _showScrollDown = false; + final Set _selectedIds = {}; + + // Unread state captured at session open (before marking as read) + String? _sessionFullyReadId; + bool _sessionHasUnread = false; + bool _sessionCaptured = false; + bool _didScrollToUnread = false; + bool _loadingFuture = false; + // Fade-out of the "Neue Nachrichten" divider once the user reaches the bottom. + bool _unreadFading = false; + Timer? _unreadFadeTimer; + + // Jump-to-message (from search): scroll to + briefly highlight a target event. + final _jumpKey = GlobalKey(); + String? _jumpEventId; + String? _highlightEventId; + bool _highlightOn = false; + bool _jumpInProgress = false; + Timer? _highlightTimer; + + void _startJump(String eventId) { + _highlightTimer?.cancel(); + setState(() { + _jumpEventId = eventId; + _highlightEventId = eventId; + _highlightOn = true; + _jumpInProgress = true; + }); + // Consume the request so it doesn't re-fire. + ref.read(pendingJumpEventProvider.notifier).state = null; + WidgetsBinding.instance.addPostFrameCallback((_) => _attemptJump(0)); + } + + void _attemptJump(int attempt) { + if (!mounted || _jumpEventId == null) return; + final ctx = _jumpKey.currentContext; + if (ctx != null) { + Scrollable.ensureVisible( + ctx, + alignment: 0.4, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ); + _jumpInProgress = false; + // Hold the highlight briefly, then fade it out smoothly. + _highlightTimer?.cancel(); + _highlightTimer = Timer(const Duration(milliseconds: 1300), () { + if (!mounted) return; + setState(() => _highlightOn = false); // triggers the AnimatedOpacity fade + _highlightTimer = Timer(const Duration(milliseconds: 950), () { + if (mounted) setState(() { _highlightEventId = null; _jumpEventId = null; }); + }); + }); + return; + } + if (attempt >= 40) { + // Couldn't reach the event — give up gracefully (room is at least open). + setState(() { _jumpInProgress = false; _highlightEventId = null; _jumpEventId = null; _highlightOn = false; }); + return; + } + // Not built yet — load older history toward the target every few tries. + final timeline = ref.read(timelineProvider(widget.roomId)).valueOrNull; + if (timeline != null && timeline.canRequestHistory && attempt % 3 == 0) { + timeline.requestHistory(historyCount: 100).catchError((_) {}); + } + WidgetsBinding.instance.addPostFrameCallback((_) { + Future.delayed(const Duration(milliseconds: 120), () => _attemptJump(attempt + 1)); + }); + } + + // GlobalKey for the "Neue Nachrichten" divider — used by ensureVisible to + // scroll precisely to the divider on chat open. + final _unreadDividerKey = GlobalKey(); + + bool get _inSelectionMode => _selectedIds.isNotEmpty; + + void _toggleSelect(String eventId) { + setState(() { + if (_selectedIds.contains(eventId)) { + _selectedIds.remove(eventId); + } else { + _selectedIds.add(eventId); + } + }); + } + + void _clearSelection() => setState(() => _selectedIds.clear()); + + @override + void initState() { + super.initState(); + _scrollCtrl.addListener(_onScroll); + } + + @override + void didUpdateWidget(ChatView oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.roomId != widget.roomId) { + _profileExpanded = false; + _sessionFullyReadId = null; + _sessionHasUnread = false; + _sessionCaptured = false; + _didScrollToUnread = false; + _loadingFuture = false; + _historyExhausted = false; + _unreadFading = false; + _unreadFadeTimer?.cancel(); + _jumpEventId = null; + _highlightEventId = null; + _highlightOn = false; + _jumpInProgress = false; + _highlightTimer?.cancel(); + // The GlobalKey stays alive — it'll simply have no context until the + // new room's divider (if any) is built. + } + } + + @override + void dispose() { + _unreadFadeTimer?.cancel(); + _highlightTimer?.cancel(); + _scrollCtrl.dispose(); + super.dispose(); + } + + void _captureAndMarkRead(Timeline timeline) { + if (!_sessionCaptured) { + final room = timeline.room; + final fullyRead = room.fullyRead; // "" if never set + final newFullyReadId = fullyRead.isNotEmpty ? fullyRead : null; + + // Show the divider only if there's a genuinely unread VISIBLE message + // FROM SOMEONE ELSE after the read marker. Own messages and hidden events + // (reactions, receipts, edits) don't count — otherwise the divider ends + // up below all messages (e.g. right after one's own latest message). + final me = room.client.userID; + final events = timeline.events; // newest-first + final frIndex = + fullyRead.isEmpty ? -1 : events.indexWhere((e) => e.eventId == fullyRead); + // Indices [0, upTo) are newer than the read marker. + final upTo = frIndex >= 0 ? frIndex : events.length; + var newHasUnread = false; + for (var i = 0; i < upTo; i++) { + final e = events[i]; + if (_MessageList._isVisible(e) && e.senderId != me) { + newHasUnread = true; + break; + } + } + + _sessionCaptured = true; + + // setState so _MessageList rebuilds with the captured unread marker. + if (mounted) { + setState(() { + _sessionFullyReadId = newFullyReadId; + _sessionHasUnread = newHasUnread; + }); + if (newHasUnread) { + WidgetsBinding.instance.addPostFrameCallback((_) => _scrollToUnread(timeline)); + } + } + } + _markRead(timeline); + } + + void _scrollToUnread(Timeline timeline) { + if (_didScrollToUnread) return; + _attemptScrollToUnread(0); + } + + // The "Neue Nachrichten" divider may not be laid out yet on first open (lazy + // reverse ListView only builds visible + cacheExtent items). Retry until its + // context exists, nudging the scroll upward periodically so the list builds + // toward the divider when there are many unread messages. + void _attemptScrollToUnread(int attempt) { + if (_didScrollToUnread || !mounted) return; + final ctx = _unreadDividerKey.currentContext; + if (ctx != null) { + _didScrollToUnread = true; + // alignment 0.85: in a reverse list this lands the divider near the top + // of the viewport with a little read context above it and the unread + // messages filling the screen below. + Scrollable.ensureVisible( + ctx, + alignment: 0.85, + duration: const Duration(milliseconds: 250), + curve: Curves.easeOut, + ); + return; + } + if (attempt >= 24) { + _didScrollToUnread = true; // give up — stay at the newest messages + return; + } + if (attempt > 0 && attempt % 4 == 0 && _scrollCtrl.hasClients) { + final pos = _scrollCtrl.position; + final target = (pos.pixels + 1500).clamp(0.0, pos.maxScrollExtent); + if (target > pos.pixels) _scrollCtrl.jumpTo(target); + } + WidgetsBinding.instance.addPostFrameCallback((_) { + Future.delayed(const Duration(milliseconds: 70), + () => _attemptScrollToUnread(attempt + 1)); + }); + } + + void _markRead([Timeline? tl]) { + // Cancel any pending notification for this room (user is now reading it). + cancelNotificationForRoom(widget.roomId); + + final sendReceipts = ref.read(privacyReadReceiptsProvider); + if (!sendReceipts) return; + final room = ref.read(roomProvider(widget.roomId)); + if (room == null) return; + final timeline = tl ?? ref.read(timelineProvider(widget.roomId)).valueOrNull; + final latest = timeline?.events.firstOrNull; + if (latest != null && latest.status.isSynced) { + room.setReadMarker(latest.eventId, mRead: latest.eventId) + .catchError((_) {}); + } else { + room.markUnread(false).catchError((_) {}); + } + } + + Future _onScroll() async { + if (!_scrollCtrl.hasClients) return; + final pixels = _scrollCtrl.position.pixels; + final maxExtent = _scrollCtrl.position.maxScrollExtent; + + if (pixels < 60) { + _markRead(null); + // Reached the newest messages → the "Neue Nachrichten" divider is no + // longer useful. Fade it out, then remove it. + if (_sessionHasUnread && !_unreadFading) { + setState(() => _unreadFading = true); + _unreadFadeTimer?.cancel(); + _unreadFadeTimer = Timer(const Duration(milliseconds: 900), () { + if (mounted) setState(() { _sessionHasUnread = false; _unreadFading = false; }); + }); + } + } + final shouldShow = pixels > 400; + if (shouldShow != _showScrollDown) { + setState(() => _showScrollDown = shouldShow); + } + + final timeline = ref.read(timelineProvider(widget.roomId)).valueOrNull; + if (timeline == null) return; + + // Backward pagination — older events near the top. We keep requesting until + // a request genuinely returns nothing new (real start of room), tracked via + // _historyExhausted, so we neither stop early nor hammer the server. + if (!_loadingHistory && + !_historyExhausted && + pixels >= maxExtent - 600) { + _loadingHistory = true; + final oldestBefore = timeline.events.isNotEmpty ? timeline.events.last.eventId : null; + final lenBefore = timeline.events.length; + try { + await timeline.requestHistory(historyCount: 60); + } catch (_) {} + final oldestAfter = timeline.events.isNotEmpty ? timeline.events.last.eventId : null; + // Nothing older arrived → we've reached the beginning of the room. + if (timeline.events.length == lenBefore && oldestBefore == oldestAfter) { + _historyExhausted = true; + } + await Future.delayed(const Duration(milliseconds: 200)); + _loadingHistory = false; + } + + // Forward pagination — only relevant after jumping to a historical anchor + // (e.g. from search). At the live edge canRequestFuture is false, so this + // won't fire during normal reading and can't pull the view back down. + if (!_loadingFuture && + timeline.canRequestFuture && + pixels < 200) { + _loadingFuture = true; + try { + await timeline.requestFuture(historyCount: 60); + } catch (_) {} + await Future.delayed(const Duration(milliseconds: 250)); + _loadingFuture = false; + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final room = ref.watch(roomProvider(widget.roomId)); + final timelineAsync = ref.watch(timelineProvider(widget.roomId)); + final membersOpen = ref.watch(membersPanelOpenProvider); + + // A search result requested a jump to a specific message. Using watch (not + // listen) so it also fires when this ChatView is freshly mounted for a + // DIFFERENT room — listen would miss a value set before registration. + final pendingJump = ref.watch(pendingJumpEventProvider); + if (pendingJump != null && !_jumpInProgress && pendingJump != _jumpEventId) { + WidgetsBinding.instance.addPostFrameCallback((_) { + if (mounted && + !_jumpInProgress && + ref.read(pendingJumpEventProvider) == pendingJump) { + _startJump(pendingJump); + } + }); + } + + final isDesktop = Platform.isWindows || Platform.isMacOS || Platform.isLinux; + final body = Stack( + fit: StackFit.expand, + children: [ + Row( + children: [ + Expanded( + child: Container( + color: pt.bg1, + child: Column( + children: [ + if (_inSelectionMode) + _SelectionHeader( + pt: pt, + count: _selectedIds.length, + selectedIds: Set.from(_selectedIds), + room: room, + timeline: ref.read(timelineProvider(widget.roomId)).valueOrNull, + currentUserId: room?.client.userID ?? '', + onClear: _clearSelection, + onReply: () { + final tl = ref.read(timelineProvider(widget.roomId)).valueOrNull; + if (tl == null) return; + try { + final event = tl.events.firstWhere((e) => e.eventId == _selectedIds.first); + setState(() { _replyTo = event; _selectedIds.clear(); }); + } catch (_) {} + }, + ) + else if (room != null && room.isDirectChat) + // DM: aufklappbarer Banner-Header — Avatar und Name + // skalieren mit, Banner und Bio blenden ein. + // ValueKey: pro Raum ein frischer State, damit beim + // schnellen Kanalwechsel keinerlei Daten (Avatar, + // Banner, laufende Futures) vom Vorgänger übrigbleiben. + _DmExpandingHeader( + key: ValueKey('dmheader:${room.id}'), + room: room, + roomId: widget.roomId, + pt: pt, + expanded: _profileExpanded, + onToggle: () => setState( + () => _profileExpanded = !_profileExpanded), + membersOpen: membersOpen, + pinnedOpen: _pinnedOpen, + onToggleMembers: () => ref + .read(membersPanelOpenProvider.notifier) + .update((s) => !s), + onOpenSearch: () => + ref.read(activeModalProvider.notifier).state = + ModalKind.search, + onTogglePinned: () => + setState(() => _pinnedOpen = !_pinnedOpen), + ) + else + _ChatHeader( + room: room, + roomId: widget.roomId, + pt: pt, + membersOpen: membersOpen, + pinnedOpen: _pinnedOpen, + onToggleMembers: () => ref + .read(membersPanelOpenProvider.notifier) + .update((s) => !s), + onOpenSearch: () => + ref.read(activeModalProvider.notifier).state = + ModalKind.search, + onTogglePinned: () => + setState(() => _pinnedOpen = !_pinnedOpen), + ), + const _ConnectionBanner(), + Expanded( + child: Stack( + children: [ + timelineAsync.when( + loading: () => Center( + child: CircularProgressIndicator( + strokeWidth: 2, + color: pt.accent, + ), + ), + error: (e, _) => Center( + child: Text( + 'Could not load messages', + style: TextStyle(color: pt.fgDim, fontSize: 14), + ), + ), + data: (timeline) { + WidgetsBinding.instance.addPostFrameCallback( + (_) => _captureAndMarkRead(timeline)); + return _MessageList( + timeline: timeline, + scrollCtrl: _scrollCtrl, + currentUserId: room?.client.userID ?? '', + pt: pt, + onReply: (event) => setState(() => _replyTo = event), + selectedIds: _selectedIds, + onToggleSelect: _toggleSelect, + sessionFullyReadId: _sessionFullyReadId, + sessionHasUnread: _sessionHasUnread, + unreadFading: _unreadFading, + unreadDividerKey: _sessionHasUnread ? _unreadDividerKey : null, + jumpEventId: _jumpEventId, + jumpKey: _jumpKey, + highlightEventId: _highlightEventId, + highlightOn: _highlightOn, + ); + }, + ), + if (_showScrollDown) + Positioned( + right: 16, + bottom: 12, + child: AnimatedOpacity( + opacity: _showScrollDown ? 1 : 0, + duration: const Duration(milliseconds: 150), + child: GestureDetector( + onTap: () => _scrollCtrl.animateTo( + 0, + duration: const Duration(milliseconds: 300), + curve: Curves.easeOut, + ), + child: Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: pt.bg0, + borderRadius: BorderRadius.circular(18), + border: Border.all(color: pt.border), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(80), + blurRadius: 8, + offset: const Offset(0, 2), + ), + ], + ), + child: Icon(Icons.keyboard_arrow_down_rounded, size: 20, color: pt.fgMuted), + ), + ), + ), + ), + ], + ), + ), + if (room != null) _TypingIndicator(room: room, pt: pt), + if (room != null) + ChatComposer( + room: room, + replyTo: _replyTo, + onClearReply: () => setState(() => _replyTo = null), + ), + ], + ), + ), + ), + if (_pinnedOpen) + PinnedMessagesPanel( + roomId: widget.roomId, + onClose: () => setState(() => _pinnedOpen = false), + ), + ], + ), + // Drag-and-drop overlay — bleibt gemountet und blendet animiert + // ein/aus, damit der Übergang flüssig statt abrupt ist. + Positioned.fill( + child: IgnorePointer( + child: AnimatedOpacity( + opacity: _draggingOver ? 1 : 0, + duration: const Duration(milliseconds: 160), + curve: Curves.easeOutCubic, + child: _DragOverlay(pt: pt, active: _draggingOver), + ), + ), + ), + ], + ); + + if (!isDesktop) return body; + + return DropTarget( + onDragEntered: (_) => setState(() => _draggingOver = true), + onDragExited: (_) => setState(() => _draggingOver = false), + onDragDone: (details) async { + setState(() => _draggingOver = false); + if (room == null) return; + final files = details.files.map((xf) => File(xf.path)).toList(); + if (files.isEmpty) return; + if (!mounted) return; + await AttachmentDialog.show(context, files, room, replyTo: _replyTo); + if (mounted) setState(() => _replyTo = null); + }, + child: body, + ); + } +} + +class _ChatHeader extends ConsumerWidget { + final Room? room; + final String roomId; + final PyramidTheme pt; + final bool membersOpen; + final bool pinnedOpen; + final VoidCallback onToggleMembers; + final VoidCallback onOpenSearch; + final VoidCallback onTogglePinned; + + const _ChatHeader({ + required this.room, + required this.roomId, + required this.pt, + required this.membersOpen, + required this.pinnedOpen, + required this.onToggleMembers, + required this.onOpenSearch, + required this.onTogglePinned, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final name = room?.getLocalizedDisplayname() ?? roomId; + final isDm = room?.isDirectChat ?? false; + final isEncrypted = room?.encrypted ?? false; + final topic = room?.topic ?? (isDm ? '' : 'Welcome to #$name'); + final client = ref.watch(matrixClientProvider).valueOrNull; + final size = MediaQuery.sizeOf(context); + final isMobile = size.width < 900 || size.height < 500; + + return Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + color: pt.bg1, + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + // Back button on mobile + if (isMobile) ...[ + GestureDetector( + onTap: () => ref.read(activeRoomIdProvider.notifier).state = null, + child: Icon(Icons.arrow_back_rounded, size: 22, color: pt.fg), + ), + const SizedBox(width: 12), + ], + // Room icon / avatar + if (isDm && client != null) ...[ + _DmHeaderAvatar(room: room, name: name, client: client), + ] else if (!isDm) ...[ + Icon( + isEncrypted ? Icons.lock_outline_rounded : Icons.tag_rounded, + size: 16, + color: pt.fgDim, + ), + ], + const SizedBox(width: 8), + // Name + presence for DMs + if (isDm) + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: TextStyle( + color: pt.fg, + fontSize: 15, + fontWeight: FontWeight.w600), + overflow: TextOverflow.ellipsis, + ), + if (room != null && client != null) + _PresenceLine( + userId: room!.directChatMatrixID, + client: client, + pt: pt, + ), + ], + ), + ) + else + Text( + name, + style: TextStyle( + color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600), + ), + const SizedBox(width: 12), + if (!isDm && topic.isNotEmpty) ...[ + Container(width: 1, height: 18, color: pt.border), + const SizedBox(width: 12), + Expanded( + child: Text( + topic, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + overflow: TextOverflow.ellipsis, + ), + ), + ] else if (!isDm) + const Spacer(), + // Right actions + Row( + children: [ + if (isDm) ...[ + PyrIconBtn( + size: 28, + icon: const Icon(Icons.phone_rounded), + tooltip: 'Voice call', + onPressed: () => _startCall(ref, room, cam: false), + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.videocam_rounded), + tooltip: 'Video call', + onPressed: () => _startCall(ref, room, cam: true), + ), + if (size.width > 700) + Container( + width: 1, + height: 20, + margin: const EdgeInsets.symmetric(horizontal: 4), + color: pt.border, + ), + ], + if (size.width > 800) ...[ + PyrIconBtn( + size: 28, + icon: const Icon(Icons.inbox_rounded), + tooltip: 'Threads', + onPressed: () {}, + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.push_pin_rounded), + tooltip: 'Angepinnte Nachrichten', + active: pinnedOpen, + onPressed: onTogglePinned, + ), + ], + PyrIconBtn( + size: 28, + icon: const Icon(Icons.search_rounded), + tooltip: 'Search', + onPressed: onOpenSearch, + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.group_rounded), + tooltip: 'Members', + active: membersOpen, + onPressed: onToggleMembers, + ), + ], + ), + ], + ), + ); + } + + void _startCall(WidgetRef ref, Room? room, {required bool cam}) async { + if (room == null) return; + + if (room.isDirectChat) { + // Use native Matrix VoIP for 1:1 DMs + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + await PyramidVoipManager.instance.startCall(room.id, video: cam); + return; + } + + // Use LiveKit for group voice rooms + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + await ref.read(callStateProvider).startCall( + roomName: roomId, + roomDisplayName: room.getLocalizedDisplayname(), + identity: 'user_${DateTime.now().millisecondsSinceEpoch}', + audioOnly: !cam, + ); + } +} + +/// DM-Header, der sich per Klick aufklappt: Das Banner blendet als Hintergrund +/// ein, Avatar und Name skalieren mit, Handle + Bio erscheinen darunter +/// (Design nach Nutzer-Mockup, Twitter/Discord-artig). +class _DmExpandingHeader extends ConsumerStatefulWidget { + final Room room; + final String roomId; + final PyramidTheme pt; + final bool expanded; + final VoidCallback onToggle; + final bool membersOpen; + final bool pinnedOpen; + final VoidCallback onToggleMembers; + final VoidCallback onOpenSearch; + final VoidCallback onTogglePinned; + + const _DmExpandingHeader({ + super.key, + required this.room, + required this.roomId, + required this.pt, + required this.expanded, + required this.onToggle, + required this.membersOpen, + required this.pinnedOpen, + required this.onToggleMembers, + required this.onOpenSearch, + required this.onTogglePinned, + }); + + @override + ConsumerState<_DmExpandingHeader> createState() => + _DmExpandingHeaderState(); +} + +class _DmExpandingHeaderState extends ConsumerState<_DmExpandingHeader> { + static const _animDuration = Duration(milliseconds: 280); + static const _animCurve = Curves.easeOutCubic; + + Profile? _profile; + String? _bannerMxcUri; + String? _statusMsg; + bool _online = false; + + String? get _partnerId => widget.room.directChatMatrixID; + + @override + void initState() { + super.initState(); + // Direkt laden, damit das Banner beim ersten Aufklappen schon da ist. + _load(); + } + + @override + void didUpdateWidget(_DmExpandingHeader old) { + super.didUpdateWidget(old); + if (old.room.id != widget.room.id) { + _profile = null; + _bannerMxcUri = null; + _statusMsg = null; + _online = false; + _load(); + } + } + + Future _load() async { + final userId = _partnerId; + if (userId == null) return; + final client = widget.room.client; + // Race-Guard: Beim schnellen DM-Wechsel dürfen verspätete Antworten des + // VORHERIGEN Partners das Profil des aktuellen nicht überschreiben. + bool stillCurrent() => mounted && _partnerId == userId; + try { + final p = await client.getProfileFromUserId(userId); + if (stillCurrent()) setState(() => _profile = p); + } catch (_) {} + try { + final p = await client.fetchCurrentPresence(userId); + final last = p.lastActiveTimestamp; + final fresh = p.currentlyActive == true || + (last != null && + DateTime.now().difference(last) < const Duration(minutes: 5)); + if (stillCurrent()) { + setState(() { + _online = p.presence == PresenceType.online && fresh; + _statusMsg = p.statusMsg; + }); + } + } catch (_) {} + // Banner aus dem Profil-Custom-Field (io.pyramid.profile.banner_url). + try { + final apiUri = client.homeserver!.replace( + path: '/_matrix/client/v3/profile/${Uri.encodeComponent(userId)}', + ); + final resp = await client.httpClient.get( + apiUri, + headers: {'Authorization': 'Bearer ${client.accessToken}'}, + ); + if (resp.statusCode == 200) { + final data = jsonDecode(resp.body) as Map; + final url = data['io.pyramid.profile.banner_url'] as String?; + if (url != null && stillCurrent()) { + setState(() => _bannerMxcUri = url); + } + } + } catch (_) {} + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final expanded = widget.expanded; + final size = MediaQuery.sizeOf(context); + final isMobile = size.width < 900 || size.height < 500; + final client = ref.watch(matrixClientProvider).valueOrNull; + + final userId = _partnerId ?? ''; + final member = widget.room.unsafeGetUserFromMemoryOrFallback(userId); + final name = _profile?.displayName ?? + member.displayName ?? + widget.room.getLocalizedDisplayname(); + final avatarUrl = + _profile?.avatarUrl ?? member.avatarUrl ?? widget.room.avatar; + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + + // Im Querformat (wenig Höhe) kompakter aufklappen. + final expandedHeight = size.height < 500 ? 140.0 : 190.0; + final avatarSize = expanded + ? (size.height < 500 ? 72.0 : 96.0) + : 32.0; + + return AnimatedContainer( + duration: _animDuration, + curve: _animCurve, + height: expanded ? expandedHeight : 52, + decoration: BoxDecoration( + color: pt.bg1, + border: Border(bottom: BorderSide(color: pt.border)), + ), + clipBehavior: Clip.hardEdge, + child: Stack( + fit: StackFit.expand, + children: [ + // Banner als Hintergrund — blendet beim Aufklappen ein. + if (_bannerMxcUri != null && client != null) + Positioned.fill( + child: AnimatedOpacity( + opacity: expanded ? 1 : 0, + duration: _animDuration, + curve: Curves.easeOut, + child: MxcImage( + mxcUri: _bannerMxcUri!, + client: client, + fit: BoxFit.cover, + placeholder: const SizedBox.shrink(), + ), + ), + ), + // Scrim: links dunkel, damit Avatar/Text lesbar bleiben (Mockup). + if (_bannerMxcUri != null) + Positioned.fill( + child: AnimatedOpacity( + opacity: expanded ? 1 : 0, + duration: _animDuration, + child: DecoratedBox( + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.centerLeft, + end: Alignment.centerRight, + colors: [ + pt.bg1, + pt.bg1.withAlpha(210), + pt.bg1.withAlpha(0), + ], + stops: const [0.0, 0.32, 0.72], + ), + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 16), + child: Row( + children: [ + if (isMobile) ...[ + GestureDetector( + onTap: () => + ref.read(activeRoomIdProvider.notifier).state = null, + child: + Icon(Icons.arrow_back_rounded, size: 22, color: pt.fg), + ), + const SizedBox(width: 12), + ], + // Klickbarer Profilbereich: Avatar + Name + Details + Expanded( + child: MouseRegion( + cursor: SystemMouseCursors.click, + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: widget.onToggle, + child: Row( + children: [ + // Avatar — skaliert mit (rund, wie im Mockup) + AnimatedContainer( + duration: _animDuration, + curve: _animCurve, + width: avatarSize, + height: avatarSize, + decoration: BoxDecoration( + shape: BoxShape.circle, + color: pt.bg3, + ), + clipBehavior: Clip.antiAlias, + child: avatarUrl != null && client != null + ? MxcImage( + mxcUri: avatarUrl.toString(), + client: client, + fit: BoxFit.cover, + placeholder: _initialBox(initial, pt), + ) + : _initialBox(initial, pt), + ), + AnimatedContainer( + duration: _animDuration, + curve: _animCurve, + width: expanded ? 20 : 10, + ), + Expanded( + child: Column( + mainAxisAlignment: MainAxisAlignment.center, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Name skaliert mit; Status blendet daneben ein + Row( + crossAxisAlignment: CrossAxisAlignment.center, + children: [ + Flexible( + child: AnimatedDefaultTextStyle( + duration: _animDuration, + curve: _animCurve, + style: TextStyle( + color: pt.fg, + fontSize: expanded ? 24 : 15, + fontWeight: expanded + ? FontWeight.w700 + : FontWeight.w600, + ), + child: Text( + name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ), + AnimatedOpacity( + opacity: expanded ? 1 : 0, + duration: _animDuration, + child: Padding( + padding: + const EdgeInsets.only(left: 8), + child: Text( + _online ? 'online' : 'offline', + style: TextStyle( + color: _online + ? pt.online + : pt.fgMuted, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + ), + ), + ), + ], + ), + // Eingeklappt: "zuletzt online vor…", + // aufgeklappt: Handle + Biographie. + AnimatedCrossFade( + duration: _animDuration, + sizeCurve: _animCurve, + crossFadeState: expanded + ? CrossFadeState.showSecond + : CrossFadeState.showFirst, + firstChild: client != null + ? _PresenceLine( + userId: _partnerId, + client: client, + pt: pt, + ) + : const SizedBox.shrink(), + secondChild: Column( + crossAxisAlignment: + CrossAxisAlignment.start, + children: [ + const SizedBox(height: 4), + Text( + userId, + style: TextStyle( + color: pt.fgMuted, fontSize: 13), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + if (_statusMsg != null && + _statusMsg!.isNotEmpty) ...[ + const SizedBox(height: 8), + Text( + _statusMsg!, + style: TextStyle( + color: pt.fgMuted, + fontSize: 13, + height: 1.35), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + const SizedBox(width: 12), + // Aktionen — bleiben immer sichtbar + Row( + children: [ + PyrIconBtn( + size: 28, + icon: const Icon(Icons.phone_rounded), + tooltip: 'Voice call', + onPressed: () => _startCall(cam: false), + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.videocam_rounded), + tooltip: 'Video call', + onPressed: () => _startCall(cam: true), + ), + if (size.width > 700) + Container( + width: 1, + height: 20, + margin: const EdgeInsets.symmetric(horizontal: 4), + color: pt.border, + ), + if (size.width > 800) + PyrIconBtn( + size: 28, + icon: const Icon(Icons.push_pin_rounded), + tooltip: 'Angepinnte Nachrichten', + active: widget.pinnedOpen, + onPressed: widget.onTogglePinned, + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.search_rounded), + tooltip: 'Search', + onPressed: widget.onOpenSearch, + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.group_rounded), + tooltip: 'Members', + active: widget.membersOpen, + onPressed: widget.onToggleMembers, + ), + ], + ), + ], + ), + ), + ], + ), + ); + } + + Widget _initialBox(String initial, PyramidTheme pt) => Center( + child: FittedBox( + fit: BoxFit.scaleDown, + child: Padding( + padding: const EdgeInsets.all(6), + child: Text( + initial, + style: TextStyle( + color: pt.fg, fontSize: 28, fontWeight: FontWeight.w700), + ), + ), + ), + ); + + void _startCall({required bool cam}) async { + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + await PyramidVoipManager.instance.startCall(widget.room.id, video: cam); + } +} + +class _DmHeaderAvatar extends StatelessWidget { + final Room? room; + final String name; + final Client client; + + const _DmHeaderAvatar({required this.room, required this.name, required this.client}); + + @override + Widget build(BuildContext context) { + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + const size = 32.0; + return MxcAvatar( + mxcUri: room?.avatar, + client: client, + size: size, + borderRadius: BorderRadius.circular(size / 2), + placeholder: (_) => _InitialCircle(initial: initial, size: size), + ); + } +} + +class _InitialCircle extends StatelessWidget { + final String initial; + final double size; + const _InitialCircle({required this.initial, required this.size}); + + @override + Widget build(BuildContext context) { + const color = Color(0xFF06B6D4); + return Container( + width: size, + height: size, + decoration: const BoxDecoration(color: color, shape: BoxShape.circle), + child: Center( + child: Text(initial, + style: const TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w600)), + ), + ); + } +} + +class _PresenceLine extends StatefulWidget { + final String? userId; + final Client client; + final PyramidTheme pt; + + const _PresenceLine({required this.userId, required this.client, required this.pt}); + + @override + State<_PresenceLine> createState() => _PresenceLineState(); +} + +class _PresenceLineState extends State<_PresenceLine> { + CachedPresence? _presence; + StreamSubscription? _sub; + // Debounce timer: delay "online" updates 4s to filter out background-sync + // false positives (push notifications briefly wake the recipient's client). + Timer? _onlineDebounce; + + @override + void initState() { + super.initState(); + _load(widget.userId); + } + + @override + void didUpdateWidget(_PresenceLine oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.userId != widget.userId) { + _sub?.cancel(); + _sub = null; + _onlineDebounce?.cancel(); + setState(() => _presence = null); + _load(widget.userId); + } + } + + @override + void dispose() { + _sub?.cancel(); + _onlineDebounce?.cancel(); + super.dispose(); + } + + // "online" only when the server's presence enum says online AND the last + // activity is recent. Using currentlyActive (the old logic) reported online + // long after the user left, because that flag lingers. + static bool _isOnline(CachedPresence p) { + if (p.presence != PresenceType.online) return false; + final last = p.lastActiveTimestamp; + return last == null || DateTime.now().difference(last).inSeconds < 90; + } + + void _applyPresence(CachedPresence p) { + _onlineDebounce?.cancel(); + if (_isOnline(p)) { + // Wait 4 seconds before committing "online" to filter single-sync spikes + // (a backgrounded client briefly reports online when a push wakes it). + _onlineDebounce = Timer(const Duration(seconds: 4), () { + if (mounted) setState(() => _presence = p); + }); + } else { + if (mounted) setState(() => _presence = p); + } + } + + Future _load(String? userId) async { + if (userId == null) return; + // Never show our own presence in a DM header + if (userId == widget.client.userID) return; + try { + final p = await widget.client.fetchCurrentPresence(userId); + if (mounted) _applyPresence(p); + } catch (_) {} + _sub = widget.client.onPresenceChanged.stream + .where((p) => p.userid == userId) + .listen((p) => _applyPresence(p)); + } + + @override + Widget build(BuildContext context) { + final p = _presence; + if (p == null) return const SizedBox.shrink(); + + String text; + Color color = widget.pt.fgDim; + if (_isOnline(p)) { + text = 'online'; + color = const Color(0xFF3BA55D); + } else if (p.lastActiveTimestamp != null) { + text = 'zuletzt online ${_relativeTime(p.lastActiveTimestamp!)}'; + } else { + return const SizedBox.shrink(); + } + + return Text( + text, + style: TextStyle(color: color, fontSize: 11), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ); + } + + String _relativeTime(DateTime t) { + final diff = DateTime.now().difference(t); + if (diff.inMinutes < 1) return 'gerade eben'; + if (diff.inMinutes < 60) return 'vor ${diff.inMinutes}min'; + if (diff.inHours < 24) return 'vor ${diff.inHours}h'; + if (diff.inDays < 7) return 'vor ${diff.inDays}d'; + if (diff.inDays < 365) return 'vor ${(diff.inDays / 7).floor()}w'; + return 'vor ${(diff.inDays / 365).floor()}j'; + } +} + +// Shows a slim banner when the client loses its connection to the homeserver. +// Debounced so brief transient sync errors don't flicker a banner. +class _ConnectionBanner extends ConsumerStatefulWidget { + const _ConnectionBanner(); + @override + ConsumerState<_ConnectionBanner> createState() => _ConnectionBannerState(); +} + +class _ConnectionBannerState extends ConsumerState<_ConnectionBanner> { + StreamSubscription? _sub; + Timer? _debounce; + bool _lost = false; + + @override + void initState() { + super.initState(); + _attach(); + } + + Future _attach() async { + try { + final client = await ref.read(matrixClientProvider.future); + _sub = client.onSyncStatus.stream.listen((s) { + if (s.status == SyncStatus.error) { + // Only surface after the error persists a few seconds. + _debounce ??= Timer(const Duration(seconds: 4), () { + _debounce = null; + if (mounted) setState(() => _lost = true); + }); + } else if (s.status == SyncStatus.finished || + s.status == SyncStatus.processing) { + _debounce?.cancel(); + _debounce = null; + if (_lost && mounted) setState(() => _lost = false); + } + }); + } catch (_) {} + } + + @override + void dispose() { + _sub?.cancel(); + _debounce?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return AnimatedSize( + duration: const Duration(milliseconds: 200), + curve: Curves.easeOut, + alignment: Alignment.topCenter, + child: _lost + ? Container( + width: double.infinity, + color: pt.danger.withAlpha(36), + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.cloud_off_rounded, size: 14, color: pt.danger), + const SizedBox(width: 8), + Flexible( + child: Text( + 'Keine Verbindung zum Server – Wiederverbindung läuft…', + style: TextStyle(color: pt.danger, fontSize: 12, fontWeight: FontWeight.w500), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ) + : const SizedBox.shrink(), + ); + } +} + +class _MessageList extends StatelessWidget { + final Timeline timeline; + final ScrollController scrollCtrl; + final String currentUserId; + final PyramidTheme pt; + final ValueChanged onReply; + final Set selectedIds; + final ValueChanged onToggleSelect; + final String? sessionFullyReadId; + final bool sessionHasUnread; + final bool unreadFading; + /// Attached to the group-level _UnreadDivider so ensureVisible can scroll to it. + final GlobalKey? unreadDividerKey; + /// Jump-to-message target (from search): scroll to + highlight this event. + final String? jumpEventId; + final GlobalKey? jumpKey; + final String? highlightEventId; + final bool highlightOn; + + const _MessageList({ + required this.timeline, + required this.scrollCtrl, + required this.currentUserId, + required this.pt, + required this.onReply, + required this.selectedIds, + required this.onToggleSelect, + this.sessionFullyReadId, + this.sessionHasUnread = false, + this.unreadFading = false, + this.unreadDividerKey, + this.jumpEventId, + this.jumpKey, + this.highlightEventId, + this.highlightOn = false, + }); + + @override + Widget build(BuildContext context) { + // Dedupe by eventId — during concurrent forward/backward pagination the + // timeline can transiently contain the same event twice, which would + // produce duplicate ListView keys and crash the sliver (indexOf assertion). + final seenIds = {}; + final events = timeline.events + .where(_isVisible) + .where((e) => seenIds.add(e.eventId)) + .toList(); + + if (events.isEmpty) { + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.forum_outlined, size: 48, color: pt.fgDim), + const SizedBox(height: 16), + Text( + 'No messages yet', + style: TextStyle(color: pt.fgMuted, fontSize: 14), + ), + ], + ), + ); + } + + final groups = _buildGroups(events); + final hasUnread = sessionHasUnread; + + // Resolve the effective fullyReadId: if the captured ID points to a + // non-visible event (reaction, edit, state) walk the timeline forward + // (toward older events) until we find the nearest visible one. + String? fullyReadId = sessionFullyReadId; + if (fullyReadId != null) { + final inGroups = groups.any((g) => g.any((e) => e.eventId == fullyReadId)); + if (!inGroups) { + final tlEvents = timeline.events; // newest-first + final idx = tlEvents.indexWhere((e) => e.eventId == fullyReadId); + if (idx >= 0) { + fullyReadId = null; + for (int i = idx; i < tlEvents.length; i++) { + if (_isVisible(tlEvents[i])) { + fullyReadId = tlEvents[i].eventId; + break; + } + } + } else { + fullyReadId = null; // event not even in loaded timeline + } + } + } + + // Read-receipt display — matching Element behaviour: + // • The newest unread own group shows ✓ (sent but not read) + // • The newest own group AT or BEFORE the partner's receipt shows ✓✓ + // • If those are the same group → just ✓✓ + final room = timeline.room; + + // Read receipts (Element-style): + // • ✓✓ at the single newest event another member has read (any sender) — + // moves next to the partner's own reply when they reply/read everything. + // • grey ✓ only on my newest message while it's still unread by them. + // timeline.events is newest-first → lower index = newer. + // + // Receipts können je nach Client in `global` ODER `mainThread` stehen + // (threaded read receipts) — beide zusammenführen, neuere ts gewinnt. + final mergedReceipts = {}; + for (final source in [ + room.receiptState.global.otherUsers, + room.receiptState.mainThread?.otherUsers ?? const {}, + ]) { + source.forEach((userId, data) { + final existing = mergedReceipts[userId]; + if (existing == null || data.ts > existing.ts) { + mergedReceipts[userId] = data; + } + }); + } + + int readIndex = -1; + int latestReceiptTs = 0; + mergedReceipts.forEach((userId, data) { + if (userId == currentUserId) return; + if (data.ts > latestReceiptTs) latestReceiptTs = data.ts; + var ri = timeline.events.indexWhere((e) => e.eventId == data.eventId); + // Receipt kann auf ein unsichtbares Event zeigen (Reaktion, Edit) — + // zum nächstälteren sichtbaren Event vorrücken, sonst geht der Marker + // verloren. + while (ri >= 0 && + ri < timeline.events.length && + !_isVisible(timeline.events[ri])) { + ri++; + } + if (ri >= timeline.events.length) ri = -1; + if (ri >= 0 && (readIndex < 0 || ri < readIndex)) readIndex = ri; + }); + final readEventIds = + readIndex >= 0 ? {timeline.events[readIndex].eventId} : {}; + + // Newest own visible message, and whether it's still unread (newer than the + // partner's read position, or no read position yet). + final newestOwnIndex = + timeline.events.indexWhere((e) => _isVisible(e) && e.senderId == currentUserId); + var ownUnread = newestOwnIndex >= 0 && (readIndex < 0 || newestOwnIndex < readIndex); + // Fallback: Das Receipt-Event liegt außerhalb des geladenen Fensters + // (z.B. sehr alte Nachricht) — wenn der Receipt-Zeitstempel jünger ist als + // meine neueste Nachricht, gilt sie trotzdem als gelesen. + if (ownUnread && + readIndex < 0 && + latestReceiptTs >= + timeline.events[newestOwnIndex].originServerTs.millisecondsSinceEpoch) { + readEventIds.add(timeline.events[newestOwnIndex].eventId); + ownUnread = false; + } + final lastOwnGroupKey = (ownUnread) + ? () { + for (final g in groups) { + if (g.first.senderId == currentUserId) return 'g:${g.first.eventId}'; + } + return null; + }() + : null; + + // Flatten groups + date dividers + unread divider into independent list items. + // itemFullyReadIds[i] is non-null only for a group item that contains the + // fullyRead event at a non-last position — MessageGroup renders an inline + // divider after that event. + final itemKeys = []; + final itemGroups = ?>[]; + final itemDates = []; + final itemUnread = []; + final itemFullyReadIds = []; + + bool unreadInserted = false; + + for (var i = 0; i < groups.length; i++) { + final group = groups[i]; + // Use the newest event (group.last after reversal) for date comparison. + final groupNewest = group.last.originServerTs; + final nextGroupNewest = i < groups.length - 1 ? groups[i + 1].last.originServerTs : null; + final isLastOfDay = nextGroupNewest == null || !_sameDay(groupNewest, nextGroupNewest); + + // Check if this group contains the effective fullyRead event. + final groupContainsFullyRead = fullyReadId != null && + group.any((e) => e.eventId == fullyReadId); + + if (!unreadInserted && hasUnread && groupContainsFullyRead) { + if (group.last.eventId == fullyReadId) { + // fullyRead is the NEWEST event in the group → the whole group is + // read. Insert a group-level divider between this group and the + // newer (lower-index) groups. + itemKeys.add('unread'); + itemGroups.add(null); + itemDates.add(null); + itemUnread.add(true); + itemFullyReadIds.add(null); + } + // Whether group-level or inline, we've now handled the marker. + unreadInserted = true; + } + + // Key based on oldest event (group.first) — stable identifier. + itemKeys.add('g:${group.first.eventId}'); + itemGroups.add(group); + itemDates.add(null); + itemUnread.add(false); + // Pass fullyReadId to the group only when the event is mid-group + // (not the last event) so MessageGroup can render an inline divider. + // groupContainsFullyRead already guarantees fullyReadId != null. + final passedFullyReadId = + (groupContainsFullyRead && group.last.eventId != fullyReadId) + ? fullyReadId + : null; + itemFullyReadIds.add(passedFullyReadId); + + if (isLastOfDay) { + final d = groupNewest; + itemKeys.add('d:${d.year}-${d.month}-${d.day}'); + itemGroups.add(null); + itemDates.add(d); + itemUnread.add(false); + itemFullyReadIds.add(null); + } + } + + // Fallback: fullyRead event is older than all loaded events — all visible + // messages are unread. Insert divider above the oldest loaded group (top of list). + if (!unreadInserted && hasUnread) { + itemKeys.add('unread'); + itemGroups.add(null); + itemDates.add(null); + itemUnread.add(true); + itemFullyReadIds.add(null); + } + + final keyIndex = { + for (var i = 0; i < itemKeys.length; i++) itemKeys[i]: i, + }; + + return ListView.builder( + controller: scrollCtrl, + reverse: true, + physics: const ClampingScrollPhysics(), + padding: const EdgeInsets.only(bottom: 8), + cacheExtent: 2500, + itemCount: itemKeys.length, + findChildIndexCallback: (Key key) { + // Only return an index when the key still maps to that exact slot — + // returning a stale/duplicate index trips the sliver indexOf assertion. + if (key is ValueKey) { + final idx = keyIndex[key.value]; + if (idx != null && idx < itemKeys.length && itemKeys[idx] == key.value) { + return idx; + } + } + return null; + }, + itemBuilder: (context, i) { + final key = ValueKey(itemKeys[i]); + if (itemUnread[i]) { + // Wrap in SizedBox so the list can use the ValueKey for optimisation + // while _UnreadDivider carries the GlobalKey for ensureVisible. + return SizedBox( + key: key, + child: _UnreadDivider(key: unreadDividerKey, pt: pt, fading: unreadFading), + ); + } + final date = itemDates[i]; + if (date != null) return DateDivider(key: key, date: date); + final group = itemGroups[i]!; + final groupKey = itemKeys[i]; + // Show the sending/sent indicator on the newest own group. + final showStatus = groupKey == lastOwnGroupKey; + return MessageGroup( + key: key, + events: group, + currentUserId: currentUserId, + room: room, + timeline: timeline, + onReply: () => onReply(group.last), + selectedIds: selectedIds, + onToggleSelect: onToggleSelect, + showStatusIndicator: showStatus, + readEventIds: readEventIds, + fullyReadId: itemFullyReadIds[i], + jumpEventId: jumpEventId, + jumpKey: jumpKey, + highlightEventId: highlightEventId, + highlightOn: highlightOn, + ); + }, + ); + } + + List> _buildGroups(List events) { + final groups = >[]; + List? current; + + for (final event in events) { + if (current == null || + current.first.senderId != event.senderId || + event.originServerTs.difference(current.last.originServerTs).abs() > + const Duration(minutes: 5)) { + current = [event]; + groups.add(current); + } else { + current.add(event); + } + } + // The timeline is newest-first, so each group is [newest, ..., oldest]. + // Reverse each group so messages render oldest-to-newest (top to bottom). + return groups.map((g) => g.reversed.toList()).toList(); + } + + bool _sameDay(DateTime a, DateTime b) => + a.year == b.year && a.month == b.month && a.day == b.day; + + static bool _isVisible(Event e) { + // NOTE: error-status events are kept visible so a failed send shows a + // "not sent" state with retry/delete instead of silently disappearing. + if (!{ + EventTypes.Message, + EventTypes.Sticker, + EventTypes.Encrypted, + }.contains(e.type)) { return false; } + if ({ + RelationshipTypes.edit, + RelationshipTypes.reaction, + }.contains(e.relationshipType)) { return false; } + if (e.type == EventTypes.Redaction) { return false; } + return true; + } +} + +class _SelectionHeader extends StatelessWidget { + final PyramidTheme pt; + final int count; + final Set selectedIds; + final Room? room; + final Timeline? timeline; + final String currentUserId; + final VoidCallback onClear; + final VoidCallback onReply; + + const _SelectionHeader({ + required this.pt, + required this.count, + required this.selectedIds, + required this.room, + required this.timeline, + required this.currentUserId, + required this.onClear, + required this.onReply, + }); + + List _resolveEvents() { + if (timeline == null) return []; + return selectedIds + .map((id) { + try { return timeline!.events.firstWhere((e) => e.eventId == id); } catch (_) { return null; } + }) + .whereType() + .toList(); + } + + void _copyAll() { + final texts = _resolveEvents().map((e) => e.body).join('\n'); + Clipboard.setData(ClipboardData(text: texts)); + } + + void _deleteAll(BuildContext context) { + for (final e in _resolveEvents()) { + if (e.senderId == currentUserId) { + e.redactEvent(reason: 'Vom Nutzer gelöscht').catchError((_) => null); + } + } + onClear(); + } + + void _pinAll() { + if (room == null) return; + final pinned = List.from( + room!.getState(EventTypes.RoomPinnedEvents)?.content['pinned'] as List? ?? [], + ); + for (final e in _resolveEvents()) { + if (!pinned.contains(e.eventId)) pinned.add(e.eventId); + } + room!.setPinnedEvents(pinned).catchError((_) => ''); + onClear(); + } + + + @override + Widget build(BuildContext context) { + final events = _resolveEvents(); + final canDelete = events.isNotEmpty && events.every((e) => e.senderId == currentUserId); + final isTextOnly = events.every((e) => e.messageType == 'm.text'); + + return Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: pt.accentSoft, + border: Border(bottom: BorderSide(color: pt.accent.withAlpha(80))), + ), + child: Row( + children: [ + IconButton( + onPressed: onClear, + icon: Icon(Icons.close_rounded, size: 20, color: pt.accent), + tooltip: 'Auswahl aufheben', + constraints: const BoxConstraints(minWidth: 36, minHeight: 36), + padding: EdgeInsets.zero, + ), + const SizedBox(width: 4), + Text( + '$count ausgewählt', + style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600), + ), + const Spacer(), + if (count == 1) + _SelBtn(icon: Icons.reply_rounded, tooltip: 'Antworten', pt: pt, onTap: onReply), + if (isTextOnly) + _SelBtn(icon: Icons.copy_rounded, tooltip: 'Kopieren', pt: pt, onTap: _copyAll), + _SelBtn(icon: Icons.push_pin_outlined, tooltip: 'Anpinnen', pt: pt, onTap: _pinAll), + if (canDelete) + _SelBtn( + icon: Icons.delete_outline_rounded, + tooltip: 'Löschen', + pt: pt, + color: pt.danger, + onTap: () => _deleteAll(context), + ), + ], + ), + ); + } +} + +class _SelBtn extends StatelessWidget { + final IconData icon; + final String tooltip; + final PyramidTheme pt; + final Color? color; + final VoidCallback onTap; + + const _SelBtn({required this.icon, required this.tooltip, required this.pt, required this.onTap, this.color}); + + @override + Widget build(BuildContext context) { + return IconButton( + onPressed: onTap, + icon: Icon(icon, size: 20, color: color ?? pt.fg), + tooltip: tooltip, + constraints: const BoxConstraints(minWidth: 36, minHeight: 36), + padding: EdgeInsets.zero, + ); + } +} + +class _UnreadDivider extends StatelessWidget { + final PyramidTheme pt; + final bool fading; + const _UnreadDivider({super.key, required this.pt, this.fading = false}); + + @override + Widget build(BuildContext context) { + return AnimatedOpacity( + opacity: fading ? 0.0 : 1.0, + duration: const Duration(milliseconds: 700), + curve: Curves.easeOut, + child: Padding( + padding: const EdgeInsets.fromLTRB(20, 8, 20, 4), + child: Row( + children: [ + Expanded(child: Divider(color: pt.accent.withAlpha(160), height: 1)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Neue Nachrichten', + style: TextStyle(color: pt.accent, fontSize: 11, fontWeight: FontWeight.w600), + ), + ), + Expanded(child: Divider(color: pt.accent.withAlpha(160), height: 1)), + ], + ), + ), + ); + } +} + +// ─── Typing indicator ───────────────────────────────────────────────────────── + +class _TypingIndicator extends StatefulWidget { + final Room room; + final PyramidTheme pt; + const _TypingIndicator({required this.room, required this.pt}); + + @override + State<_TypingIndicator> createState() => _TypingIndicatorState(); +} + +class _TypingIndicatorState extends State<_TypingIndicator> { + StreamSubscription? _sub; + List _typing = []; + + StreamSubscription _listenTyping(Room room) { + // client.onSync fires after every sync — cheap to filter for typing events. + return room.client.onSync.stream.listen((_) { + if (!mounted) return; + final typing = room.typingUsers + .where((u) => u.id != room.client.userID) + .toList(); + if (typing.length != _typing.length || + !typing.every((u) => _typing.any((t) => t.id == u.id))) { + setState(() => _typing = typing); + } + }); + } + + @override + void initState() { + super.initState(); + _sub = _listenTyping(widget.room); + } + + @override + void didUpdateWidget(_TypingIndicator oldWidget) { + super.didUpdateWidget(oldWidget); + if (oldWidget.room.id != widget.room.id) { + _sub?.cancel(); + setState(() => _typing = []); + _sub = _listenTyping(widget.room); + } + } + + @override + void dispose() { + _sub?.cancel(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (_typing.isEmpty) return const SizedBox.shrink(); + final pt = widget.pt; + final names = _typing.map((u) => u.calcDisplayname()).toList(); + final label = names.length == 1 + ? '${names[0]} tippt…' + : names.length == 2 + ? '${names[0]} und ${names[1]} tippen…' + : '${names[0]} und ${names.length - 1} weitere tippen…'; + return Padding( + padding: const EdgeInsets.fromLTRB(20, 2, 20, 0), + child: Row( + children: [ + _TypingDots(color: pt.fgDim), + const SizedBox(width: 8), + Flexible( + child: Text( + label, + style: TextStyle(color: pt.fgDim, fontSize: 12, fontStyle: FontStyle.italic), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ); + } +} + +class _TypingDots extends StatefulWidget { + final Color color; + const _TypingDots({required this.color}); + + @override + State<_TypingDots> createState() => _TypingDotsState(); +} + +class _TypingDotsState extends State<_TypingDots> + with SingleTickerProviderStateMixin { + late final AnimationController _ctrl; + + @override + void initState() { + super.initState(); + _ctrl = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 900), + )..repeat(); + } + + @override + void dispose() { + _ctrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + return AnimatedBuilder( + animation: _ctrl, + builder: (context, child) { + return Row( + mainAxisSize: MainAxisSize.min, + children: List.generate(3, (i) { + // Each dot peaks at a different phase. + final phase = ((_ctrl.value * 3) - i).clamp(0.0, 1.0); + final opacity = (phase < 0.5 ? phase * 2 : (1 - phase) * 2).clamp(0.3, 1.0); + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 1), + child: Opacity( + opacity: opacity, + child: Container( + width: 4, + height: 4, + decoration: BoxDecoration(color: widget.color, shape: BoxShape.circle), + ), + ), + ); + }), + ); + }, + ); + } +} + +// ─── Drag-and-drop overlay ──────────────────────────────────────────────────── + +class _DragOverlay extends StatefulWidget { + final PyramidTheme pt; + final bool active; + const _DragOverlay({required this.pt, required this.active}); + + @override + State<_DragOverlay> createState() => _DragOverlayState(); +} + +class _DragOverlayState extends State<_DragOverlay> + with SingleTickerProviderStateMixin { + // Sanftes Auf-und-ab des Icons, solange das Overlay aktiv ist. + late final AnimationController _bob = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 900), + ); + + @override + void initState() { + super.initState(); + if (widget.active) _bob.repeat(reverse: true); + } + + @override + void didUpdateWidget(_DragOverlay old) { + super.didUpdateWidget(old); + if (widget.active && !old.active) { + _bob.repeat(reverse: true); + } else if (!widget.active && old.active) { + _bob.stop(); + } + } + + @override + void dispose() { + _bob.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Container( + color: pt.bg0.withAlpha(200), + child: Center( + child: AnimatedScale( + scale: widget.active ? 1.0 : 0.88, + duration: const Duration(milliseconds: 220), + curve: Curves.easeOutBack, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 40, vertical: 32), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(20), + border: Border.all(color: pt.accent, width: 2), + boxShadow: [ + BoxShadow( + color: pt.accent.withAlpha(60), + blurRadius: 32, + spreadRadius: 4, + ), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + AnimatedBuilder( + animation: _bob, + builder: (_, child) => Transform.translate( + offset: Offset( + 0, -7 * Curves.easeInOut.transform(_bob.value)), + child: child, + ), + child: + Icon(Icons.upload_file_rounded, size: 56, color: pt.accent), + ), + const SizedBox(height: 16), + Text( + 'Datei hier ablegen', + style: TextStyle( + color: pt.fg, + fontSize: 20, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(height: 8), + Text( + 'Loslassen zum Hochladen', + style: TextStyle(color: pt.fgMuted, fontSize: 14), + ), + ], + ), + ), + ), + ), + ); + } +} + +// Placeholder shown when no room is selected +class NoChatSelected extends StatelessWidget { + const NoChatSelected({super.key}); + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Container( + color: pt.bg1, + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.forum_outlined, size: 64, color: pt.fgDim), + const SizedBox(height: 16), + Text( + 'Select a room to start chatting', + style: TextStyle(color: pt.fgMuted, fontSize: 16), + ), + const SizedBox(height: 8), + Text( + 'Choose from the sidebar on the left', + style: TextStyle(color: pt.fgDim, fontSize: 13), + ), + ], + ), + ), + ); + } +} diff --git a/lib/features/chat/document_viewer.dart b/lib/features/chat/document_viewer.dart new file mode 100644 index 0000000..57c8c7a --- /dev/null +++ b/lib/features/chat/document_viewer.dart @@ -0,0 +1,1773 @@ +import 'dart:convert'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:archive/archive.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_markdown/flutter_markdown.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pdfx/pdfx.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:url_launcher/url_launcher.dart'; + +// ─── Static render cache ────────────────────────────────────────────────────── +// Survives widget dispose/recreate (e.g. scroll in chat list). +// Key: filename + file-size-bytes + page + render-dimensions. +// Evicts the oldest entry (FIFO) when the limit is reached. + +class _RenderCache { + static const _max = 80; + static final _data = {}; + + static String _k(String name, int sz, int page, int w, int h) => + '$name\x00$sz\x00$page\x00${w}x$h'; + + static Uint8List? get(String name, int sz, int page, int w, int h) => + _data[_k(name, sz, page, w, h)]; + + static void put(String name, int sz, int page, int w, int h, Uint8List img) { + if (_data.length >= _max) _data.remove(_data.keys.first); + _data[_k(name, sz, page, w, h)] = img; + } +} + +// ─── Inline chat preview ────────────────────────────────────────────────────── +// Used by _DocPreviewContent in message_group.dart. +// Shows the first page of a PDF as an image with page navigation arrows. +// Tap → opens the full DocumentViewer overlay. + +class PdfInlinePreview extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + final String senderName; + final VoidCallback? onDownload; + + const PdfInlinePreview({ + super.key, + required this.bytes, + required this.filename, + required this.pt, + required this.senderName, + this.onDownload, + }); + + @override + State createState() => _PdfInlinePreviewState(); +} + +class _PdfInlinePreviewState extends State { + PdfDocument? _doc; + int _currentPage = 1; + int _pageCount = 0; + double? _pageAspect; // width/height + final Map _cache = {}; + bool _loading = true; + String? _error; + bool _rendering = false; + + static const _previewW = 280.0; + static const _renderScale = 2.0; + + @override + void initState() { + super.initState(); + _init(); + } + + Future _init() async { + try { + final doc = await PdfDocument.openData(widget.bytes); + if (!mounted) { await doc.close(); return; } + _doc = doc; + _pageCount = doc.pagesCount; + setState(() => _loading = false); + await _ensurePage(1); + } catch (e) { + if (mounted) setState(() { _loading = false; _error = e.toString().split('\n').first; }); + } + } + + Future _ensurePage(int n) async { + if (_cache.containsKey(n) || _rendering) return; + _rendering = true; + try { + final page = await _doc!.getPage(n); + if (mounted && _pageAspect == null) { + setState(() => _pageAspect = page.width / page.height); + } + final rw = (page.width * _renderScale).round(); + final rh = (page.height * _renderScale).round(); + final hit = _RenderCache.get(widget.filename, widget.bytes.length, n, rw, rh); + if (hit != null) { + await page.close(); + if (mounted) setState(() => _cache[n] = hit); + return; + } + final img = await page.render( + width: page.width * _renderScale, + height: page.height * _renderScale, + format: PdfPageImageFormat.jpeg, + backgroundColor: '#ffffff', + ); + await page.close(); + if (img?.bytes != null) { + _RenderCache.put(widget.filename, widget.bytes.length, n, rw, rh, img!.bytes); + } + if (mounted) setState(() => _cache[n] = img?.bytes); + } catch (_) { + _cache[n] = null; + } finally { + _rendering = false; + } + } + + void _goTo(int page) { + if (page < 1 || page > _pageCount) return; + setState(() => _currentPage = page); + _ensurePage(page); + _ensurePage((page + 1).clamp(1, _pageCount)); + } + + void _openFull() { + DocumentViewer.show( + context, + filename: widget.filename, + bytes: widget.bytes, + senderName: widget.senderName, + initialPage: _currentPage, + ); + } + + @override + void dispose() { + _doc?.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final radius = BorderRadius.circular(pt.rBase); + + if (_loading) { + return Container( + width: _previewW, + // Match the typical loaded A4 height so the preview doesn't jump (and + // shift the scroll position) once the first page finishes rendering. + height: (_previewW / 0.707).clamp(160.0, 400.0), + margin: const EdgeInsets.only(top: 4, bottom: 4), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: radius, + border: Border.all(color: pt.border), + ), + child: Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ); + } + + if (_error != null) { + return _FileFallback(filename: widget.filename, pt: pt, onDownload: widget.onDownload); + } + + final pageBytes = _cache[_currentPage]; + final aspect = _pageAspect ?? 0.707; // A4 fallback + final imgH = (_previewW / aspect).clamp(160.0, 400.0); + + return Listener( + onPointerSignal: (event) { + if (event is PointerScrollEvent) { + GestureBinding.instance.pointerSignalResolver.register(event, (resolved) { + final dy = (resolved as PointerScrollEvent).scrollDelta.dy; + if (dy > 0) { _goTo(_currentPage + 1); } + else if (dy < 0) { _goTo(_currentPage - 1); } + }); + } + }, + child: GestureDetector( + onTap: _openFull, + onHorizontalDragEnd: (d) { + if ((d.primaryVelocity ?? 0) < -200) _goTo(_currentPage + 1); + if ((d.primaryVelocity ?? 0) > 200) _goTo(_currentPage - 1); + }, + child: Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + width: _previewW, + decoration: BoxDecoration( + borderRadius: radius, + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + // Page image + Container( + width: _previewW, + height: imgH, + color: Colors.white, + child: pageBytes != null + ? Image.memory(pageBytes, width: _previewW, height: imgH, fit: BoxFit.cover, alignment: Alignment.topCenter) + : Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ), + // Footer + Container( + color: pt.bg2, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + child: Row( + children: [ + Icon(Icons.picture_as_pdf_outlined, size: 14, color: pt.fgDim), + const SizedBox(width: 6), + Expanded( + child: Text( + widget.filename, + style: TextStyle(color: pt.fg, fontSize: 12, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ), + ), + if (_pageCount > 1) ...[ + _NavArrow( + icon: Icons.chevron_left_rounded, + enabled: _currentPage > 1, + pt: pt, + onTap: () => _goTo(_currentPage - 1), + ), + Text( + '$_currentPage/$_pageCount', + style: TextStyle(color: pt.fgMuted, fontSize: 11, fontFeatures: const [FontFeature.tabularFigures()]), + ), + _NavArrow( + icon: Icons.chevron_right_rounded, + enabled: _currentPage < _pageCount, + pt: pt, + onTap: () => _goTo(_currentPage + 1), + ), + ], + if (widget.onDownload != null) ...[ + const SizedBox(width: 4), + GestureDetector( + onTap: widget.onDownload, + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.all(2), + child: Icon(Icons.download_rounded, size: 16, color: pt.fgMuted), + ), + ), + ], + ], + ), + ), + ], + ), + ), + ), + ); + } +} + +class _NavArrow extends StatelessWidget { + final IconData icon; + final bool enabled; + final PyramidTheme pt; + final VoidCallback onTap; + const _NavArrow({required this.icon, required this.enabled, required this.pt, required this.onTap}); + + @override + Widget build(BuildContext context) => GestureDetector( + onTap: enabled ? onTap : null, + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 2), + child: Icon(icon, size: 18, color: enabled ? pt.fg : pt.fgDim), + ), + ); +} + +class _FileFallback extends StatelessWidget { + final String filename; + final PyramidTheme pt; + final VoidCallback? onDownload; + const _FileFallback({required this.filename, required this.pt, this.onDownload}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + constraints: const BoxConstraints(maxWidth: 300), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 36, height: 36, + decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rSm)), + child: Icon(Icons.picture_as_pdf_outlined, size: 20, color: pt.accent), + ), + const SizedBox(width: 10), + Expanded( + child: Text(filename, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), maxLines: 2, overflow: TextOverflow.ellipsis), + ), + if (onDownload != null) + IconButton( + onPressed: onDownload, + icon: Icon(Icons.download_rounded, size: 20, color: pt.fgMuted), + constraints: const BoxConstraints(minWidth: 32, minHeight: 32), + padding: EdgeInsets.zero, + ), + ], + ), + ); + } +} + +// ─── Full overlay viewer ────────────────────────────────────────────────────── + +class DocumentViewer extends StatelessWidget { + final String filename; + final Uint8List bytes; + final String senderName; + final int initialPage; + + const DocumentViewer({ + super.key, + required this.filename, + required this.bytes, + required this.senderName, + this.initialPage = 1, + }); + + static bool supportsPreview(String filename) => + _detectType(filename) != _DocType.unknown; + + /// True for formats rendered inline in chat (pdf/svg types, including ai/eps). + static bool isInlinePreviewable(String filename) { + final t = _detectType(filename); + return t == _DocType.pdf || t == _DocType.svg; + } + + /// True for formats that show a card inline in chat (needs download-on-tap). + static bool showsInlineCard(String filename) { + final t = _detectType(filename); + return t == _DocType.proprietary || t == _DocType.psdThumb || t == _DocType.zipPreview; + } + + /// Kept for compatibility — same as showsInlineCard. + static bool isProprietaryFormat(String filename) => showsInlineCard(filename); + + static Future show( + BuildContext context, { + required String filename, + required Uint8List bytes, + required String senderName, + int initialPage = 1, + }) { + return showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: 'Schließen', + barrierColor: Colors.black.withAlpha(178), + transitionDuration: const Duration(milliseconds: 180), + transitionBuilder: (ctx, anim, a, child) => + FadeTransition(opacity: anim, child: child), + pageBuilder: (ctx, a, b) => DocumentViewer( + filename: filename, + bytes: bytes, + senderName: senderName, + initialPage: initialPage, + ), + ); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final type = _detectType(filename); + final size = MediaQuery.sizeOf(context); + final maxW = (size.width - 48).clamp(300.0, 1100.0); + final maxH = (size.height - 48).clamp(300.0, 900.0); + + return Material( + type: MaterialType.transparency, + child: Center( + child: Container( + width: maxW, + height: maxH, + decoration: BoxDecoration( + color: pt.bg0, + borderRadius: BorderRadius.circular(pt.rLg), + border: Border.all(color: pt.border), + boxShadow: [BoxShadow(color: Colors.black.withAlpha(80), blurRadius: 32, offset: const Offset(0, 8))], + ), + clipBehavior: Clip.hardEdge, + child: Column( + children: [ + _DocHeader(filename: filename, senderName: senderName, pt: pt), + Expanded( + child: _DocContent( + filename: filename, + bytes: bytes, + type: type, + pt: pt, + initialPage: initialPage, + ), + ), + ], + ), + ), + ), + ); + } +} + +// ─── Header ────────────────────────────────────────────────────────────────── + +class _DocHeader extends StatelessWidget { + final String filename; + final String senderName; + final PyramidTheme pt; + const _DocHeader({required this.filename, required this.senderName, required this.pt}); + + @override + Widget build(BuildContext context) { + final ext = filename.contains('.') ? filename.split('.').last.toUpperCase() : ''; + return Container( + padding: const EdgeInsets.fromLTRB(16, 12, 8, 12), + decoration: BoxDecoration( + color: pt.bg1, + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + _ExtBadge(ext: ext, pt: pt), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(filename, style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis), + Text(senderName, style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: Icon(Icons.close_rounded, color: pt.fgMuted, size: 20), + tooltip: 'Schließen', + ), + ], + ), + ); + } +} + +class _ExtBadge extends StatelessWidget { + final String ext; + final PyramidTheme pt; + const _ExtBadge({required this.ext, required this.pt}); + + @override + Widget build(BuildContext context) { + final label = ext.length > 4 ? ext.substring(0, 4) : ext; + return Container( + width: 44, height: 44, + decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rSm)), + child: Center( + child: Text(label, style: TextStyle(color: pt.accent, fontSize: label.length > 3 ? 10 : 12, fontWeight: FontWeight.w700)), + ), + ); + } +} + +// ─── Content dispatcher ─────────────────────────────────────────────────────── + +class _DocContent extends StatelessWidget { + final String filename; + final Uint8List bytes; + final _DocType type; + final PyramidTheme pt; + final int initialPage; + const _DocContent({required this.filename, required this.bytes, required this.type, required this.pt, required this.initialPage}); + + @override + Widget build(BuildContext context) { + return switch (type) { + _DocType.pdf => _PdfFullViewer(bytes: bytes, filename: filename, pt: pt, initialPage: initialPage), + _DocType.svg => _SvgViewer(bytes: bytes, pt: pt), + _DocType.markdown => _MarkdownViewer(bytes: bytes, pt: pt), + _DocType.text => _TextViewer(bytes: bytes, pt: pt, mono: false), + _DocType.code => _TextViewer(bytes: bytes, pt: pt, mono: true), + _DocType.office => _OfficeTextViewer(bytes: bytes, filename: filename, pt: pt), + _DocType.archive => _ArchiveViewer(bytes: bytes, filename: filename, pt: pt), + _DocType.psdThumb => _PsdThumbViewer(bytes: bytes, filename: filename, pt: pt), + _DocType.zipPreview => _ZipPreviewViewer(bytes: bytes, filename: filename, pt: pt), + _DocType.proprietary => _ProprietaryViewer(filename: filename, bytes: bytes, pt: pt), + _DocType.unknown => _UnsupportedViewer(pt: pt), + }; + } +} + +// ─── PDF full viewer with thumbnail strip ──────────────────────────────────── + +class _PdfFullViewer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + final int initialPage; + const _PdfFullViewer({required this.bytes, required this.filename, required this.pt, required this.initialPage}); + + @override + State<_PdfFullViewer> createState() => _PdfFullViewerState(); +} + +class _PdfFullViewerState extends State<_PdfFullViewer> { + late final PdfController _ctrl; + PdfDocument? _thumbDoc; + final Map _thumbs = {}; + int _pageCount = 0; + int _currentPage = 1; + bool _animating = false; + + @override + void initState() { + super.initState(); + _currentPage = widget.initialPage; + _ctrl = PdfController( + document: PdfDocument.openData(widget.bytes), + initialPage: widget.initialPage, + ); + _ctrl.pageListenable.addListener(_onPage); + _initThumbs(); + } + + Future _initThumbs() async { + final doc = await PdfDocument.openData(widget.bytes); + if (!mounted) { await doc.close(); return; } + _thumbDoc = doc; + if (!mounted) { await doc.close(); _thumbDoc = null; return; } + setState(() => _pageCount = doc.pagesCount); + for (var i = 1; i <= doc.pagesCount; i++) { + _renderThumb(i); + } + } + + Future _renderThumb(int n) async { + final doc = _thumbDoc; + if (doc == null) return; + try { + final page = await doc.getPage(n); + final rw = (page.width * 0.12).round(); + final rh = (page.height * 0.12).round(); + final hit = _RenderCache.get(widget.filename, widget.bytes.length, n, rw, rh); + if (hit != null) { + await page.close(); + if (mounted) setState(() => _thumbs[n] = hit); + return; + } + final img = await page.render( + width: page.width * 0.12, + height: page.height * 0.12, + format: PdfPageImageFormat.jpeg, + backgroundColor: '#ffffff', + ); + await page.close(); + if (img?.bytes != null) { + _RenderCache.put(widget.filename, widget.bytes.length, n, rw, rh, img!.bytes); + } + if (mounted) setState(() => _thumbs[n] = img?.bytes); + } catch (_) { + _thumbs[n] = null; + } + } + + void _onPage() => setState(() => _currentPage = _ctrl.page); + + void _onScrollPage(int delta) { + if (_animating) return; + final pageCount = _ctrl.pagesCount ?? _pageCount; + if (pageCount == 0) return; + final target = (_currentPage + delta).clamp(1, pageCount); + if (target == _currentPage) return; + _animating = true; + _ctrl.animateToPage( + target, + duration: const Duration(milliseconds: 280), + curve: Curves.easeInOut, + ).then((_) { if (mounted) setState(() => _animating = false); }); + } + + @override + void dispose() { + _ctrl.pageListenable.removeListener(_onPage); + _ctrl.dispose(); + _thumbDoc?.close(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Column( + children: [ + Expanded( + child: Stack( + children: [ + Listener( + onPointerSignal: (event) { + if (event is PointerScrollEvent) { + if (event.scrollDelta.dy > 0) { _onScrollPage(1); } + else if (event.scrollDelta.dy < 0) { _onScrollPage(-1); } + } + }, + child: PdfView( + controller: _ctrl, + scrollDirection: Axis.vertical, + physics: const NeverScrollableScrollPhysics(), + backgroundDecoration: BoxDecoration(color: pt.bg0), + onPageChanged: (p) => setState(() => _currentPage = p), + // Render at high resolution in PNG: sharper text/line-art and no + // JPEG chroma artifacts (matters most for AI/EPS/vector content), + // and gives headroom for the InteractiveViewer zoom. + renderer: (page) => page.render( + width: page.width * 4, + height: page.height * 4, + format: PdfPageImageFormat.png, + backgroundColor: '#ffffff', + ), + builders: PdfViewBuilders( + options: const DefaultBuilderOptions(), + documentLoaderBuilder: (ctx) => Center( + child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent), + ), + errorBuilder: (ctx, error) => _ErrorView(message: error.toString(), pt: pt), + ), + ), + ), + // Launch the immersive fullscreen page viewer. + Positioned( + top: 8, + right: 8, + child: Material( + color: pt.bg0.withAlpha(200), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rSm), + side: BorderSide(color: pt.border), + ), + child: IconButton( + tooltip: 'Vollbild', + icon: Icon(Icons.fullscreen_rounded, size: 22, color: pt.fg), + onPressed: () => _PdfFullscreenViewer.show( + context, + bytes: widget.bytes, + filename: widget.filename, + initialPage: _currentPage, + ), + ), + ), + ), + ], + ), + ), + if (_pageCount > 1) _ThumbnailStrip( + pageCount: _pageCount, + currentPage: _currentPage, + thumbs: _thumbs, + pt: pt, + onTap: (p) { + _ctrl.jumpToPage(p); + setState(() => _currentPage = p); + }, + ), + ], + ); + } +} + +// ─── Immersive fullscreen PDF viewer ───────────────────────────────────────── +// Launched from the enlarged preview. Per-page high-res render, pan via drag, +// zoom via +/− buttons (20%/click) and Ctrl+wheel, page nav via wheel/arrows. + +Future _saveBytes(BuildContext context, Uint8List bytes, String filename) async { + try { + Directory? dir; + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + dir = await getDownloadsDirectory(); + } + dir ??= await getTemporaryDirectory(); + final ext = filename.contains('.') ? filename.split('.').last : 'bin'; + final name = 'pyramid_${DateTime.now().millisecondsSinceEpoch}.$ext'; + final file = File('${dir.path}/$name'); + await file.writeAsBytes(bytes); + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Gespeichert: ${file.path}'), duration: const Duration(seconds: 4)), + ); + } + } catch (e) { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Fehler: $e'))); + } + } +} + +class _PdfFullscreenViewer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final int initialPage; + const _PdfFullscreenViewer({required this.bytes, required this.filename, required this.initialPage}); + + static Future show(BuildContext context, { + required Uint8List bytes, + required String filename, + required int initialPage, + }) { + return Navigator.of(context, rootNavigator: true).push(PageRouteBuilder( + opaque: true, + barrierColor: Colors.black, + transitionDuration: const Duration(milliseconds: 180), + pageBuilder: (_, __, ___) => + _PdfFullscreenViewer(bytes: bytes, filename: filename, initialPage: initialPage), + transitionsBuilder: (_, anim, __, child) => FadeTransition(opacity: anim, child: child), + )); + } + + @override + State<_PdfFullscreenViewer> createState() => _PdfFullscreenViewerState(); +} + +class _PdfFullscreenViewerState extends State<_PdfFullscreenViewer> { + PdfDocument? _doc; + final _tc = TransformationController(); + final _viewerKey = GlobalKey(); + int _page = 1; + int _count = 0; + Uint8List? _img; + bool _loading = true; + bool _rendering = false; + bool _uiVisible = true; + + bool get _isMobile => Platform.isAndroid || Platform.isIOS; + + static const _minScale = 1.0; + static const _maxScale = 8.0; + static const _renderScale = 5.0; // high-res page render for crisp zoom + + @override + void initState() { + super.initState(); + _page = widget.initialPage; + _open(); + } + + Future _open() async { + try { + final doc = await PdfDocument.openData(widget.bytes); + if (!mounted) { await doc.close(); return; } + _doc = doc; + _count = doc.pagesCount; + await _render(_page); + } catch (_) { + if (mounted) setState(() => _loading = false); + } + } + + Future _render(int n) async { + final doc = _doc; + if (doc == null || _rendering) return; + _rendering = true; + if (mounted) setState(() => _loading = true); + try { + final page = await doc.getPage(n); + final rw = (page.width * _renderScale).round(); + final rh = (page.height * _renderScale).round(); + var bytes = _RenderCache.get(widget.filename, widget.bytes.length, n, rw, rh); + if (bytes == null) { + final img = await page.render( + width: page.width * _renderScale, + height: page.height * _renderScale, + format: PdfPageImageFormat.png, + backgroundColor: '#ffffff', + ); + bytes = img?.bytes; + if (bytes != null) { + _RenderCache.put(widget.filename, widget.bytes.length, n, rw, rh, bytes); + } + } + await page.close(); + if (mounted) setState(() { _img = bytes; _loading = false; }); + } catch (_) { + if (mounted) setState(() => _loading = false); + } finally { + _rendering = false; + } + } + + void _goto(int n) { + final t = n.clamp(1, _count); + if (t == _page) return; + _tc.value = Matrix4.identity(); // reset zoom on page change + setState(() => _page = t); + _render(t); + } + + // factor 1.2 = +20%, 1/1.2 = −20% + void _zoom(double factor) { + final size = _viewerKey.currentContext?.size; + if (size == null) return; + final current = _tc.value.getMaxScaleOnAxis(); + final target = (current * factor).clamp(_minScale, _maxScale); + final applied = target / current; + if ((applied - 1).abs() < 0.001) return; + final cx = size.width / 2, cy = size.height / 2; + final m = _tc.value.clone() + ..translate(cx, cy) + ..scale(applied) + ..translate(-cx, -cy); + setState(() => _tc.value = m); + } + + @override + void dispose() { + _doc?.close(); + _tc.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Scaffold( + backgroundColor: Colors.black, + body: SafeArea( + child: Stack( + children: [ + Positioned.fill( + child: GestureDetector( + // Single tap on the page (not on a control) toggles the UI. + behavior: HitTestBehavior.translucent, + onTap: () => setState(() => _uiVisible = !_uiVisible), + child: Listener( + onPointerSignal: (e) { + if (e is! PointerScrollEvent) return; + final ctrl = HardwareKeyboard.instance.isControlPressed || + HardwareKeyboard.instance.isMetaPressed; + if (ctrl) { + _zoom(e.scrollDelta.dy < 0 ? 1.2 : 1 / 1.2); + } else { + _goto(e.scrollDelta.dy > 0 ? _page + 1 : _page - 1); + } + }, + child: _img == null + ? Center( + child: _loading + ? CircularProgressIndicator(color: pt.accent) + : const Icon(Icons.error_outline_rounded, color: Colors.white54, size: 40), + ) + : InteractiveViewer( + key: _viewerKey, + transformationController: _tc, + minScale: _minScale, + maxScale: _maxScale, + // Pinch-zoom on mobile only. On desktop the built-in + // scroll-wheel zoom is disabled so plain scrolling + // pages instead; zoom is Ctrl+wheel and the +/− buttons. + scaleEnabled: _isMobile, + child: Center( + child: Image.memory(_img!, fit: BoxFit.contain, gaplessPlayback: true), + ), + ), + ), + ), + ), + + // Right-side control column + if (_uiVisible) + Positioned( + right: 10, + top: 0, + bottom: 0, + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _FsBtn(icon: Icons.add_rounded, tooltip: 'Vergrößern', pt: pt, onTap: () => _zoom(1.2)), + const SizedBox(height: 8), + _FsBtn(icon: Icons.remove_rounded, tooltip: 'Verkleinern', pt: pt, onTap: () => _zoom(1 / 1.2)), + const SizedBox(height: 8), + _FsBtn(icon: Icons.download_rounded, tooltip: 'Herunterladen', pt: pt, + onTap: () => _saveBytes(context, widget.bytes, widget.filename)), + const SizedBox(height: 8), + _FsBtn(icon: Icons.fullscreen_exit_rounded, tooltip: 'Vollbild beenden', pt: pt, + onTap: () => Navigator.of(context).maybePop()), + ], + ), + ), + ), + + // Bottom-center page navigation + if (_uiVisible && _count > 1) + Positioned( + bottom: 16, + left: 0, + right: 0, + child: Center( + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + decoration: BoxDecoration( + color: Colors.black.withAlpha(160), + borderRadius: BorderRadius.circular(24), + border: Border.all(color: Colors.white24), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + _FsBtn(icon: Icons.chevron_left_rounded, tooltip: 'Vorherige', pt: pt, + enabled: _page > 1, onTap: () => _goto(_page - 1), flat: true), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text('$_page / $_count', + style: const TextStyle(color: Colors.white, fontSize: 13, + fontFeatures: [FontFeature.tabularFigures()])), + ), + _FsBtn(icon: Icons.chevron_right_rounded, tooltip: 'Nächste', pt: pt, + enabled: _page < _count, onTap: () => _goto(_page + 1), flat: true), + ], + ), + ), + ), + ), + ], + ), + ), + ); + } +} + +class _FsBtn extends StatelessWidget { + final IconData icon; + final String tooltip; + final PyramidTheme pt; + final VoidCallback onTap; + final bool enabled; + final bool flat; + const _FsBtn({required this.icon, required this.tooltip, required this.pt, + required this.onTap, this.enabled = true, this.flat = false}); + + @override + Widget build(BuildContext context) { + final btn = Material( + color: flat ? Colors.transparent : Colors.black.withAlpha(160), + shape: flat + ? const CircleBorder() + : RoundedRectangleBorder(borderRadius: BorderRadius.circular(10), side: const BorderSide(color: Colors.white24)), + child: IconButton( + tooltip: tooltip, + icon: Icon(icon, color: enabled ? Colors.white : Colors.white30, size: 22), + onPressed: enabled ? onTap : null, + ), + ); + return btn; + } +} + +class _ThumbnailStrip extends StatefulWidget { + final int pageCount; + final int currentPage; + final Map thumbs; + final PyramidTheme pt; + final ValueChanged onTap; + const _ThumbnailStrip({required this.pageCount, required this.currentPage, required this.thumbs, required this.pt, required this.onTap}); + + @override + State<_ThumbnailStrip> createState() => _ThumbnailStripState(); +} + +class _ThumbnailStripState extends State<_ThumbnailStrip> { + late final ScrollController _sc; + + @override + void initState() { + super.initState(); + _sc = ScrollController(); + } + + @override + void didUpdateWidget(_ThumbnailStrip old) { + super.didUpdateWidget(old); + if (old.currentPage != widget.currentPage) { + _scrollToPage(widget.currentPage); + } + } + + void _scrollToPage(int page) { + const thumbW = 60.0 + 8.0; // thumb + margin + final target = (page - 1) * thumbW - 80; + if (_sc.hasClients) { + _sc.animateTo( + target.clamp(0.0, _sc.position.maxScrollExtent), + duration: const Duration(milliseconds: 200), + curve: Curves.easeOut, + ); + } + } + + @override + void dispose() { + _sc.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Container( + height: 88, + decoration: BoxDecoration( + color: pt.bg1, + border: Border(top: BorderSide(color: pt.border)), + ), + child: ListView.builder( + controller: _sc, + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + itemCount: widget.pageCount, + itemBuilder: (ctx, i) { + final page = i + 1; + final isCurrent = page == widget.currentPage; + final bytes = widget.thumbs[page]; + return GestureDetector( + onTap: () => widget.onTap(page), + child: Container( + width: 52, + margin: const EdgeInsets.only(right: 8), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(4), + border: Border.all( + color: isCurrent ? pt.accent : pt.border, + width: isCurrent ? 2 : 1, + ), + ), + clipBehavior: Clip.hardEdge, + child: bytes != null + ? Image.memory(bytes, fit: BoxFit.cover) + : Center( + child: Text('$page', style: TextStyle(color: pt.fgDim, fontSize: 10)), + ), + ), + ); + }, + ), + ); + } +} + +// ─── SVG viewer ─────────────────────────────────────────────────────────────── + +class _SvgViewer extends StatelessWidget { + final Uint8List bytes; + final PyramidTheme pt; + const _SvgViewer({required this.bytes, required this.pt}); + + @override + Widget build(BuildContext context) { + return Center( + child: InteractiveViewer( + minScale: 0.5, + maxScale: 10, + child: Padding( + padding: const EdgeInsets.all(24), + child: SvgPicture.memory(bytes), + ), + ), + ); + } +} + +// ─── Markdown viewer ────────────────────────────────────────────────────────── + +class _MarkdownViewer extends StatelessWidget { + final Uint8List bytes; + final PyramidTheme pt; + const _MarkdownViewer({required this.bytes, required this.pt}); + + @override + Widget build(BuildContext context) { + final String text; + try { + text = utf8.decode(bytes, allowMalformed: true); + } catch (e) { + return _ErrorView(message: e.toString(), pt: pt); + } + + return Markdown( + data: text, + selectable: true, + padding: const EdgeInsets.all(24), + styleSheet: MarkdownStyleSheet( + p: TextStyle(color: pt.fg, fontSize: 14, height: 1.65), + h1: TextStyle(color: pt.fg, fontSize: 22, fontWeight: FontWeight.w700), + h2: TextStyle(color: pt.fg, fontSize: 18, fontWeight: FontWeight.w600), + h3: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w600), + h4: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), + code: TextStyle(color: pt.accent, fontFamily: 'monospace', fontSize: 13, backgroundColor: pt.bg2), + codeblockDecoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rSm), + border: Border.all(color: pt.border), + ), + blockquoteDecoration: BoxDecoration( + border: Border(left: BorderSide(color: pt.accent, width: 3)), + color: pt.accentSoft, + ), + blockquotePadding: const EdgeInsets.fromLTRB(12, 8, 12, 8), + a: TextStyle(color: pt.accent, decoration: TextDecoration.underline, decorationColor: pt.accent), + strong: TextStyle(color: pt.fg, fontWeight: FontWeight.w600), + em: TextStyle(color: pt.fg, fontStyle: FontStyle.italic), + listBullet: TextStyle(color: pt.fgMuted), + horizontalRuleDecoration: BoxDecoration(border: Border(top: BorderSide(color: pt.border))), + ), + onTapLink: (text, href, title) { + if (href != null) launchUrl(Uri.parse(href), mode: LaunchMode.externalApplication); + }, + ); + } +} + +// ─── Text / Code viewer ─────────────────────────────────────────────────────── + +class _TextViewer extends StatelessWidget { + final Uint8List bytes; + final PyramidTheme pt; + final bool mono; + static const _maxBytes = 512 * 1024; + const _TextViewer({required this.bytes, required this.pt, required this.mono}); + + @override + Widget build(BuildContext context) { + final bool truncated = bytes.length > _maxBytes; + final slice = truncated ? bytes.sublist(0, _maxBytes) : bytes; + final String text; + try { + text = utf8.decode(slice, allowMalformed: true); + } catch (e) { + return _ErrorView(message: e.toString(), pt: pt); + } + + return Column( + children: [ + if (truncated) + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + color: pt.bg2, + child: Text('Zeige erste ${_maxBytes ~/ 1024} KB', style: TextStyle(color: pt.fgDim, fontSize: 11)), + ), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: SelectableText( + text, + style: mono + ? TextStyle(color: pt.fg, fontFamily: 'monospace', fontSize: 13, height: 1.5) + : TextStyle(color: pt.fg, fontSize: 14, height: 1.65), + ), + ), + ), + ], + ); + } +} + +// ─── Office text extraction (DOCX / PPTX / XLSX) ──────────────────────────── + +class _OfficeTextViewer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + const _OfficeTextViewer({required this.bytes, required this.filename, required this.pt}); + + @override + State<_OfficeTextViewer> createState() => _OfficeTextViewerState(); +} + +class _OfficeTextViewerState extends State<_OfficeTextViewer> { + String? _text; + String? _error; + + @override + void initState() { + super.initState(); + _extract(); + } + + void _extract() { + try { + final archive = ZipDecoder().decodeBytes(widget.bytes); + final ext = widget.filename.contains('.') ? widget.filename.split('.').last.toLowerCase() : ''; + + final xmlFiles = []; + for (final f in archive.files) { + if (!f.isFile) continue; + final n = f.name.toLowerCase(); + if (ext == 'docx' && n == 'word/document.xml') { xmlFiles.add(f); break; } + if (ext == 'xlsx' && n.startsWith('xl/worksheets/') && n.endsWith('.xml')) xmlFiles.add(f); + if (ext == 'pptx' && n.startsWith('ppt/slides/slide') && n.endsWith('.xml')) xmlFiles.add(f); + // ODF formats (Writer/Impress/Calc) all use content.xml + if ((ext == 'odt' || ext == 'odp' || ext == 'ods') && n == 'content.xml') { xmlFiles.add(f); break; } + } + + final buf = StringBuffer(); + for (final f in xmlFiles) { + final xml = utf8.decode(f.content as List, allowMalformed: true); + // Strip XML tags, collapse whitespace + final stripped = xml + .replaceAll(RegExp(r'<[^>]+>'), ' ') + .replaceAll(RegExp(r'&'), '&') + .replaceAll(RegExp(r'<'), '<') + .replaceAll(RegExp(r'>'), '>') + .replaceAll(RegExp(r' '), ' ') + .replaceAll(RegExp(r'\s+'), ' ') + .trim(); + buf.writeln(stripped); + buf.writeln(); + } + + _text = buf.toString().trim().isEmpty + ? '(Kein lesbarer Text gefunden)' + : buf.toString().trim(); + } catch (e) { + _error = e.toString().split('\n').first; + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + if (_error != null) return _ErrorView(message: _error!, pt: pt); + + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + color: pt.bg2, + child: Row( + children: [ + Icon(Icons.info_outline_rounded, size: 14, color: pt.fgDim), + const SizedBox(width: 8), + Text('Textvorschau (Formatierung nicht verfügbar)', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + Expanded( + child: SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: SelectableText( + _text ?? '', + style: TextStyle(color: pt.fg, fontSize: 14, height: 1.65), + ), + ), + ), + ], + ); + } +} + +// ─── Archive viewer ─────────────────────────────────────────────────────────── + +class _ArchiveViewer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + const _ArchiveViewer({required this.bytes, required this.filename, required this.pt}); + + @override + State<_ArchiveViewer> createState() => _ArchiveViewerState(); +} + +class _ArchiveViewerState extends State<_ArchiveViewer> { + List<_ArchiveEntry>? _entries; + String? _error; + + @override + void initState() { + super.initState(); + _decode(); + } + + void _decode() { + try { + final ext = widget.filename.contains('.') ? widget.filename.split('.').last.toLowerCase() : ''; + Archive archive; + if (ext == 'tar') { + archive = TarDecoder().decodeBytes(widget.bytes); + } else if (ext == 'gz' || ext == 'tgz') { + final inner = GZipDecoder().decodeBytes(widget.bytes); + archive = TarDecoder().decodeBytes(inner); + } else { + archive = ZipDecoder().decodeBytes(widget.bytes); + } + + final entries = archive.files.map((f) => _ArchiveEntry(name: f.name, size: f.size, isDir: !f.isFile)).toList() + ..sort((a, b) { + if (a.isDir != b.isDir) return a.isDir ? -1 : 1; + return a.name.compareTo(b.name); + }); + setState(() => _entries = entries); + } catch (e) { + setState(() => _error = e.toString()); + } + } + + String _fmtSize(int b) { + if (b < 1024) return '$b B'; + if (b < 1024 * 1024) return '${(b / 1024).toStringAsFixed(1)} KB'; + return '${(b / (1024 * 1024)).toStringAsFixed(1)} MB'; + } + + @override + Widget build(BuildContext context) { + if (_error != null) return _ErrorView(message: _error!, pt: widget.pt); + if (_entries == null) return Center(child: CircularProgressIndicator(strokeWidth: 2, color: widget.pt.accent)); + + final pt = widget.pt; + final entries = _entries!; + final totalBytes = entries.fold(0, (s, e) => s + (e.isDir ? 0 : e.size)); + + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8), + color: pt.bg1, + child: Row( + children: [ + Icon(Icons.folder_zip_outlined, size: 15, color: pt.fgDim), + const SizedBox(width: 8), + Text('${entries.length} Einträge · ${_fmtSize(totalBytes)} unkomprimiert', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric(vertical: 4), + itemCount: entries.length, + itemBuilder: (ctx, i) { + final e = entries[i]; + return ListTile( + dense: true, + visualDensity: VisualDensity.compact, + leading: Icon(e.isDir ? Icons.folder_outlined : _fileIcon(e.name), size: 18, color: e.isDir ? pt.accent : pt.fgDim), + title: Text(e.name, style: TextStyle(color: pt.fg, fontSize: 13), overflow: TextOverflow.ellipsis), + trailing: e.isDir ? null : Text(_fmtSize(e.size), style: TextStyle(color: pt.fgDim, fontSize: 11)), + ); + }, + ), + ), + ], + ); + } + + IconData _fileIcon(String name) { + final ext = name.contains('.') ? name.split('.').last.toLowerCase() : ''; + return switch (ext) { + 'dart' || 'py' || 'js' || 'ts' || 'json' || 'xml' || 'yaml' || 'toml' => Icons.code_rounded, + 'png' || 'jpg' || 'jpeg' || 'gif' || 'webp' || 'svg' => Icons.image_outlined, + 'mp4' || 'mov' || 'avi' || 'mkv' => Icons.videocam_outlined, + 'mp3' || 'ogg' || 'flac' || 'wav' => Icons.music_note_outlined, + 'pdf' => Icons.picture_as_pdf_outlined, + 'zip' || 'tar' || 'gz' || '7z' || 'rar' => Icons.folder_zip_outlined, + 'md' || 'markdown' => Icons.article_outlined, + _ => Icons.insert_drive_file_outlined, + }; + } +} + +class _ArchiveEntry { + final String name; + final int size; + final bool isDir; + const _ArchiveEntry({required this.name, required this.size, required this.isDir}); +} + +// ─── PSD/PSB thumbnail viewer ──────────────────────────────────────────────── +// Extracts the JPEG thumbnail stored in PSD Image Resource 1036. + +Uint8List? _extractPsdThumbnail(Uint8List bytes) { + try { + if (bytes.length < 34) return null; + final data = ByteData.sublistView(bytes); + // Verify '8BPS' signature + if (bytes[0] != 0x38 || bytes[1] != 0x42 || bytes[2] != 0x50 || bytes[3] != 0x53) return null; + + // PSD is big-endian throughout. + // Color Mode Data section length at offset 26. + final cmdLen = data.getUint32(26, Endian.big); + // Image Resources section starts after 26-byte header + 4-byte length field + cmdLen bytes. + final irPos = 30 + cmdLen; + if (irPos + 4 > bytes.length) return null; + final irLen = data.getUint32(irPos, Endian.big); + + int pos = irPos + 4; + final irEnd = pos + irLen; + + while (pos + 10 <= irEnd && pos + 10 <= bytes.length) { + // Signature: '8BIM' + if (bytes[pos] != 0x38 || bytes[pos+1] != 0x42 || bytes[pos+2] != 0x49 || bytes[pos+3] != 0x4D) break; + pos += 4; + + final resourceId = data.getUint16(pos, Endian.big); + pos += 2; + + // Pascal string: 1-byte length + string, total padded to even. + final nameLen = bytes[pos]; + pos += (nameLen + 2) & ~1; + + if (pos + 4 > bytes.length) break; + final dataSize = data.getUint32(pos, Endian.big); + pos += 4; + + // Resource 1036 (Photoshop 5+) or 1033 (older) = Thumbnail + if ((resourceId == 0x040C || resourceId == 0x0409) && dataSize >= 28) { + final format = data.getUint32(pos, Endian.big); + if (format == 1) { // kJpegRGB + // Use dataSize-28 for the JPEG extent (more reliable than the + // compressedSize field at pos+20, which varies across PS versions). + final jpegStart = pos + 28; + final jpegEnd = (pos + dataSize).clamp(jpegStart, bytes.length); + if (jpegEnd > jpegStart) { + final thumb = Uint8List.sublistView(bytes, jpegStart, jpegEnd); + // Validate JPEG magic bytes (FF D8) + if (thumb.length >= 2 && thumb[0] == 0xFF && thumb[1] == 0xD8) { + return thumb; + } + // Some files need a forward scan for the actual JPEG start + for (var i = 0; i < thumb.length - 1; i++) { + if (thumb[i] == 0xFF && thumb[i + 1] == 0xD8) { + return Uint8List.sublistView(thumb, i); + } + } + } + } + return null; + } + + // Advance past this resource's data (padded to even). + final advance = (dataSize + 1) & ~1; + if (advance == 0 && dataSize == 0) { pos += 0; } else { pos += advance; } + } + return null; + } catch (_) { + return null; + } +} + +class _PsdThumbViewer extends StatelessWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + const _PsdThumbViewer({required this.bytes, required this.filename, required this.pt}); + + @override + Widget build(BuildContext context) { + final thumb = _extractPsdThumbnail(bytes); + if (thumb == null) { + return _ProprietaryViewer(filename: filename, bytes: bytes, pt: pt); + } + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + color: pt.bg2, + child: Row( + children: [ + Icon(Icons.info_outline_rounded, size: 14, color: pt.fgDim), + const SizedBox(width: 8), + Text('Eingebettete Vorschau (Vollbild nicht verfügbar)', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + Expanded( + child: InteractiveViewer( + minScale: 0.5, + maxScale: 10, + child: Padding( + padding: const EdgeInsets.all(24), + child: Image.memory(thumb, fit: BoxFit.contain), + ), + ), + ), + ], + ); + } +} + +// ─── ZIP-preview viewer (Sketch, XD) ───────────────────────────────────────── +// These formats are ZIP archives that embed a preview PNG. + +class _ZipPreviewViewer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + const _ZipPreviewViewer({required this.bytes, required this.filename, required this.pt}); + + @override + State<_ZipPreviewViewer> createState() => _ZipPreviewViewerState(); +} + +class _ZipPreviewViewerState extends State<_ZipPreviewViewer> { + Uint8List? _preview; + bool _loaded = false; + bool _isImage = false; + + @override + void initState() { + super.initState(); + _extract(); + } + + void _extract() { + try { + final archive = ZipDecoder().decodeBytes(widget.bytes); + // Priority search list + const candidates = [ + 'previews/preview.png', 'preview.png', 'thumbnail.png', + 'thumbnails/thumbnail.png', 'preview.jpg', 'thumbnail.jpg', + ]; + ArchiveFile? found; + for (final path in candidates) { + found = archive.findFile(path); + if (found != null && found.isFile) break; + } + // Fallback: any file with preview/thumbnail in the name + if (found == null) { + for (final f in archive.files) { + if (!f.isFile) continue; + final n = f.name.toLowerCase(); + if ((n.contains('preview') || n.contains('thumb')) && + (n.endsWith('.png') || n.endsWith('.jpg') || n.endsWith('.jpeg'))) { + found = f; + break; + } + } + } + if (found != null) { + setState(() { + _preview = Uint8List.fromList(found!.content as List); + _isImage = true; + _loaded = true; + }); + } else { + setState(() => _loaded = true); + } + } catch (_) { + setState(() => _loaded = true); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + if (!_loaded) { + return Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)); + } + if (_isImage && _preview != null) { + return Column( + children: [ + Container( + width: double.infinity, + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 6), + color: pt.bg2, + child: Row( + children: [ + Icon(Icons.info_outline_rounded, size: 14, color: pt.fgDim), + const SizedBox(width: 8), + Text('Eingebettete Vorschau', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + Expanded( + child: InteractiveViewer( + minScale: 0.5, + maxScale: 10, + child: Padding( + padding: const EdgeInsets.all(24), + child: Image.memory(_preview!, fit: BoxFit.contain), + ), + ), + ), + ], + ); + } + // No preview image found — fall back to archive listing + return _ArchiveViewer(bytes: widget.bytes, filename: widget.filename, pt: pt); + } +} + +// ─── Proprietary format info card ──────────────────────────────────────────── + +class _ProprietaryViewer extends StatelessWidget { + final String filename; + final Uint8List bytes; + final PyramidTheme pt; + const _ProprietaryViewer({required this.filename, required this.bytes, required this.pt}); + + String _fmtSize(int b) { + if (b < 1024) return '$b B'; + if (b < 1024 * 1024) return '${(b / 1024).toStringAsFixed(1)} KB'; + return '${(b / (1024 * 1024)).toStringAsFixed(1)} MB'; + } + + IconData _iconFor(String ext) => switch (ext) { + 'psd' || 'psb' => Icons.photo_camera_outlined, + 'ai' || 'eps' => Icons.gesture_outlined, + 'indd' || 'inx' => Icons.menu_book_outlined, + 'afphoto' || 'afdesign' || 'afpub' => Icons.palette_outlined, + 'sketch' || 'fig' || 'xd' => Icons.design_services_outlined, + 'doc' => Icons.description_outlined, + 'ppt' => Icons.slideshow_outlined, + 'xls' => Icons.table_chart_outlined, + _ => Icons.insert_drive_file_outlined, + }; + + @override + Widget build(BuildContext context) { + final ext = filename.contains('.') ? filename.split('.').last.toLowerCase() : ''; + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 80, height: 80, + decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rBase)), + child: Icon(_iconFor(ext), size: 40, color: pt.accent), + ), + const SizedBox(height: 16), + Text( + filename, + style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600), + textAlign: TextAlign.center, + ), + const SizedBox(height: 6), + Text(_fmtSize(bytes.length), style: TextStyle(color: pt.fgDim, fontSize: 13)), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rSm), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.info_outline_rounded, size: 16, color: pt.fgDim), + const SizedBox(width: 8), + Text( + 'Format kann nicht nativ dargestellt werden', + style: TextStyle(color: pt.fgDim, fontSize: 13), + ), + ], + ), + ), + ], + ), + ); + } +} + +// ─── Unsupported / Error ───────────────────────────────────────────────────── + +class _UnsupportedViewer extends StatelessWidget { + final PyramidTheme pt; + const _UnsupportedViewer({required this.pt}); + + @override + Widget build(BuildContext context) => Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.preview_outlined, size: 48, color: pt.fgDim), + const SizedBox(height: 12), + Text('Vorschau nicht verfügbar', style: TextStyle(color: pt.fgDim, fontSize: 15)), + const SizedBox(height: 4), + Text('Proprietäres Format — bitte herunterladen.', style: TextStyle(color: pt.fgMuted, fontSize: 12)), + ], + ), + ); +} + +class _ErrorView extends StatelessWidget { + final String message; + final PyramidTheme pt; + const _ErrorView({required this.message, required this.pt}); + + @override + Widget build(BuildContext context) => Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline_rounded, size: 32, color: pt.danger), + const SizedBox(height: 8), + Text('Fehler beim Laden', style: TextStyle(color: pt.danger, fontSize: 14, fontWeight: FontWeight.w600)), + const SizedBox(height: 6), + Text(message, style: TextStyle(color: pt.fgMuted, fontSize: 12), textAlign: TextAlign.center), + ], + ), + ), + ); +} + +// ─── Type detection ─────────────────────────────────────────────────────────── + +enum _DocType { pdf, svg, text, code, markdown, office, archive, psdThumb, zipPreview, proprietary, unknown } + +_DocType _detectType(String filename) { + final ext = filename.contains('.') ? filename.split('.').last.toLowerCase() : ''; + return switch (ext) { + // AI/EPS files embed a full PDF when saved with PDF compatibility + 'pdf' || 'ai' || 'eps' => _DocType.pdf, + 'svg' => _DocType.svg, + 'md' || 'markdown' || 'rst' => _DocType.markdown, + 'zip' || 'tar' || 'gz' || 'tgz' || 'tar.gz' => _DocType.archive, + 'txt' || 'log' || 'csv' || 'tsv' || + 'rtf' || 'tex' || 'srt' || 'vtt' || 'nfo' => _DocType.text, + // ODF formats are ZIP+XML, same extraction approach as OOXML + 'docx' || 'xlsx' || 'pptx' || + 'odt' || 'odp' || 'ods' => _DocType.office, + 'dart' || 'py' || 'js' || 'mjs' || 'cjs' || 'ts' || 'jsx' || 'tsx' || + 'json' || 'jsonl' || 'ndjson' || 'yaml' || 'yml' || 'xml' || 'plist' || + 'html' || 'htm' || 'css' || 'scss' || 'sass' || 'less' || + 'vue' || 'svelte' || 'astro' || + 'sh' || 'bash' || 'zsh' || 'fish' || 'ps' || 'ps1' || 'bat' || 'cmd' || + 'kt' || 'kts' || 'gradle' || 'java' || 'swift' || 'go' || 'rs' || + 'cpp' || 'cc' || 'cxx' || 'c' || 'h' || 'hpp' || 'hxx' || 'm' || 'mm' || + 'cs' || 'rb' || 'php' || 'r' || 'lua' || 'pl' || 'pm' || 'scala' || + 'clj' || 'ex' || 'exs' || 'erl' || 'hs' || 'jl' || 'nim' || 'zig' || + 'toml' || 'ini' || 'conf' || 'cfg' || 'env' || 'editorconfig' || + 'properties' || 'diff' || 'patch' || 'gitignore' || 'dockerfile' || + 'sql' || 'graphql' || 'gql' || 'proto' => _DocType.code, + // PSD/PSB embed a JPEG thumbnail in Image Resource 1036 + 'psd' || 'psb' => _DocType.psdThumb, + // Sketch and XD are ZIP archives containing a preview PNG + 'sketch' || 'xd' => _DocType.zipPreview, + // Truly proprietary — no extractable preview + 'afphoto' || 'afdesign' || 'afpub' || + 'indd' || 'inx' || 'fig' || + 'doc' || 'ppt' || 'xls' => _DocType.proprietary, + _ => _DocType.unknown, + }; +} diff --git a/lib/features/chat/emoji_picker.dart b/lib/features/chat/emoji_picker.dart new file mode 100644 index 0000000..e14acbd --- /dev/null +++ b/lib/features/chat/emoji_picker.dart @@ -0,0 +1,710 @@ +import 'package:flutter/material.dart'; +import 'package:pyramid/core/theme.dart'; + +class EmojiPicker extends StatefulWidget { + final ValueChanged onEmojiSelected; + final VoidCallback onClose; + + const EmojiPicker({ + super.key, + required this.onEmojiSelected, + required this.onClose, + }); + + @override + State createState() => _EmojiPickerState(); +} + +class _EmojiPickerState extends State { + int _categoryIndex = 0; + final _searchCtrl = TextEditingController(); + String _query = ''; + + @override + void dispose() { + _searchCtrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final filtered = _query.isEmpty + ? _kCategories[_categoryIndex].emojis + : _kCategories + .expand((c) => c.emojis) + .where((e) => e.keywords.any((k) => k.contains(_query.toLowerCase()))) + .toList(); + + return Container( + width: 340, + height: 380, + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: pt.border), + boxShadow: const [ + BoxShadow(color: Color(0x50000000), blurRadius: 24, offset: Offset(0, 8)), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Column( + children: [ + // Search bar + Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 4), + child: TextField( + controller: _searchCtrl, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + hintText: 'Emoji suchen…', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 13), + prefixIcon: Icon(Icons.search, size: 16, color: pt.fgDim), + isDense: true, + suffixIcon: _query.isNotEmpty + ? IconButton( + icon: Icon(Icons.clear, size: 14, color: pt.fgDim), + onPressed: () { + _searchCtrl.clear(); + setState(() => _query = ''); + }, + ) + : null, + contentPadding: const EdgeInsets.symmetric(vertical: 8), + filled: true, + fillColor: pt.bg2, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.accent), + ), + ), + onChanged: (v) => setState(() => _query = v.trim()), + ), + ), + // Category tabs (hidden during search) + if (_query.isEmpty) + SizedBox( + height: 36, + child: ListView.builder( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 6), + itemCount: _kCategories.length, + itemBuilder: (ctx, i) { + final selected = i == _categoryIndex; + return GestureDetector( + onTap: () => setState(() => _categoryIndex = i), + child: Container( + width: 36, + margin: const EdgeInsets.symmetric(vertical: 4, horizontal: 2), + decoration: BoxDecoration( + color: selected ? pt.accentSoft : Colors.transparent, + borderRadius: BorderRadius.circular(6), + border: Border.all( + color: selected ? pt.accent : Colors.transparent, + ), + ), + child: Center( + child: Text( + _kCategories[i].icon, + style: const TextStyle(fontSize: 16), + ), + ), + ), + ); + }, + ), + ), + Container(height: 1, color: pt.border), + // Emoji grid + Expanded( + child: GridView.builder( + padding: const EdgeInsets.all(4), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 8, + childAspectRatio: 1, + ), + itemCount: filtered.length, + itemBuilder: (ctx, i) { + final emoji = filtered[i]; + return _EmojiCell( + emoji: emoji.char, + tooltip: emoji.keywords.isNotEmpty ? emoji.keywords.first : '', + pt: pt, + onTap: () => widget.onEmojiSelected(emoji.char), + ); + }, + ), + ), + ], + ), + ), + ); + } +} + +class _EmojiCell extends StatefulWidget { + final String emoji; + final String tooltip; + final PyramidTheme pt; + final VoidCallback onTap; + + const _EmojiCell({ + required this.emoji, + required this.tooltip, + required this.pt, + required this.onTap, + }); + + @override + State<_EmojiCell> createState() => _EmojiCellState(); +} + +class _EmojiCellState extends State<_EmojiCell> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: Tooltip( + message: widget.tooltip, + waitDuration: const Duration(milliseconds: 600), + child: AnimatedContainer( + duration: const Duration(milliseconds: 100), + decoration: BoxDecoration( + color: _hovered ? widget.pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(6), + ), + child: Center( + child: Text(widget.emoji, style: const TextStyle(fontSize: 20)), + ), + ), + ), + ), + ); + } +} + +// ─── Emoji data ──────────────────────────────────────────────────────────── + +class _EmojiEntry { + final String char; + final List keywords; + const _EmojiEntry(this.char, this.keywords); +} + +class _EmojiCategory { + final String icon; + final String name; + final List<_EmojiEntry> emojis; + const _EmojiCategory(this.icon, this.name, this.emojis); +} + +const _kCategories = [ + _EmojiCategory('😀', 'Smileys', _kSmileys), + _EmojiCategory('👋', 'Personen', _kPeople), + _EmojiCategory('🐶', 'Natur', _kNature), + _EmojiCategory('🍕', 'Essen', _kFood), + _EmojiCategory('⚽', 'Aktivitäten', _kActivities), + _EmojiCategory('🚗', 'Reise', _kTravel), + _EmojiCategory('💡', 'Objekte', _kObjects), + _EmojiCategory('❤️', 'Symbole', _kSymbols), +]; + +const _kSmileys = [ + _EmojiEntry('😀', ['lächeln', 'grinsen', 'happy', 'smiley']), + _EmojiEntry('😁', ['breit', 'grinsen']), + _EmojiEntry('😂', ['lachen', 'tränen', 'witzig', 'lol']), + _EmojiEntry('🤣', ['rollen', 'lachen', 'rofl']), + _EmojiEntry('😃', ['lächeln', 'glücklich']), + _EmojiEntry('😄', ['lächeln', 'augen']), + _EmojiEntry('😅', ['schwitzen', 'erleichtert']), + _EmojiEntry('😆', ['lachen', 'augen']), + _EmojiEntry('😉', ['zwinkern', 'wink']), + _EmojiEntry('😊', ['schüchtern', 'lächeln', 'rot']), + _EmojiEntry('😋', ['lecker', 'zunge']), + _EmojiEntry('😎', ['cool', 'sonnenbrille']), + _EmojiEntry('😍', ['verliebt', 'herz', 'augen']), + _EmojiEntry('🥰', ['verliebt', 'herzen']), + _EmojiEntry('😘', ['kuss', 'herz']), + _EmojiEntry('😗', ['kuss']), + _EmojiEntry('😚', ['kuss', 'augen']), + _EmojiEntry('😙', ['kuss', 'lächeln']), + _EmojiEntry('🥲', ['lächeln', 'tränen']), + _EmojiEntry('😏', ['verschmitzt', 'smirk']), + _EmojiEntry('😒', ['unzufrieden', 'unamused']), + _EmojiEntry('😞', ['enttäuscht']), + _EmojiEntry('😔', ['nachdenklich', 'traurig']), + _EmojiEntry('😟', ['besorgt']), + _EmojiEntry('😕', ['verwirrt', 'confused']), + _EmojiEntry('🙁', ['leicht', 'traurig']), + _EmojiEntry('☹️', ['traurig', 'frowning']), + _EmojiEntry('😣', ['kämpfend']), + _EmojiEntry('😖', ['verwirrt', 'confounded']), + _EmojiEntry('😫', ['erschöpft', 'tired']), + _EmojiEntry('😩', ['müde', 'weary']), + _EmojiEntry('🥺', ['bitte', 'augen']), + _EmojiEntry('😢', ['weinen', 'cry']), + _EmojiEntry('😭', ['laut', 'weinen', 'sob']), + _EmojiEntry('😤', ['wütend', 'frustriert']), + _EmojiEntry('😠', ['wütend', 'angry']), + _EmojiEntry('😡', ['sehr wütend', 'rage']), + _EmojiEntry('🤬', ['fluchen', 'wütend']), + _EmojiEntry('🤯', ['explodierend', 'schockiert']), + _EmojiEntry('😳', ['errötend', 'flushed']), + _EmojiEntry('🥵', ['heiß', 'hot']), + _EmojiEntry('🥶', ['kalt', 'cold']), + _EmojiEntry('😱', ['schreien', 'angst']), + _EmojiEntry('😨', ['ängstlich', 'fearful']), + _EmojiEntry('😰', ['schwitzen', 'angst']), + _EmojiEntry('😥', ['enttäuscht', 'erleichtert']), + _EmojiEntry('😓', ['schwitzen', 'niedergeschlagen']), + _EmojiEntry('🤗', ['umarmen', 'hug']), + _EmojiEntry('🤔', ['denken', 'thinking']), + _EmojiEntry('🫡', ['salutieren']), + _EmojiEntry('🤭', ['kichern', 'hand']), + _EmojiEntry('🫢', ['schockiert']), + _EmojiEntry('🤫', ['shush', 'flüstern']), + _EmojiEntry('🤥', ['lügen', 'pinocchio']), + _EmojiEntry('😶', ['kein mund', 'sprachlos']), + _EmojiEntry('😐', ['neutral']), + _EmojiEntry('😑', ['ausdruckslos']), + _EmojiEntry('😬', ['zähne', 'grimasse']), + _EmojiEntry('🙄', ['augen', 'genervt']), + _EmojiEntry('😯', ['überrascht', 'staunen']), + _EmojiEntry('😦', ['grimasse', 'frowning']), + _EmojiEntry('😧', ['gequält']), + _EmojiEntry('😮', ['überrascht', 'open mouth']), + _EmojiEntry('😲', ['erstaunt', 'astonished']), + _EmojiEntry('🥱', ['gähnen', 'müde']), + _EmojiEntry('🤤', ['sabbern', 'drooling']), + _EmojiEntry('😴', ['schlafen', 'zzz']), + _EmojiEntry('🤢', ['krank', 'übel']), + _EmojiEntry('🤮', ['erbrechen', 'krank']), + _EmojiEntry('🤧', ['niesen', 'krank']), + _EmojiEntry('😷', ['maske', 'krank']), + _EmojiEntry('🤒', ['fieber', 'krank']), + _EmojiEntry('🤕', ['verletzt', 'verband']), + _EmojiEntry('🤑', ['geld', 'reich']), + _EmojiEntry('🤠', ['cowboy', 'hut']), + _EmojiEntry('🥳', ['feiern', 'party']), + _EmojiEntry('🥸', ['verkleidet']), + _EmojiEntry('😎', ['cool', 'sonnenbrille']), + _EmojiEntry('🤓', ['nerd', 'brille']), + _EmojiEntry('🧐', ['monokel', 'nachdenklich']), + _EmojiEntry('😈', ['teufel', 'böse']), + _EmojiEntry('👿', ['teufel', 'wütend']), + _EmojiEntry('💀', ['tot', 'schädel']), + _EmojiEntry('☠️', ['totenkopf', 'kreuzknochgen']), + _EmojiEntry('👻', ['geist', 'halloween']), + _EmojiEntry('💩', ['häufchen', 'poop']), + _EmojiEntry('🤡', ['clown']), + _EmojiEntry('👾', ['monster', 'spiel']), + _EmojiEntry('🎃', ['halloween', 'kürbis']), +]; + +const _kPeople = [ + _EmojiEntry('👋', ['hallo', 'winken', 'wave']), + _EmojiEntry('🤚', ['hand', 'stopp']), + _EmojiEntry('✋', ['hand', 'hoch']), + _EmojiEntry('🖐️', ['hand', 'finger']), + _EmojiEntry('👌', ['ok', 'prima']), + _EmojiEntry('🤌', ['finger', 'pinch']), + _EmojiEntry('✌️', ['frieden', 'victory', 'peace']), + _EmojiEntry('🤞', ['finger', 'daumen']), + _EmojiEntry('🤟', ['liebe', 'rock']), + _EmojiEntry('🤘', ['rock', 'metal']), + _EmojiEntry('👈', ['links', 'zeigen']), + _EmojiEntry('👉', ['rechts', 'zeigen']), + _EmojiEntry('👆', ['hoch', 'zeigen']), + _EmojiEntry('👇', ['runter', 'zeigen']), + _EmojiEntry('☝️', ['eins', 'oben']), + _EmojiEntry('👍', ['daumen', 'hoch', 'gut', 'like']), + _EmojiEntry('👎', ['daumen', 'runter', 'schlecht', 'dislike']), + _EmojiEntry('✊', ['faust', 'punch']), + _EmojiEntry('👊', ['faust', 'schlag']), + _EmojiEntry('🤛', ['faust', 'links']), + _EmojiEntry('🤜', ['faust', 'rechts']), + _EmojiEntry('👏', ['klatschen', 'applaus']), + _EmojiEntry('🙌', ['feiern', 'hände']), + _EmojiEntry('🤝', ['handschlag', 'vereinbarung']), + _EmojiEntry('🙏', ['bitte', 'danke', 'beten']), + _EmojiEntry('✍️', ['schreiben', 'stift']), + _EmojiEntry('💪', ['muskel', 'stark']), + _EmojiEntry('🦵', ['bein']), + _EmojiEntry('🦶', ['fuß']), + _EmojiEntry('👂', ['ohr', 'hören']), + _EmojiEntry('👃', ['nase', 'riechen']), + _EmojiEntry('🧠', ['gehirn', 'denken']), + _EmojiEntry('🦷', ['zahn']), + _EmojiEntry('👀', ['augen', 'schauen']), + _EmojiEntry('👁️', ['auge']), + _EmojiEntry('👅', ['zunge']), + _EmojiEntry('👄', ['lippen', 'kuss']), + _EmojiEntry('💋', ['kuss', 'lippen']), + _EmojiEntry('👶', ['baby']), + _EmojiEntry('🧒', ['kind']), + _EmojiEntry('👦', ['junge']), + _EmojiEntry('👧', ['mädchen']), + _EmojiEntry('🧑', ['person']), + _EmojiEntry('👱', ['blond']), + _EmojiEntry('👩', ['frau']), + _EmojiEntry('👨', ['mann']), + _EmojiEntry('🧓', ['älter']), + _EmojiEntry('👴', ['alter mann']), + _EmojiEntry('👵', ['alte frau']), + _EmojiEntry('🧑‍💻', ['programmierer', 'developer']), + _EmojiEntry('👨‍💻', ['mann', 'programmierer']), + _EmojiEntry('👩‍💻', ['frau', 'programmierin']), +]; + +const _kNature = [ + _EmojiEntry('🐶', ['hund', 'dog']), + _EmojiEntry('🐱', ['katze', 'cat']), + _EmojiEntry('🐭', ['maus', 'mouse']), + _EmojiEntry('🐹', ['hamster']), + _EmojiEntry('🐰', ['hase', 'rabbit']), + _EmojiEntry('🦊', ['fuchs', 'fox']), + _EmojiEntry('🐻', ['bär', 'bear']), + _EmojiEntry('🐼', ['panda']), + _EmojiEntry('🐨', ['koala']), + _EmojiEntry('🐯', ['tiger']), + _EmojiEntry('🦁', ['löwe', 'lion']), + _EmojiEntry('🐮', ['kuh', 'cow']), + _EmojiEntry('🐷', ['schwein', 'pig']), + _EmojiEntry('🐸', ['frosch', 'frog']), + _EmojiEntry('🐵', ['affe', 'monkey']), + _EmojiEntry('🐔', ['huhn', 'chicken']), + _EmojiEntry('🐧', ['pinguin', 'penguin']), + _EmojiEntry('🐦', ['vogel', 'bird']), + _EmojiEntry('🦆', ['ente', 'duck']), + _EmojiEntry('🦅', ['adler', 'eagle']), + _EmojiEntry('🦉', ['eule', 'owl']), + _EmojiEntry('🦇', ['fledermaus', 'bat']), + _EmojiEntry('🐺', ['wolf']), + _EmojiEntry('🐗', ['wildschwein', 'boar']), + _EmojiEntry('🐴', ['pferd', 'horse']), + _EmojiEntry('🦄', ['einhorn', 'unicorn']), + _EmojiEntry('🐝', ['biene', 'bee']), + _EmojiEntry('🐛', ['raupe', 'caterpillar']), + _EmojiEntry('🦋', ['schmetterling', 'butterfly']), + _EmojiEntry('🐌', ['schnecke', 'snail']), + _EmojiEntry('🐞', ['marienkäfer', 'ladybug']), + _EmojiEntry('🐜', ['ameise', 'ant']), + _EmojiEntry('🌸', ['kirschblüte', 'cherry blossom']), + _EmojiEntry('🌺', ['hibiskus']), + _EmojiEntry('🌻', ['sonnenblume', 'sunflower']), + _EmojiEntry('🌹', ['rose']), + _EmojiEntry('🌷', ['tulpe', 'tulip']), + _EmojiEntry('🌼', ['blume', 'flower']), + _EmojiEntry('🌿', ['pflanze', 'plant']), + _EmojiEntry('☘️', ['kleeblatt', 'shamrock']), + _EmojiEntry('🍀', ['vierblättriges', 'glück', 'luck']), + _EmojiEntry('🌲', ['baum', 'tree']), + _EmojiEntry('🌳', ['baum', 'deciduous']), + _EmojiEntry('🌴', ['palme', 'palm']), + _EmojiEntry('🌵', ['kaktus', 'cactus']), + _EmojiEntry('🌾', ['gras', 'getreide']), + _EmojiEntry('🍄', ['pilz', 'mushroom']), + _EmojiEntry('🌊', ['welle', 'wave', 'ozean']), + _EmojiEntry('⛅', ['wolken', 'sonne']), + _EmojiEntry('🌈', ['regenbogen', 'rainbow']), + _EmojiEntry('❄️', ['schnee', 'schneflocke', 'cold']), + _EmojiEntry('⭐', ['stern', 'star']), + _EmojiEntry('🌟', ['stern', 'glitzern']), + _EmojiEntry('✨', ['funken', 'glitzern', 'sparkle']), + _EmojiEntry('🔥', ['feuer', 'fire', 'heiß']), + _EmojiEntry('🌙', ['mond', 'moon']), + _EmojiEntry('☀️', ['sonne', 'sun']), +]; + +const _kFood = [ + _EmojiEntry('🍎', ['apfel', 'apple']), + _EmojiEntry('🍊', ['orange', 'mandarine']), + _EmojiEntry('🍋', ['zitrone', 'lemon']), + _EmojiEntry('🍇', ['trauben', 'grapes']), + _EmojiEntry('🍓', ['erdbeere', 'strawberry']), + _EmojiEntry('🍒', ['kirsche', 'cherry']), + _EmojiEntry('🍑', ['pfirsich', 'peach']), + _EmojiEntry('🥭', ['mango']), + _EmojiEntry('🍍', ['ananas', 'pineapple']), + _EmojiEntry('🥥', ['kokosnuss', 'coconut']), + _EmojiEntry('🍅', ['tomate', 'tomato']), + _EmojiEntry('🫐', ['blaubeere', 'blueberry']), + _EmojiEntry('🍆', ['aubergine', 'eggplant']), + _EmojiEntry('🥑', ['avocado']), + _EmojiEntry('🫑', ['paprika']), + _EmojiEntry('🌽', ['mais', 'corn']), + _EmojiEntry('🥕', ['karotte', 'carrot']), + _EmojiEntry('🧄', ['knoblauch', 'garlic']), + _EmojiEntry('🧅', ['zwiebel', 'onion']), + _EmojiEntry('🥔', ['kartoffel', 'potato']), + _EmojiEntry('🍞', ['brot', 'bread']), + _EmojiEntry('🥐', ['croissant']), + _EmojiEntry('🧀', ['käse', 'cheese']), + _EmojiEntry('🥚', ['ei', 'egg']), + _EmojiEntry('🍳', ['bratpfanne', 'kochen']), + _EmojiEntry('🥓', ['speck', 'bacon']), + _EmojiEntry('🍗', ['hühnchen', 'chicken']), + _EmojiEntry('🍖', ['fleisch', 'knochen']), + _EmojiEntry('🌭', ['hotdog']), + _EmojiEntry('🍔', ['burger', 'hamburger']), + _EmojiEntry('🍟', ['pommes', 'fries']), + _EmojiEntry('🍕', ['pizza']), + _EmojiEntry('🥪', ['sandwich']), + _EmojiEntry('🌮', ['taco']), + _EmojiEntry('🌯', ['wrap']), + _EmojiEntry('🥗', ['salat', 'salad']), + _EmojiEntry('🍜', ['nudeln', 'noodles', 'ramen']), + _EmojiEntry('🍣', ['sushi']), + _EmojiEntry('🍦', ['eis', 'softeis']), + _EmojiEntry('🎂', ['torte', 'geburtstag']), + _EmojiEntry('🍰', ['kuchen', 'cake']), + _EmojiEntry('🧁', ['muffin', 'cupcake']), + _EmojiEntry('🍩', ['donut']), + _EmojiEntry('🍪', ['keks', 'cookie']), + _EmojiEntry('🍫', ['schokolade', 'chocolate']), + _EmojiEntry('🍬', ['bonbon', 'candy']), + _EmojiEntry('☕', ['kaffee', 'coffee']), + _EmojiEntry('🍵', ['tee', 'tea']), + _EmojiEntry('🧋', ['bubble tea']), + _EmojiEntry('🥤', ['getränk', 'cup']), + _EmojiEntry('🍺', ['bier', 'beer']), + _EmojiEntry('🍻', ['bier', 'prost', 'cheers']), + _EmojiEntry('🥂', ['sekt', 'cheers', 'toast']), + _EmojiEntry('🍷', ['wein', 'wine']), + _EmojiEntry('🥃', ['whiskey']), +]; + +const _kActivities = [ + _EmojiEntry('⚽', ['fußball', 'soccer']), + _EmojiEntry('🏀', ['basketball']), + _EmojiEntry('🏈', ['american football']), + _EmojiEntry('⚾', ['baseball']), + _EmojiEntry('🎾', ['tennis']), + _EmojiEntry('🏐', ['volleyball']), + _EmojiEntry('🏉', ['rugby']), + _EmojiEntry('🥏', ['frisbee']), + _EmojiEntry('🎱', ['billard', 'pool']), + _EmojiEntry('🏓', ['tischtennis', 'ping pong']), + _EmojiEntry('🏸', ['badminton']), + _EmojiEntry('🥊', ['boxen', 'boxing']), + _EmojiEntry('🥋', ['kampfsport', 'martial arts']), + _EmojiEntry('🥅', ['tor', 'goal']), + _EmojiEntry('⛳', ['golf']), + _EmojiEntry('🎿', ['ski']), + _EmojiEntry('🛷', ['schlitten', 'sled']), + _EmojiEntry('🏆', ['pokal', 'trophy', 'gewonnen']), + _EmojiEntry('🥇', ['gold', 'erster']), + _EmojiEntry('🥈', ['silber', 'zweiter']), + _EmojiEntry('🥉', ['bronze', 'dritter']), + _EmojiEntry('🎮', ['spiel', 'gaming', 'controller']), + _EmojiEntry('🕹️', ['joystick', 'spiel']), + _EmojiEntry('🎲', ['würfel', 'dice']), + _EmojiEntry('🧩', ['puzzle']), + _EmojiEntry('🎯', ['ziel', 'dartscheibe']), + _EmojiEntry('🎳', ['bowling']), + _EmojiEntry('🎪', ['zirkus', 'circus']), + _EmojiEntry('🎨', ['kunst', 'malen', 'art']), + _EmojiEntry('🎭', ['theater', 'drama']), + _EmojiEntry('🎬', ['film', 'klappe', 'movie']), + _EmojiEntry('🎵', ['musik', 'note']), + _EmojiEntry('🎶', ['musik', 'noten']), + _EmojiEntry('🎸', ['gitarre', 'guitar']), + _EmojiEntry('🎹', ['klavier', 'piano']), + _EmojiEntry('🥁', ['schlagzeug', 'drum']), + _EmojiEntry('🎷', ['saxophon']), + _EmojiEntry('🎺', ['trompete', 'trumpet']), + _EmojiEntry('🎻', ['geige', 'violin']), + _EmojiEntry('🎤', ['mikrofon', 'microphone']), +]; + +const _kTravel = [ + _EmojiEntry('🚗', ['auto', 'car']), + _EmojiEntry('🚕', ['taxi']), + _EmojiEntry('🚙', ['suv', 'auto']), + _EmojiEntry('🚌', ['bus']), + _EmojiEntry('🚎', ['trolleybus']), + _EmojiEntry('🏎️', ['rennauto', 'racecar']), + _EmojiEntry('🚓', ['polizei', 'police']), + _EmojiEntry('🚑', ['krankenwagen', 'ambulance']), + _EmojiEntry('🚒', ['feuerwehr', 'fire truck']), + _EmojiEntry('🚐', ['minibus', 'van']), + _EmojiEntry('🛻', ['pickup']), + _EmojiEntry('🚚', ['lieferwagen', 'truck']), + _EmojiEntry('🚛', ['lkw', 'truck']), + _EmojiEntry('🏍️', ['motorrad', 'motorcycle']), + _EmojiEntry('🚲', ['fahrrad', 'bicycle', 'bike']), + _EmojiEntry('🛵', ['roller', 'scooter']), + _EmojiEntry('✈️', ['flugzeug', 'plane', 'fliegen']), + _EmojiEntry('🚀', ['rakete', 'rocket', 'space']), + _EmojiEntry('🛸', ['ufo']), + _EmojiEntry('🚁', ['hubschrauber', 'helicopter']), + _EmojiEntry('⛵', ['segelboot', 'sailboat']), + _EmojiEntry('🚢', ['schiff', 'ship']), + _EmojiEntry('🚂', ['zug', 'train']), + _EmojiEntry('🚄', ['hochgeschwindigkeitszug', 'bullet train']), + _EmojiEntry('🏠', ['haus', 'home']), + _EmojiEntry('🏡', ['haus', 'garten']), + _EmojiEntry('🏢', ['büro', 'office']), + _EmojiEntry('🏰', ['schloss', 'castle']), + _EmojiEntry('🗼', ['turm', 'eiffelturm']), + _EmojiEntry('🗽', ['freiheitsstatue']), + _EmojiEntry('🌍', ['erde', 'europa', 'africa']), + _EmojiEntry('🌎', ['erde', 'americas']), + _EmojiEntry('🌏', ['erde', 'asia']), + _EmojiEntry('🗺️', ['karte', 'map']), + _EmojiEntry('🧭', ['kompass', 'compass']), + _EmojiEntry('⛺', ['zelt', 'camping']), + _EmojiEntry('🏖️', ['strand', 'beach']), + _EmojiEntry('🏔️', ['berg', 'mountain']), + _EmojiEntry('🌋', ['vulkan', 'volcano']), +]; + +const _kObjects = [ + _EmojiEntry('💡', ['idee', 'licht', 'light', 'lamp']), + _EmojiEntry('🔦', ['taschenlampe', 'flashlight']), + _EmojiEntry('💻', ['laptop', 'computer']), + _EmojiEntry('🖥️', ['monitor', 'desktop']), + _EmojiEntry('🖨️', ['drucker', 'printer']), + _EmojiEntry('⌨️', ['tastatur', 'keyboard']), + _EmojiEntry('🖱️', ['maus', 'mouse']), + _EmojiEntry('📱', ['handy', 'phone', 'smartphone']), + _EmojiEntry('☎️', ['telefon', 'phone']), + _EmojiEntry('📞', ['telefon', 'anruf', 'call']), + _EmojiEntry('📷', ['kamera', 'camera']), + _EmojiEntry('📸', ['foto', 'kamera', 'selfie']), + _EmojiEntry('📹', ['video', 'kamera']), + _EmojiEntry('🎥', ['film', 'kamera', 'movie']), + _EmojiEntry('📺', ['tv', 'fernseher', 'television']), + _EmojiEntry('📻', ['radio']), + _EmojiEntry('🎙️', ['mikrofon', 'microphone']), + _EmojiEntry('📡', ['satellit', 'satellite']), + _EmojiEntry('🔋', ['batterie', 'battery']), + _EmojiEntry('🔌', ['stecker', 'plug']), + _EmojiEntry('💾', ['diskette', 'speichern', 'save']), + _EmojiEntry('💿', ['cd', 'disk']), + _EmojiEntry('📀', ['dvd', 'disc']), + _EmojiEntry('📁', ['ordner', 'folder']), + _EmojiEntry('📂', ['ordner', 'offen']), + _EmojiEntry('📄', ['datei', 'dokument', 'file']), + _EmojiEntry('📃', ['seite', 'dokument']), + _EmojiEntry('📋', ['zwischenablage', 'clipboard']), + _EmojiEntry('📊', ['grafik', 'diagramm', 'chart']), + _EmojiEntry('📈', ['aufwärts', 'wachstum', 'chart']), + _EmojiEntry('📉', ['abwärts', 'rückgang', 'chart']), + _EmojiEntry('📌', ['pin', 'nadel']), + _EmojiEntry('📍', ['ort', 'pin', 'location']), + _EmojiEntry('✏️', ['stift', 'pen']), + _EmojiEntry('✒️', ['füllfeder', 'pen']), + _EmojiEntry('🖊️', ['kugelschreiber', 'pen']), + _EmojiEntry('📝', ['notiz', 'memo', 'schreiben']), + _EmojiEntry('📚', ['bücher', 'books']), + _EmojiEntry('📖', ['buch', 'lesen']), + _EmojiEntry('🔑', ['schlüssel', 'key']), + _EmojiEntry('🔒', ['schloss', 'lock']), + _EmojiEntry('🔓', ['offen', 'unlock']), + _EmojiEntry('🔨', ['hammer']), + _EmojiEntry('🪛', ['schraubenzieher']), + _EmojiEntry('⚙️', ['zahnrad', 'einstellungen', 'settings']), + _EmojiEntry('🧲', ['magnet']), + _EmojiEntry('🔭', ['teleskop', 'telescope']), + _EmojiEntry('🔬', ['mikroskop', 'microscope']), + _EmojiEntry('💊', ['pille', 'medikament']), + _EmojiEntry('🩺', ['stethoskop', 'arzt']), + _EmojiEntry('🧪', ['reagenzglas', 'experiment']), + _EmojiEntry('💰', ['geld', 'tasche', 'money']), + _EmojiEntry('💳', ['karte', 'kreditkarte']), + _EmojiEntry('🎁', ['geschenk', 'present']), + _EmojiEntry('🎀', ['schleife', 'ribbon']), + _EmojiEntry('🧨', ['feuerwerk', 'cracker']), + _EmojiEntry('🎉', ['feier', 'party', 'celebration']), + _EmojiEntry('🎊', ['konfetti', 'party']), + _EmojiEntry('🏮', ['laterne', 'lantern']), + _EmojiEntry('⌚', ['uhr', 'watch', 'zeit']), + _EmojiEntry('📅', ['kalender', 'calendar']), + _EmojiEntry('⏰', ['wecker', 'alarm']), + _EmojiEntry('⏳', ['sanduhr', 'hourglass']), +]; + +const _kSymbols = [ + _EmojiEntry('❤️', ['herz', 'liebe', 'love', 'heart']), + _EmojiEntry('🧡', ['orange', 'herz']), + _EmojiEntry('💛', ['gelb', 'herz']), + _EmojiEntry('💚', ['grün', 'herz']), + _EmojiEntry('💙', ['blau', 'herz']), + _EmojiEntry('💜', ['lila', 'herz']), + _EmojiEntry('🖤', ['schwarz', 'herz']), + _EmojiEntry('🤍', ['weiß', 'herz']), + _EmojiEntry('🤎', ['braun', 'herz']), + _EmojiEntry('💔', ['gebrochenes herz', 'broken heart']), + _EmojiEntry('❣️', ['herz', 'ausrufezeichen']), + _EmojiEntry('💕', ['zwei herzen', 'love']), + _EmojiEntry('💞', ['herzen', 'drehend']), + _EmojiEntry('💓', ['herz', 'schlagen']), + _EmojiEntry('💗', ['herz', 'wachsend']), + _EmojiEntry('💖', ['herz', 'glitzer']), + _EmojiEntry('💝', ['herz', 'schleife']), + _EmojiEntry('💘', ['herz', 'pfeil', 'cupid']), + _EmojiEntry('💟', ['herz', 'dekoration']), + _EmojiEntry('☮️', ['frieden', 'peace']), + _EmojiEntry('✝️', ['kreuz', 'christian']), + _EmojiEntry('☯️', ['yin yang']), + _EmojiEntry('🔴', ['rot', 'kreis', 'red']), + _EmojiEntry('🟠', ['orange', 'kreis']), + _EmojiEntry('🟡', ['gelb', 'kreis']), + _EmojiEntry('🟢', ['grün', 'kreis']), + _EmojiEntry('🔵', ['blau', 'kreis']), + _EmojiEntry('🟣', ['lila', 'kreis']), + _EmojiEntry('⚫', ['schwarz', 'kreis']), + _EmojiEntry('⚪', ['weiß', 'kreis']), + _EmojiEntry('🟤', ['braun', 'kreis']), + _EmojiEntry('🔺', ['rot', 'dreieck']), + _EmojiEntry('🔻', ['rot', 'dreieck', 'runter']), + _EmojiEntry('♾️', ['unendlich', 'infinity']), + _EmojiEntry('✅', ['haken', 'check', 'ok', 'ja']), + _EmojiEntry('❌', ['x', 'nein', 'falsch', 'close']), + _EmojiEntry('❎', ['x', 'kreuz', 'nein']), + _EmojiEntry('⭕', ['kreis', 'richtig']), + _EmojiEntry('🚫', ['verboten', 'nein']), + _EmojiEntry('⚠️', ['warnung', 'warning']), + _EmojiEntry('🔞', ['verboten', '18+']), + _EmojiEntry('❗', ['ausrufezeichen', 'wichtig']), + _EmojiEntry('❓', ['fragezeichen', 'frage']), + _EmojiEntry('💯', ['100', 'perfekt', 'perfect']), + _EmojiEntry('🆗', ['ok', 'schaltfläche']), + _EmojiEntry('🆕', ['neu', 'new']), + _EmojiEntry('🆙', ['up']), + _EmojiEntry('🔝', ['top', 'oben']), + _EmojiEntry('🔛', ['an']), + _EmojiEntry('🔜', ['bald', 'soon']), + _EmojiEntry('🔚', ['ende', 'end']), + _EmojiEntry('♻️', ['recycling', 'wiederverwertung']), + _EmojiEntry('💲', ['dollar', 'geld']), + _EmojiEntry('©️', ['copyright']), + _EmojiEntry('®️', ['eingetragen', 'trademark']), + _EmojiEntry('™️', ['markenzeichen', 'trademark']), + _EmojiEntry('🔔', ['glocke', 'bell', 'benachrichtigung']), + _EmojiEntry('🔕', ['stille', 'no bell']), + _EmojiEntry('🎵', ['musik', 'note']), + _EmojiEntry('🎶', ['musik', 'noten']), + _EmojiEntry('#️⃣', ['raute', 'hash', 'hashtag']), + _EmojiEntry('*️⃣', ['stern', 'asterisk']), + _EmojiEntry('0️⃣', ['null', 'zero']), + _EmojiEntry('1️⃣', ['eins', 'one']), + _EmojiEntry('2️⃣', ['zwei', 'two']), + _EmojiEntry('3️⃣', ['drei', 'three']), +]; diff --git a/lib/features/chat/gif_sticker_picker.dart b/lib/features/chat/gif_sticker_picker.dart new file mode 100644 index 0000000..eb18cb3 --- /dev/null +++ b/lib/features/chat/gif_sticker_picker.dart @@ -0,0 +1,696 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:http/http.dart' as http; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/utils/gif_favorite_service.dart'; + +const _giphyApiKey = 'QtEyHWSKVIZJersKNBbJGYIgOhwawjkk'; +const _stickerServerUrl = 'https://stickers.steggi-matrix.work'; + +class GifStickerPicker extends StatefulWidget { + final Room room; + final VoidCallback onClose; + + const GifStickerPicker({ + super.key, + required this.room, + required this.onClose, + }); + + @override + State createState() => _GifStickerPickerState(); +} + +class _GifStickerPickerState extends State + with SingleTickerProviderStateMixin { + late TabController _tabController; + final _searchController = TextEditingController(); + final _customUrlController = TextEditingController(); + final _gifScrollController = ScrollController(); + final _packSelectorScroll = ScrollController(); + + List _gifs = []; + bool _gifLoading = false; + int _gifOffset = 0; + int _gifTotal = 0; + String _gifQuery = ''; + int? _hoveredGifIndex; + int? _hoveredFavIndex; + + static const _kFavsPack = '__favs__'; + static const _kMyPack = '__my__'; + + List _packs = []; + final Map _packData = {}; + String? _selectedPack; + bool _stickerLoading = false; + bool _packLoading = false; + PyramidTheme? _pt; + + List get _allPackTabs { + final tabs = []; + if (GifFavoriteService.stickerFavoritesItems.isNotEmpty) tabs.add(_kFavsPack); + if (GifFavoriteService.userStickerItems.isNotEmpty) tabs.add(_kMyPack); + tabs.addAll(_packs); + return tabs; + } + + void _selectDefaultTab() { + final tabs = _allPackTabs; + if (tabs.isNotEmpty && (_selectedPack == null || !tabs.contains(_selectedPack))) { + setState(() => _selectedPack = tabs.first); + } + } + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + _gifScrollController.addListener(_onGifScroll); + _loadTrendingGifs(); + GifFavoriteService.load().then((_) => setState(() {})); + GifFavoriteService.loadStickers().then((_) { + _selectDefaultTab(); + setState(() {}); + }); + _loadStickerPacks(); + } + + @override + void dispose() { + _tabController.dispose(); + _searchController.dispose(); + _customUrlController.dispose(); + _gifScrollController.dispose(); + _packSelectorScroll.dispose(); + super.dispose(); + } + + void _onGifScroll() { + if (_gifScrollController.position.pixels >= + _gifScrollController.position.maxScrollExtent - 300) { + if (!_gifLoading && _gifOffset < _gifTotal) _loadMoreGifs(); + } + } + + Future _loadTrendingGifs() async { + setState(() { _gifLoading = true; _gifs = []; _gifOffset = 0; _gifQuery = ''; }); + try { + final res = await http.get(Uri.parse( + 'https://api.giphy.com/v1/gifs/trending?api_key=$_giphyApiKey&limit=24&offset=0', + )); + final data = jsonDecode(res.body); + setState(() { + _gifs = data['data'] ?? []; + _gifTotal = data['pagination']?['total_count'] ?? 0; + _gifOffset = _gifs.length; + _gifLoading = false; + }); + } catch (_) { + setState(() => _gifLoading = false); + } + } + + Future _searchGifs(String query) async { + if (query.isEmpty) { _loadTrendingGifs(); return; } + setState(() { _gifLoading = true; _gifs = []; _gifOffset = 0; _gifQuery = query; }); + try { + final res = await http.get(Uri.parse( + 'https://api.giphy.com/v1/gifs/search?api_key=$_giphyApiKey&q=${Uri.encodeComponent(query)}&limit=24&offset=0', + )); + final data = jsonDecode(res.body); + setState(() { + _gifs = data['data'] ?? []; + _gifTotal = data['pagination']?['total_count'] ?? 0; + _gifOffset = _gifs.length; + _gifLoading = false; + }); + } catch (_) { + setState(() => _gifLoading = false); + } + } + + Future _loadMoreGifs() async { + if (_gifLoading) return; + setState(() => _gifLoading = true); + try { + final url = _gifQuery.isEmpty + ? 'https://api.giphy.com/v1/gifs/trending?api_key=$_giphyApiKey&limit=24&offset=$_gifOffset' + : 'https://api.giphy.com/v1/gifs/search?api_key=$_giphyApiKey&q=${Uri.encodeComponent(_gifQuery)}&limit=24&offset=$_gifOffset'; + final res = await http.get(Uri.parse(url)); + final data = jsonDecode(res.body); + setState(() { + _gifs.addAll(data['data'] ?? []); + _gifOffset = _gifs.length; + _gifLoading = false; + }); + } catch (_) { + setState(() => _gifLoading = false); + } + } + + Future _toggleGifFav(String url, String previewUrl, String title) async { + await GifFavoriteService.toggle(url, previewUrl, title); + setState(() {}); + } + + Future _loadStickerPacks() async { + setState(() => _stickerLoading = true); + try { + final userId = widget.room.client.userID ?? ''; + final res = await http.get(Uri.parse( + '$_stickerServerUrl/packs/index.json?userId=${Uri.encodeComponent(userId)}', + )); + final data = jsonDecode(res.body); + final packs = List.from(data['packs'] ?? []) + .where((p) => !p.startsWith('__')) + .toList(); + setState(() { _packs = packs; _stickerLoading = false; }); + _selectDefaultTab(); + if (_selectedPack != null && _selectedPack != _kFavsPack && _selectedPack != _kMyPack) { + await _loadPack(_selectedPack!); + } + } catch (_) { + setState(() => _stickerLoading = false); + } + } + + Future _loadPack(String packId) async { + if (_packData.containsKey(packId)) return; + setState(() => _packLoading = true); + try { + final res = await http.get(Uri.parse('$_stickerServerUrl/packs/$packId/pack.json')); + setState(() { _packData[packId] = jsonDecode(res.body); _packLoading = false; }); + } catch (_) { + setState(() => _packLoading = false); + } + } + + Future _sendGif(String url, String title) async { + widget.onClose(); + await widget.room.sendEvent({ + 'msgtype': 'm.image', + 'body': title.isNotEmpty ? title : 'GIF', + 'url': url, + 'info': {'mimetype': 'image/gif'}, + }); + } + + Future _sendSticker(String mxcUrl, String body, Map info) async { + widget.onClose(); + await widget.room.sendEvent( + {'body': body, 'url': mxcUrl, 'info': info}, + type: EventTypes.Sticker, + ); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + _pt = pt; + return Container( + width: 380, + height: 460, + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: pt.border), + boxShadow: const [ + BoxShadow(color: Color(0x50000000), blurRadius: 24, offset: Offset(0, 8)) + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Column( + children: [ + // Header with tabs + Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: TabBar( + controller: _tabController, + indicatorColor: pt.accent, + labelColor: pt.accent, + unselectedLabelColor: pt.fgMuted, + tabs: const [ + Tab(icon: Icon(Icons.gif_box_outlined, size: 20)), + Tab(icon: Icon(Icons.sticky_note_2_outlined, size: 20)), + ], + ), + ), + Expanded( + child: TabBarView( + controller: _tabController, + children: [_buildGifTab(), _buildStickerTab()], + ), + ), + ], + ), + ), + ); + } + + // ── GIF Tab ────────────────────────────────────────────────────────────── + + Widget _buildGifTab() { + final favorites = GifFavoriteService.cache; + final isSearching = _gifQuery.isNotEmpty; + + return Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 4), + child: TextField( + controller: _searchController, + style: TextStyle(color: _pt!.fg, fontSize: 13), + decoration: InputDecoration( + hintText: 'GIFs suchen…', + hintStyle: TextStyle(color: _pt!.fgDim, fontSize: 13), + prefixIcon: Icon(Icons.search, size: 16, color: _pt!.fgDim), + isDense: true, + suffixIcon: _searchController.text.isNotEmpty + ? IconButton( + icon: Icon(Icons.clear, size: 16, color: _pt!.fgDim), + onPressed: () { + _searchController.clear(); + setState(() {}); + _loadTrendingGifs(); + }, + ) + : null, + contentPadding: const EdgeInsets.symmetric(vertical: 8), + filled: true, + fillColor: _pt!.bg2, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: _pt!.border)), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: _pt!.border)), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: _pt!.accent)), + ), + onChanged: (v) => setState(() {}), + onSubmitted: _searchGifs, + ), + ), + Expanded( + child: _gifLoading && _gifs.isEmpty + ? Center(child: CircularProgressIndicator(color: _pt!.accent)) + : CustomScrollView( + controller: _gifScrollController, + slivers: [ + if (!isSearching && favorites.isNotEmpty) ...[ + SliverToBoxAdapter(child: _SectionLabel('❤ Favoriten')), + _gifGrid( + count: favorites.length, + builder: (i) { + final fav = favorites[i]; + final url = fav['url'] ?? ''; + final preview = fav['preview_url'] ?? url; + final title = fav['title'] ?? 'GIF'; + return _GifCell( + imageUrl: preview, + isFavorite: true, + isHovered: _hoveredFavIndex == i, + onHoverChanged: (h) => setState(() => _hoveredFavIndex = h ? i : null), + onTap: () => _sendGif(url, title), + onFavToggle: () => _toggleGifFav(url, preview, title), + ); + }, + ), + SliverToBoxAdapter(child: _SectionLabel('Trending')), + ], + _gifGrid( + count: _gifs.length, + builder: (i) { + final gif = _gifs[i]; + final preview = gif['images']?['fixed_height_small']?['url'] ?? gif['images']?['fixed_height']?['url'] ?? ''; + final full = gif['images']?['fixed_height']?['url'] ?? ''; + final title = gif['title'] ?? 'GIF'; + final fav = GifFavoriteService.isFavorite(full); + return _GifCell( + imageUrl: preview, + isFavorite: fav, + isHovered: _hoveredGifIndex == i, + onHoverChanged: (h) => setState(() => _hoveredGifIndex = h ? i : null), + onTap: () => _sendGif(full, title), + onFavToggle: () => _toggleGifFav(full, preview, title), + ); + }, + ), + if (_gifLoading) + SliverToBoxAdapter( + child: Padding( + padding: const EdgeInsets.all(12), + child: Center(child: CircularProgressIndicator( + strokeWidth: 2, color: _pt!.accent)), + ), + ), + ], + ), + ), + ], + ); + } + + SliverGrid _gifGrid({required int count, required Widget Function(int) builder}) => + SliverGrid( + delegate: SliverChildBuilderDelegate((ctx, i) => builder(i), childCount: count), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 3, crossAxisSpacing: 2, mainAxisSpacing: 2, childAspectRatio: 1, + ), + ); + + // ── Sticker Tab ────────────────────────────────────────────────────────── + + Widget _buildStickerTab() { + final allTabs = _allPackTabs; + if (_stickerLoading) { + return Center(child: CircularProgressIndicator(color: _pt!.accent)); + } + if (allTabs.isEmpty) { + return Center(child: Text('Keine Sticker verfügbar', style: TextStyle(color: _pt!.fgMuted))); + } + final selected = (allTabs.contains(_selectedPack) ? _selectedPack : allTabs.first)!; + + return Column( + children: [ + SizedBox( + height: 38, + child: ListView.builder( + controller: _packSelectorScroll, + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 4), + itemCount: allTabs.length, + itemBuilder: (context, index) { + final tab = allTabs[index]; + final isSelected = tab == selected; + String label = tab == _kFavsPack ? '⭐ Favoriten' : tab == _kMyPack ? '🎨 Meine' : (_packData[tab]?['title'] as String? ?? tab); + return Padding( + padding: const EdgeInsets.only(right: 6), + child: GestureDetector( + onTap: () async { + setState(() => _selectedPack = tab); + if (tab != _kFavsPack && tab != _kMyPack) await _loadPack(tab); + }, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 2), + decoration: BoxDecoration( + color: isSelected ? _pt!.accentSoft : Colors.transparent, + borderRadius: BorderRadius.circular(14), + border: Border.all( + color: isSelected ? _pt!.accent : _pt!.border, + ), + ), + child: Text(label, + style: TextStyle( + fontSize: 11, + color: isSelected ? _pt!.accent : _pt!.fgMuted, + )), + ), + ), + ); + }, + ), + ), + Container(height: 1, color: _pt!.border), + Expanded( + child: selected == _kFavsPack + ? _buildStickerGrid(GifFavoriteService.stickerFavoritesItems) + : selected == _kMyPack + ? _buildStickerGrid(GifFavoriteService.userStickerItems, isMyStickers: true) + : _buildPackGrid(selected), + ), + ], + ); + } + + Widget _buildStickerGrid(List> items, {bool isMyStickers = false}) { + if (items.isEmpty) { + return Center(child: Text('Keine Sticker', style: TextStyle(color: _pt!.fgMuted))); + } + return GridView.builder( + padding: const EdgeInsets.all(4), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, crossAxisSpacing: 3, mainAxisSpacing: 3, + ), + itemCount: items.length, + itemBuilder: (ctx, i) { + final s = items[i]; + final piUrl = s['url'] as String? ?? ''; + final sendMxc = (s['mxc'] as String?)?.isNotEmpty == true + ? s['mxc'] as String + : (s['mxc_source'] as String? ?? ''); + final mxcSource = s['mxc_source'] as String? ?? ''; + final title = s['title'] as String? ?? 'Sticker'; + final info = {'mimetype': s['mimetype'] ?? 'image/webp'}; + final isUserSticker = s['user_sticker'] == true; + + return _StickerCell( + piUrl: piUrl, + isFavorited: s['favorited'] == true, + showHeart: isMyStickers && isUserSticker, + onTap: () => _sendSticker(sendMxc, title, info), + onToggleFavorite: (isMyStickers && isUserSticker) + ? () async { + final newFav = !(s['favorited'] == true); + await GifFavoriteService.setUserStickerFavorited(mxcSource, newFav); + if (mounted) setState(() {}); + } + : null, + ); + }, + ); + } + + Widget _buildPackGrid(String packId) { + if (_packLoading) { + return Center(child: CircularProgressIndicator(color: _pt!.accent)); + } + final stickers = (_packData[packId]?['stickers'] as List?) ?? []; + if (stickers.isEmpty) { + return Center(child: Text('Leer', style: TextStyle(color: _pt!.fgMuted))); + } + return GridView.builder( + padding: const EdgeInsets.all(4), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 4, crossAxisSpacing: 3, mainAxisSpacing: 3, + ), + itemCount: stickers.length, + itemBuilder: (ctx, i) { + final s = stickers[i]; + final id = s['id']?.toString() ?? ''; + final thumbUrl = '$_stickerServerUrl/packs/$packId/${id}_thumb.png'; + final mxcUrl = (s['url'] as String?) ?? ''; + final body = (s['body'] as String?) ?? ''; + final mimetype = (s['info']?['mimetype'] as String?) ?? 'image/webp'; + final info = Map.from(s['info'] as Map? ?? {}); + + final isFav = GifFavoriteService.isStickerFavorite(mxcUrl); + + return GestureDetector( + onTap: () => _sendSticker(mxcUrl, body, info), + onLongPressStart: (details) { + final dx = details.globalPosition.dx; + final dy = details.globalPosition.dy; + final screen = MediaQuery.sizeOf(context); + showMenu( + context: context, + position: RelativeRect.fromLTRB( + dx, dy, screen.width - dx, screen.height - dy, + ), + items: [ + PopupMenuItem( + value: 'fav', + child: Row(children: [ + Icon( + isFav ? Icons.favorite_border : Icons.favorite, + size: 16, + color: isFav ? _pt!.fgMuted : Colors.red, + ), + const SizedBox(width: 8), + Text( + isFav ? 'Aus Favoriten entfernen' : 'Zu Favoriten hinzufügen', + style: TextStyle(color: _pt!.fg, fontSize: 14), + ), + ]), + ), + ], + ).then((val) async { + if (val == 'fav') { + await GifFavoriteService.togglePackStickerFavorite( + mxcUrl: mxcUrl, + thumbUrl: thumbUrl, + title: body, + mimetype: mimetype, + ); + if (mounted) setState(() {}); + } + }); + }, + child: ClipRRect( + borderRadius: BorderRadius.circular(6), + child: Image.network( + thumbUrl, + fit: BoxFit.contain, + errorBuilder: (_, __, ___) => Container(color: _pt!.bg2), + ), + ), + ); + }, + ); + } +} + +class _StickerCell extends StatefulWidget { + final String piUrl; + final bool isFavorited; + final bool showHeart; + final VoidCallback onTap; + final Future Function()? onToggleFavorite; + + const _StickerCell({ + required this.piUrl, + required this.isFavorited, + required this.showHeart, + required this.onTap, + this.onToggleFavorite, + }); + + @override + State<_StickerCell> createState() => _StickerCellState(); +} + +class _StickerCellState extends State<_StickerCell> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final showOverlay = widget.showHeart && (_hovered || widget.isFavorited); + + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: ClipRRect( + borderRadius: BorderRadius.circular(6), + child: Stack( + fit: StackFit.expand, + children: [ + Image.network( + widget.piUrl, + fit: BoxFit.contain, + errorBuilder: (_, __, ___) => Container(color: pt.bg2), + ), + if (showOverlay) + Positioned( + top: 4, + right: 4, + child: GestureDetector( + onTap: widget.onToggleFavorite, + behavior: HitTestBehavior.opaque, + child: Container( + width: 22, + height: 22, + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.5), + shape: BoxShape.circle, + ), + child: Icon( + widget.isFavorited ? Icons.favorite : Icons.favorite_border, + color: widget.isFavorited ? Colors.red : Colors.white, + size: 13, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +class _SectionLabel extends StatelessWidget { + final String title; + const _SectionLabel(this.title); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 4), + child: Text(title, + style: TextStyle(color: PyramidColors.fgDim, + fontSize: 10, + fontWeight: FontWeight.w700, + letterSpacing: 0.6)), + ); + } +} + +class _GifCell extends StatelessWidget { + final String imageUrl; + final bool isFavorite; + final bool isHovered; + final ValueChanged onHoverChanged; + final VoidCallback onTap; + final VoidCallback onFavToggle; + + const _GifCell({ + required this.imageUrl, + required this.isFavorite, + required this.isHovered, + required this.onHoverChanged, + required this.onTap, + required this.onFavToggle, + }); + + @override + Widget build(BuildContext context) { + return MouseRegion( + onEnter: (_) => onHoverChanged(true), + onExit: (_) => onHoverChanged(false), + child: GestureDetector( + onTap: onTap, + child: ClipRRect( + borderRadius: BorderRadius.circular(4), + child: Stack( + fit: StackFit.expand, + children: [ + Image.network(imageUrl, fit: BoxFit.cover, + errorBuilder: (_, __, ___) => Container(color: PyramidTheme.of(context).bg3)), + if (isHovered || isFavorite) + Positioned( + top: 4, right: 4, + child: GestureDetector( + onTap: onFavToggle, + behavior: HitTestBehavior.opaque, + child: Container( + width: 22, height: 22, + decoration: BoxDecoration( + color: Colors.black.withValues(alpha: 0.5), + shape: BoxShape.circle, + ), + child: Icon( + isFavorite ? Icons.favorite : Icons.favorite_border, + color: isFavorite ? Colors.red : Colors.white, + size: 13, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} diff --git a/lib/features/chat/media_player.dart b/lib/features/chat/media_player.dart new file mode 100644 index 0000000..d5236cf --- /dev/null +++ b/lib/features/chat/media_player.dart @@ -0,0 +1,904 @@ +import 'dart:io'; +import 'dart:math' as math; +import 'dart:typed_data'; + +import 'package:flutter/material.dart'; +import 'package:media_kit/media_kit.dart'; +import 'package:media_kit_video/media_kit_video.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/media_viewer.dart'; + +// ─── Audio Player ───────────────────────────────────────────────────────────── +// +// isVoice=true → compact row (Sprachnachricht in Chat) +// isVoice=false → defaultBars card mit Waveform (Audiodatei) + +class PyramidAudioPlayer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + final bool isVoice; + + const PyramidAudioPlayer({ + super.key, + required this.bytes, + required this.filename, + required this.pt, + this.isVoice = false, + }); + + @override + State createState() => _PyramidAudioPlayerState(); +} + +class _PyramidAudioPlayerState extends State { + late final Player _player; + bool _loading = true; + double _speed = 1.0; + + static const _speeds = [1.0, 1.5, 2.0]; + + @override + void initState() { + super.initState(); + _player = Player(); + _init(); + } + + Future _init() async { + final ext = widget.filename.contains('.') ? widget.filename.split('.').last : 'ogg'; + final dir = await getTemporaryDirectory(); + final file = File('${dir.path}/pyr_audio_${widget.bytes.hashCode}.$ext'); + await file.writeAsBytes(widget.bytes); + await _player.open(Media('file://${file.path}'), play: false); + if (mounted) setState(() => _loading = false); + } + + @override + void dispose() { + _player.dispose(); + super.dispose(); + } + + String _fmt(Duration d) { + final m = d.inMinutes.remainder(60); + final s = d.inSeconds.remainder(60).toString().padLeft(2, '0'); + return '$m:$s'; + } + + void _seek(Duration to) => _player.seek(to); + void _skipBack() => _player.seek(_player.state.position - const Duration(seconds: 10)); + void _skipForward() => _player.seek(_player.state.position + const Duration(seconds: 10)); + void _setSpeed(double s) { setState(() => _speed = s); _player.setRate(s); } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + if (_loading) return _buildLoading(pt); + + return StreamBuilder( + stream: _player.stream.playing, + builder: (_, playSnap) => StreamBuilder( + stream: _player.stream.position, + builder: (_, posSnap) => StreamBuilder( + stream: _player.stream.duration, + builder: (_, durSnap) => StreamBuilder( + stream: _player.stream.volume, + builder: (_, volSnap) { + final playing = playSnap.data ?? false; + final pos = posSnap.data ?? Duration.zero; + final dur = durSnap.data ?? Duration.zero; + final vol = (volSnap.data ?? 100.0) / 100.0; + return widget.isVoice + ? _buildCompact(pt, playing, pos, dur) + : _buildDefaultBars(pt, playing, pos, dur, vol); + }, + ), + ), + ), + ); + } + + Widget _buildLoading(PyramidTheme pt) => Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + constraints: const BoxConstraints(maxWidth: 340), + decoration: BoxDecoration( + color: pt.bg1, border: Border.all(color: pt.border), + borderRadius: BorderRadius.circular(pt.rLg), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + SizedBox(width: 32, height: 32, + child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + const SizedBox(width: 12), + Text('Lade…', style: TextStyle(color: pt.fgMuted, fontSize: 12)), + ]), + ); + + // ── Compact: Sprachnachricht ─────────────────────────────────────────────── + + Widget _buildCompact(PyramidTheme pt, bool playing, Duration pos, Duration dur) { + final progress = dur.inMilliseconds == 0 + ? 0.0 : pos.inMilliseconds / dur.inMilliseconds; + final title = widget.filename.contains('.') + ? widget.filename.split('.').first : widget.filename; + + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + padding: const EdgeInsets.fromLTRB(12, 12, 14, 12), + constraints: const BoxConstraints(maxWidth: 340), + decoration: BoxDecoration( + color: pt.bg1, border: Border.all(color: pt.border), + borderRadius: BorderRadius.circular(pt.rLg), + ), + child: Row(children: [ + _AArtwork(size: 36, accent: pt.accent), + const SizedBox(width: 10), + Flexible(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, + children: [ + Text(title, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + Text('Sprachnachricht', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ], + )), + const SizedBox(width: 10), + _APlayButton(playing: playing, onTap: () => playing ? _player.pause() : _player.play(), + size: 32, accent: pt.accent, accentGlow: pt.accentGlow), + const SizedBox(width: 10), + Text(_fmt(pos), style: TextStyle(color: pt.fgDim, fontSize: 11, letterSpacing: 0.3)), + const SizedBox(width: 8), + Expanded(child: _AScrubber(progress: progress, accent: pt.accent, track: pt.bg3, + onSeek: (f) => _seek(Duration(milliseconds: (dur.inMilliseconds * f).round())))), + const SizedBox(width: 8), + Text(_fmt(dur), style: TextStyle(color: pt.fgDim, fontSize: 11, letterSpacing: 0.3)), + ]), + ); + } + + // ── DefaultBars: Audiodatei mit Waveform ─────────────────────────────────── + + Widget _buildDefaultBars(PyramidTheme pt, bool playing, Duration pos, Duration dur, double vol) { + final progress = dur.inMilliseconds == 0 ? 0.0 : pos.inMilliseconds / dur.inMilliseconds; + final nameParts = widget.filename.split('.'); + final title = nameParts.length > 1 + ? nameParts.sublist(0, nameParts.length - 1).join('.') : widget.filename; + final ext = nameParts.length > 1 ? nameParts.last.toUpperCase() : 'AUDIO'; + final remaining = pos <= dur ? dur - pos : Duration.zero; + + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + padding: const EdgeInsets.fromLTRB(20, 18, 20, 18), + constraints: const BoxConstraints(maxWidth: 380), + decoration: BoxDecoration( + color: pt.bg1, border: Border.all(color: pt.border), + borderRadius: BorderRadius.circular(pt.rLg), + ), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + // ── Header ─────────────────────────────────────────────────────────── + Row(children: [ + _AArtwork(size: 48, accent: pt.accent), + const SizedBox(width: 14), + Expanded(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, mainAxisSize: MainAxisSize.min, + children: [ + Text(title, style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + Text(ext, style: TextStyle(color: pt.fgMuted, fontSize: 12)), + ], + )), + ]), + const SizedBox(height: 14), + + // ── Waveform ───────────────────────────────────────────────────────── + LayoutBuilder(builder: (_, c) => GestureDetector( + onTapDown: (d) { + final f = (d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0); + _seek(Duration(milliseconds: (dur.inMilliseconds * f).round())); + }, + onPanUpdate: (d) { + final f = (d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0); + _seek(Duration(milliseconds: (dur.inMilliseconds * f).round())); + }, + child: SizedBox(height: 40, child: CustomPaint( + painter: _ChunkyBarsPainter( + progress: progress, + played: pt.accent, unplayed: pt.bg3, cursor: pt.fg, + ), + size: Size.infinite, + )), + )), + const SizedBox(height: 8), + + // ── Zeitanzeige ────────────────────────────────────────────────────── + Row(mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ + Text(_fmt(pos), style: TextStyle(color: pt.fgDim, fontSize: 11, letterSpacing: 0.3)), + Text('−${_fmt(remaining)}', style: TextStyle(color: pt.fgDim, fontSize: 11, letterSpacing: 0.3)), + ]), + const SizedBox(height: 14), + + // ── Steuerung ──────────────────────────────────────────────────────── + Row(children: [ + Icon(Icons.volume_up_outlined, size: 16, color: pt.fgMuted), + const SizedBox(width: 6), + SizedBox(width: 64, child: _AMiniBar(value: vol, track: pt.bg3, fill: pt.fgMuted)), + const Spacer(), + _AIconBtn(icon: Icons.replay_10, color: pt.fgMuted, rSm: pt.rSm, onTap: _skipBack), + const SizedBox(width: 4), + _APlayButton( + playing: playing, + onTap: () => playing ? _player.pause() : _player.play(), + size: 40, accent: pt.accent, accentGlow: pt.accentGlow, + ), + const SizedBox(width: 4), + _AIconBtn(icon: Icons.forward_10, color: pt.fgMuted, rSm: pt.rSm, onTap: _skipForward), + const Spacer(), + ..._speeds.map((s) => _ASpeedPill( + label: '${s == s.toInt() ? s.toInt() : s}x', + active: _speed == s, + accent: pt.accent, accentSoft: pt.accentSoft, + bg: pt.bg2, fgMuted: pt.fgMuted, rSm: pt.rSm, + onTap: () => _setSpeed(s), + )), + ]), + ]), + ); + } +} + +// ─── Audio: Bausteine ──────────────────────────────────────────────────────── + +class _AArtwork extends StatelessWidget { + final double size; + final Color accent; + const _AArtwork({required this.size, required this.accent}); + + @override + Widget build(BuildContext context) { + final hsl = HSLColor.fromColor(accent); + final c1 = hsl.withLightness((hsl.lightness - 0.08).clamp(0.0, 1.0)).toColor(); + final c2 = hsl.withHue((hsl.hue + 30) % 360) + .withLightness((hsl.lightness - 0.18).clamp(0.0, 1.0)).toColor(); + return Container( + width: size, height: size, + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(size * 0.3), + gradient: LinearGradient(begin: Alignment.topLeft, end: Alignment.bottomRight, colors: [c1, c2]), + ), + child: Icon(Icons.music_note, color: Colors.white.withOpacity(0.85), size: size * 0.48), + ); + } +} + +class _APlayButton extends StatelessWidget { + final bool playing; + final VoidCallback? onTap; + final double size; + final Color accent, accentGlow; + const _APlayButton({required this.playing, this.onTap, required this.size, + required this.accent, required this.accentGlow}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: Container( + width: size, height: size, + decoration: BoxDecoration( + color: accent, shape: BoxShape.circle, + boxShadow: [BoxShadow(color: accentGlow, blurRadius: 16, offset: const Offset(0, 4))], + ), + child: Icon(playing ? Icons.pause : Icons.play_arrow, + color: PyramidColors.accentFg, size: size * 0.48), + ), + ); + } +} + +class _AIconBtn extends StatelessWidget { + final IconData icon; + final Color color; + final double rSm; + final VoidCallback? onTap; + const _AIconBtn({required this.icon, required this.color, required this.rSm, this.onTap}); + + @override + Widget build(BuildContext context) => InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(rSm), + child: SizedBox(width: 32, height: 32, + child: Icon(icon, size: 18, color: color)), + ); +} + +class _ASpeedPill extends StatelessWidget { + final String label; + final bool active; + final VoidCallback? onTap; + final Color accent, accentSoft, bg, fgMuted; + final double rSm; + const _ASpeedPill({required this.label, this.active = false, this.onTap, + required this.accent, required this.accentSoft, required this.bg, + required this.fgMuted, required this.rSm}); + + @override + Widget build(BuildContext context) => GestureDetector( + onTap: onTap, + child: Container( + margin: const EdgeInsets.symmetric(horizontal: 1), + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: active ? accentSoft : bg, + borderRadius: BorderRadius.circular(rSm), + ), + child: Text(label, style: TextStyle( + fontSize: 11, fontWeight: FontWeight.w500, + color: active ? accent : fgMuted, + letterSpacing: 0.2, + )), + ), + ); +} + +class _AScrubber extends StatelessWidget { + final double progress; + final Color accent, track; + final ValueChanged? onSeek; + const _AScrubber({required this.progress, required this.accent, required this.track, this.onSeek}); + + @override + Widget build(BuildContext context) => LayoutBuilder(builder: (_, c) => GestureDetector( + onTapDown: (d) => onSeek?.call((d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0)), + onPanUpdate: (d) => onSeek?.call((d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0)), + child: SizedBox(height: 14, child: Stack(alignment: Alignment.centerLeft, children: [ + Container(height: 3, decoration: BoxDecoration(color: track, borderRadius: BorderRadius.circular(2))), + FractionallySizedBox( + widthFactor: progress, + child: Container(height: 3, decoration: BoxDecoration(color: accent, borderRadius: BorderRadius.circular(2))), + ), + ])), + )); +} + +class _AMiniBar extends StatelessWidget { + final double value; + final Color track, fill; + const _AMiniBar({required this.value, required this.track, required this.fill}); + + @override + Widget build(BuildContext context) => Stack(alignment: Alignment.centerLeft, children: [ + Container(height: 3, decoration: BoxDecoration(color: track, borderRadius: BorderRadius.circular(2))), + FractionallySizedBox( + widthFactor: value.clamp(0.0, 1.0), + child: Container(height: 3, decoration: BoxDecoration(color: fill, borderRadius: BorderRadius.circular(2))), + ), + ]); +} + +class _ChunkyBarsPainter extends CustomPainter { + final double progress; + final Color played, unplayed, cursor; + static const int _count = 56; + static final List _heights = _seed(); + + static List _seed() { + final r = math.Random(7); + return List.generate(_count, (i) { + final env = math.sin((i / _count) * math.pi) * 0.6 + 0.4; + return 0.2 + r.nextDouble() * 0.8 * env; + }); + } + + const _ChunkyBarsPainter({required this.progress, required this.played, + required this.unplayed, required this.cursor}); + + @override + void paint(Canvas canvas, Size s) { + const gap = 2.0; + final barW = (s.width - gap * (_count - 1)) / _count; + final cur = (progress * _count).floor(); + for (int i = 0; i < _count; i++) { + final h = _heights[i] * s.height; + final x = i * (barW + gap); + final y = (s.height - h) / 2; + final color = i == cur ? cursor : (i < cur ? played : unplayed); + canvas.drawRRect( + RRect.fromRectAndRadius(Rect.fromLTWH(x, y, barW, h), const Radius.circular(1)), + Paint()..color = color, + ); + } + } + + @override + bool shouldRepaint(_ChunkyBarsPainter old) => + old.progress != progress || old.played != played; +} + +// ─── Video Player ───────────────────────────────────────────────────────────── +// +// Variant: minimal — Controls immer sichtbar (overlay auf Video, kein Auto-Hide) + +class PyramidVideoPlayer extends StatefulWidget { + final Uint8List bytes; + final String filename; + final PyramidTheme pt; + final String senderName; + + const PyramidVideoPlayer({ + super.key, + required this.bytes, + required this.filename, + required this.pt, + this.senderName = '', + }); + + @override + State createState() => _PyramidVideoPlayerState(); +} + +class _PyramidVideoPlayerState extends State { + late final Player _player; + late final VideoController _controller; + bool _loading = true; + double _speed = 1.0; + String _quality = 'Auto'; + + static const _speeds = [0.5, 1.0, 1.25, 1.5, 2.0]; + static const _qualities = ['Auto', '1080p', '720p', '480p', '360p']; + + @override + void initState() { + super.initState(); + _player = Player(); + _controller = VideoController(_player); + _init(); + } + + Future _init() async { + final ext = widget.filename.contains('.') ? widget.filename.split('.').last : 'mp4'; + final dir = await getTemporaryDirectory(); + final file = File('${dir.path}/pyr_video_${widget.bytes.hashCode}.$ext'); + await file.writeAsBytes(widget.bytes); + await _player.open(Media('file://${file.path}'), play: false); + if (mounted) setState(() => _loading = false); + } + + @override + void dispose() { + _player.dispose(); + super.dispose(); + } + + String _fmt(Duration d) { + final m = d.inMinutes.remainder(60); + final s = d.inSeconds.remainder(60).toString().padLeft(2, '0'); + return '$m:$s'; + } + + void _openFullscreen() => MediaViewer.show( + context, + senderName: widget.senderName, + filename: widget.filename, + bytes: widget.bytes, + isVideo: true, + ); + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final title = widget.filename.contains('.') + ? widget.filename.split('.').first : widget.filename; + + if (_loading) { + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + constraints: const BoxConstraints(maxWidth: 360), + height: 200, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(pt.rLg), + border: Border.all(color: pt.border), + ), + child: Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ); + } + + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + constraints: const BoxConstraints(maxWidth: 420), + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(pt.rLg), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: AspectRatio( + aspectRatio: 16 / 9, + child: StreamBuilder( + stream: _player.stream.playing, + builder: (_, playSnap) => StreamBuilder( + stream: _player.stream.position, + builder: (_, posSnap) => StreamBuilder( + stream: _player.stream.duration, + builder: (_, durSnap) { + final playing = playSnap.data ?? false; + final pos = posSnap.data ?? Duration.zero; + final dur = durSnap.data ?? Duration.zero; + final progress = dur.inMilliseconds == 0 + ? 0.0 : pos.inMilliseconds / dur.inMilliseconds; + + return GestureDetector( + onTap: () => playing ? _player.pause() : _player.play(), + child: Stack(fit: StackFit.expand, children: [ + // Video + Video(controller: _controller, controls: NoVideoControls), + + // Top: Titelleiste mit Farbverlauf + Align( + alignment: Alignment.topCenter, + child: _VTopBar(title: title, onFullscreen: _openFullscreen), + ), + + // Center: Play-Button wenn pausiert + if (!playing) + const Center(child: _VCenterPlay()), + + // Bottom: Steuerleiste (minimal = immer sichtbar) + Align( + alignment: Alignment.bottomCenter, + child: _VBottomBar( + playing: playing, pos: pos, dur: dur, + progress: progress, speed: _speed, quality: _quality, + speeds: _speeds, qualities: _qualities, fmt: _fmt, pt: pt, + onTogglePlay: () => playing ? _player.pause() : _player.play(), + onSeek: (d) => _player.seek(d), + onSkipBack: () => _player.seek(pos - const Duration(seconds: 10)), + onSkipForward: () => _player.seek(pos + const Duration(seconds: 10)), + onSpeed: (s) { setState(() => _speed = s); _player.setRate(s); }, + onQuality: (q) => setState(() => _quality = q), + onFullscreen: _openFullscreen, + ), + ), + ]), + ); + }, + ), + ), + ), + ), + ); + } +} + +// ─── Video: Bausteine ──────────────────────────────────────────────────────── + +class _VTopBar extends StatelessWidget { + final String title; + final VoidCallback? onFullscreen; + const _VTopBar({required this.title, this.onFullscreen}); + + @override + Widget build(BuildContext context) => Container( + width: double.infinity, + padding: const EdgeInsets.fromLTRB(14, 12, 8, 20), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, end: Alignment.bottomCenter, + colors: [Color(0x99000000), Colors.transparent], + ), + ), + child: Row(crossAxisAlignment: CrossAxisAlignment.center, children: [ + Expanded(child: Text(title, style: const TextStyle( + color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500, + ), overflow: TextOverflow.ellipsis)), + _VOverlayBtn(icon: Icons.fullscreen, onTap: onFullscreen), + ]), + ); +} + +class _VCenterPlay extends StatelessWidget { + const _VCenterPlay(); + @override + Widget build(BuildContext context) => Container( + width: 56, height: 56, + decoration: BoxDecoration( + color: Colors.white.withOpacity(0.10), + shape: BoxShape.circle, + border: Border.all(color: Colors.white.withOpacity(0.18)), + ), + child: const Icon(Icons.play_arrow, color: Colors.white, size: 26), + ); +} + +class _VBottomBar extends StatelessWidget { + final bool playing; + final Duration pos, dur; + final double progress, speed; + final String quality; + final List speeds; + final List qualities; + final String Function(Duration) fmt; + final PyramidTheme pt; + final VoidCallback onTogglePlay, onSkipBack, onSkipForward, onFullscreen; + final ValueChanged onSeek; + final ValueChanged onSpeed; + final ValueChanged onQuality; + + const _VBottomBar({ + required this.playing, required this.pos, required this.dur, + required this.progress, required this.speed, required this.quality, + required this.speeds, required this.qualities, required this.fmt, + required this.pt, required this.onTogglePlay, required this.onSeek, + required this.onSkipBack, required this.onSkipForward, + required this.onSpeed, required this.onQuality, required this.onFullscreen, + }); + + @override + Widget build(BuildContext context) => Container( + width: double.infinity, + padding: const EdgeInsets.fromLTRB(12, 16, 12, 12), + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.bottomCenter, end: Alignment.topCenter, + colors: [Color(0xCC000000), Colors.transparent], + ), + ), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + _VScrubber(progress: progress, dur: dur, onSeek: onSeek, accent: pt.accent), + const SizedBox(height: 8), + Row(children: [ + _VPlayMini(playing: playing, onTap: onTogglePlay), + _VOverlayBtn(icon: Icons.replay_10, onTap: onSkipBack), + _VOverlayBtn(icon: Icons.forward_10, onTap: onSkipForward), + const SizedBox(width: 6), + Text('${fmt(pos)} / ${fmt(dur)}', + style: const TextStyle(color: Colors.white70, fontSize: 10, letterSpacing: 0.4)), + const Spacer(), + _VSettingsButton( + speed: speed, quality: quality, + speeds: speeds, qualities: qualities, + onSpeed: onSpeed, onQuality: onQuality, + ), + _VOverlayBtn(icon: Icons.fullscreen, onTap: onFullscreen), + ]), + ]), + ); +} + +class _VScrubber extends StatelessWidget { + final double progress; + final Duration dur; + final ValueChanged onSeek; + final Color accent; + const _VScrubber({required this.progress, required this.dur, + required this.onSeek, required this.accent}); + + @override + Widget build(BuildContext context) => LayoutBuilder(builder: (_, c) => GestureDetector( + onTapDown: (d) => onSeek(Duration( + milliseconds: (dur.inMilliseconds * (d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0)).round())), + onPanUpdate: (d) => onSeek(Duration( + milliseconds: (dur.inMilliseconds * (d.localPosition.dx / c.maxWidth).clamp(0.0, 1.0)).round())), + child: SizedBox(height: 16, child: Stack(alignment: Alignment.centerLeft, children: [ + Container(height: 3, decoration: BoxDecoration( + color: Colors.white.withOpacity(0.20), borderRadius: BorderRadius.circular(2))), + FractionallySizedBox(widthFactor: progress, child: Container(height: 3, + decoration: BoxDecoration(color: accent, borderRadius: BorderRadius.circular(2)))), + Positioned( + left: c.maxWidth * progress.clamp(0.0, 1.0) - 5, + child: Container(width: 10, height: 10, + decoration: BoxDecoration(color: accent, shape: BoxShape.circle, + boxShadow: [BoxShadow(color: Colors.black.withOpacity(0.4), blurRadius: 0, spreadRadius: 2)])), + ), + ])), + )); +} + +class _VPlayMini extends StatelessWidget { + final bool playing; + final VoidCallback? onTap; + const _VPlayMini({required this.playing, this.onTap}); + + @override + Widget build(BuildContext context) => GestureDetector( + onTap: onTap, + child: Container( + width: 34, height: 34, + decoration: const BoxDecoration(color: Colors.white, shape: BoxShape.circle), + child: Icon(playing ? Icons.pause : Icons.play_arrow, + color: const Color(0xFF0A0A0C), size: 16), + ), + ); +} + +class _VOverlayBtn extends StatelessWidget { + final IconData icon; + final VoidCallback? onTap; + const _VOverlayBtn({required this.icon, this.onTap}); + + @override + Widget build(BuildContext context) => InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(6), + child: SizedBox(width: 32, height: 32, + child: Icon(icon, size: 17, color: Colors.white.withOpacity(0.85))), + ); +} + +class _VSettingsButton extends StatelessWidget { + final double speed; + final String quality; + final List speeds; + final List qualities; + final ValueChanged onSpeed; + final ValueChanged onQuality; + const _VSettingsButton({required this.speed, required this.quality, + required this.speeds, required this.qualities, + required this.onSpeed, required this.onQuality}); + + String get _speedLabel { + final s = speed; + return '${s == s.toInt() ? s.toInt() : s}x'; + } + + @override + Widget build(BuildContext context) => PopupMenuButton( + tooltip: 'Einstellungen', + offset: const Offset(0, -8), + position: PopupMenuPosition.over, + color: const Color(0xF014141A), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(color: Colors.white.withOpacity(0.1)), + ), + itemBuilder: (_) => [PopupMenuItem( + enabled: false, padding: EdgeInsets.zero, + child: _VSettingsMenu( + speed: _speedLabel, quality: quality, + speeds: speeds, qualities: qualities, + onSpeed: onSpeed, onQuality: onQuality, + ), + )], + child: SizedBox(width: 32, height: 32, + child: Icon(Icons.settings_outlined, size: 16, color: Colors.white.withOpacity(0.85))), + ); +} + +class _VSettingsMenu extends StatefulWidget { + final String speed, quality; + final List speeds; + final List qualities; + final ValueChanged onSpeed; + final ValueChanged onQuality; + const _VSettingsMenu({required this.speed, required this.quality, + required this.speeds, required this.qualities, + required this.onSpeed, required this.onQuality}); + + @override + State<_VSettingsMenu> createState() => _VSettingsMenuState(); +} + +class _VSettingsMenuState extends State<_VSettingsMenu> { + String? _section; // null | 'speed' | 'quality' + + static const _fg = Color(0xE5FFFFFF); + static const _dim = Color(0x99FFFFFF); + + @override + Widget build(BuildContext context) { + if (_section == null) { + return SizedBox( + width: 190, + child: Column(mainAxisSize: MainAxisSize.min, children: [ + _row('Geschwindigkeit', widget.speed, () => setState(() => _section = 'speed')), + _row('Qualität', widget.quality, () => setState(() => _section = 'quality')), + ]), + ); + } + final isSpeed = _section == 'speed'; + return SizedBox( + width: 170, + child: Column(mainAxisSize: MainAxisSize.min, children: [ + InkWell( + onTap: () => setState(() => _section = null), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + const Icon(Icons.arrow_back, size: 12, color: _dim), + const SizedBox(width: 8), + Text(isSpeed ? 'GESCHWINDIGKEIT' : 'QUALITÄT', + style: const TextStyle(color: _dim, fontSize: 10, letterSpacing: 0.8)), + ]), + ), + ), + Container(height: 1, color: Colors.white.withOpacity(0.08)), + if (isSpeed) + ...widget.speeds.map((s) { + final lbl = '${s == s.toInt() ? s.toInt() : s}x'; + return _item(lbl, lbl == widget.speed, () => widget.onSpeed(s)); + }) + else + ...widget.qualities.map((q) => _item(q, q == widget.quality, () => widget.onQuality(q))), + ]), + ); + } + + Widget _row(String label, String value, VoidCallback onTap) => InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Text(label, style: const TextStyle(color: _fg, fontSize: 12)), + const SizedBox(width: 16), + const Spacer(), + Text(value, style: const TextStyle(color: _dim, fontSize: 11, letterSpacing: 0.3)), + const SizedBox(width: 4), + const Icon(Icons.chevron_right, size: 14, color: _dim), + ]), + ), + ); + + Widget _item(String label, bool active, VoidCallback onTap) => InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + SizedBox(width: 18, child: active + ? const Icon(Icons.check, size: 14, color: PyramidColors.accentAmber) + : null), + Text(label, style: TextStyle( + color: active ? PyramidColors.accentAmber : _fg, fontSize: 12, + )), + ]), + ), + ); +} + +// ─── Fullscreen Video Player ────────────────────────────────────────────────── +// Verwendet AdaptiveVideoControls für native System-Fullscreen-Integration + +class FullscreenVideoPlayer extends StatefulWidget { + final Uint8List bytes; + final String filename; + + const FullscreenVideoPlayer({super.key, required this.bytes, required this.filename}); + + @override + State createState() => _FullscreenVideoPlayerState(); +} + +class _FullscreenVideoPlayerState extends State { + late final Player _player; + late final VideoController _controller; + bool _loading = true; + + @override + void initState() { + super.initState(); + _player = Player(); + _controller = VideoController(_player); + _init(); + } + + Future _init() async { + final ext = widget.filename.contains('.') ? widget.filename.split('.').last : 'mp4'; + final dir = await getTemporaryDirectory(); + final file = File('${dir.path}/pyr_vfull_${widget.bytes.hashCode}.$ext'); + await file.writeAsBytes(widget.bytes); + await _player.open(Media('file://${file.path}'), play: true); + if (mounted) setState(() => _loading = false); + } + + @override + void dispose() { + _player.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + if (_loading) return const Center(child: CircularProgressIndicator(color: Colors.white)); + return Video(controller: _controller, controls: AdaptiveVideoControls); + } +} diff --git a/lib/features/chat/media_viewer.dart b/lib/features/chat/media_viewer.dart new file mode 100644 index 0000000..571bc59 --- /dev/null +++ b/lib/features/chat/media_viewer.dart @@ -0,0 +1,255 @@ +import 'dart:io'; +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/media_player.dart'; +import 'package:pyramid/utils/gif_favorite_service.dart'; + +/// Overlay viewer for images, GIFs and videos. +/// Uses a semi-transparent backdrop; tapping outside the content closes it. +class MediaViewer extends StatefulWidget { + final String senderName; + final Uint8List? bytes; + final String? networkUrl; + final String filename; + final bool isVideo; + final Event? event; + + const MediaViewer({ + super.key, + required this.senderName, + required this.filename, + this.bytes, + this.networkUrl, + this.isVideo = false, + this.event, + }); + + static Future show( + BuildContext context, { + required String senderName, + required String filename, + Uint8List? bytes, + String? networkUrl, + bool isVideo = false, + Event? event, + }) { + return showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: 'Schließen', + barrierColor: Colors.black.withAlpha(178), + transitionDuration: const Duration(milliseconds: 180), + transitionBuilder: (context, animation, secondaryAnimation, child) => + FadeTransition(opacity: animation, child: child), + pageBuilder: (context, animation, secondaryAnimation) => MediaViewer( + senderName: senderName, + filename: filename, + bytes: bytes, + networkUrl: networkUrl, + isVideo: isVideo, + event: event, + ), + ); + } + + @override + State createState() => _MediaViewerState(); +} + +class _MediaViewerState extends State { + final _tc = TransformationController(); + bool _controlsVisible = true; + bool _saving = false; + bool _savingSticker = false; + + @override + void dispose() { + _tc.dispose(); + super.dispose(); + } + + void _toggle() => setState(() => _controlsVisible = !_controlsVisible); + + void _resetZoom() => _tc.value = Matrix4.identity(); + + Future _saveAsSticker() async { + final event = widget.event; + if (event == null || _savingSticker) return; + setState(() => _savingSticker = true); + final messenger = ScaffoldMessenger.maybeOf(context); + try { + final ok = await GifFavoriteService.addImageAsStickerFavorite(event); + messenger?.showSnackBar(SnackBar( + content: Text(ok ? 'Als Sticker gespeichert' : 'Fehler beim Speichern'), + duration: const Duration(seconds: 2), + )); + } finally { + if (mounted) setState(() => _savingSticker = false); + } + } + + Future _save() async { + final b = widget.bytes; + if (b == null || _saving) return; + setState(() => _saving = true); + try { + Directory? dir; + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + dir = await getDownloadsDirectory(); + } + dir ??= await getTemporaryDirectory(); + final ext = widget.filename.contains('.') ? widget.filename.split('.').last : 'jpg'; + final name = 'pyramid_${DateTime.now().millisecondsSinceEpoch}.$ext'; + final file = File('${dir.path}/$name'); + await file.writeAsBytes(b); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Gespeichert: ${file.path}'), + duration: const Duration(seconds: 4), + )); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Fehler: $e')), + ); + } + } finally { + if (mounted) setState(() => _saving = false); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final isVideo = widget.isVideo && widget.bytes != null; + final size = MediaQuery.sizeOf(context); + + final header = AnimatedOpacity( + opacity: _controlsVisible ? 1 : 0, + duration: const Duration(milliseconds: 180), + child: IgnorePointer( + ignoring: !_controlsVisible, + child: Container( + decoration: const BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topCenter, + end: Alignment.bottomCenter, + colors: [Colors.black54, Colors.transparent], + ), + ), + child: SafeArea( + bottom: false, + child: Row( + children: [ + IconButton( + onPressed: () => Navigator.of(context).pop(), + icon: const Icon(Icons.close_rounded, color: Colors.white), + tooltip: 'Schließen', + ), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(widget.senderName, + style: const TextStyle(color: Colors.white, fontSize: 15, fontWeight: FontWeight.w600)), + Text(widget.filename, + style: const TextStyle(color: Colors.white60, fontSize: 12), + overflow: TextOverflow.ellipsis), + ], + ), + ), + if (widget.event != null && !isVideo) + IconButton( + onPressed: _savingSticker ? null : _saveAsSticker, + tooltip: 'Als Sticker speichern', + icon: _savingSticker + ? const SizedBox(width: 20, height: 20, + child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) + : const Icon(Icons.sticky_note_2_outlined, color: Colors.white), + ), + if (widget.bytes != null) + IconButton( + onPressed: _saving ? null : _save, + tooltip: 'Speichern', + icon: _saving + ? const SizedBox(width: 20, height: 20, + child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) + : const Icon(Icons.download_rounded, color: Colors.white), + ), + if (!isVideo) + IconButton( + onPressed: _resetZoom, + tooltip: 'Zoom zurücksetzen', + icon: const Icon(Icons.zoom_out_map_rounded, color: Colors.white), + ), + ], + ), + ), + ), + ), + ); + + // Content area — constrained so the transparent Material outside it lets + // pointer events through to the barrier (which dismisses on tap). + final contentMaxW = (size.width - 48).clamp(200.0, 1200.0); + final contentMaxH = (size.height - 48).clamp(200.0, 900.0); + + if (isVideo) { + return Material( + type: MaterialType.transparency, + child: Center( + child: SizedBox( + width: contentMaxW, + height: contentMaxH, + child: Stack( + fit: StackFit.expand, + children: [ + FullscreenVideoPlayer(bytes: widget.bytes!, filename: widget.filename), + Positioned(top: 0, left: 0, right: 0, child: header), + ], + ), + ), + ), + ); + } + + Widget img; + if (widget.bytes != null) { + img = Image.memory(widget.bytes!, fit: BoxFit.contain, gaplessPlayback: true); + } else if (widget.networkUrl != null) { + img = Image.network(widget.networkUrl!, fit: BoxFit.contain); + } else { + img = Icon(Icons.broken_image_outlined, size: 64, color: pt.fgDim); + } + + return Material( + type: MaterialType.transparency, + child: Center( + child: SizedBox( + width: contentMaxW, + height: contentMaxH, + child: GestureDetector( + onTap: _toggle, + child: Stack( + fit: StackFit.expand, + children: [ + InteractiveViewer( + transformationController: _tc, + minScale: 0.5, + maxScale: 10.0, + child: Center(child: img), + ), + Positioned(top: 0, left: 0, right: 0, child: header), + ], + ), + ), + ), + ), + ); + } +} diff --git a/lib/features/chat/message_group.dart b/lib/features/chat/message_group.dart new file mode 100644 index 0000000..c55de5d --- /dev/null +++ b/lib/features/chat/message_group.dart @@ -0,0 +1,2780 @@ +import 'dart:convert'; +import 'dart:io'; + +import 'package:collection/collection.dart'; +import 'package:flutter/gestures.dart'; +import 'package:flutter/material.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pyramid/features/chat/media_player.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/media_cache.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/emoji_picker.dart'; +import 'package:flutter_svg/flutter_svg.dart'; +import 'package:pyramid/features/chat/document_viewer.dart'; +import 'package:pyramid/features/chat/media_viewer.dart'; +import 'package:pyramid/features/chat/reaction_service.dart'; +import 'package:pyramid/utils/gif_favorite_service.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; +import 'package:url_launcher/url_launcher.dart'; + +// Wraps a group of consecutive messages from the same sender +class MessageGroup extends StatefulWidget { + final List events; + final String currentUserId; + final Room? room; + final Timeline? timeline; + final VoidCallback? onReply; + final Set selectedIds; + final ValueChanged? onToggleSelect; + final bool showStatusIndicator; + /// Event IDs that another member has read up to (their last-read position). + /// A ✓✓ is rendered at any of this group's events contained here. + final Set readEventIds; + /// When non-null and pointing to a non-last event in this group, an inline + /// "Neue Nachrichten" divider is rendered after that event's row. + final String? fullyReadId; + /// Jump-to-message (from search): the row matching [jumpEventId] gets + /// [jumpKey] attached (for ensureVisible) and [highlightEventId] is tinted. + final String? jumpEventId; + final GlobalKey? jumpKey; + final String? highlightEventId; + final bool highlightOn; + + const MessageGroup({ + super.key, + required this.events, + required this.currentUserId, + this.room, + this.timeline, + this.onReply, + this.selectedIds = const {}, + this.onToggleSelect, + this.showStatusIndicator = false, + this.readEventIds = const {}, + this.fullyReadId, + this.jumpEventId, + this.jumpKey, + this.highlightEventId, + this.highlightOn = false, + }); + + @override + State createState() => _MessageGroupState(); +} + +class _MessageGroupState extends State { + // Per-message hover state (desktop): which event row the pointer is over, and + // which row currently has its reaction-picker overlay open. + String? _hoveredEventId; + String? _overlayEventId; + double _swipeOffset = 0; + static const _swipeThreshold = 56.0; + bool _swipeTriggered = false; + + bool get _isMobile => Platform.isAndroid || Platform.isIOS; + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final firstEvent = widget.events.first; + final sender = firstEvent.senderFromMemoryOrFallback; + final name = sender.calcDisplayname(); + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + final color = _colorFromId(firstEvent.senderId); + final time = _formatTime(firstEvent.originServerTs); + final avatarUri = sender.avatarUrl; + + // Build a FLAT column of rows — each message at the same indentation level. + // First event row: avatar + name + time + content + // Continuation rows: timestamp-slot + content + // This prevents the nested-Row double-indent bug. + final rows = []; + + // ── First event row ────────────────────────────────── + // Each message row is INDIVIDUALLY selectable (see _selectableRow) so two + // consecutive messages from the same sender aren't selected as one block. + rows.add(_selectableRow(firstEvent, pt, Padding( + padding: EdgeInsets.only(top: pt.msgGap / 2, left: 20, right: 20, bottom: 2), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Avatar + SizedBox( + width: 38, + child: Column(children: [ + const SizedBox(height: 2), + _Avatar(initial: initial, color: color, pt: pt, size: 38, avatarUri: avatarUri), + ]), + ), + const SizedBox(width: 14), + // Name + time + message + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Text(name, style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600)), + const SizedBox(width: 8), + Text(time, style: TextStyle(color: pt.fgDim, fontSize: 11)), + ]), + const SizedBox(height: 2), + _MessageBody( + event: firstEvent, + pt: pt, + timeline: widget.timeline, + room: widget.room, + currentUserId: widget.currentUserId, + ), + ], + ), + ), + ], + ), + ))); + if (widget.readEventIds.contains(firstEvent.eventId)) rows.add(_ReadMarker(pt: pt)); + // Inline unread divider after the first event when it's the fullyRead + // marker and there are more events in this group. + if (widget.fullyReadId == firstEvent.eventId && widget.events.length > 1) { + rows.add(_InlineUnreadDivider(pt: pt)); + } + + // ── Continuation event rows (siblings, same indentation) ── + for (var j = 1; j < widget.events.length; j++) { + final event = widget.events[j]; + rows.add(_selectableRow(event, pt, Padding( + padding: const EdgeInsets.only(top: 8, left: 20, right: 20), + child: _ContinuationMessage( + event: event, + pt: pt, + timeline: widget.timeline, + room: widget.room, + currentUserId: widget.currentUserId, + ), + ))); + if (widget.readEventIds.contains(event.eventId)) rows.add(_ReadMarker(pt: pt)); + // Inline divider after this event if it's the fullyRead and not the last. + if (widget.fullyReadId == event.eventId && j < widget.events.length - 1) { + rows.add(_InlineUnreadDivider(pt: pt)); + } + } + + // Sending/sent indicator on the newest own message — only when no read ✓✓ + // is already shown for it (the ✓✓ implies it was delivered + read). + if (widget.showStatusIndicator && + firstEvent.senderId == widget.currentUserId && + widget.room != null && + !widget.readEventIds.contains(widget.events.last.eventId)) { + rows.add(Padding( + padding: const EdgeInsets.only(right: 24, bottom: 1), + child: Align( + alignment: Alignment.centerRight, + child: _MessageStatus( + lastEvent: widget.events.last, + pt: pt, + ), + ), + )); + } + rows.add(const SizedBox(height: 2)); + + // Hover highlight + actions are now per-row (see _selectableRow), so the + // group is just the column of rows. + Widget content = Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: rows, + ); + + if (!_isMobile) return content; + + return GestureDetector( + onHorizontalDragUpdate: (d) { + if (d.delta.dx > 0) return; // Only allow right-to-left swipe for reply + setState(() { + _swipeOffset = (_swipeOffset + d.delta.dx).clamp(-_swipeThreshold, 0.0); + if (_swipeOffset <= -_swipeThreshold && !_swipeTriggered) { + _swipeTriggered = true; + HapticFeedback.mediumImpact(); + } + }); + }, + onHorizontalDragEnd: (_) { + if (_swipeTriggered) widget.onReply?.call(); + setState(() { _swipeOffset = 0; _swipeTriggered = false; }); + }, + child: Stack( + children: [ + Transform.translate( + offset: Offset(_swipeOffset, 0), + child: content, + ), + if (_swipeOffset < -8) + Positioned( + right: 12, + top: 0, + bottom: 0, + child: Center( + child: AnimatedOpacity( + opacity: (-_swipeOffset / _swipeThreshold).clamp(0.0, 1.0), + duration: const Duration(milliseconds: 60), + child: Icon(Icons.reply_rounded, size: 20, color: pt.fgMuted), + ), + ), + ), + ], + ), + ); + } + + // Wraps a single message row so it can be selected independently of the rest + // of the sender's group. Long-press enters selection mode; in selection mode a + // full-row tap overlay toggles this message's selection. + Widget _selectableRow(Event event, PyramidTheme pt, Widget child) { + final selected = widget.selectedIds.contains(event.eventId); + final inSel = widget.selectedIds.isNotEmpty; + final showActions = !_isMobile && !inSel && + (_hoveredEventId == event.eventId || _overlayEventId == event.eventId); + final isJumpTarget = widget.jumpEventId == event.eventId; + final isHighlighted = widget.highlightEventId == event.eventId; + + Widget row = GestureDetector( + key: isJumpTarget ? widget.jumpKey : null, + onLongPress: () => widget.onToggleSelect?.call(event.eventId), + child: Stack( + children: [ + AnimatedContainer( + duration: const Duration(milliseconds: 100), + color: selected + ? pt.accent.withAlpha(40) + : (showActions ? pt.bg2 : Colors.transparent), + child: child, + ), + // Jump-from-search highlight — fades out via AnimatedOpacity. + if (isHighlighted) + Positioned.fill( + child: IgnorePointer( + child: AnimatedOpacity( + opacity: widget.highlightOn ? 1.0 : 0.0, + duration: const Duration(milliseconds: 900), + curve: Curves.easeOut, + child: Container(color: pt.accent.withAlpha(48)), + ), + ), + ), + if (selected) + Positioned( + left: 0, + top: 0, + bottom: 0, + child: Container(width: 3, color: pt.accent), + ), + if (showActions) + Positioned( + top: 0, + right: 32, + child: _HoverActions( + pt: pt, + event: event, + events: [event], + room: widget.room, + currentUserId: widget.currentUserId, + onReply: widget.onReply, + onOverlayStateChanged: (active) => setState( + () => _overlayEventId = active ? event.eventId : null), + ), + ), + if (inSel) + Positioned.fill( + child: GestureDetector( + behavior: HitTestBehavior.opaque, + onTap: () => widget.onToggleSelect?.call(event.eventId), + ), + ), + ], + ), + ); + + if (_isMobile) return row; + + // Desktop: per-row hover highlight + actions. + return MouseRegion( + onEnter: (_) => setState(() => _hoveredEventId = event.eventId), + onExit: (_) => setState(() { + if (_hoveredEventId == event.eventId) _hoveredEventId = null; + }), + child: row, + ); + } + + Color _colorFromId(String id) { + const colors = [ + Color(0xFF06B6D4), Color(0xFFA855F7), Color(0xFF10B981), + Color(0xFFF43F5E), Color(0xFF3B82F6), Color(0xFFF59E0B), + Color(0xFFFF6B9D), + ]; + if (id.isEmpty) return colors[0]; + return colors[id.codeUnitAt(0) % colors.length]; + } + + String _formatTime(DateTime t) { + final h = t.hour.toString().padLeft(2, '0'); + final m = t.minute.toString().padLeft(2, '0'); + return '$h:$m'; + } +} + +// Shown under a message whose send failed (e.g. offline) — keeps the message +// visible with retry / delete instead of letting it silently disappear. +class _SendFailedRow extends StatelessWidget { + final Event event; + final PyramidTheme pt; + const _SendFailedRow({required this.event, required this.pt}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(top: 3, bottom: 1), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline_rounded, size: 13, color: pt.danger), + const SizedBox(width: 4), + Text('Nicht gesendet', style: TextStyle(color: pt.danger, fontSize: 12)), + const SizedBox(width: 10), + _link('Wiederholen', pt, () async { + try { await event.sendAgain(); } catch (_) {} + }), + const SizedBox(width: 10), + _link('Löschen', pt, () async { + try { await event.cancelSend(); } catch (_) {} + }), + ], + ), + ); + } + + Widget _link(String label, PyramidTheme pt, VoidCallback onTap) => GestureDetector( + onTap: onTap, + child: Text( + label, + style: TextStyle( + color: pt.accent, + fontSize: 12, + decoration: TextDecoration.underline, + decorationColor: pt.accent, + ), + ), + ); +} + +// Single message (first in group) with full avatar + name shown +class _MessageBody extends StatelessWidget { + final Event event; + final PyramidTheme pt; + final Timeline? timeline; + final Room? room; + final String currentUserId; + + const _MessageBody({ + required this.event, + required this.pt, + this.timeline, + this.room, + required this.currentUserId, + }); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _MessageContent(event: event, pt: pt, timeline: timeline), + if (event.status.isError) _SendFailedRow(event: event, pt: pt), + if (timeline != null) _ReactionsRow(event: event, timeline: timeline!, room: room, currentUserId: currentUserId, pt: pt), + ], + ); + } +} + +// Continuation message — no avatar, just indented text with timestamp on hover +class _ContinuationMessage extends StatefulWidget { + final Event event; + final PyramidTheme pt; + final Timeline? timeline; + final Room? room; + final String currentUserId; + + const _ContinuationMessage({ + required this.event, + required this.pt, + this.timeline, + this.room, + required this.currentUserId, + }); + + @override + State<_ContinuationMessage> createState() => _ContinuationMessageState(); +} + +class _ContinuationMessageState extends State<_ContinuationMessage> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Timestamp on hover (in avatar column space) + SizedBox( + width: 38, + child: Padding( + padding: const EdgeInsets.only(top: 4), + child: AnimatedOpacity( + opacity: _hovered ? 1 : 0, + duration: const Duration(milliseconds: 120), + child: Text( + _formatTime(widget.event.originServerTs), + textAlign: TextAlign.center, + style: TextStyle( + color: widget.pt.fgDim, + fontSize: 10, + ), + ), + ), + ), + ), + const SizedBox(width: 14), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _MessageContent(event: widget.event, pt: widget.pt, timeline: widget.timeline), + if (widget.event.status.isError) _SendFailedRow(event: widget.event, pt: widget.pt), + if (widget.timeline != null) + _ReactionsRow( + event: widget.event, + timeline: widget.timeline!, + room: widget.room, + currentUserId: widget.currentUserId, + pt: widget.pt, + ), + ], + ), + ), + ], + ), + ); + } + + String _formatTime(DateTime t) { + final h = t.hour.toString().padLeft(2, '0'); + final m = t.minute.toString().padLeft(2, '0'); + return '$h:$m'; + } +} + +class _MessageContent extends StatelessWidget { + final Event event; + final PyramidTheme pt; + final Timeline? timeline; + + const _MessageContent({required this.event, required this.pt, this.timeline}); + + // Resolves edits: returns the display event (last edit) for this event. + Event get _displayEvent => + timeline != null ? event.getDisplayEvent(timeline!) : event; + + String? _getReplyId() { + final relatesTo = event.content.tryGetMap('m.relates_to'); + final replyMap = relatesTo?.tryGetMap('m.in_reply_to'); + return replyMap?['event_id'] as String?; + } + + String _stripReplyFallback(String body) { + final norm = body.replaceAll('\r\n', '\n'); + if (!norm.startsWith('> ') && !norm.startsWith('>\n')) return norm; + final lines = norm.split('\n'); + var i = 0; + while (i < lines.length && (lines[i].startsWith('> ') || lines[i].trimRight() == '>')) { + i++; + } + if (i < lines.length && lines[i].trim().isEmpty) i++; + if (i >= lines.length) return norm; + return lines.skip(i).join('\n').trim(); + } + + Event? _findReplyEvent(String replyId) { + if (timeline == null) return null; + try { + return timeline!.events.firstWhere((e) => e.eventId == replyId); + } catch (_) { + return null; + } + } + + @override + Widget build(BuildContext context) { + final displayEvent = _displayEvent; + final isEdited = displayEvent.eventId != event.eventId; + + // Still encrypted (decryption pending or failed) + if (displayEvent.type == EventTypes.Encrypted) { + return Padding( + padding: const EdgeInsets.only(bottom: 2), + child: Wrap( + crossAxisAlignment: WrapCrossAlignment.center, + spacing: 4, + children: [ + Icon(Icons.lock_outline_rounded, size: 13, color: pt.fgDim), + Text( + 'Nachricht wird entschlüsselt…', + style: TextStyle(color: pt.fgDim, fontSize: 13, fontStyle: FontStyle.italic), + ), + if (timeline != null) + Builder( + builder: (ctx) => GestureDetector( + onTap: () { + timeline!.requestKeys(); + ScaffoldMessenger.of(ctx).showSnackBar( + const SnackBar( + content: Text('Schlüssel werden von anderen Geräten angefordert…'), + duration: Duration(seconds: 3), + ), + ); + }, + child: Text( + 'Schlüssel anfordern', + style: TextStyle( + color: pt.accent, + fontSize: 12, + decoration: TextDecoration.underline, + decorationColor: pt.accent, + ), + ), + ), + ), + ], + ), + ); + } + + if (displayEvent.type == EventTypes.Sticker) { + return _MediaContent(event: displayEvent, pt: pt); + } + + final msgType = displayEvent.messageType; + + if (msgType == 'm.image') { + final ext = displayEvent.body.contains('.') + ? displayEvent.body.split('.').last.toLowerCase() + : ''; + const kImageExts = { + 'png', 'jpg', 'jpeg', 'gif', 'webp', 'bmp', + 'tiff', 'tif', 'heic', 'heif', 'avif', 'ico', 'jfif', + }; + // SVG kann Image.memory nicht dekodieren — über den SVG-Renderer anzeigen. + if (ext == 'svg' || + displayEvent.content + .tryGetMap('info')?['mimetype'] == + 'image/svg+xml') { + return _DocPreviewContent(event: displayEvent, pt: pt); + } + if (ext.isNotEmpty && !kImageExts.contains(ext)) { + return _FileContent(event: displayEvent, pt: pt, icon: Icons.insert_drive_file_rounded); + } + return _ImageContent(event: displayEvent, pt: pt); + } + if (msgType == 'm.audio') { + return _AudioContent(event: displayEvent, pt: pt); + } + if (msgType == 'm.video') { + return _VideoContent(event: displayEvent, pt: pt); + } + if (msgType == 'm.file') { + if (DocumentViewer.isInlinePreviewable(displayEvent.body)) { + return _DocPreviewContent(event: displayEvent, pt: pt); + } + if (DocumentViewer.showsInlineCard(displayEvent.body)) { + return _ProprietaryInlineCard(event: displayEvent, pt: pt); + } + return _FileContent(event: displayEvent, pt: pt, icon: Icons.insert_drive_file_rounded); + } + + final replyId = _getReplyId(); + final replyEvent = replyId != null ? _findReplyEvent(replyId) : null; + final plainBody = replyId != null + ? _stripReplyFallback(displayEvent.body) + : displayEvent.body; + + // Use formatted_body (HTML) if the event has one, otherwise plain text. + final format = displayEvent.content.tryGet('format'); + // Strip the Matrix reply fallback block — we render + // our own quote card (_ReplyPreview) above, so the inline "In reply to @user" + // would be redundant and ugly. + final formattedBody = displayEvent.formattedText.replaceAll( + RegExp(r'.*?', caseSensitive: false, dotAll: true), + '', + ).trim(); + final hasHtml = format == 'org.matrix.custom.html' && formattedBody.isNotEmpty; + + final firstUrl = _firstUrl(plainBody); + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (replyEvent != null) _ReplyPreview(replyEvent: replyEvent, pt: pt), + Padding( + padding: const EdgeInsets.only(bottom: 2), + child: hasHtml + ? _MatrixHtmlText( + html: formattedBody, + baseStyle: TextStyle(color: pt.fg, fontSize: 14, height: 1.55), + linkColor: pt.accent, + ) + : _PlainLinkText( + text: plainBody, + baseStyle: TextStyle(color: pt.fg, fontSize: 14, height: 1.55), + linkColor: pt.accent, + ), + ), + if (isEdited) + Text( + '(bearbeitet)', + style: TextStyle(color: pt.fgDim, fontSize: 11, fontStyle: FontStyle.italic), + ), + if (firstUrl != null) _LinkPreview(url: firstUrl, pt: pt), + ], + ); + } + + // Extracts the first http(s) URL in the text, for link-preview fetching. + static final RegExp _urlRegex = RegExp(r'https?://[^\s<>()\[\]]+', caseSensitive: false); + String? _firstUrl(String text) { + final m = _urlRegex.firstMatch(text); + if (m == null) return null; + var url = m.group(0)!; + // Trim common trailing punctuation that isn't part of the URL. + url = url.replaceAll(RegExp(r'[.,;:!?]+$'), ''); + return url; + } +} + +// ─── Link preview card (Open-Graph, WhatsApp/Discord-style) ────────────────── + +class _LinkPreviewData { + final String? title; + final String? description; + final String? imageMxc; + const _LinkPreviewData({this.title, this.description, this.imageMxc}); + bool get isEmpty => + (title == null || title!.isEmpty) && + (description == null || description!.isEmpty) && + imageMxc == null; +} + +class _LinkPreview extends ConsumerStatefulWidget { + final String url; + final PyramidTheme pt; + const _LinkPreview({required this.url, required this.pt}); + + // url → preview (null = fetched but nothing usable). Avoids refetching on + // every rebuild/scroll. + static final Map _cache = {}; + + @override + ConsumerState<_LinkPreview> createState() => _LinkPreviewState(); +} + +class _LinkPreviewState extends ConsumerState<_LinkPreview> { + _LinkPreviewData? _data; + bool _done = false; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + if (_LinkPreview._cache.containsKey(widget.url)) { + setState(() { _data = _LinkPreview._cache[widget.url]; _done = true; }); + return; + } + try { + final client = await ref.read(matrixClientProvider.future); + final hs = client.homeserver.toString(); + final enc = Uri.encodeQueryComponent(widget.url); + final headers = {'authorization': 'Bearer ${client.accessToken}'}; + + var res = await client.httpClient.get( + Uri.parse('$hs/_matrix/client/v1/media/preview_url?url=$enc'), + headers: headers, + ); + if (res.statusCode == 404) { + // Legacy fallback for older servers. + res = await client.httpClient.get( + Uri.parse('$hs/_matrix/media/v3/preview_url?url=$enc'), + headers: headers, + ); + } + _LinkPreviewData? data; + if (res.statusCode == 200) { + final json = jsonDecode(utf8.decode(res.bodyBytes)) as Map; + data = _LinkPreviewData( + title: (json['og:title'] as String?)?.trim(), + description: (json['og:description'] as String?)?.trim(), + imageMxc: json['og:image'] as String?, + ); + if (data.isEmpty) data = null; + } + _LinkPreview._cache[widget.url] = data; + if (mounted) setState(() { _data = data; _done = true; }); + } catch (_) { + _LinkPreview._cache[widget.url] = null; + if (mounted) setState(() { _data = null; _done = true; }); + } + } + + @override + Widget build(BuildContext context) { + final data = _data; + if (!_done || data == null) return const SizedBox.shrink(); + final pt = widget.pt; + final client = ref.watch(matrixClientProvider).valueOrNull; + + return Padding( + padding: const EdgeInsets.only(top: 6, bottom: 2), + child: GestureDetector( + onTap: () => launchUrl(Uri.parse(widget.url), mode: LaunchMode.externalApplication), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 380), + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rBase), + child: Container( + decoration: BoxDecoration( + color: pt.bg2, + border: Border(left: BorderSide(color: pt.accent, width: 3)), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (data.imageMxc != null && client != null) + ConstrainedBox( + constraints: const BoxConstraints(maxHeight: 180), + child: SizedBox( + width: double.infinity, + child: MxcImage( + mxcUri: data.imageMxc!, + client: client, + fit: BoxFit.cover, + placeholder: const SizedBox.shrink(), + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(10, 8, 10, 8), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + if (data.title != null && data.title!.isNotEmpty) + Text( + data.title!, + style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w600), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + if (data.description != null && data.description!.isNotEmpty) ...[ + const SizedBox(height: 3), + Text( + data.description!, + style: TextStyle(color: pt.fgMuted, fontSize: 12, height: 1.35), + maxLines: 3, + overflow: TextOverflow.ellipsis, + ), + ], + ], + ), + ), + ], + ), + ), + ), + ), + ), + ); + } +} + +class _ReplyPreview extends StatelessWidget { + final Event replyEvent; + final PyramidTheme pt; + const _ReplyPreview({required this.replyEvent, required this.pt}); + + @override + Widget build(BuildContext context) { + final senderName = replyEvent.senderFromMemoryOrFallback.calcDisplayname(); + + // Media-aware preview: show an icon + label instead of a raw filename, + // matching WhatsApp/Discord. Falls back to stripped text for m.text. + final (IconData? icon, String body) = _previewFor(replyEvent); + + return Padding( + padding: const EdgeInsets.only(bottom: 4), + child: IntrinsicHeight( + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rSm), + child: Container( + color: pt.accentSoft, + child: Row( + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + // Accent bar flush with the left edge of the tinted card. + Container(width: 3, color: pt.accent), + Expanded( + child: Padding( + padding: const EdgeInsets.fromLTRB(8, 5, 10, 5), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Text(senderName, style: TextStyle(color: pt.accent, fontSize: 12, fontWeight: FontWeight.w600)), + Row( + children: [ + if (icon != null) ...[ + Icon(icon, size: 13, color: pt.fgMuted), + const SizedBox(width: 4), + ], + Expanded( + child: Text( + body, + style: TextStyle(color: pt.fgMuted, fontSize: 12), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ], + ), + ), + ), + ], + ), + ), + ), + ), + ); + } + + (IconData?, String) _previewFor(Event e) { + switch (e.messageType) { + case 'm.image': + return (Icons.image_outlined, 'Bild'); + case 'm.video': + return (Icons.videocam_outlined, 'Video'); + case 'm.audio': + return (Icons.mic_none_rounded, 'Sprachnachricht'); + case 'm.file': + return (Icons.insert_drive_file_outlined, e.body.isNotEmpty ? e.body : 'Datei'); + } + if (e.type == EventTypes.Sticker) return (Icons.emoji_emotions_outlined, 'Sticker'); + + // Plain text: strip nested reply fallback, collapse to first line. + String body = e.body.replaceAll('\r\n', '\n'); + if (body.startsWith('> ')) { + final lines = body.split('\n'); + var i = 0; + while (i < lines.length && (lines[i].startsWith('> ') || lines[i].trimRight() == '>')) { + i++; + } + if (i < lines.length && lines[i].trim().isEmpty) i++; + if (i < lines.length) body = lines.skip(i).join(' ').trim(); + } + return (null, body.split('\n').first); + } +} + +class _ImageContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + const _ImageContent({required this.event, required this.pt}); + + @override + ConsumerState<_ImageContent> createState() => _ImageContentState(); +} + +class _ImageContentState extends ConsumerState<_ImageContent> { + late Future<_MediaResult> _future; + + @override + void initState() { + super.initState(); + _future = _load(); + } + + Future<_MediaResult> _load() async { + final event = widget.event; + final rawUrl = event.content.tryGet('url') ?? ''; + if (rawUrl.startsWith('http://') || rawUrl.startsWith('https://')) { + return _MediaResult.network(rawUrl); + } + // Serve from the shared LRU cache if this image was viewed recently. + final cached = MediaCache.instance.get(event.eventId); + if (cached != null) return _MediaResult.bytes(cached); + + final client = await ref.read(matrixClientProvider.future); + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) return _MediaResult.none(); + if (event.isAttachmentEncrypted) { + try { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + MediaCache.instance.put(event.eventId, file.bytes); + return _MediaResult.bytes(file.bytes); + } catch (e) { + return _MediaResult.error(_classifyMediaError(e)); + } + } else { + try { + final httpUri = await mxcUri.getThumbnailUri(client, width: 800, height: 600, method: ThumbnailMethod.scale); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + MediaCache.instance.put(event.eventId, res.bodyBytes); + return _MediaResult.bytes(res.bodyBytes); + } catch (_) { + try { + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + MediaCache.instance.put(event.eventId, res.bodyBytes); + return _MediaResult.bytes(res.bodyBytes); + } catch (e) { + return _MediaResult.error(e.toString().split('\n').first); + } + } + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + + return LayoutBuilder(builder: (context, constraints) { + // Never exceed the available chat width (important on narrow phones), + // capped at the comfortable desktop maximum. + final maxW = constraints.maxWidth.isFinite + ? constraints.maxWidth.clamp(80.0, 420.0) + : 420.0; + const maxH = 320.0; + // Reserve the final display box up-front from the event's info dimensions, + // so the layout doesn't shift (and yank the scroll position) when the image + // finishes loading. Null when dimensions are absent. + final box = _reservedImageSize(widget.event, maxW: maxW, maxH: maxH); + + return FutureBuilder<_MediaResult>( + future: _future, + builder: (context, snap) { + Widget inner; + if (snap.connectionState == ConnectionState.waiting) { + inner = Center(child: SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2, color: pt.fgDim))); + } else if (snap.hasData) { + final result = snap.data!; + if (result.bytes != null) { + inner = Image.memory( + result.bytes!, + fit: BoxFit.contain, + gaplessPlayback: true, + errorBuilder: (context, e, stack) => _mediaFallback(pt, e.toString().split('\n').first, widget.event.body), + ); + } else if (result.networkUrl != null) { + inner = Image.network(result.networkUrl!, fit: BoxFit.contain); + } else { + inner = _mediaFallback(pt, result.error, widget.event.body); + } + } else { + inner = _mediaFallback(pt, null, widget.event.body); + } + + final result = snap.data; + return GestureDetector( + onTap: (snap.hasData && result != null) + ? () => MediaViewer.show( + context, + senderName: widget.event.senderFromMemoryOrFallback.calcDisplayname(), + filename: widget.event.body, + bytes: result.bytes, + networkUrl: result.networkUrl, + event: widget.event, + ) + : null, + child: Align( + alignment: Alignment.centerLeft, + child: Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + width: box?.width, + height: box?.height, + constraints: box == null + ? BoxConstraints( + minWidth: 120, minHeight: 90, + maxWidth: maxW, maxHeight: maxH, + ) + : null, + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rBase), + ), + clipBehavior: Clip.hardEdge, + child: inner, + ), + ), + ); + }, + ); + }); + } +} + +// Computes the on-screen box for an image/video event, fitting within +// [maxW]×[maxH] while preserving the aspect ratio from the event's `info` +// (w/h). Used to reserve layout space before the media loads so nothing shifts. +// Returns null when the event carries no dimensions — callers should then use +// loose constraints instead of a fixed box. +Size? _reservedImageSize(Event event, {required double maxW, required double maxH}) { + final info = event.content.tryGetMap('info'); + final w = (info?['w'] as num?)?.toDouble(); + final h = (info?['h'] as num?)?.toDouble(); + if (w == null || h == null || w <= 0 || h <= 0) return null; + // Fit inside maxW×maxH without distorting; never upscale small images. + var scale = (maxW / w).clamp(0.0, maxH / h); + if (scale > 1.0) scale = 1.0; + return Size(w * scale, h * scale); +} + +// Downloads media bytes then hands off to PyramidAudioPlayer / PyramidVideoPlayer +class _AudioContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + const _AudioContent({required this.event, required this.pt}); + + @override + ConsumerState<_AudioContent> createState() => _AudioContentState(); +} + +class _AudioContentState extends ConsumerState<_AudioContent> { + late Future<_MediaResult> _future; + + @override + void initState() { + super.initState(); + _future = _loadBytes(); + } + + Future<_MediaResult> _loadBytes() async { + final client = await ref.read(matrixClientProvider.future); + final event = widget.event; + if (event.isAttachmentEncrypted) { + try { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + return _MediaResult.bytes(file.bytes); + } catch (e) { + return _MediaResult.error(_classifyMediaError(e)); + } + } + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) return _MediaResult.none(); + try { + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + return _MediaResult.bytes(res.bodyBytes); + } catch (e) { + return _MediaResult.error(e.toString().split('\n').first); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return FutureBuilder<_MediaResult>( + future: _future, + builder: (ctx, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + SizedBox(width: 22, height: 22, child: CircularProgressIndicator(strokeWidth: 2, color: pt.fgDim)), + const SizedBox(width: 10), + Text('Lade Audio…', style: TextStyle(color: pt.fgMuted, fontSize: 12)), + ]), + ); + } + final result = snap.data; + if (result?.bytes == null) { + return _mediaFallback(pt, result?.error, widget.event.body); + } + return PyramidAudioPlayer( + bytes: result!.bytes!, + filename: widget.event.body, + pt: pt, + isVoice: widget.event.content['msgtype'] == 'm.audio', + ); + }, + ); + } +} + +class _VideoContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + const _VideoContent({required this.event, required this.pt}); + + @override + ConsumerState<_VideoContent> createState() => _VideoContentState(); +} + +class _VideoContentState extends ConsumerState<_VideoContent> { + late Future<_MediaResult> _future; + + @override + void initState() { + super.initState(); + _future = _loadBytes(); + } + + Future<_MediaResult> _loadBytes() async { + final client = await ref.read(matrixClientProvider.future); + final event = widget.event; + if (event.isAttachmentEncrypted) { + try { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + return _MediaResult.bytes(file.bytes); + } catch (e) { + return _MediaResult.error(_classifyMediaError(e)); + } + } + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) return _MediaResult.none(); + try { + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + return _MediaResult.bytes(res.bodyBytes); + } catch (e) { + return _MediaResult.error(e.toString().split('\n').first); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return FutureBuilder<_MediaResult>( + future: _future, + builder: (ctx, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + constraints: const BoxConstraints(maxWidth: 360), + height: 200, + decoration: BoxDecoration( + color: Colors.black, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ); + } + final result = snap.data; + if (result?.bytes == null) { + return _FileContent(event: widget.event, pt: pt, icon: Icons.videocam_rounded); + } + return PyramidVideoPlayer( + bytes: result!.bytes!, + filename: widget.event.body, + pt: pt, + senderName: widget.event.senderFromMemoryOrFallback.calcDisplayname(), + ); + }, + ); + } +} + +class _MediaContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + + const _MediaContent({required this.event, required this.pt}); + + @override + ConsumerState<_MediaContent> createState() => _MediaContentState(); +} + +class _MediaContentState extends ConsumerState<_MediaContent> { + late Future<_MediaResult> _future; + + @override + void initState() { + super.initState(); + _future = _load(); + } + + Future<_MediaResult> _load() async { + final client = await ref.read(matrixClientProvider.future); + final event = widget.event; + + // External URL (e.g. Giphy GIFs) — not an MXC URI + final rawUrl = event.content.tryGet('url') ?? ''; + if (rawUrl.startsWith('http://') || rawUrl.startsWith('https://')) { + return _MediaResult.network(rawUrl); + } + + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) return _MediaResult.none(); + + if (event.isAttachmentEncrypted) { + try { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + return _MediaResult.bytes(file.bytes); + } catch (e) { + return _MediaResult.error(_classifyMediaError(e)); + } + } else { + try { + final httpUri = await mxcUri.getThumbnailUri( + client, + width: 800, + height: 600, + method: ThumbnailMethod.scale, + ); + final res = await client.httpClient.get( + httpUri, + headers: {'authorization': 'Bearer ${client.accessToken}'}, + ); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + return _MediaResult.bytes(res.bodyBytes); + } catch (_) { + // Fall back to full-size download + try { + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get( + httpUri, + headers: {'authorization': 'Bearer ${client.accessToken}'}, + ); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + return _MediaResult.bytes(res.bodyBytes); + } catch (e) { + return _MediaResult.error(e.toString().split('\n').first); + } + } + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final isSticker = widget.event.type == EventTypes.Sticker; + final maxW = isSticker ? 160.0 : 420.0; + final maxH = isSticker ? 160.0 : 320.0; + + return FutureBuilder<_MediaResult>( + future: _future, + builder: (context, snap) { + Widget inner; + if (snap.connectionState == ConnectionState.waiting) { + inner = Center( + child: SizedBox( + width: 24, height: 24, + child: CircularProgressIndicator(strokeWidth: 2, color: pt.fgDim), + ), + ); + } else if (snap.hasData) { + final result = snap.data!; + if (result.networkUrl != null) { + inner = Image.network( + result.networkUrl!, + fit: BoxFit.contain, + errorBuilder: (context, e, stack) => _fallback(pt), + ); + } else if (result.bytes != null) { + inner = Image.memory( + result.bytes!, + fit: BoxFit.contain, + errorBuilder: (context, e, stack) => _fallback(pt), + ); + } else { + inner = _fallback(pt, result.error); + } + } else { + inner = _fallback(pt); + } + + return Align( + alignment: Alignment.centerLeft, + child: Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + constraints: BoxConstraints(maxWidth: maxW, maxHeight: maxH), + decoration: isSticker ? null : BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: isSticker ? Clip.none : Clip.hardEdge, + child: inner, + ), + ); + }, + ); + } + + Widget _fallback(PyramidTheme pt, [String? error]) => + _mediaFallback(pt, error, widget.event.body); +} + +// Downloads bytes for a PDF/SVG file and shows PdfInlinePreview or SvgImage. +class _DocPreviewContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + const _DocPreviewContent({required this.event, required this.pt}); + + @override + ConsumerState<_DocPreviewContent> createState() => _DocPreviewContentState(); +} + +class _DocPreviewContentState extends ConsumerState<_DocPreviewContent> { + late Future<_MediaResult> _future; + + @override + void initState() { + super.initState(); + _future = _loadBytes(); + } + + Future<_MediaResult> _loadBytes() async { + final event = widget.event; + // Serve from cache if we already downloaded this attachment this session. + final cached = _DocBytesCache.get(event.eventId); + if (cached != null) return _MediaResult.bytes(cached); + + final client = await ref.read(matrixClientProvider.future); + if (event.isAttachmentEncrypted) { + try { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + _DocBytesCache.put(event.eventId, file.bytes); + return _MediaResult.bytes(file.bytes); + } catch (e) { + return _MediaResult.error(_classifyMediaError(e)); + } + } + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) return _MediaResult.none(); + try { + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) return _MediaResult.error('HTTP ${res.statusCode}'); + _DocBytesCache.put(event.eventId, res.bodyBytes); + return _MediaResult.bytes(res.bodyBytes); + } catch (e) { + return _MediaResult.error(e.toString().split('\n').first); + } + } + + Future _saveFile(Uint8List bytes) async { + try { + Directory? dir; + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + dir = await getDownloadsDirectory(); + } + dir ??= await getTemporaryDirectory(); + final filename = widget.event.body.isNotEmpty ? widget.event.body : 'file'; + final ext = filename.contains('.') ? filename.split('.').last : 'bin'; + final name = 'pyramid_${DateTime.now().millisecondsSinceEpoch}.$ext'; + final file = File('${dir.path}/$name'); + await file.writeAsBytes(bytes); + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text('Gespeichert: ${file.path}'), + duration: const Duration(seconds: 4), + )); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Fehler: $e'))); + } + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final ext = widget.event.body.contains('.') + ? widget.event.body.split('.').last.toLowerCase() + : ''; + + return FutureBuilder<_MediaResult>( + future: _future, + builder: (ctx, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return Container( + width: 280, + height: 80, + margin: const EdgeInsets.only(top: 4, bottom: 4), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Center(child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ); + } + + final result = snap.data; + if (result?.bytes == null) { + return _FileContent(event: widget.event, pt: pt, icon: Icons.picture_as_pdf_outlined); + } + + final bytes = result!.bytes!; + final sender = widget.event.senderFromMemoryOrFallback.calcDisplayname(); + + if (ext == 'pdf' || ext == 'ai' || ext == 'eps') { + return PdfInlinePreview( + bytes: bytes, + filename: widget.event.body, + pt: pt, + senderName: sender, + onDownload: () => _saveFile(bytes), + ); + } + + // SVG — show inline like an image + return GestureDetector( + onTap: () => DocumentViewer.show( + context, + filename: widget.event.body, + bytes: bytes, + senderName: sender, + ), + child: Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + constraints: const BoxConstraints(maxWidth: 300, maxHeight: 300), + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: SvgPicture.memory(bytes, fit: BoxFit.contain), + ), + ); + }, + ); + } +} + +// Inline card for proprietary formats — shows immediately from event metadata, +// downloads lazily only when the user taps or hits the download button. +class _ProprietaryInlineCard extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + const _ProprietaryInlineCard({required this.event, required this.pt}); + + @override + ConsumerState<_ProprietaryInlineCard> createState() => _ProprietaryInlineCardState(); +} + +class _ProprietaryInlineCardState extends ConsumerState<_ProprietaryInlineCard> { + bool _loading = false; + Uint8List? _cachedBytes; + + String get _filename => widget.event.body.isNotEmpty ? widget.event.body : 'file'; + String get _ext => _filename.contains('.') ? _filename.split('.').last.toLowerCase() : ''; + int? get _fileSize => widget.event.content.tryGetMap('info')?['size'] as int?; + + String _fmtSize(int b) { + if (b < 1024) return '$b B'; + if (b < 1024 * 1024) return '${(b / 1024).toStringAsFixed(1)} KB'; + return '${(b / (1024 * 1024)).toStringAsFixed(1)} MB'; + } + + IconData get _icon => switch (_ext) { + 'psd' || 'psb' => Icons.photo_camera_outlined, + 'ai' || 'eps' => Icons.gesture_outlined, + 'indd' || 'inx' => Icons.menu_book_outlined, + 'afphoto' || 'afdesign' || 'afpub' => Icons.palette_outlined, + 'sketch' || 'fig' || 'xd' => Icons.design_services_outlined, + 'doc' => Icons.description_outlined, + 'ppt' => Icons.slideshow_outlined, + 'xls' => Icons.table_chart_outlined, + _ => Icons.insert_drive_file_outlined, + }; + + Future _download() async { + if (_cachedBytes != null) return _cachedBytes!; + final event = widget.event; + final shared = _DocBytesCache.get(event.eventId); + if (shared != null) return _cachedBytes = shared; + + final client = await ref.read(matrixClientProvider.future); + if (event.isAttachmentEncrypted) { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + _DocBytesCache.put(event.eventId, file.bytes); + return _cachedBytes = file.bytes; + } + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) throw Exception('Kein URI'); + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) throw Exception('HTTP ${res.statusCode}'); + _DocBytesCache.put(event.eventId, res.bodyBytes); + return _cachedBytes = res.bodyBytes; + } + + Future _openViewer() async { + if (_loading) return; + setState(() => _loading = true); + try { + final bytes = await _download(); + if (!mounted) return; + await DocumentViewer.show( + context, + filename: _filename, + bytes: bytes, + senderName: widget.event.senderFromMemoryOrFallback.calcDisplayname(), + ); + } catch (e) { + if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Fehler: $e'), duration: const Duration(seconds: 3))); + } finally { + if (mounted) setState(() => _loading = false); + } + } + + Future _save() async { + if (_loading) return; + setState(() => _loading = true); + try { + final bytes = await _download(); + Directory? dir; + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + dir = await getDownloadsDirectory(); + } + dir ??= await getTemporaryDirectory(); + final outFile = File('${dir.path}/pyramid_${DateTime.now().millisecondsSinceEpoch}.$_ext'); + await outFile.writeAsBytes(bytes); + if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Gespeichert: ${outFile.path}'), duration: const Duration(seconds: 4))); + } catch (e) { + if (mounted) ScaffoldMessenger.of(context).showSnackBar(SnackBar(content: Text('Fehler: $e'), duration: const Duration(seconds: 3))); + } finally { + if (mounted) setState(() => _loading = false); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final extLabel = _ext.toUpperCase(); + final size = _fileSize; + + return GestureDetector( + onTap: _openViewer, + child: Container( + width: 280, + margin: const EdgeInsets.only(top: 4, bottom: 4), + decoration: BoxDecoration( + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + // Visual area + Container( + width: 280, + height: 140, + color: pt.accentSoft, + child: Stack( + alignment: Alignment.center, + children: [ + Icon(_icon, size: 56, color: pt.accent.withAlpha(180)), + Positioned( + bottom: 12, + right: 12, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: pt.accent, + borderRadius: BorderRadius.circular(4), + ), + child: Text( + extLabel.length > 4 ? extLabel.substring(0, 4) : extLabel, + style: const TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.w700), + ), + ), + ), + ], + ), + ), + // Footer + Container( + color: pt.bg2, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + child: Row( + children: [ + Icon(_icon, size: 14, color: pt.fgDim), + const SizedBox(width: 6), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(_filename, style: TextStyle(color: pt.fg, fontSize: 12, fontWeight: FontWeight.w500), overflow: TextOverflow.ellipsis), + if (size != null) + Text(_fmtSize(size), style: TextStyle(color: pt.fgMuted, fontSize: 10)), + ], + ), + ), + if (_loading) + SizedBox(width: 16, height: 16, child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)) + else + GestureDetector( + onTap: _save, + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.all(2), + child: Icon(Icons.download_rounded, size: 16, color: pt.fgMuted), + ), + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _FileContent extends ConsumerStatefulWidget { + final Event event; + final PyramidTheme pt; + final IconData icon; + const _FileContent({required this.event, required this.pt, required this.icon}); + + @override + ConsumerState<_FileContent> createState() => _FileContentState(); +} + +class _FileContentState extends ConsumerState<_FileContent> { + bool _saving = false; + bool _previewing = false; + + String get _filename => widget.event.body.isNotEmpty ? widget.event.body : 'file'; + + String _ext() { + final n = _filename; + return n.contains('.') ? n.split('.').last.toLowerCase() : 'bin'; + } + + Future _preview() async { + if (_previewing || _saving) return; + setState(() => _previewing = true); + try { + final client = await ref.read(matrixClientProvider.future); + final event = widget.event; + Uint8List bytes; + if (event.isAttachmentEncrypted) { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + bytes = file.bytes; + } else { + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) throw Exception('Kein URI'); + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) throw Exception('HTTP ${res.statusCode}'); + bytes = res.bodyBytes; + } + if (!mounted) return; + await DocumentViewer.show( + context, + filename: _filename, + bytes: bytes, + senderName: event.senderFromMemoryOrFallback.calcDisplayname(), + ); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Fehler: $e'), duration: const Duration(seconds: 3)), + ); + } + } finally { + if (mounted) setState(() => _previewing = false); + } + } + + Future _save({bool openAfter = false}) async { + if (_saving) return; + setState(() => _saving = true); + try { + final client = await ref.read(matrixClientProvider.future); + final event = widget.event; + Uint8List bytes; + if (event.isAttachmentEncrypted) { + final file = await event.downloadAndDecryptAttachment(getThumbnail: false, downloadCallback: _checkedDownload(client)); + bytes = file.bytes; + } else { + final mxcUri = event.attachmentMxcUrl; + if (mxcUri == null) throw Exception('Kein URI'); + final httpUri = await mxcUri.getDownloadUri(client); + final res = await client.httpClient.get(httpUri, headers: {'authorization': 'Bearer ${client.accessToken}'}); + if (res.statusCode != 200) throw Exception('HTTP ${res.statusCode}'); + bytes = res.bodyBytes; + } + + Directory? dir; + if (Platform.isWindows || Platform.isMacOS || Platform.isLinux) { + dir = await getDownloadsDirectory(); + } + dir ??= await getTemporaryDirectory(); + final name = 'pyramid_${DateTime.now().millisecondsSinceEpoch}.${_ext()}'; + final outFile = File('${dir.path}/$name'); + await outFile.writeAsBytes(bytes); + + if (openAfter) { + if (Platform.isWindows) { + await Process.run('cmd', ['/c', 'start', '', outFile.path]); + } else if (Platform.isMacOS) { + await Process.run('open', [outFile.path]); + } else { + await Process.run('xdg-open', [outFile.path]); + } + } + + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text(openAfter ? 'Geöffnet: ${outFile.path}' : 'Gespeichert: ${outFile.path}'), + duration: const Duration(seconds: 4), + )); + } + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Fehler: $e'), duration: const Duration(seconds: 3)), + ); + } + } finally { + if (mounted) setState(() => _saving = false); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final isVideo = widget.event.messageType == 'm.video'; + + return Container( + margin: const EdgeInsets.only(top: 4, bottom: 4), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + constraints: const BoxConstraints(maxWidth: 340), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 40, + height: 40, + decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(pt.rSm)), + child: Icon(widget.icon, size: 22, color: pt.accent), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text(_filename, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), maxLines: 2, overflow: TextOverflow.ellipsis), + const SizedBox(height: 2), + Text(_ext().toUpperCase(), style: TextStyle(color: pt.fgDim, fontSize: 11)), + ], + ), + ), + const SizedBox(width: 8), + if (_saving || _previewing) + SizedBox(width: 20, height: 20, child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)) + else + Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (DocumentViewer.supportsPreview(_filename)) + IconButton( + onPressed: _preview, + tooltip: 'Vorschau', + icon: Icon(Icons.visibility_outlined, size: 22, color: pt.fgMuted), + constraints: const BoxConstraints(minWidth: 32, minHeight: 32), + padding: EdgeInsets.zero, + ), + if (isVideo) + IconButton( + onPressed: () => _save(openAfter: true), + tooltip: 'Öffnen', + icon: Icon(Icons.play_circle_outline_rounded, size: 22, color: pt.fgMuted), + constraints: const BoxConstraints(minWidth: 32, minHeight: 32), + padding: EdgeInsets.zero, + ), + IconButton( + onPressed: () => _save(), + tooltip: 'Herunterladen', + icon: Icon(Icons.download_rounded, size: 22, color: pt.fgMuted), + constraints: const BoxConstraints(minWidth: 32, minHeight: 32), + padding: EdgeInsets.zero, + ), + ], + ), + ], + ), + ); + } +} + +String _classifyMediaError(Object e) { + final s = e.toString(); + if (s.contains('HandshakeException') || s.contains('CERTIFICATE') || s.contains('SocketException')) { + return 'Verbindungsfehler (TLS/Netzwerk)'; + } + if (s.contains('HTTP 4') || s.contains('HTTP 5') || s.contains('Unknown error when fetching')) { + return 'Datei nicht verfügbar (Serverfehler)'; + } + if (s.contains('decrypt') || s.contains('Decrypt') || s.contains('OlmException')) { + return 'Entschlüsselung fehlgeschlagen'; + } + return 'Download fehlgeschlagen'; +} + +// Thin wrapper over the shared MediaCache so document previews share the same +// LRU byte budget as chat images (keeps the last-viewed media instantly +// available, evicts the oldest). +class _DocBytesCache { + static Uint8List? get(String eventId) => MediaCache.instance.get(eventId); + static void put(String eventId, Uint8List bytes) => + MediaCache.instance.put(eventId, bytes); +} + +// Download callback that validates HTTP status before returning bytes. +// Prevents false "decryption failed" errors when the server returns an +// error page instead of the actual encrypted file bytes. +Future Function(Uri) _checkedDownload(Client client) { + return (Uri url) async { + final res = await client.httpClient.get( + url, + headers: {'authorization': 'Bearer ${client.accessToken}'}, + ); + if (res.statusCode != 200) { + throw Exception('HTTP ${res.statusCode}: ${res.body}'); + } + return res.bodyBytes; + }; +} + +Widget _mediaFallback(PyramidTheme pt, String? error, String body) => Padding( + padding: const EdgeInsets.all(12), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.broken_image_outlined, size: 16, color: pt.fgDim), + const SizedBox(width: 6), + Flexible(child: Text(error ?? body, style: TextStyle(color: pt.fgDim, fontSize: 12), overflow: TextOverflow.ellipsis)), + ], + ), +); + +class _MediaResult { + final String? networkUrl; + final Uint8List? bytes; + final String? error; + + _MediaResult._({this.networkUrl, this.bytes, this.error}); + factory _MediaResult.network(String url) => _MediaResult._(networkUrl: url); + factory _MediaResult.bytes(Uint8List b) => _MediaResult._(bytes: b); + factory _MediaResult.error(String e) => _MediaResult._(error: e); + factory _MediaResult.none() => _MediaResult._(); +} + +// ── Reactions row ───────────────────────────────────────────────────────── + +class _ReactionsRow extends StatelessWidget { + final Event event; + final Timeline timeline; + final Room? room; + final String currentUserId; + final PyramidTheme pt; + + const _ReactionsRow({ + required this.event, + required this.timeline, + required this.currentUserId, + required this.pt, + this.room, + }); + + @override + Widget build(BuildContext context) { + final reactionEvents = event.aggregatedEvents(timeline, RelationshipTypes.reaction); + if (reactionEvents.isEmpty) return const SizedBox.shrink(); + + // Group by emoji key → list of senders + final Map> grouped = {}; + for (final r in reactionEvents) { + final key = r.content.tryGetMap('m.relates_to')?['key'] as String?; + if (key == null || key.isEmpty) continue; + (grouped[key] ??= []).add(r.senderId); + } + if (grouped.isEmpty) return const SizedBox.shrink(); + + return Padding( + padding: const EdgeInsets.only(top: 4, bottom: 2), + child: Wrap( + spacing: 4, + runSpacing: 4, + children: grouped.entries.map((e) { + final myReaction = e.value.contains(currentUserId); + return _ReactionChip( + emoji: e.key, + count: e.value.length, + mine: myReaction, + pt: pt, + onTap: () { + if (myReaction) { + // Find own reaction event to redact + for (final r in reactionEvents) { + final key = r.content.tryGetMap('m.relates_to')?['key'] as String?; + if (key == e.key && r.senderId == currentUserId) { + r.redactEvent().catchError((_) => null); + break; + } + } + } else { + room?.sendReaction(event.eventId, e.key).catchError((_) => ''); + ReactionService.recordUsed(e.key); + } + }, + ); + }).toList(), + ), + ); + } +} + +class _ReactionChip extends StatefulWidget { + final String emoji; + final int count; + final bool mine; + final PyramidTheme pt; + final VoidCallback onTap; + + const _ReactionChip({ + required this.emoji, + required this.count, + required this.mine, + required this.pt, + required this.onTap, + }); + + @override + State<_ReactionChip> createState() => _ReactionChipState(); +} + +class _ReactionChipState extends State<_ReactionChip> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 120), + padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3), + decoration: BoxDecoration( + color: widget.mine + ? pt.accentSoft + : (_hovered ? pt.bgHover : pt.bg2), + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all( + color: widget.mine ? pt.accent : (_hovered ? pt.borderStrong : pt.border), + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Text(widget.emoji, style: const TextStyle(fontSize: 13)), + const SizedBox(width: 4), + Text( + '${widget.count}', + style: TextStyle( + color: widget.mine ? pt.accent : pt.fgMuted, + fontSize: 12, + fontWeight: FontWeight.w500, + ), + ), + ], + ), + ), + ), + ); + } +} + +class _Avatar extends ConsumerStatefulWidget { + final String initial; + final Color color; + final PyramidTheme pt; + final double size; + final Uri? avatarUri; + + const _Avatar({ + required this.initial, + required this.color, + required this.pt, + required this.size, + this.avatarUri, + }); + + @override + ConsumerState<_Avatar> createState() => _AvatarState(); +} + +class _AvatarState extends ConsumerState<_Avatar> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final client = ref.watch(matrixClientProvider).valueOrNull; + final radius = BorderRadius.circular(widget.size / 2); + + Widget child; + if (client != null && widget.avatarUri != null) { + child = MxcAvatar( + mxcUri: widget.avatarUri, + client: client, + size: widget.size, + borderRadius: radius, + placeholder: (_) => _InitialBox( + initial: widget.initial, + color: widget.color, + size: widget.size, + radius: radius, + ), + ); + } else { + child = _InitialBox( + initial: widget.initial, + color: widget.color, + size: widget.size, + radius: radius, + ); + } + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: AnimatedContainer( + duration: const Duration(milliseconds: 180), + curve: Curves.easeOutBack, + transform: _hovered + ? Matrix4.diagonal3Values(1.06, 1.06, 1.0) + : Matrix4.identity(), + transformAlignment: Alignment.center, + width: widget.size, + height: widget.size, + child: child, + ), + ); + } +} + +class _InitialBox extends StatelessWidget { + final String initial; + final Color color; + final double size; + final BorderRadius radius; + const _InitialBox({required this.initial, required this.color, required this.size, required this.radius}); + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration(color: color, borderRadius: radius), + child: Center( + child: Text(initial, style: const TextStyle(color: Colors.white, fontSize: 14, fontWeight: FontWeight.w600)), + ), + ); + } +} + +class _HoverActions extends StatefulWidget { + final PyramidTheme pt; + final Event event; + final List events; + final Room? room; + final String currentUserId; + final VoidCallback? onReply; + final ValueChanged? onOverlayStateChanged; + + const _HoverActions({ + required this.pt, + required this.event, + required this.events, + required this.currentUserId, + this.room, + this.onReply, + this.onOverlayStateChanged, + }); + + @override + State<_HoverActions> createState() => _HoverActionsState(); +} + +class _HoverActionsState extends State<_HoverActions> { + OverlayEntry? _reactionOverlay; + List _quickReactions = ReactionService.quickReactions; + + @override + void initState() { + super.initState(); + ReactionService.load().then((_) { + if (mounted) setState(() => _quickReactions = ReactionService.quickReactions); + }); + } + + void _closeReactionOverlay() { + _reactionOverlay?.remove(); + _reactionOverlay = null; + widget.onOverlayStateChanged?.call(false); + } + + void _toggleReactionPicker() { + if (_reactionOverlay != null) { + _closeReactionOverlay(); + return; + } + + final box = context.findRenderObject() as RenderBox?; + final offset = box?.localToGlobal(Offset.zero) ?? Offset.zero; + + _reactionOverlay = OverlayEntry(builder: (ctx) { + final screenSize = MediaQuery.sizeOf(ctx); + const pickerW = 340.0; + const pickerH = 380.0; + double left = (offset.dx - pickerW / 2).clamp(8.0, screenSize.width - pickerW - 8); + double top = (offset.dy - pickerH - 8).clamp(8.0, screenSize.height - pickerH - 8); + + return Material( + type: MaterialType.transparency, + child: Stack(children: [ + GestureDetector( + onTap: _closeReactionOverlay, + behavior: HitTestBehavior.translucent, + child: const SizedBox.expand(), + ), + Positioned( + left: left, + top: top, + child: EmojiPicker( + onEmojiSelected: (emoji) { + _closeReactionOverlay(); + widget.room?.sendReaction(widget.event.eventId, emoji) + .catchError((_) => ''); + ReactionService.recordUsed(emoji).then((_) { + if (mounted) setState(() => _quickReactions = ReactionService.quickReactions); + }); + }, + onClose: _closeReactionOverlay, + ), + ), + ]), + ); + }); + widget.onOverlayStateChanged?.call(true); + Overlay.of(context).insert(_reactionOverlay!); + } + + void _showMoreMenu() { + final box = context.findRenderObject() as RenderBox?; + final offset = box?.localToGlobal(Offset.zero) ?? Offset.zero; + final size = box?.size ?? Size.zero; + + final isOwnMessage = widget.event.senderId == widget.currentUserId; + final text = widget.event.body; + + // Find any image or sticker event in the group that can be saved as a sticker. + final imageEvent = widget.events.firstWhereOrNull( + (e) => e.messageType == 'm.image' || e.type == EventTypes.Sticker, + ); + + // Capture messenger synchronously before showMenu's async gap so the + // snackbar can be shown even if the widget is unmounted by then. + final messenger = ScaffoldMessenger.maybeOf(context); + + showMenu( + context: context, + position: RelativeRect.fromLTRB( + offset.dx, offset.dy - size.height, + offset.dx + size.width, offset.dy, + ), + items: [ + PopupMenuItem(value: 'copy', child: Row(children: [ + Icon(Icons.copy_rounded, size: 16, color: widget.pt.fgMuted), + const SizedBox(width: 10), + Text('Kopieren', style: TextStyle(color: widget.pt.fg, fontSize: 14)), + ])), + if (imageEvent != null) + PopupMenuItem(value: 'save_sticker', child: Row(children: [ + Icon(Icons.sticky_note_2_outlined, size: 16, color: widget.pt.fgMuted), + const SizedBox(width: 10), + Text('Als Sticker speichern', style: TextStyle(color: widget.pt.fg, fontSize: 14)), + ])), + if (isOwnMessage) + PopupMenuItem(value: 'delete', child: Row(children: [ + Icon(Icons.delete_outline_rounded, size: 16, color: widget.pt.danger), + const SizedBox(width: 10), + Text('Löschen', style: TextStyle(color: widget.pt.danger, fontSize: 14)), + ])), + PopupMenuItem(value: 'pin', child: Row(children: [ + Icon(Icons.push_pin_outlined, size: 16, color: widget.pt.fgMuted), + const SizedBox(width: 10), + Text('Anpinnen', style: TextStyle(color: widget.pt.fg, fontSize: 14)), + ])), + ], + ).then((value) async { + if (value == 'copy') { + Clipboard.setData(ClipboardData(text: text)); + } else if (value == 'save_sticker' && imageEvent != null) { + final ok = await GifFavoriteService.addImageAsStickerFavorite(imageEvent); + messenger?.showSnackBar(SnackBar( + content: Text(ok ? 'Als Sticker gespeichert' : 'Fehler beim Speichern'), + duration: const Duration(seconds: 2), + )); + } else if (value == 'delete') { + widget.event.redactEvent(reason: 'Vom Nutzer gelöscht') + .catchError((_) => null); + } else if (value == 'pin') { + final room = widget.room; + if (room == null) return; + final pinned = List.from( + room.getState(EventTypes.RoomPinnedEvents)?.content['pinned'] as List? ?? [], + ); + final eventId = widget.event.eventId; + if (!pinned.contains(eventId)) pinned.add(eventId); + room.setPinnedEvents(pinned).catchError((_) => ''); + } + }); + } + + @override + void dispose() { + if (_reactionOverlay != null) { + _reactionOverlay!.remove(); + _reactionOverlay = null; + widget.onOverlayStateChanged?.call(false); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Container( + padding: const EdgeInsets.all(2), + decoration: BoxDecoration( + color: pt.bg0, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(100), + blurRadius: 12, + offset: const Offset(0, 4), + ), + ], + ), + child: Row( + children: [ + // Quick reactions + ..._quickReactions.map((emoji) => _QuickReactionBtn( + emoji: emoji, + pt: pt, + onTap: () { + widget.room?.sendReaction(widget.event.eventId, emoji) + .catchError((_) => ''); + ReactionService.recordUsed(emoji).then((_) { + if (mounted) setState(() => _quickReactions = ReactionService.quickReactions); + }); + }, + )), + Container(width: 1, height: 18, color: pt.border, margin: const EdgeInsets.symmetric(horizontal: 2)), + _ActionBtn( + icon: Icons.add_reaction_outlined, + tooltip: 'Reaktion', + pt: pt, + accent: true, + onTap: _toggleReactionPicker, + ), + _ActionBtn( + icon: Icons.reply_rounded, + tooltip: 'Antworten', + pt: pt, + onTap: widget.onReply, + ), + _ActionBtn( + icon: Icons.more_horiz_rounded, + tooltip: 'Mehr', + pt: pt, + onTap: _showMoreMenu, + ), + ], + ), + ); + } +} + +class _QuickReactionBtn extends StatefulWidget { + final String emoji; + final PyramidTheme pt; + final VoidCallback? onTap; + + const _QuickReactionBtn({required this.emoji, required this.pt, this.onTap}); + + @override + State<_QuickReactionBtn> createState() => _QuickReactionBtnState(); +} + +class _QuickReactionBtnState extends State<_QuickReactionBtn> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 100), + width: 28, + height: 28, + decoration: BoxDecoration( + color: _hovered ? widget.pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(widget.pt.rSm), + ), + child: Center( + child: Text(widget.emoji, style: const TextStyle(fontSize: 15)), + ), + ), + ), + ); + } +} + +class _ActionBtn extends StatefulWidget { + final IconData icon; + final String tooltip; + final PyramidTheme pt; + final bool accent; + final VoidCallback? onTap; + + const _ActionBtn({ + required this.icon, + required this.tooltip, + required this.pt, + this.accent = false, + this.onTap, + }); + + @override + State<_ActionBtn> createState() => _ActionBtnState(); +} + +class _ActionBtnState extends State<_ActionBtn> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final color = _hovered + ? (widget.accent ? widget.pt.accent : widget.pt.fg) + : widget.pt.fgMuted; + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: Tooltip( + message: widget.tooltip, + waitDuration: const Duration(milliseconds: 400), + child: AnimatedContainer( + duration: const Duration(milliseconds: 120), + width: 32, + height: 32, + decoration: BoxDecoration( + color: _hovered ? widget.pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(widget.pt.rSm), + ), + child: Center( + child: Icon(widget.icon, size: 16, color: color), + ), + ), + ), + ), + ); + } +} + +// Inline "Neue Nachrichten" divider rendered inside a MessageGroup when the +// fullyRead event is in the middle of the group (same sender, <5 min window). +class _InlineUnreadDivider extends StatelessWidget { + final PyramidTheme pt; + const _InlineUnreadDivider({required this.pt}); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(0, 8, 0, 4), + child: Row( + children: [ + Expanded(child: Divider(color: pt.accent.withAlpha(160), height: 1)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 10), + child: Text( + 'Neue Nachrichten', + style: TextStyle(color: pt.accent, fontSize: 11, fontWeight: FontWeight.w600), + ), + ), + Expanded(child: Divider(color: pt.accent.withAlpha(160), height: 1)), + ], + ), + ); + } +} + +// Date divider between message groups +class DateDivider extends StatelessWidget { + final DateTime date; + + const DateDivider({super.key, required this.date}); + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 20, 8), + child: Row( + children: [ + Expanded(child: Divider(color: pt.border, height: 1)), + Padding( + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Text( + _formatDate(date), + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 0.06 * 11, + ), + ), + ), + Expanded(child: Divider(color: pt.border, height: 1)), + ], + ), + ); + } + + String _formatDate(DateTime d) { + final now = DateTime.now(); + if (d.year == now.year && d.month == now.month && d.day == now.day) { + return 'Heute · ${d.day}. ${_monthName(d.month)}'; + } + final yesterday = now.subtract(const Duration(days: 1)); + if (d.year == yesterday.year && d.month == yesterday.month && d.day == yesterday.day) { + return 'Gestern'; + } + return '${d.day}. ${_monthName(d.month)} ${d.year}'; + } + + String _monthName(int m) => const [ + '', 'Januar', 'Februar', 'März', 'April', 'Mai', 'Juni', + 'Juli', 'August', 'September', 'Oktober', 'November', 'Dezember' + ][m]; +} + +class _MessageStatus extends StatelessWidget { + final Event lastEvent; + final PyramidTheme pt; + + const _MessageStatus({required this.lastEvent, required this.pt}); + + @override + Widget build(BuildContext context) { + final status = lastEvent.status; + if (status == EventStatus.error) { + return Icon(Icons.error_outline_rounded, size: 12, color: pt.danger); + } + if (status == EventStatus.sending) { + return Icon(Icons.access_time_rounded, size: 12, color: pt.fgDim); + } + // Sent (delivered). "Read" is shown by the per-event ✓✓ marker. + return Icon(Icons.done_rounded, size: 13, color: pt.fgDim); + } +} + +// Read receipt: a ✓✓ shown at the partner's last-read message (any sender), +// so it moves next to their own message when they reply. +class _ReadMarker extends StatelessWidget { + final PyramidTheme pt; + const _ReadMarker({required this.pt}); + + // Goldener Doppelhaken — bewusst nicht die Akzentfarbe, damit "gelesen" + // unabhängig vom Theme sofort erkennbar ist. + static const _gold = Color(0xFFE6B422); + + @override + Widget build(BuildContext context) { + return const Padding( + padding: EdgeInsets.only(right: 24, top: 1, bottom: 1), + child: Align( + alignment: Alignment.centerRight, + child: Icon(Icons.done_all_rounded, size: 13, color: _gold), + ), + ); + } +} + + +// ─── Matrix HTML renderer ────────────────────────────────────────────────────── +// +// Handles the subset of HTML that Matrix clients emit in formatted_body: +// / → bold +// / → italic +// / → strikethrough +// → underline +// → monospace, slightly different background +// → tappable link (url_launcher) +//
→ newline +// HTML entities → decoded +// Anything else → text content preserved, tags stripped +// +// Note:

 and 
are simplified (rendered as indented code/text). + +class _MatrixHtmlText extends StatelessWidget { + final String html; + final TextStyle baseStyle; + final Color linkColor; + + const _MatrixHtmlText({ + required this.html, + required this.baseStyle, + required this.linkColor, + }); + + @override + Widget build(BuildContext context) { + final spans = _parseHtml(html, baseStyle, linkColor); + return SelectionArea( + child: RichText(text: TextSpan(children: spans, style: baseStyle)), + ); + } + + List _parseHtml(String html, TextStyle base, Color linkColor) { + // Normalise line endings and collapse whitespace around block elements. + var src = html + .replaceAll('\r\n', '\n') + .replaceAll(RegExp(r'', caseSensitive: false), '\n') + .replaceAll(RegExp(r'', caseSensitive: false), '\n') + .replaceAll(RegExp(r'<(p|div|li)[^>]*>', caseSensitive: false), '') + .replaceAll(RegExp(r']*>', caseSensitive: false), ' ') + .replaceAll(RegExp(r']*>', caseSensitive: false), ''); + + final spans = []; + + // Simple recursive stack-based parser. + // We tokenise into (tag | text) chunks, then apply style based on open tags. + final tagRe = RegExp(r'<(/?)(\w+)([^>]*)>', caseSensitive: false); + + var bold = 0; + var italic = 0; + var strike = 0; + var underline = 0; + var code = 0; + String? pendingHref; + + int pos = 0; + for (final m in tagRe.allMatches(src)) { + // Text before this tag. + if (m.start > pos) { + final text = _decodeEntities(src.substring(pos, m.start)); + if (text.isNotEmpty) { + spans.add(_buildSpan( + text, base, bold > 0, italic > 0, strike > 0, underline > 0, + code > 0, pendingHref, linkColor, + )); + if (pendingHref != null) pendingHref = null; + } + } + pos = m.end; + + final closing = m.group(1) == '/'; + final tag = m.group(2)!.toLowerCase(); + final attrs = m.group(3) ?? ''; + + if (closing) { + switch (tag) { + case 'b': case 'strong': bold = (bold - 1).clamp(0, 99); break; + case 'i': case 'em': italic = (italic - 1).clamp(0, 99); break; + case 'del': case 's': case 'strike': strike = (strike - 1).clamp(0, 99); break; + case 'u': underline = (underline - 1).clamp(0, 99); break; + case 'code': code = (code - 1).clamp(0, 99); break; + case 'a': pendingHref = null; break; + } + } else { + switch (tag) { + case 'b': case 'strong': bold++; break; + case 'i': case 'em': italic++; break; + case 'del': case 's': case 'strike': strike++; break; + case 'u': underline++; break; + case 'code': code++; break; + case 'a': + final hrefMatch = RegExp("""href=["']([^"']+)["']""", caseSensitive: false) + .firstMatch(attrs); + pendingHref = hrefMatch?.group(1); + break; + } + } + } + + // Remaining text after last tag. + if (pos < src.length) { + final text = _decodeEntities(src.substring(pos)); + if (text.isNotEmpty) { + spans.add(_buildSpan( + text, base, bold > 0, italic > 0, strike > 0, underline > 0, + code > 0, pendingHref, linkColor, + )); + } + } + + return spans; + } + + InlineSpan _buildSpan( + String text, + TextStyle base, + bool bold, bool italic, bool strike, bool underline, bool code, + String? href, Color linkColor, + ) { + var style = base.copyWith( + fontWeight: bold ? FontWeight.bold : null, + fontStyle: italic ? FontStyle.italic : null, + decoration: TextDecoration.combine([ + if (strike) TextDecoration.lineThrough, + if (underline) TextDecoration.underline, + ]), + fontFamily: code ? 'monospace' : null, + fontSize: code ? (base.fontSize ?? 14) * 0.9 : null, + ); + + if (href != null) { + style = style.copyWith( + color: linkColor, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ); + return TextSpan( + text: text, + style: style, + recognizer: TapGestureRecognizer() + ..onTap = () => launchUrl(Uri.parse(href), mode: LaunchMode.externalApplication), + ); + } + return TextSpan(text: text, style: style); + } + + static String _decodeEntities(String s) => s + .replaceAll('&', '&') + .replaceAll('<', '<') + .replaceAll('>', '>') + .replaceAll('"', '"') + .replaceAll(''', "'") + .replaceAll(''', "'") + .replaceAll(' ', ' '); +} + +// ─── Plain text with clickable URLs ─────────────────────────────────────────── + +class _PlainLinkText extends StatelessWidget { + final String text; + final TextStyle baseStyle; + final Color linkColor; + + const _PlainLinkText({ + required this.text, + required this.baseStyle, + required this.linkColor, + }); + + static final _urlRe = RegExp( + r'https?://[^\s\]\)>]+', + caseSensitive: false, + ); + + @override + Widget build(BuildContext context) { + final matches = _urlRe.allMatches(text).toList(); + if (matches.isEmpty) { + return SelectableText(text, style: baseStyle); + } + + final spans = []; + int pos = 0; + for (final m in matches) { + if (m.start > pos) { + spans.add(TextSpan(text: text.substring(pos, m.start))); + } + final url = m.group(0)!; + spans.add(TextSpan( + text: url, + style: baseStyle.copyWith( + color: linkColor, + decoration: TextDecoration.underline, + decorationColor: linkColor, + ), + recognizer: TapGestureRecognizer() + ..onTap = () => launchUrl(Uri.parse(url), mode: LaunchMode.externalApplication), + )); + pos = m.end; + } + if (pos < text.length) { + spans.add(TextSpan(text: text.substring(pos))); + } + + return SelectionArea( + child: RichText(text: TextSpan(children: spans, style: baseStyle)), + ); + } +} diff --git a/lib/features/chat/pinned_messages_panel.dart b/lib/features/chat/pinned_messages_panel.dart new file mode 100644 index 0000000..dbbe16c --- /dev/null +++ b/lib/features/chat/pinned_messages_panel.dart @@ -0,0 +1,215 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/chat_provider.dart'; + +class PinnedMessagesPanel extends ConsumerWidget { + final String roomId; + final VoidCallback onClose; + + const PinnedMessagesPanel({ + super.key, + required this.roomId, + required this.onClose, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + final room = ref.watch(roomProvider(roomId)); + final timeline = ref.watch(timelineProvider(roomId)).valueOrNull; + + if (room == null) return const SizedBox.shrink(); + + final pinnedIds = List.from( + room.getState(EventTypes.RoomPinnedEvents)?.content['pinned'] as List? ?? [], + ); + + final pinned = pinnedIds + .map((id) => timeline?.events.where((e) => e.eventId == id).firstOrNull) + .where((e) => e != null) + .cast() + .toList(); + + return Container( + width: 320, + decoration: BoxDecoration( + color: pt.bg1, + border: Border(left: BorderSide(color: pt.border)), + ), + child: Column( + children: [ + // Header + Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + Icon(Icons.push_pin_rounded, size: 16, color: pt.fgMuted), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Angepinnte Nachrichten', + style: TextStyle( + color: pt.fg, + fontSize: 15, + fontWeight: FontWeight.w600, + ), + ), + ), + GestureDetector( + onTap: onClose, + child: Icon(Icons.close_rounded, size: 18, color: pt.fgDim), + ), + ], + ), + ), + // List + Expanded( + child: pinnedIds.isEmpty + ? Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.push_pin_outlined, size: 40, color: pt.fgDim), + const SizedBox(height: 12), + Text( + 'Keine angepinnten Nachrichten', + style: TextStyle(color: pt.fgMuted, fontSize: 14), + ), + ], + ), + ) + : ListView.builder( + padding: const EdgeInsets.all(12), + itemCount: pinned.isEmpty ? pinnedIds.length : pinned.length, + itemBuilder: (ctx, i) { + if (pinned.isEmpty) { + return _PinnedPlaceholder(pt: pt); + } + return _PinnedMessageCard( + event: pinned[i], + room: room, + pt: pt, + onUnpin: () => _unpin(room, pinned[i].eventId), + ); + }, + ), + ), + ], + ), + ); + } + + void _unpin(Room room, String eventId) { + final pinned = List.from( + room.getState(EventTypes.RoomPinnedEvents)?.content['pinned'] as List? ?? [], + ); + pinned.remove(eventId); + room.setPinnedEvents(pinned).catchError((_) => ''); + } +} + +class _PinnedPlaceholder extends StatelessWidget { + final PyramidTheme pt; + const _PinnedPlaceholder({required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Text( + 'Nachricht wird geladen…', + style: TextStyle(color: pt.fgDim, fontSize: 13, fontStyle: FontStyle.italic), + ), + ); + } +} + +class _PinnedMessageCard extends StatelessWidget { + final Event event; + final Room room; + final PyramidTheme pt; + final VoidCallback onUnpin; + + const _PinnedMessageCard({ + required this.event, + required this.room, + required this.pt, + required this.onUnpin, + }); + + @override + Widget build(BuildContext context) { + final sender = event.senderFromMemoryOrFallback.calcDisplayname(); + final time = _formatTime(event.originServerTs); + final body = event.body; + + return Container( + margin: const EdgeInsets.only(bottom: 8), + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.push_pin_rounded, size: 12, color: pt.accent), + const SizedBox(width: 6), + Expanded( + child: Text( + sender, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w600, + ), + ), + ), + Text(time, style: TextStyle(color: pt.fgDim, fontSize: 11)), + const SizedBox(width: 6), + GestureDetector( + onTap: onUnpin, + child: Tooltip( + message: 'Entpinnen', + child: Icon(Icons.push_pin_outlined, size: 14, color: pt.fgDim), + ), + ), + ], + ), + const SizedBox(height: 6), + Text( + body, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + maxLines: 5, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + } + + String _formatTime(DateTime t) { + final now = DateTime.now(); + final diff = now.difference(t); + if (diff.inDays == 0) { + return '${t.hour.toString().padLeft(2, '0')}:${t.minute.toString().padLeft(2, '0')}'; + } + if (diff.inDays < 7) return 'vor ${diff.inDays}d'; + return '${t.day}.${t.month}.${t.year}'; + } +} diff --git a/lib/features/chat/reaction_service.dart b/lib/features/chat/reaction_service.dart new file mode 100644 index 0000000..7fb6a03 --- /dev/null +++ b/lib/features/chat/reaction_service.dart @@ -0,0 +1,38 @@ +import 'package:shared_preferences/shared_preferences.dart'; + +class ReactionService { + static const _key = 'recent_reactions'; + static const _maxRecent = 6; + + static final _defaultReactions = ['👍', '❤️', '😂', '😮', '😢', '🙏']; + + static List _recent = []; + static bool _loaded = false; + + static Future load() async { + if (_loaded) return; + final prefs = await SharedPreferences.getInstance(); + _recent = prefs.getStringList(_key) ?? []; + _loaded = true; + } + + static List get quickReactions { + if (_recent.isEmpty) return _defaultReactions; + // Fill up to 6 with defaults not already in recent + final result = List.from(_recent); + for (final d in _defaultReactions) { + if (result.length >= _maxRecent) break; + if (!result.contains(d)) result.add(d); + } + return result.take(_maxRecent).toList(); + } + + static Future recordUsed(String emoji) async { + await load(); + _recent.remove(emoji); + _recent.insert(0, emoji); + if (_recent.length > _maxRecent) _recent = _recent.sublist(0, _maxRecent); + final prefs = await SharedPreferences.getInstance(); + await prefs.setStringList(_key, _recent); + } +} diff --git a/lib/features/members/members_panel.dart b/lib/features/members/members_panel.dart new file mode 100644 index 0000000..872f48f --- /dev/null +++ b/lib/features/members/members_panel.dart @@ -0,0 +1,263 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/pyramid_logo.dart'; + +class MembersPanel extends ConsumerWidget { + final String roomId; + /// When set, a close button is shown in the header (used on mobile/overlay). + final VoidCallback? onClose; + /// Panel width. Defaults to 280 (desktop side panel). + final double width; + const MembersPanel({super.key, required this.roomId, this.onClose, this.width = 280}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + final client = ref.watch(matrixClientProvider).valueOrNull; + final room = client?.getRoomById(roomId); + final members = room?.getParticipants() ?? []; + + // Show all members; presence info may not be available + final online = members.toList(); + final offline = []; + + return Container( + width: width, + decoration: BoxDecoration( + color: pt.bg1, + border: Border(left: BorderSide(color: pt.border)), + ), + child: Column( + children: [ + Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 16), + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + Icon(Icons.group_rounded, size: 16, color: pt.fg), + const SizedBox(width: 8), + Text( + 'Members', + style: TextStyle( + color: pt.fg, + fontSize: 14, + fontWeight: FontWeight.w600, + ), + ), + const SizedBox(width: 6), + Text( + '${members.length}', + style: TextStyle(color: pt.fgDim, fontSize: 14), + ), + if (onClose != null) ...[ + const Spacer(), + GestureDetector( + onTap: onClose, + behavior: HitTestBehavior.opaque, + child: Padding( + padding: const EdgeInsets.all(4), + child: Icon(Icons.close_rounded, size: 20, color: pt.fgMuted), + ), + ), + ], + ], + ), + ), + Expanded( + child: ListView( + padding: const EdgeInsets.all(8), + children: [ + if (online.isNotEmpty) ...[ + _SectionLabel('Online — ${online.length}', pt), + ...online.map((m) => _MemberItem(member: m, pt: pt)), + ], + if (offline.isNotEmpty) ...[ + const SizedBox(height: 14), + _SectionLabel('Offline — ${offline.length}', pt), + ...offline.map((m) => _MemberItem( + member: m, + pt: pt, + isOffline: true, + )), + ], + if (members.isEmpty) ...[ + // Show placeholder members when room has none loaded + _SectionLabel('Online — 0', pt), + _SectionLabel('', pt), + Center( + child: Padding( + padding: const EdgeInsets.only(top: 24), + child: Text( + 'No members loaded', + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + ), + ), + ], + ], + ), + ), + ], + ), + ); + } +} + +class _SectionLabel extends StatelessWidget { + final String text; + final PyramidTheme pt; + + const _SectionLabel(this.text, this.pt); + + @override + Widget build(BuildContext context) { + if (text.isEmpty) return const SizedBox.shrink(); + return Padding( + padding: const EdgeInsets.fromLTRB(8, 8, 8, 4), + child: Text( + text.toUpperCase(), + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 0.04 * 11, + ), + ), + ); + } +} + +class _MemberItem extends StatefulWidget { + final User member; + final PyramidTheme pt; + final bool isOffline; + + const _MemberItem({ + required this.member, + required this.pt, + this.isOffline = false, + }); + + @override + State<_MemberItem> createState() => _MemberItemState(); +} + +class _MemberItemState extends State<_MemberItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final member = widget.member; + final name = member.calcDisplayname(); + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + final color = _colorFromName(name); + final status = widget.isOffline ? 'offline' : _memberStatus(member); + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + padding: const EdgeInsets.fromLTRB(8, 6, 8, 6), + decoration: BoxDecoration( + color: _hovered ? pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + children: [ + Opacity( + opacity: widget.isOffline ? 0.5 : 1, + child: Stack( + children: [ + Container( + width: 28, + height: 28, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Center( + child: Text( + initial, + style: const TextStyle( + color: Colors.white, + fontSize: 11, + fontWeight: FontWeight.w600, + ), + ), + ), + ), + if (!widget.isOffline) + Positioned( + bottom: -2, + right: -2, + child: PresenceDot( + status: status, + size: 9, + borderColor: pt.bgHover, + ), + ), + ], + ), + ), + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + name, + style: TextStyle( + color: widget.isOffline ? pt.fgMuted : pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + ], + ), + ), + ); + } + + String _memberStatus(User m) { + try { + // ignore: deprecated_member_use + final p = m.room.client.presences[m.id]; + if (p == null) return 'offline'; + // Veraltete "online"-Presence vom Server nicht blind übernehmen: + // nur online zeigen, wenn die letzte Aktivität frisch ist. + final last = p.lastActiveTimestamp; + final fresh = last != null && + DateTime.now().difference(last) < const Duration(minutes: 5); + return switch (p.presence) { + PresenceType.online when p.currentlyActive == true || fresh => 'online', + PresenceType.online => 'offline', + PresenceType.unavailable => 'away', + _ => 'offline', + }; + } catch (_) { + return 'offline'; + } + } + + Color _colorFromName(String name) { + const colors = [ + Color(0xFF06B6D4), Color(0xFFA855F7), Color(0xFF10B981), + Color(0xFFF43F5E), Color(0xFF3B82F6), Color(0xFFF59E0B), + ]; + if (name.isEmpty) return colors[0]; + return colors[name.codeUnitAt(0) % colors.length]; + } +} diff --git a/lib/features/rooms/room_list_item.dart b/lib/features/rooms/room_list_item.dart deleted file mode 100644 index 7ae29a9..0000000 --- a/lib/features/rooms/room_list_item.dart +++ /dev/null @@ -1,148 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:matrix/matrix.dart'; -import 'package:pyramid/widgets/mxc_image.dart'; - -class RoomListItem extends StatelessWidget { - final Room room; - final VoidCallback onTap; - - const RoomListItem({super.key, required this.room, required this.onTap}); - - @override - Widget build(BuildContext context) { - final unread = room.notificationCount; - final lastEvent = room.lastEvent; - final theme = Theme.of(context); - - return ListTile( - onTap: onTap, - leading: _RoomAvatar(room: room), - title: Text( - room.getLocalizedDisplayname(), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: unread > 0 - ? theme.textTheme.bodyLarge?.copyWith(fontWeight: FontWeight.bold) - : theme.textTheme.bodyLarge, - ), - subtitle: lastEvent != null - ? Text( - _previewText(lastEvent), - maxLines: 1, - overflow: TextOverflow.ellipsis, - style: theme.textTheme.bodySmall, - ) - : null, - trailing: Column( - mainAxisAlignment: MainAxisAlignment.center, - crossAxisAlignment: CrossAxisAlignment.end, - children: [ - if (lastEvent != null) - Text( - _formatTime(lastEvent.originServerTs), - style: theme.textTheme.labelSmall?.copyWith( - color: unread > 0 - ? theme.colorScheme.primary - : theme.colorScheme.onSurfaceVariant, - ), - ), - if (unread > 0) ...[ - const SizedBox(height: 4), - _UnreadBadge(count: unread), - ], - ], - ), - ); - } - - String _previewText(Event event) { - if (event.type == EventTypes.Message) { - final body = event.body; - if (body.isNotEmpty) return body; - } - return event.type; - } - - String _formatTime(DateTime time) { - final now = DateTime.now(); - if (time.day == now.day && - time.month == now.month && - time.year == now.year) { - return '${time.hour.toString().padLeft(2, '0')}:${time.minute.toString().padLeft(2, '0')}'; - } - return '${time.day.toString().padLeft(2, '0')}.${time.month.toString().padLeft(2, '0')}'; - } -} - -class _RoomAvatar extends StatelessWidget { - final Room room; - const _RoomAvatar({required this.room}); - - @override - Widget build(BuildContext context) { - final avatar = room.avatar; - final name = room.getLocalizedDisplayname(); - final initials = name.isNotEmpty ? name[0].toUpperCase() : '?'; - final color = _colorForName(name, Theme.of(context).colorScheme); - - return CircleAvatar( - radius: 24, - backgroundColor: color, - child: ClipOval( - child: avatar != null - ? MxcImage( - mxcUri: avatar, - width: 48, - height: 48, - placeholder: (_) => Text( - initials, - style: const TextStyle( - color: Colors.white, fontWeight: FontWeight.bold), - ), - ) - : Text( - initials, - style: const TextStyle( - color: Colors.white, fontWeight: FontWeight.bold), - ), - ), - ); - } - - Color _colorForName(String name, ColorScheme scheme) { - final colors = [ - scheme.primary, - scheme.secondary, - scheme.tertiary, - Colors.teal, - Colors.indigo, - Colors.orange, - ]; - final hash = name.codeUnits.fold(0, (a, b) => a + b); - return colors[hash % colors.length]; - } -} - -class _UnreadBadge extends StatelessWidget { - final int count; - const _UnreadBadge({required this.count}); - - @override - Widget build(BuildContext context) { - final theme = Theme.of(context); - return Container( - padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), - decoration: BoxDecoration( - color: theme.colorScheme.primary, - borderRadius: BorderRadius.circular(10), - ), - child: Text( - count > 99 ? '99+' : '$count', - style: theme.textTheme.labelSmall?.copyWith( - color: theme.colorScheme.onPrimary, - fontWeight: FontWeight.bold, - ), - ), - ); - } -} diff --git a/lib/features/rooms/rooms_page.dart b/lib/features/rooms/rooms_page.dart deleted file mode 100644 index 399ab95..0000000 --- a/lib/features/rooms/rooms_page.dart +++ /dev/null @@ -1,55 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:go_router/go_router.dart'; -import 'package:pyramid/features/rooms/room_list_item.dart'; -import 'package:pyramid/features/rooms/rooms_provider.dart'; - -class RoomsPage extends ConsumerWidget { - const RoomsPage({super.key}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final roomsAsync = ref.watch(roomListProvider); - - return Scaffold( - appBar: AppBar( - title: const Text('Pyramid'), - actions: [ - IconButton( - icon: const Icon(Icons.settings_outlined), - onPressed: () => context.go('/settings'), - ), - ], - ), - body: roomsAsync.when( - loading: () => const Center(child: CircularProgressIndicator()), - error: (e, _) => Center(child: Text('Fehler: $e')), - data: (rooms) { - if (rooms.isEmpty) { - return const Center( - child: Column( - mainAxisSize: MainAxisSize.min, - children: [ - Icon(Icons.forum_outlined, size: 64), - SizedBox(height: 16), - Text('Noch keine Räume'), - ], - ), - ); - } - return ListView.separated( - itemCount: rooms.length, - separatorBuilder: (context, i) => const Divider(height: 1, indent: 72), - itemBuilder: (context, i) { - final room = rooms[i]; - return RoomListItem( - room: room, - onTap: () => context.go('/chat/${Uri.encodeComponent(room.id)}'), - ); - }, - ); - }, - ), - ); - } -} diff --git a/lib/features/rooms/rooms_panel.dart b/lib/features/rooms/rooms_panel.dart index 1b9d89b..3325e73 100644 --- a/lib/features/rooms/rooms_panel.dart +++ b/lib/features/rooms/rooms_panel.dart @@ -65,18 +65,28 @@ class _RoomsPanelState extends ConsumerState { activeSpaceId != 'dms' && activeSpaceId != 'rooms'; + final client = ref.watch(matrixClientProvider).valueOrNull; + final forceJoined = ref.watch(forceJoinedSpacesProvider); + final activeSpaceRoom = + isRealSpace ? client?.getRoomById(activeSpaceId) : null; + final isInvitedSpace = activeSpaceRoom?.membership == Membership.invite && + !forceJoined.contains(activeSpaceId); + return Container( color: pt.bg1, child: Column( children: [ _Header(pt: pt, spaceId: activeSpaceId), - _FilterInput( - controller: _filterCtrl, - pt: pt, - onChanged: (v) => setState(() => _filter = v), - ), + if (!isInvitedSpace) + _FilterInput( + controller: _filterCtrl, + pt: pt, + onChanged: (v) => setState(() => _filter = v), + ), Expanded( - child: isRealSpace + child: isInvitedSpace + ? _SpaceInviteView(space: activeSpaceRoom!, pt: pt) + : isRealSpace ? _SpaceRoomsList( spaceId: activeSpaceId, filter: _filter, @@ -111,21 +121,213 @@ class _RoomsPanelState extends ConsumerState { ), ), ), - if (call.isActive && !call.isVoiceChannel) MiniCallWidget(call: call), - if (voip.currentCall != null && - voip.currentCall!.state != CallState.kEnded) - MiniCallWidget(call: voip), - const UserPanel(), + // Call-Dock: immer ÜBER dem Konto-Balken, animiert ein-/ausblenden. + // Im Mobil-Querformat (Höhe knapp) liegen Call-Balken und + // Konto-Balken nebeneinander statt übereinander. + Builder(builder: (context) { + final hasVoipCall = voip.currentCall != null && + voip.currentCall!.state != CallState.kEnded; + final hasCallDock = call.isActive || hasVoipCall; + final isLandscapeCompact = + MediaQuery.sizeOf(context).height < 500; + + final callDock = AnimatedSize( + duration: const Duration(milliseconds: 220), + curve: Curves.easeOutCubic, + alignment: Alignment.bottomCenter, + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + if (call.isActive) MiniCallWidget(call: call), + if (hasVoipCall) MiniCallWidget(call: voip), + ], + ), + ); + + if (isLandscapeCompact && hasCallDock) { + return Row( + crossAxisAlignment: CrossAxisAlignment.end, + children: [ + Expanded(child: callDock), + const Expanded(child: UserPanel()), + ], + ); + } + return Column( + mainAxisSize: MainAxisSize.min, + children: [callDock, const UserPanel()], + ); + }), ], ), ); } } +// ─── Space invite view ───────────────────────────────────────────────────────── + +class _SpaceInviteView extends ConsumerStatefulWidget { + final Room space; + final PyramidTheme pt; + const _SpaceInviteView({required this.space, required this.pt}); + + @override + ConsumerState<_SpaceInviteView> createState() => _SpaceInviteViewState(); +} + +class _SpaceInviteViewState extends ConsumerState<_SpaceInviteView> { + bool _accepting = false; + bool _declining = false; + + Future _accept() async { + setState(() => _accepting = true); + final client = widget.space.client; + final id = widget.space.id; + try { + await client.joinRoomById(id).timeout(const Duration(seconds: 20)); + // Server confirmed the join. Switch to the channel list optimistically — + // the local sync membership may lag behind, so don't wait for it. + ref.read(forceJoinedSpacesProvider.notifier).add(id); + if (mounted) setState(() => _accepting = false); + } catch (e) { + if (mounted) { + setState(() => _accepting = false); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: Text( + 'Beitritt fehlgeschlagen: ${e.toString().split('\n').first}'), + backgroundColor: widget.pt.danger, + )); + } + } + } + + Future _decline() async { + setState(() => _declining = true); + try { + await widget.space.leave(); + if (mounted) { + ref.read(activeSpaceIdProvider.notifier).state = 'rooms'; + } + } catch (_) { + if (mounted) setState(() => _declining = false); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final client = ref.watch(matrixClientProvider).valueOrNull; + final name = widget.space.getLocalizedDisplayname(); + final busy = _accepting || _declining; + + return Center( + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 72, + height: 72, + decoration: BoxDecoration( + color: pt.accent.withAlpha(40), + borderRadius: BorderRadius.circular(20), + ), + child: client != null && widget.space.avatar != null + ? ClipRRect( + borderRadius: BorderRadius.circular(20), + child: MxcAvatar( + mxcUri: widget.space.avatar, + client: client, + size: 72, + borderRadius: BorderRadius.circular(20), + placeholder: (_) => Center( + child: Text( + name.isNotEmpty ? name[0].toUpperCase() : '?', + style: TextStyle( + color: pt.accent, + fontSize: 28, + fontWeight: FontWeight.w700), + ), + ), + ), + ) + : Center( + child: Text( + name.isNotEmpty ? name[0].toUpperCase() : '?', + style: TextStyle( + color: pt.accent, + fontSize: 28, + fontWeight: FontWeight.w700), + ), + ), + ), + const SizedBox(height: 16), + Text('Einladung zum Space', + style: TextStyle(color: pt.fgDim, fontSize: 13)), + const SizedBox(height: 4), + Text( + name, + textAlign: TextAlign.center, + style: TextStyle( + color: pt.fg, fontSize: 18, fontWeight: FontWeight.w700), + ), + const SizedBox(height: 24), + Row( + children: [ + Expanded( + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: pt.danger, + side: BorderSide(color: pt.danger.withAlpha(100)), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + onPressed: busy ? null : _decline, + child: _declining + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2)) + : const Text('Ablehnen'), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + onPressed: busy ? null : _accept, + child: _accepting + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2)) + : const Text('Beitreten'), + ), + ), + ], + ), + ], + ), + ), + ); + } +} + // ─── Header ─────────────────────────────────────────────────────────────────── enum _SpaceMenuItem { - newDm, createRoom, joinRoom, discoverRooms, + newDm, createGroup, createRoom, joinRoom, discoverRooms, editSpace, adminSpace, leaveSpace, } @@ -159,6 +361,9 @@ class _Header extends ConsumerWidget { switch (item) { case _SpaceMenuItem.newDm: showDialog(context: context, builder: (_) => const NewDmDialog()); + case _SpaceMenuItem.createGroup: + showDialog( + context: context, builder: (_) => const CreateJoinDialog()); case _SpaceMenuItem.createRoom: showDialog( context: context, builder: (_) => const CreateJoinDialog()); @@ -237,6 +442,9 @@ class _Header extends ConsumerWidget { value: _SpaceMenuItem.newDm, child: _MenuRow( Icons.chat_bubble_outline_rounded, 'Neue Unterhaltung', pt)), + PopupMenuItem( + value: _SpaceMenuItem.createGroup, + child: _MenuRow(Icons.group_add_rounded, 'Gruppe erstellen', pt)), ]; } else if (spaceId == 'rooms') { return [ @@ -270,14 +478,17 @@ class _Header extends ConsumerWidget { } } - // Check for space banner — prefer local override (set immediately on save) - // over the state event (only available after next Matrix sync) + // Check for banner — space banner for real spaces, server banner otherwise. final bannerOverrides = ref.watch(spaceBannerOverrideProvider); - final bannerUrl = isRealSpace && activeSpace != null - ? (bannerOverrides.containsKey(activeSpace.id) - ? bannerOverrides[activeSpace.id] - : activeSpace.getState(_kSpaceBannerType)?.content['url'] as String?) - : null; + final serverBanners = ref.watch(serverBannerProvider).valueOrNull ?? {}; + String? bannerUrl; + if (isRealSpace && activeSpace != null) { + bannerUrl = bannerOverrides.containsKey(activeSpace.id) + ? bannerOverrides[activeSpace.id] + : activeSpace.getState(_kSpaceBannerType)?.content['url'] as String?; + } else if (client != null) { + bannerUrl = serverBanners[client.homeserver.toString()]; + } final hasBanner = bannerUrl != null && client != null; Widget controlsRow = Row( @@ -359,13 +570,9 @@ class _Header extends ConsumerWidget { onPressed: () => handleMenu(_SpaceMenuItem.adminSpace), ), if (!isRealSpace) - PyrIconBtn( - icon: const Icon(Icons.notifications_none_rounded), - tooltip: 'Notifications', - onPressed: () {}, - ), + _NotificationsButton(pt: pt, hasBanner: hasBanner), PopupMenuButton<_SpaceMenuItem>( - tooltip: 'Optionen', + tooltip: 'Erstellen', color: pt.bg2, shape: RoundedRectangleBorder( borderRadius: BorderRadius.circular(10), @@ -374,8 +581,8 @@ class _Header extends ConsumerWidget { onSelected: handleMenu, child: Padding( padding: const EdgeInsets.all(8), - child: Icon(Icons.keyboard_arrow_down_rounded, - color: hasBanner ? Colors.white70 : pt.fgDim, size: 16), + child: Icon(Icons.add_rounded, + color: hasBanner ? Colors.white70 : pt.fgDim, size: 18), ), ), ], @@ -460,6 +667,122 @@ class _MenuRow extends StatelessWidget { ]); } +// ─── Notifications button ────────────────────────────────────────────────────── + +/// Glocke im Header: Popup mit allen Räumen, die ungelesene Nachrichten oder +/// Mentions haben. Tippen öffnet den jeweiligen Raum. +class _NotificationsButton extends ConsumerWidget { + final PyramidTheme pt; + final bool hasBanner; + const _NotificationsButton({required this.pt, required this.hasBanner}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final rooms = ref.watch(roomListProvider).valueOrNull ?? []; + final unread = rooms + .where((r) => + r.membership == Membership.join && + (r.notificationCount > 0 || r.highlightCount > 0)) + .toList() + ..sort((a, b) { + final hl = b.highlightCount.compareTo(a.highlightCount); + if (hl != 0) return hl; + return b.notificationCount.compareTo(a.notificationCount); + }); + + return PopupMenuButton( + tooltip: 'Benachrichtigungen', + color: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(10), + side: BorderSide(color: pt.border)), + offset: const Offset(0, 36), + onSelected: (roomId) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + }, + itemBuilder: (_) { + if (unread.isEmpty) { + return [ + PopupMenuItem( + enabled: false, + child: Text('Keine neuen Benachrichtigungen', + style: TextStyle(color: pt.fgDim, fontSize: 13)), + ), + ]; + } + return unread + .map((r) => PopupMenuItem( + value: r.id, + child: Row( + children: [ + Icon( + r.highlightCount > 0 + ? Icons.alternate_email_rounded + : (r.isDirectChat + ? Icons.chat_bubble_outline_rounded + : Icons.tag_rounded), + size: 14, + color: + r.highlightCount > 0 ? pt.danger : pt.fgMuted, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + r.getLocalizedDisplayname(), + style: TextStyle(color: pt.fg, fontSize: 13), + overflow: TextOverflow.ellipsis, + ), + ), + const SizedBox(width: 8), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 1), + decoration: BoxDecoration( + color: r.highlightCount > 0 ? pt.danger : pt.accent, + borderRadius: BorderRadius.circular(999), + ), + child: Text( + '${r.notificationCount > 0 ? r.notificationCount : r.highlightCount}', + style: const TextStyle( + color: Colors.white, + fontSize: 10, + fontWeight: FontWeight.w700), + ), + ), + ], + ), + )) + .toList(); + }, + child: Padding( + padding: const EdgeInsets.all(8), + child: Stack( + clipBehavior: Clip.none, + children: [ + Icon(Icons.notifications_none_rounded, + size: 18, color: hasBanner ? Colors.white70 : pt.fgDim), + if (unread.isNotEmpty) + Positioned( + top: -1, + right: -1, + child: Container( + width: 8, + height: 8, + decoration: BoxDecoration( + color: pt.danger, + shape: BoxShape.circle, + border: Border.all(color: pt.bg1, width: 1.5), + ), + ), + ), + ], + ), + ), + ); + } +} + // ─── Filter input ────────────────────────────────────────────────────────────── class _FilterInput extends StatelessWidget { @@ -534,6 +857,106 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { // Local order override after drag-and-drop (room IDs in order per category key) final Map> _localOrder = {}; + // Joinable channels discovered via the space hierarchy (not yet a member). + List<_JoinableRoom> _joinable = []; + final Set _joining = {}; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) { + final client = ref.read(matrixClientProvider).valueOrNull; + if (client != null) _loadHierarchy(client); + }); + } + + @override + void didUpdateWidget(covariant _SpaceRoomsList old) { + super.didUpdateWidget(old); + if (old.spaceId != widget.spaceId) { + setState(() => _joinable = []); + final client = ref.read(matrixClientProvider).valueOrNull; + if (client != null) _loadHierarchy(client); + } + } + + /// Queries the server-side space hierarchy and keeps only rooms the user is + /// not yet a member of — these are the channels they can still join. + Future _loadHierarchy(Client client) async { + try { + final resp = await client.getSpaceHierarchy( + widget.spaceId, + maxDepth: 3, + suggestedOnly: false, + ); + final joinable = <_JoinableRoom>[]; + for (final chunk in resp.rooms) { + if (chunk.roomId == widget.spaceId) continue; + if (chunk.roomType == 'm.space') continue; // skip sub-spaces + // Keep every channel the hierarchy reports. The build method filters out + // the ones already rendered in the joined sections — relying on local + // membership here is unreliable because Continuwuity's sync lags behind. + joinable.add(_JoinableRoom( + roomId: chunk.roomId, + name: chunk.name ?? chunk.canonicalAlias ?? chunk.roomId, + isVoice: chunk.roomType == _kVoiceRoomType, + memberCount: chunk.numJoinedMembers, + )); + } + if (mounted) setState(() => _joinable = joinable); + } catch (_) { + // Hierarchy endpoint unavailable / no permission — silently ignore. + } + } + + Future _joinAndEnter(Client client, _JoinableRoom jr) async { + setState(() => _joining.add(jr.roomId)); + try { + await client.joinRoomById(jr.roomId).timeout(const Duration(seconds: 20)); + // Give the sync a brief chance to deliver the room object, but don't block + // on it — the local membership may lag behind the server. + Room? room = client.getRoomById(jr.roomId); + if (room == null) { + try { + await client.onSync.stream + .firstWhere((_) => client.getRoomById(jr.roomId) != null) + .timeout(const Duration(seconds: 4)); + } catch (_) {} + room = client.getRoomById(jr.roomId); + } + if (!mounted) return; + setState(() => _joining.remove(jr.roomId)); + if (jr.isVoice) { + // LiveKit only needs the room id + a display name, so connect even if the + // matrix room object hasn't synced locally yet. + final call = ref.read(callStateProvider); + if (call.isActive) await call.hangUp(); + ref.read(activeVoiceRoomIdProvider.notifier).state = jr.roomId; + await call.startCall( + roomName: jr.roomId, + roomDisplayName: room?.getLocalizedDisplayname() ?? jr.name, + identity: client.userID ?? '', + audioOnly: true, + voiceChannel: true, + matrixClient: client, + matrixRoomId: jr.roomId, + ); + } else if (room != null) { + ref.read(activeRoomIdProvider.notifier).state = room.id; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + } + } catch (e) { + if (mounted) { + setState(() => _joining.remove(jr.roomId)); + ScaffoldMessenger.of(context).showSnackBar(SnackBar( + content: + Text('Beitritt fehlgeschlagen: ${e.toString().split('\n').first}'), + backgroundColor: widget.pt.danger, + )); + } + } + } + Future _applyReorder( Room space, String categoryKey, List newOrder) async { try { @@ -600,6 +1023,10 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { .where((r) => r.membership == Membership.invite) .toList(); + // IDs already rendered in the joined/invited sections — used to avoid showing + // them again under "available channels" from the hierarchy. + final shownIds = {...invites.map((r) => r.id)}; + void selectRoom(Room room) { ref.read(activeRoomIdProvider.notifier).state = room.id; ref.read(viewModeProvider.notifier).state = ViewMode.chat; @@ -643,6 +1070,7 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { .where((r) => r.membership != Membership.leave && !r.isSpace) .toList(); + shownIds.addAll(catChildren.map((r) => r.id)); final filtered = catChildren .where((r) => widget.filter.isEmpty || @@ -677,6 +1105,7 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { .map((c) => client.getRoomById(c.roomId!)) .whereType() .toList(); + shownIds.addAll(directRooms.map((r) => r.id)); // Apply local order override if present final localOrd = _localOrder['__direct__']; @@ -698,6 +1127,14 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { .contains(widget.filter.toLowerCase())) .toList(); + // Joinable channels from the hierarchy that aren't already listed above. + final visibleJoinable = _joinable + .where((jr) => + !shownIds.contains(jr.roomId) && + (widget.filter.isEmpty || + jr.name.toLowerCase().contains(widget.filter.toLowerCase()))) + .toList(); + // Build the complete list return ListView( padding: const EdgeInsets.fromLTRB(8, 4, 8, 12), @@ -776,9 +1213,28 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { ); }), ], + // Joinable channels from the space hierarchy (not yet a member) + if (visibleJoinable.isNotEmpty) ...[ + Padding( + padding: const EdgeInsets.fromLTRB(8, 12, 8, 2), + child: Text('VERFÜGBARE KANÄLE', + style: TextStyle( + color: widget.pt.fgDim, + fontSize: 10, + fontWeight: FontWeight.w700, + letterSpacing: 0.6)), + ), + ...visibleJoinable.map((jr) => _JoinableRoomItem( + jr: jr, + joining: _joining.contains(jr.roomId), + pt: widget.pt, + onJoin: () => _joinAndEnter(client, jr), + )), + ], if (filteredDirect.isEmpty && categoryWidgets.isEmpty && - invites.isEmpty) + invites.isEmpty && + visibleJoinable.isEmpty) Padding( padding: const EdgeInsets.all(16), child: Center( @@ -791,6 +1247,110 @@ class _SpaceRoomsListState extends ConsumerState<_SpaceRoomsList> { } } +// ─── Joinable room (from space hierarchy) ───────────────────────────────────── + +class _JoinableRoom { + final String roomId; + final String name; + final bool isVoice; + final int memberCount; + const _JoinableRoom({ + required this.roomId, + required this.name, + required this.isVoice, + required this.memberCount, + }); +} + +class _JoinableRoomItem extends StatefulWidget { + final _JoinableRoom jr; + final bool joining; + final PyramidTheme pt; + final VoidCallback onJoin; + const _JoinableRoomItem({ + required this.jr, + required this.joining, + required this.pt, + required this.onJoin, + }); + + @override + State<_JoinableRoomItem> createState() => _JoinableRoomItemState(); +} + +class _JoinableRoomItemState extends State<_JoinableRoomItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final jr = widget.jr; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.joining ? null : widget.onJoin, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + margin: const EdgeInsets.symmetric(vertical: 1), + padding: EdgeInsets.symmetric( + horizontal: pt.rowPadX, vertical: pt.rowPadY), + decoration: BoxDecoration( + color: _hovered ? pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + children: [ + SizedBox( + width: 16, + height: 16, + child: Icon( + jr.isVoice ? Icons.mic_rounded : Icons.tag_rounded, + size: 14, + color: pt.fgDim, + ), + ), + const SizedBox(width: 8), + Expanded( + child: Text( + jr.name, + style: TextStyle( + color: pt.fgMuted, + fontSize: 14, + fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ), + ), + if (widget.joining) + const SizedBox( + width: 14, + height: 14, + child: CircularProgressIndicator.adaptive(strokeWidth: 2), + ) + else + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: _hovered ? pt.accent : pt.bg3, + borderRadius: BorderRadius.circular(6), + ), + child: Text( + 'Beitreten', + style: TextStyle( + color: _hovered ? pt.accentFg : pt.fgMuted, + fontSize: 11, + fontWeight: FontWeight.w600), + ), + ), + ], + ), + ), + ), + ); + } +} + // ─── Category header ─────────────────────────────────────────────────────────── class _CategoryHeader extends StatefulWidget { @@ -1258,6 +1818,67 @@ class _RoomItemState extends ConsumerState<_RoomItem> { } } + /// Touch-friendly action menu — opened via long-press (the hover menu is not + /// reachable on touch devices). + void _showContextMenu() { + final pt = widget.pt; + final room = widget.room; + final isDm = room.isDirectChat; + + Widget action(IconData icon, String label, VoidCallback onTap, + {bool danger = false}) { + return ListTile( + leading: Icon(icon, size: 20, color: danger ? pt.danger : pt.fgMuted), + title: Text(label, + style: TextStyle( + color: danger ? pt.danger : pt.fg, fontSize: 14)), + onTap: () { + Navigator.pop(context); + onTap(); + }, + ); + } + + showModalBottomSheet( + context: context, + backgroundColor: pt.bg2, + shape: const RoundedRectangleBorder( + borderRadius: BorderRadius.vertical(top: Radius.circular(16))), + builder: (ctx) => SafeArea( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 20, 8), + child: Row(children: [ + Expanded( + child: Text(room.getLocalizedDisplayname(), + style: TextStyle( + color: pt.fg, + fontSize: 15, + fontWeight: FontWeight.w700), + overflow: TextOverflow.ellipsis), + ), + ]), + ), + Divider(height: 1, color: pt.border), + if (!isDm) ...[ + action(Icons.person_add_outlined, 'Nutzer einladen', _inviteUser), + action(Icons.settings_rounded, 'Einstellungen', _showRoomSettings), + ], + action( + Icons.exit_to_app_rounded, + isDm ? 'Chat verlassen' : 'Raum verlassen', + isDm ? _leaveDm : _leaveRoom, + danger: true, + ), + const SizedBox(height: 8), + ], + ), + ), + ); + } + @override Widget build(BuildContext context) { final pt = widget.pt; @@ -1279,6 +1900,7 @@ class _RoomItemState extends ConsumerState<_RoomItem> { onExit: (_) => setState(() => _hovered = false), child: GestureDetector( onTap: widget.onTap, + onLongPress: _showContextMenu, child: Stack( children: [ if (active) @@ -1693,7 +2315,15 @@ class _DmAvatarState extends ConsumerState<_DmAvatar> { Color? _dotColor() { final p = _presence; if (p == null) return null; - if (p.currentlyActive == true) return PyramidColors.online; + // Server-Presence kann veraltet sein (z.B. nie als offline gemeldet). + // Nur als online werten, wenn die letzte Aktivität wirklich frisch ist. + final last = p.lastActiveTimestamp; + final fresh = last != null && + DateTime.now().difference(last) < const Duration(minutes: 5); + if (p.presence == PresenceType.online && + (p.currentlyActive == true || fresh)) { + return PyramidColors.online; + } if (p.presence == PresenceType.unavailable) return PyramidColors.away; return null; } diff --git a/lib/features/rooms/rooms_provider.dart b/lib/features/rooms/rooms_provider.dart index d4a5ccf..999aa47 100644 --- a/lib/features/rooms/rooms_provider.dart +++ b/lib/features/rooms/rooms_provider.dart @@ -12,6 +12,22 @@ final roomListProvider = StreamProvider>((ref) async* { } }); +final dmUnreadCountProvider = StreamProvider((ref) async* { + final client = await ref.watch(matrixClientProvider.future); + + yield _countDmUnread(client); + + await for (final _ in client.onSync.stream) { + yield _countDmUnread(client); + } +}); + +int _countDmUnread(Client client) { + return client.rooms + .where((r) => !r.isSpace && r.isDirectChat && r.notificationCount > 0) + .length; +} + List _sortedRooms(Client client) { final rooms = client.rooms .where((r) => !r.isSpace) diff --git a/lib/features/rooms/user_panel.dart b/lib/features/rooms/user_panel.dart new file mode 100644 index 0000000..a616184 --- /dev/null +++ b/lib/features/rooms/user_panel.dart @@ -0,0 +1,165 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/hover_region.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; +import 'package:pyramid/widgets/pyramid_logo.dart'; + +final _ownProfileProvider = FutureProvider.autoDispose((ref) async { + final client = await ref.watch(matrixClientProvider.future); + final userId = client.userID; + if (userId == null) return null; + try { + return await client.getProfileFromUserId(userId); + } catch (_) { + return null; + } +}); + +class UserPanel extends ConsumerWidget { + const UserPanel({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + final clientAsync = ref.watch(matrixClientProvider); + final profile = ref.watch(_ownProfileProvider).valueOrNull; + + final client = clientAsync.valueOrNull; + final fallbackName = client?.userID?.split(':').first.replaceFirst('@', '') ?? '...'; + final displayName = profile?.displayName ?? fallbackName; + final avatarUri = profile?.avatarUrl; + + return Padding( + padding: const EdgeInsets.fromLTRB(8, 0, 8, 8), + child: Container( + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(4), + border: Border.all(color: pt.border), + ), + child: _ProfileRow( + pt: pt, + client: client, + avatarUri: avatarUri, + displayName: displayName, + ref: ref, + ), + ), + ); + } +} + +class _ProfileRow extends StatelessWidget { + final PyramidTheme pt; + final Client? client; + final Uri? avatarUri; + final String displayName; + final WidgetRef ref; + + const _ProfileRow({ + required this.pt, + required this.client, + required this.avatarUri, + required this.displayName, + required this.ref, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + child: Row( + children: [ + Stack( + clipBehavior: Clip.none, + children: [ + if (client != null && avatarUri != null) + MxcAvatar( + mxcUri: avatarUri!, + client: client!, + size: 32, + borderRadius: BorderRadius.circular(4), + placeholder: (_) => _InitialAvatar(name: displayName, radius: 4), + ) + else + _InitialAvatar(name: displayName, radius: 4), + Positioned( + bottom: -2, + right: -2, + child: PresenceDot(status: 'online', size: 10, borderColor: pt.bg2), + ), + ], + ), + const SizedBox(width: 8), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + mainAxisSize: MainAxisSize.min, + children: [ + Text( + displayName, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w600, + ), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + Text( + 'online', + style: TextStyle(color: pt.fgMuted, fontSize: 11), + maxLines: 1, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ), + PyrIconBtn( + size: 28, + icon: const Icon(Icons.settings_rounded), + tooltip: 'Einstellungen', + onPressed: () => ref.read(activeModalProvider.notifier).state = ModalKind.settings, + ), + ], + ), + ); + } +} + +class _InitialAvatar extends StatelessWidget { + final String name; + final double radius; + final double size; + const _InitialAvatar({required this.name, required this.radius, this.size = 32}); + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration( + gradient: const LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [Color(0xFFFF6B9D), Color(0xFFC471F5)], + ), + borderRadius: BorderRadius.circular(radius), + ), + child: Center( + child: Text( + name.isNotEmpty ? name[0].toUpperCase() : '?', + style: TextStyle( + color: Colors.white, + fontSize: size * 0.44, + fontWeight: FontWeight.w600, + ), + ), + ), + ); + } +} diff --git a/lib/features/spaces/space_admin_dialog.dart b/lib/features/spaces/space_admin_dialog.dart new file mode 100644 index 0000000..3b0b8cd --- /dev/null +++ b/lib/features/spaces/space_admin_dialog.dart @@ -0,0 +1,2278 @@ +import 'dart:typed_data'; + +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/material.dart' hide Visibility; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/banner_crop_dialog.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +const _kSpaceBannerEvent = 'io.pyramid.space.banner'; + +/// Ändert die Power-Levels auf Basis des aktuellen SERVER-Stands (nicht des +/// lokalen Caches!). Das SDK-`setPower` und ein lokal fehlendes +/// power_levels-Event haben sonst zur Folge, dass die users-Map des Servers +/// mit einem Minimal-Event überschrieben wird — und Admins sich selbst +/// aussperren (genau das ist hier bereits passiert). +Future updatePowerLevelsSafely( + Room room, + void Function(Map content) mutate, +) async { + Map content; + try { + content = Map.from( + await room.client + .getRoomStateWithKey(room.id, EventTypes.RoomPowerLevels, ''), + ); + } on MatrixException catch (e) { + if (e.errcode == 'M_NOT_FOUND') { + content = {}; + } else { + rethrow; + } + } + final users = content['users']; + content['users'] = + users is Map ? Map.from(users) : {}; + mutate(content); + + // Selbst-Aussperr-Schutz: Nach der Änderung muss der eigene Account immer + // noch hoch genug stehen, um Power-Levels erneut zu ändern — sonst gäbe es + // kein Zurück mehr. Greift bei versehentlicher Selbst-Degradierung ODER + // wenn ein neu geschriebenes Event den eigenen Eintrag nicht enthält. + final myId = room.client.userID; + if (myId != null) { + int asInt(Object? v, int fallback) => v is int ? v : fallback; + final usersMap = content['users'] as Map; + final myLevel = asInt(usersMap[myId], asInt(content['users_default'], 0)); + final events = content['events']; + final neededForPl = (events is Map && events['m.room.power_levels'] != null) + ? asInt(events['m.room.power_levels'], 50) + : asInt(content['state_default'], 50); + if (myLevel < neededForPl) { + throw Exception( + 'Abgebrochen, um eine Selbst-Aussperrung zu verhindern: ' + 'Diese Änderung würde dein Level auf $myLevel senken, ' + 'aber zum Verwalten der Berechtigungen sind $neededForPl nötig.', + ); + } + } + + await room.client + .setRoomStateWithKey(room.id, EventTypes.RoomPowerLevels, '', content); +} + +// Power level labels +const _kPowerAdmin = 100; +const _kPowerMod = 50; +const _kPowerMember = 0; + +String _powerLabel(int level) { + if (level >= _kPowerAdmin) return 'Admin'; + if (level >= _kPowerMod) return 'Moderator'; + return 'Mitglied'; +} + +Color _powerColor(int level, PyramidTheme pt) { + if (level >= _kPowerAdmin) return const Color(0xFFED4245); + if (level >= _kPowerMod) return const Color(0xFFF59E0B); + return pt.fgDim; +} + +class SpaceAdminDialog extends ConsumerStatefulWidget { + final Room space; + const SpaceAdminDialog({super.key, required this.space}); + + @override + ConsumerState createState() => _SpaceAdminDialogState(); +} + +class _SpaceAdminDialogState extends ConsumerState + with SingleTickerProviderStateMixin { + late TabController _tabs; + + @override + void initState() { + super.initState(); + _tabs = TabController(length: 4, vsync: this); + } + + @override + void dispose() { + _tabs.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(pt.rLg)), + insetPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 560, maxHeight: 680), + child: Column( + children: [ + _DialogHeader(space: widget.space, pt: pt, tabs: _tabs), + Expanded( + child: TabBarView( + controller: _tabs, + children: [ + _OverviewTab(space: widget.space), + _MembersTab(space: widget.space), + _PermissionsTab(space: widget.space), + _ChannelsTab(space: widget.space), + ], + ), + ), + ], + ), + ), + ); + } +} + +// ─── Header + TabBar ───────────────────────────────────────────────────────── + +class _DialogHeader extends ConsumerWidget { + final Room space; + final PyramidTheme pt; + final TabController tabs; + const _DialogHeader({required this.space, required this.pt, required this.tabs}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final client = ref.watch(matrixClientProvider).valueOrNull; + final name = space.getLocalizedDisplayname(); + final avatarUri = space.avatar; + final letter = name.isNotEmpty ? name[0].toUpperCase() : '?'; + + Widget avatar; + if (client != null && avatarUri != null) { + avatar = MxcAvatar( + mxcUri: avatarUri, + client: client, + size: 40, + borderRadius: BorderRadius.circular(pt.rBase), + placeholder: (_) => _InitialAvatar(letter: letter, pt: pt, size: 40), + ); + } else { + avatar = _InitialAvatar(letter: letter, pt: pt, size: 40); + } + + return Container( + decoration: BoxDecoration( + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 12, 12), + child: Row( + children: [ + avatar, + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(name, + style: TextStyle( + color: pt.fg, + fontSize: 17, + fontWeight: FontWeight.w700)), + Text('Space-Einstellungen', + style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + IconButton( + icon: Icon(Icons.close, color: pt.fgDim, size: 20), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ), + ), + TabBar( + controller: tabs, + labelColor: pt.accent, + unselectedLabelColor: pt.fgDim, + indicatorColor: pt.accent, + indicatorSize: TabBarIndicatorSize.label, + tabs: const [ + Tab(text: 'Übersicht'), + Tab(text: 'Mitglieder'), + Tab(text: 'Berechtigungen'), + Tab(text: 'Kanäle'), + ], + ), + ], + ), + ); + } +} + +// ─── Overview Tab ───────────────────────────────────────────────────────────── + +class _OverviewTab extends ConsumerStatefulWidget { + final Room space; + const _OverviewTab({required this.space}); + + @override + ConsumerState<_OverviewTab> createState() => _OverviewTabState(); +} + +class _OverviewTabState extends ConsumerState<_OverviewTab> { + late TextEditingController _nameCtrl; + late TextEditingController _topicCtrl; + bool _saving = false; + String? _error; + String? _success; + Uint8List? _pendingBanner; + String? _bannerMxcUri; + Uint8List? _pendingAvatar; + + @override + void initState() { + super.initState(); + _nameCtrl = TextEditingController( + text: widget.space.getLocalizedDisplayname()); + _topicCtrl = TextEditingController(text: widget.space.topic); + // Prefer local override (set on last save) over room state event + final overrides = ref.read(spaceBannerOverrideProvider); + _bannerMxcUri = overrides.containsKey(widget.space.id) + ? overrides[widget.space.id] + : widget.space.getState(_kSpaceBannerEvent)?.content['url'] as String?; + } + + @override + void dispose() { + _nameCtrl.dispose(); + _topicCtrl.dispose(); + super.dispose(); + } + + Future _pickBanner() async { + final result = await FilePicker.platform + .pickFiles(type: FileType.image, withData: true); + final file = result?.files.first; + if (file == null) return; + final raw = file.bytes ?? await file.xFile.readAsBytes(); + if (!mounted) return; + final cropped = await showDialog( + context: context, + builder: (_) => BannerCropDialog(imageBytes: raw, aspectRatio: 2.4), + ); + if (cropped == null || !mounted) return; + setState(() => _pendingBanner = cropped); + } + + Future _pickAvatar() async { + final result = await FilePicker.platform + .pickFiles(type: FileType.image, withData: true); + final file = result?.files.first; + if (file == null) return; + final raw = file.bytes ?? await file.xFile.readAsBytes(); + if (!mounted) return; + setState(() => _pendingAvatar = raw); + } + + Future _removeAvatar() async { + setState(() => _pendingAvatar = null); + try { + await widget.space.client.setRoomStateWithKey( + widget.space.id, EventTypes.RoomAvatar, '', {}); + } catch (_) {} + } + + Future _removeBanner() async { + setState(() { _pendingBanner = null; _bannerMxcUri = null; }); + try { + await widget.space.client.setRoomStateWithKey( + widget.space.id, _kSpaceBannerEvent, '', {}); + } catch (_) {} + } + + Future _save() async { + setState(() { _saving = true; _error = null; _success = null; }); + // Welcher Schritt gerade läuft — für präzise Fehlermeldungen statt eines + // pauschalen "keine Berechtigung" (das auch von Upload-Fehlern kam). + var step = 'Speichern'; + try { + final client = widget.space.client; + final newName = _nameCtrl.text.trim(); + final newTopic = _topicCtrl.text.trim(); + if (newName.isNotEmpty && + newName != widget.space.getLocalizedDisplayname()) { + step = 'Name ändern'; + await widget.space.setName(newName); + } + if (newTopic != widget.space.topic) { + step = 'Beschreibung ändern'; + await widget.space.setDescription(newTopic); + } + if (_pendingAvatar != null) { + step = 'Avatar hochladen'; + final uri = await client.uploadContent( + _pendingAvatar!, + filename: 'space_avatar.jpg', + contentType: 'image/jpeg', + ); + step = 'Avatar setzen'; + await _setStateWithRepair( + client, + EventTypes.RoomAvatar, + {'url': uri.toString()}, + ); + setState(() => _pendingAvatar = null); + } + if (_pendingBanner != null) { + step = 'Banner hochladen'; + final uri = await client.uploadContent( + _pendingBanner!, + filename: 'space_banner.jpg', + contentType: 'image/jpeg', + ); + step = 'Banner setzen'; + await _setStateWithRepair( + client, + _kSpaceBannerEvent, + {'url': uri.toString()}, + ); + final uriStr = uri.toString(); + // Update local override immediately so header updates before next sync + ref.read(spaceBannerOverrideProvider.notifier).update( + (m) => {...m, widget.space.id: uriStr}, + ); + setState(() { + _bannerMxcUri = uriStr; + _pendingBanner = null; + }); + } + setState(() { _success = 'Gespeichert'; }); + } catch (e) { + // Server-Fehlertext anzeigen (MatrixException liefert lesbare Meldung) — + // nicht pauschal auf "Admin-Level erforderlich" mappen. + final raw = e is MatrixException + ? '${e.errcode}: ${e.errorMessage}' + : e.toString().split('\n').first; + var detail = ''; + if (e is MatrixException && e.errcode == 'M_FORBIDDEN') { + detail = '\n${_permDiagnostics()}'; + // Zusätzlich die SERVER-Sicht der Power-Levels holen — die lokale + // Kopie kann von der des Servers abweichen. + try { + final pl = await widget.space.client.getRoomStateWithKey( + widget.space.id, EventTypes.RoomPowerLevels, ''); + detail += + '\nServer-PL: users=${pl['users']}, state_default=${pl['state_default']}, events=${pl['events']}'; + } on MatrixException catch (se) { + detail += '\nServer-PL: ${se.errcode} (Event fehlt auch serverseitig)'; + } catch (_) {} + } + setState(() { + _error = '$step fehlgeschlagen – $raw$detail'; + }); + } finally { + setState(() { _saving = false; }); + } + } + + /// Sendet ein State-Event; bei M_FORBIDDEN in einem Raum OHNE + /// power_levels-Event (Continuwuity-Sonderfall: Server verweigert dann + /// Custom-State trotz Creator-Rechten) werden einmalig Standard-Power-Levels + /// mit uns als Admin angelegt und der Vorgang wiederholt. + Future _setStateWithRepair( + Client client, + String type, + Map content, + ) async { + try { + await client.setRoomStateWithKey(widget.space.id, type, '', content); + } on MatrixException catch (e) { + if (e.errcode != 'M_FORBIDDEN') rethrow; + final repaired = await _ensurePowerLevels(client); + if (!repaired) rethrow; + await client.setRoomStateWithKey(widget.space.id, type, '', content); + } + } + + /// Legt Standard-Power-Levels an, falls der Raum keine hat. + /// Gibt true zurück, wenn das Event neu angelegt wurde. + Future _ensurePowerLevels(Client client) async { + try { + await client.getRoomStateWithKey( + widget.space.id, EventTypes.RoomPowerLevels, ''); + return false; // existiert bereits — Ablehnung hat andere Ursache + } catch (_) { + // fehlt (M_NOT_FOUND) → anlegen + } + try { + await client.setRoomStateWithKey( + widget.space.id, + EventTypes.RoomPowerLevels, + '', + { + 'users': {client.userID!: 100}, + 'users_default': 0, + 'events': const {}, + 'events_default': 0, + 'state_default': 50, + 'ban': 50, + 'kick': 50, + 'redact': 50, + 'invite': 0, + 'notifications': {'room': 50}, + }, + ); + return true; + } catch (_) { + return false; + } + } + + /// Kompakte Berechtigungs-Diagnose für M_FORBIDDEN-Fehler: zeigt, wie der + /// Server die Lage vermutlich sieht (Raumversion, Creator, Power-Level). + String _permDiagnostics() { + try { + final space = widget.space; + final create = space.getState(EventTypes.RoomCreate); + final version = create?.content['room_version'] ?? '1'; + final creator = create?.senderId ?? '?'; + final own = space.ownPowerLevel; + final needed = space.powerForChangingStateEvent(_kSpaceBannerEvent); + final hasPl = space.getState(EventTypes.RoomPowerLevels) != null; + return 'Diagnose: dein Level $own, benötigt $needed, ' + 'Raumversion $version, Creator $creator' + '${hasPl ? '' : ', kein power_levels-Event vorhanden!'}'; + } catch (_) { + return ''; + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final client = ref.watch(matrixClientProvider).valueOrNull; + // SDK-Berechtigungsprüfung (berücksichtigt events-Overrides und + // state_default) statt hartcodiertem Admin-Level 100. + final canEdit = widget.space.canChangeStateEvent(EventTypes.RoomName) || + widget.space.ownPowerLevel >= _kPowerAdmin; + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // ── Banner ──────────────────────────────────────────────────────── + _SectionLabel('Banner', pt), + const SizedBox(height: 6), + GestureDetector( + onTap: canEdit ? _pickBanner : null, + child: Stack( + children: [ + AspectRatio( + aspectRatio: 2.4, + child: Container( + width: double.infinity, + decoration: BoxDecoration( + color: pt.bg0, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: _pendingBanner != null + ? Image.memory(_pendingBanner!, + fit: BoxFit.cover, width: double.infinity) + : (_bannerMxcUri != null && client != null + ? MxcImage( + mxcUri: _bannerMxcUri!, + client: client, + fit: BoxFit.cover, + width: double.infinity, + placeholder: Container(color: pt.bg0), + ) + : Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.add_photo_alternate_outlined, + size: 24, color: pt.fgDim), + const SizedBox(height: 4), + Text('Banner hinzufügen', + style: TextStyle( + color: pt.fgDim, fontSize: 12)), + ], + ), + )), + ), // Container + ), // AspectRatio + if (canEdit) + Positioned( + right: 6, + bottom: 6, + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + if (_bannerMxcUri != null || _pendingBanner != null) + GestureDetector( + onTap: _removeBanner, + child: Container( + margin: const EdgeInsets.only(right: 4), + padding: const EdgeInsets.symmetric( + horizontal: 7, vertical: 3), + decoration: BoxDecoration( + color: const Color(0xFFED4245).withAlpha(200), + borderRadius: BorderRadius.circular(5), + ), + child: const Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.delete_outline, + size: 11, color: Colors.white), + SizedBox(width: 3), + Text('Entfernen', + style: TextStyle( + color: Colors.white, fontSize: 11)), + ], + ), + ), + ), + Container( + padding: const EdgeInsets.symmetric( + horizontal: 7, vertical: 3), + decoration: BoxDecoration( + color: pt.bg0.withAlpha(200), + borderRadius: BorderRadius.circular(5), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_rounded, + size: 11, color: pt.fgMuted), + const SizedBox(width: 3), + Text('Banner ändern', + style: TextStyle( + color: pt.fgMuted, fontSize: 11)), + ], + ), + ), + ], + ), + ), + ], + ), + ), + const SizedBox(height: 16), + // ── Avatar ─────────────────────────────────────────────────────── + _SectionLabel('Serverbild', pt), + const SizedBox(height: 8), + _AvatarEditor( + space: widget.space, + pendingAvatar: _pendingAvatar, + canEdit: canEdit, + onPick: _pickAvatar, + onRemove: _removeAvatar, + pt: pt, + client: client, + ), + const SizedBox(height: 16), + // ── Name / Topic ───────────────────────────────────────────────── + _SectionLabel('Name', pt), + const SizedBox(height: 6), + _Field(controller: _nameCtrl, hint: 'Space-Name', pt: pt), + const SizedBox(height: 16), + _SectionLabel('Beschreibung', pt), + const SizedBox(height: 6), + _Field( + controller: _topicCtrl, + hint: 'Worum geht es in diesem Space?', + maxLines: 4, + pt: pt), + const SizedBox(height: 8), + _SpaceVisibilityToggle(space: widget.space), + const SizedBox(height: 20), + if (_error != null) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text(_error!, + style: const TextStyle(color: Color(0xFFED4245), fontSize: 12)), + ), + if (_success != null) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text(_success!, + style: const TextStyle(color: Color(0xFF57F287), fontSize: 12)), + ), + SizedBox( + width: double.infinity, + child: FilledButton( + onPressed: _saving ? null : _save, + style: FilledButton.styleFrom( + backgroundColor: pt.accent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase)), + ), + child: _saving + ? SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.bg0)) + : const Text('Speichern', + style: TextStyle( + color: Colors.white, fontWeight: FontWeight.w600)), + ), + ), + const SizedBox(height: 24), + _DangerZone(space: widget.space), + ], + ), + ); + } +} + +class _SpaceVisibilityToggle extends ConsumerStatefulWidget { + final Room space; + const _SpaceVisibilityToggle({required this.space}); + + @override + ConsumerState<_SpaceVisibilityToggle> createState() => + _SpaceVisibilityToggleState(); +} + +class _SpaceVisibilityToggleState + extends ConsumerState<_SpaceVisibilityToggle> { + bool? _isPublic; + bool _loading = true; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + try { + final joinRules = widget.space.joinRules; + setState(() { + _isPublic = joinRules == JoinRules.public; + _loading = false; + }); + } catch (_) { + setState(() => _loading = false); + } + } + + Future _toggle(bool value) async { + setState(() => _isPublic = value); + try { + await widget.space.setJoinRules( + value ? JoinRules.public : JoinRules.invite); + } catch (_) { + setState(() => _isPublic = !value); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + if (_loading) return const SizedBox.shrink(); + return Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Öffentlicher Space', + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w600)), + Text('Jeder kann diesem Space beitreten', + style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + Switch( + value: _isPublic ?? false, + onChanged: _toggle, + activeThumbColor: pt.accent, + ), + ], + ); + } +} + +class _DangerZone extends ConsumerWidget { + final Room space; + const _DangerZone({required this.space}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + return Container( + decoration: BoxDecoration( + border: Border.all(color: const Color(0xFFED4245).withAlpha(80)), + borderRadius: BorderRadius.circular(pt.rBase), + ), + padding: const EdgeInsets.all(16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Gefahrenzone', + style: TextStyle( + color: const Color(0xFFED4245), + fontSize: 13, + fontWeight: FontWeight.w700)), + const SizedBox(height: 12), + Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Space verlassen', + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w600)), + Text('Du verlässt diesen Space', + style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + OutlinedButton( + onPressed: () => _confirmLeave(context, ref), + style: OutlinedButton.styleFrom( + foregroundColor: const Color(0xFFED4245), + side: const BorderSide(color: Color(0xFFED4245)), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(8)), + ), + child: const Text('Verlassen'), + ), + ], + ), + ], + ), + ); + } + + void _confirmLeave(BuildContext context, WidgetRef ref) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('Space verlassen?'), + content: Text( + 'Möchtest du "${space.getLocalizedDisplayname()}" wirklich verlassen?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Abbrechen')), + TextButton( + onPressed: () async { + Navigator.pop(context); + Navigator.pop(context); + await space.leave(); + }, + child: const Text('Verlassen', + style: TextStyle(color: Color(0xFFED4245))), + ), + ], + ), + ); + } +} + +// ─── Members Tab ────────────────────────────────────────────────────────────── + +class _MembersTab extends ConsumerStatefulWidget { + final Room space; + const _MembersTab({required this.space}); + + @override + ConsumerState<_MembersTab> createState() => _MembersTabState(); +} + +class _MembersTabState extends ConsumerState<_MembersTab> { + List? _members; + bool _loading = true; + String? _error; + String _filter = ''; + final _filterCtrl = TextEditingController(); + + @override + void initState() { + super.initState(); + _load(); + } + + @override + void dispose() { + _filterCtrl.dispose(); + super.dispose(); + } + + Future _load() async { + try { + final members = + await widget.space.requestParticipants([Membership.join, Membership.invite]); + if (mounted) setState(() { _members = members; _loading = false; }); + } catch (e) { + if (mounted) setState(() { _error = e.toString(); _loading = false; }); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + + if (_loading) { + return Center( + child: CircularProgressIndicator(color: pt.accent, strokeWidth: 2)); + } + if (_error != null) { + return Center( + child: Text(_error!, style: TextStyle(color: pt.fgDim, fontSize: 13))); + } + + final members = _members ?? []; + final filtered = _filter.isEmpty + ? members + : members + .where((m) => + (m.displayName ?? m.id) + .toLowerCase() + .contains(_filter.toLowerCase()) || + m.id.toLowerCase().contains(_filter.toLowerCase())) + .toList() + ..sort((a, b) => (b.powerLevel).compareTo(a.powerLevel)); + + final ownPower = widget.space.ownPowerLevel; + + return Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), + child: Row( + children: [ + Expanded( + child: _SearchField( + controller: _filterCtrl, + hint: 'Mitglieder suchen…', + pt: pt, + onChanged: (v) => setState(() => _filter = v), + ), + ), + if (ownPower >= _kPowerMod) ...[ + const SizedBox(width: 8), + _InviteButton(space: widget.space), + ], + ], + ), + ), + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 8), + itemCount: filtered.length, + itemBuilder: (context, i) { + final member = filtered[i]; + return _MemberTile( + member: member, + space: widget.space, + ownPower: ownPower, + onChanged: _load, + ); + }, + ), + ), + ], + ); + } +} + +class _InviteButton extends ConsumerStatefulWidget { + final Room space; + const _InviteButton({required this.space}); + + @override + ConsumerState<_InviteButton> createState() => _InviteButtonState(); +} + +class _InviteButtonState extends ConsumerState<_InviteButton> { + bool _inviting = false; + String? _inviteError; + + void _showInvite() { + final pt = PyramidTheme.of(context); + final ctrl = TextEditingController(); + showDialog( + context: context, + builder: (ctx) => StatefulBuilder( + builder: (ctx, setS) => AlertDialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rLg)), + title: Text('Zu Space einladen', + style: TextStyle(color: pt.fg, fontWeight: FontWeight.w700)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _Field(controller: ctrl, hint: '@user:server.org', pt: pt), + const SizedBox(height: 6), + Text('Lädt zu Space und allen Kanälen ein.', + style: TextStyle(color: pt.fgDim, fontSize: 11)), + if (_inviteError != null) ...[ + const SizedBox(height: 6), + Text(_inviteError!, + style: TextStyle(color: pt.danger, fontSize: 12)), + ], + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx), + child: const Text('Abbrechen')), + FilledButton( + style: FilledButton.styleFrom(backgroundColor: pt.accent), + onPressed: _inviting + ? null + : () async { + final userId = ctrl.text.trim(); + if (userId.isEmpty) return; + setS(() { _inviting = true; _inviteError = null; }); + try { + // 1. Invite to space itself + await widget.space.invite(userId); + // 2. Invite to every joined child room + final client = widget.space.client; + for (final child in widget.space.spaceChildren) { + final roomId = child.roomId; + if (roomId == null) continue; + final room = client.getRoomById(roomId); + if (room == null || room.membership == Membership.leave) continue; + try { + await room.invite(userId); + } catch (_) {} + } + if (ctx.mounted) Navigator.pop(ctx); + } catch (e) { + setS(() { _inviteError = e.toString().split('\n').first; }); + } finally { + setS(() => _inviting = false); + } + }, + child: _inviting + ? const SizedBox( + width: 16, height: 16, + child: CircularProgressIndicator(strokeWidth: 2, color: Colors.white)) + : const Text('Einladen', + style: TextStyle(color: Colors.white)), + ), + ], + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return IconButton( + icon: Icon(Icons.person_add_outlined, color: pt.accent, size: 20), + tooltip: 'Einladen', + onPressed: _showInvite, + ); + } +} + +class _MemberTile extends ConsumerStatefulWidget { + final User member; + final Room space; + final int ownPower; + final VoidCallback onChanged; + + const _MemberTile({ + required this.member, + required this.space, + required this.ownPower, + required this.onChanged, + }); + + @override + ConsumerState<_MemberTile> createState() => _MemberTileState(); +} + +class _MemberTileState extends ConsumerState<_MemberTile> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final member = widget.member; + final power = member.powerLevel; + final name = member.displayName ?? member.id; + final client = ref.watch(matrixClientProvider).valueOrNull; + final avatarUri = member.avatarUrl; + final isMe = member.id == widget.space.client.userID; + final canManage = widget.ownPower > power && !isMe; + + Widget avatar; + final letter = name.isNotEmpty ? name[0].toUpperCase() : '?'; + if (client != null && avatarUri != null) { + avatar = MxcAvatar( + mxcUri: avatarUri, + client: client, + size: 32, + borderRadius: BorderRadius.circular(16), + placeholder: (_) => _InitialAvatar(letter: letter, pt: pt, size: 32), + ); + } else { + avatar = _InitialAvatar(letter: letter, pt: pt, size: 32); + } + + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: Container( + margin: const EdgeInsets.symmetric(vertical: 1), + decoration: BoxDecoration( + color: _hovered ? pt.bg2 : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: ListTile( + dense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 8), + leading: avatar, + title: Text(name, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + subtitle: Text(member.id, + style: TextStyle(color: pt.fgDim, fontSize: 11), + overflow: TextOverflow.ellipsis), + trailing: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 7, vertical: 3), + decoration: BoxDecoration( + color: _powerColor(power, pt).withAlpha(30), + borderRadius: BorderRadius.circular(6), + ), + child: Text(_powerLabel(power), + style: TextStyle( + color: _powerColor(power, pt), + fontSize: 11, + fontWeight: FontWeight.w600)), + ), + if (canManage) ...[ + const SizedBox(width: 4), + _MemberActions( + member: member, + space: widget.space, + ownPower: widget.ownPower, + onChanged: widget.onChanged), + ], + ], + ), + ), + ), + ); + } +} + +class _MemberActions extends ConsumerWidget { + final User member; + final Room space; + final int ownPower; + final VoidCallback onChanged; + + const _MemberActions({ + required this.member, + required this.space, + required this.ownPower, + required this.onChanged, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + return PopupMenuButton<_MemberAction>( + icon: Icon(Icons.more_vert, color: pt.fgDim, size: 18), + color: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase)), + itemBuilder: (_) => [ + if (ownPower >= _kPowerAdmin && member.powerLevel < _kPowerMod) + const PopupMenuItem( + value: _MemberAction.makeMod, + child: Text('Zum Moderator machen'), + ), + if (ownPower >= _kPowerAdmin && member.powerLevel == _kPowerMod) + const PopupMenuItem( + value: _MemberAction.removeMod, + child: Text('Moderator-Rechte entziehen'), + ), + if (ownPower >= _kPowerAdmin && member.powerLevel < _kPowerAdmin) + const PopupMenuItem( + value: _MemberAction.makeAdmin, + child: Text('Zum Admin machen'), + ), + const PopupMenuItem( + value: _MemberAction.kick, + child: Text('Kicken', style: TextStyle(color: Color(0xFFF59E0B))), + ), + const PopupMenuItem( + value: _MemberAction.ban, + child: Text('Bannen', style: TextStyle(color: Color(0xFFED4245))), + ), + ], + onSelected: (action) => _handleAction(context, action), + ); + } + + Future _handleAction(BuildContext context, _MemberAction action) async { + switch (action) { + case _MemberAction.makeMod: + await _setPower(context, _kPowerMod); + case _MemberAction.removeMod: + await _setPower(context, _kPowerMember); + case _MemberAction.makeAdmin: + _confirmAdmin(context); + case _MemberAction.kick: + _confirmKick(context); + case _MemberAction.ban: + _confirmBan(context); + } + } + + Future _setPower(BuildContext context, int level) async { + try { + // NICHT space.setPower() — das merged nur mit dem lokalen Cache und + // kann die users-Map des Servers zerstören (Admin-Aussperrung). + await updatePowerLevelsSafely(space, (content) { + (content['users'] as Map)[member.id] = level; + }); + onChanged(); + } catch (e) { + if (context.mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text(e.toString()))); + } + } + } + + void _confirmAdmin(BuildContext context) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('Admin machen?'), + content: Text( + '${member.displayName ?? member.id} zum Admin befördern? ' + 'Admin-Rechte können nicht einfach entzogen werden.'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Abbrechen')), + TextButton( + onPressed: () async { + Navigator.pop(context); + await _setPower(context, _kPowerAdmin); + }, + child: const Text('Admin machen', + style: TextStyle(color: Color(0xFFED4245))), + ), + ], + ), + ); + } + + void _confirmKick(BuildContext context) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('Mitglied kicken?'), + content: Text('${member.displayName ?? member.id} aus dem Space entfernen?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Abbrechen')), + TextButton( + onPressed: () async { + Navigator.pop(context); + try { + await space.kick(member.id); + onChanged(); + } catch (_) {} + }, + child: const Text('Kicken', + style: TextStyle(color: Color(0xFFF59E0B))), + ), + ], + ), + ); + } + + void _confirmBan(BuildContext context) { + showDialog( + context: context, + builder: (_) => AlertDialog( + title: const Text('Mitglied bannen?'), + content: Text( + '${member.displayName ?? member.id} dauerhaft aus dem Space ausschließen?'), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Abbrechen')), + TextButton( + onPressed: () async { + Navigator.pop(context); + try { + await space.ban(member.id); + onChanged(); + } catch (_) {} + }, + child: const Text('Bannen', + style: TextStyle(color: Color(0xFFED4245))), + ), + ], + ), + ); + } +} + +enum _MemberAction { makeMod, removeMod, makeAdmin, kick, ban } + +// ─── Permissions Tab ────────────────────────────────────────────────────────── + +class _PermissionsTab extends ConsumerStatefulWidget { + final Room space; + const _PermissionsTab({required this.space}); + + @override + ConsumerState<_PermissionsTab> createState() => _PermissionsTabState(); +} + +class _PermissionsTabState extends ConsumerState<_PermissionsTab> { + bool _saving = false; + String? _status; + + // Current power level values (loaded from room state) + late Map _levels; + + static const _defaults = { + 'events_default': 0, + 'state_default': 50, + 'invite': 0, + 'kick': 50, + 'ban': 50, + 'redact': 50, + }; + + static const _labels = { + 'events_default': 'Nachrichten senden', + 'state_default': 'Raum-Einstellungen ändern', + 'invite': 'Mitglieder einladen', + 'kick': 'Mitglieder kicken', + 'ban': 'Mitglieder bannen', + 'redact': 'Nachrichten löschen', + }; + + @override + void initState() { + super.initState(); + _load(); + } + + void _load() { + final content = widget.space + .getState(EventTypes.RoomPowerLevels) + ?.content ?? + {}; + _levels = { + for (final key in _defaults.keys) + key: (content[key] as int?) ?? _defaults[key]!, + }; + } + + Future _save() async { + setState(() { _saving = true; _status = null; }); + try { + // Server-Stand holen und nur die geänderten Schlüssel mergen — der + // lokale Cache kann unvollständig sein und würde users/events wipen. + await updatePowerLevelsSafely(widget.space, (content) { + for (final entry in _levels.entries) { + content[entry.key] = entry.value; + } + }); + setState(() => _status = 'Gespeichert'); + } catch (e) { + final msg = e is MatrixException + ? '${e.errcode}: ${e.errorMessage}' + : e.toString().split('\n').first; + setState(() => _status = 'Fehler: $msg'); + } finally { + setState(() => _saving = false); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final ownPower = widget.space.ownPowerLevel; + final canEdit = ownPower >= _kPowerAdmin; + + return SingleChildScrollView( + padding: const EdgeInsets.all(20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Mindestberechtigungen', + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w700, + letterSpacing: 0.8)), + const SizedBox(height: 4), + Text( + 'Lege fest, welche Stufe ein Mitglied mindestens haben muss, um diese Aktion auszuführen.', + style: TextStyle(color: pt.fgDim, fontSize: 12)), + const SizedBox(height: 16), + ...(_labels.entries.map((e) => _PermissionRow( + label: e.value, + value: _levels[e.key]!, + enabled: canEdit, + pt: pt, + onChanged: (v) => setState(() => _levels[e.key] = v), + ))), + if (canEdit) ...[ + const SizedBox(height: 20), + if (_status != null) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Text(_status!, + style: TextStyle( + color: _status!.startsWith('F') + ? const Color(0xFFED4245) + : const Color(0xFF57F287), + fontSize: 12)), + ), + SizedBox( + width: double.infinity, + child: FilledButton( + onPressed: _saving ? null : _save, + style: FilledButton.styleFrom( + backgroundColor: pt.accent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase)), + ), + child: _saving + ? SizedBox( + width: 18, + height: 18, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.bg0)) + : const Text('Speichern', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600)), + ), + ), + ], + ], + ), + ); + } +} + +class _PermissionRow extends StatelessWidget { + final String label; + final int value; + final bool enabled; + final PyramidTheme pt; + final ValueChanged onChanged; + + const _PermissionRow({ + required this.label, + required this.value, + required this.enabled, + required this.pt, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.only(bottom: 12), + child: Row( + children: [ + Expanded( + child: Text(label, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500)), + ), + if (enabled) + DropdownButton( + value: value, + dropdownColor: pt.bg2, + underline: const SizedBox.shrink(), + style: TextStyle(color: pt.fg, fontSize: 13), + items: const [ + DropdownMenuItem(value: 0, child: Text('Mitglied (0)')), + DropdownMenuItem(value: 50, child: Text('Moderator (50)')), + DropdownMenuItem(value: 100, child: Text('Admin (100)')), + ], + onChanged: (v) => v != null ? onChanged(v) : null, + ) + else + Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + decoration: BoxDecoration( + color: _powerColor(value, pt).withAlpha(30), + borderRadius: BorderRadius.circular(6), + ), + child: Text(_powerLabel(value), + style: TextStyle( + color: _powerColor(value, pt), + fontSize: 12, + fontWeight: FontWeight.w600)), + ), + ], + ), + ); + } +} + +// ─── Channels Tab ───────────────────────────────────────────────────────────── + +const _kSpaceChild = 'm.space.child'; +const _kSpaceParent = 'm.space.parent'; +const _kVoiceChannelType = 'io.pyramid.voice_channel'; + +class _ChannelsTab extends ConsumerStatefulWidget { + final Room space; + const _ChannelsTab({required this.space}); + + @override + ConsumerState<_ChannelsTab> createState() => _ChannelsTabState(); +} + +class _ChannelsTabState extends ConsumerState<_ChannelsTab> { + bool _busy = false; + + List<({String roomId, Room? room, bool isVoice})> _getChildren(Client client) { + final childStates = widget.space.states[_kSpaceChild] ?? {}; + final result = <({String roomId, Room? room, bool isVoice})>[]; + for (final entry in childStates.entries) { + final content = entry.value.content; + if (content.isEmpty) continue; + final childRoomId = entry.key; + final room = client.getRoomById(childRoomId); + final createContent = room?.getState('m.room.create')?.content; + final isVoice = createContent?['type'] == _kVoiceChannelType; + result.add((roomId: childRoomId, room: room, isVoice: isVoice)); + } + result.sort((a, b) { + final nameA = a.room?.getLocalizedDisplayname() ?? a.roomId; + final nameB = b.room?.getLocalizedDisplayname() ?? b.roomId; + return nameA.compareTo(nameB); + }); + return result; + } + + Future _removeChild(String roomId) async { + final client = ref.read(matrixClientProvider).valueOrNull; + if (client == null) return; + setState(() => _busy = true); + try { + await client.setRoomStateWithKey(widget.space.id, _kSpaceChild, roomId, {}); + if (mounted) setState(() {}); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(e.toString()))); + } + } finally { + if (mounted) setState(() => _busy = false); + } + } + + Future _addChild(String roomId) async { + final client = ref.read(matrixClientProvider).valueOrNull; + if (client == null) return; + final serverName = client.userID?.split(':').last ?? ''; + try { + await client.setRoomStateWithKey( + widget.space.id, + _kSpaceChild, + roomId, + {'via': [serverName], 'suggested': false}, + ); + // Best-effort: set parent in child room + try { + await client.setRoomStateWithKey( + roomId, + _kSpaceParent, + widget.space.id, + {'via': [serverName], 'canonical': true}, + ); + } catch (_) {} + if (mounted) setState(() {}); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(e.toString()))); + } + } + } + + Future _createAndAdd({ + required String name, + required bool isVoice, + required Client client, + }) async { + setState(() => _busy = true); + try { + final serverName = client.userID?.split(':').last ?? ''; + final roomId = await client.createRoom( + name: name, + visibility: Visibility.private, + preset: CreateRoomPreset.privateChat, + creationContent: isVoice ? {'type': _kVoiceChannelType} : null, + initialState: [ + StateEvent( + type: 'm.room.join_rules', + content: {'join_rule': 'restricted', 'allow': [ + {'type': 'm.room_membership', 'room_id': widget.space.id} + ]}, + ), + ], + ); + await client.setRoomStateWithKey( + widget.space.id, + _kSpaceChild, + roomId, + {'via': [serverName], 'suggested': false}, + ); + try { + await client.setRoomStateWithKey( + roomId, + _kSpaceParent, + widget.space.id, + {'via': [serverName], 'canonical': true}, + ); + } catch (_) {} + if (mounted) setState(() {}); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context) + .showSnackBar(SnackBar(content: Text(e.toString()))); + } + } finally { + if (mounted) setState(() => _busy = false); + } + } + + void _showCreateDialog(BuildContext context, Client client) { + showDialog( + context: context, + builder: (_) => _CreateChannelDialog( + onConfirm: (name, isVoice) => + _createAndAdd(name: name, isVoice: isVoice, client: client), + ), + ); + } + + void _showAddExistingDialog(BuildContext context, Client client) { + final childStates = widget.space.states[_kSpaceChild] ?? {}; + final existingIds = { + for (final e in childStates.entries) + if (e.value.content.isNotEmpty) e.key + }; + final available = client.rooms + .where((r) => !r.isSpace && !existingIds.contains(r.id)) + .toList() + ..sort((a, b) => a.getLocalizedDisplayname() + .compareTo(b.getLocalizedDisplayname())); + + showDialog( + context: context, + builder: (_) => _AddExistingDialog( + rooms: available, + client: client, + onConfirm: (roomId) => _addChild(roomId), + ), + ); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final client = ref.watch(matrixClientProvider).valueOrNull; + final ownPower = widget.space.ownPowerLevel; + final canManage = ownPower >= _kPowerMod; + + if (client == null) { + return Center( + child: CircularProgressIndicator(color: pt.accent, strokeWidth: 2)); + } + + final children = _getChildren(client); + + return Column( + children: [ + if (canManage) + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 4), + child: Row( + children: [ + Expanded( + child: OutlinedButton.icon( + icon: const Icon(Icons.add, size: 16), + label: const Text('Kanal erstellen'), + style: OutlinedButton.styleFrom( + foregroundColor: pt.accent, + side: BorderSide(color: pt.accent), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rSm)), + ), + onPressed: _busy + ? null + : () => _showCreateDialog(context, client), + ), + ), + const SizedBox(width: 8), + Expanded( + child: OutlinedButton.icon( + icon: const Icon(Icons.link, size: 16), + label: const Text('Raum hinzufügen'), + style: OutlinedButton.styleFrom( + foregroundColor: pt.fgDim, + side: BorderSide(color: pt.border), + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rSm)), + ), + onPressed: _busy + ? null + : () => _showAddExistingDialog(context, client), + ), + ), + ], + ), + ), + if (children.isEmpty) + Expanded( + child: Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.forum_outlined, color: pt.fgDim, size: 40), + const SizedBox(height: 8), + Text('Noch keine Kanäle', + style: TextStyle(color: pt.fgDim, fontSize: 13)), + ], + ), + ), + ) + else + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + itemCount: children.length, + itemBuilder: (context, i) { + final child = children[i]; + final name = child.room?.getLocalizedDisplayname() ?? + child.roomId; + return _ChannelItem( + name: name, + isVoice: child.isVoice, + roomId: child.roomId, + pt: pt, + canRemove: canManage, + onRemove: () => _removeChild(child.roomId), + ); + }, + ), + ), + ], + ); + } +} + +class _ChannelItem extends StatefulWidget { + final String name; + final bool isVoice; + final String roomId; + final PyramidTheme pt; + final bool canRemove; + final VoidCallback onRemove; + + const _ChannelItem({ + required this.name, + required this.isVoice, + required this.roomId, + required this.pt, + required this.canRemove, + required this.onRemove, + }); + + @override + State<_ChannelItem> createState() => _ChannelItemState(); +} + +class _ChannelItemState extends State<_ChannelItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: Container( + margin: const EdgeInsets.symmetric(vertical: 1), + decoration: BoxDecoration( + color: _hovered ? pt.bg2 : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: ListTile( + dense: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 10, vertical: 0), + leading: Icon( + widget.isVoice + ? Icons.volume_up_outlined + : Icons.tag, + color: pt.fgDim, + size: 18, + ), + title: Text( + widget.name, + style: TextStyle( + color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ), + subtitle: Text( + widget.isVoice ? 'Sprachkanal' : 'Textkanal', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + trailing: widget.canRemove && _hovered + ? IconButton( + icon: Icon(Icons.link_off, + color: const Color(0xFFED4245), size: 18), + tooltip: 'Aus Space entfernen', + onPressed: widget.onRemove, + ) + : null, + ), + ), + ); + } +} + +class _CreateChannelDialog extends StatefulWidget { + final void Function(String name, bool isVoice) onConfirm; + const _CreateChannelDialog({required this.onConfirm}); + + @override + State<_CreateChannelDialog> createState() => _CreateChannelDialogState(); +} + +class _CreateChannelDialogState extends State<_CreateChannelDialog> { + final _ctrl = TextEditingController(); + bool _isVoice = false; + + @override + void dispose() { + _ctrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return AlertDialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rLg)), + title: Text('Neuen Kanal erstellen', + style: TextStyle(color: pt.fg, fontWeight: FontWeight.w700)), + content: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionLabel('Name', pt), + const SizedBox(height: 6), + _Field(controller: _ctrl, hint: 'kanal-name', pt: pt), + const SizedBox(height: 16), + _SectionLabel('Typ', pt), + const SizedBox(height: 8), + Row( + children: [ + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isVoice = false), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 10), + decoration: BoxDecoration( + color: !_isVoice ? pt.accent.withAlpha(40) : pt.bg0, + border: Border.all( + color: !_isVoice ? pt.accent : pt.border), + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.tag, + color: !_isVoice ? pt.accent : pt.fgDim, + size: 16), + const SizedBox(width: 6), + Text('Text', + style: TextStyle( + color: !_isVoice ? pt.accent : pt.fgDim, + fontSize: 13, + fontWeight: FontWeight.w600)), + ], + ), + ), + ), + ), + const SizedBox(width: 8), + Expanded( + child: GestureDetector( + onTap: () => setState(() => _isVoice = true), + child: Container( + padding: const EdgeInsets.symmetric( + horizontal: 12, vertical: 10), + decoration: BoxDecoration( + color: _isVoice ? pt.accent.withAlpha(40) : pt.bg0, + border: Border.all( + color: _isVoice ? pt.accent : pt.border), + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.center, + children: [ + Icon(Icons.volume_up_outlined, + color: _isVoice ? pt.accent : pt.fgDim, + size: 16), + const SizedBox(width: 6), + Text('Sprache', + style: TextStyle( + color: _isVoice ? pt.accent : pt.fgDim, + fontSize: 13, + fontWeight: FontWeight.w600)), + ], + ), + ), + ), + ), + ], + ), + ], + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: const Text('Abbrechen')), + FilledButton( + style: FilledButton.styleFrom(backgroundColor: pt.accent), + onPressed: () { + final name = _ctrl.text.trim(); + if (name.isEmpty) return; + Navigator.pop(context); + widget.onConfirm(name, _isVoice); + }, + child: const Text('Erstellen', + style: TextStyle(color: Colors.white)), + ), + ], + ); + } +} + +class _AddExistingDialog extends StatefulWidget { + final List rooms; + final Client client; + final void Function(String roomId) onConfirm; + + const _AddExistingDialog({ + required this.rooms, + required this.client, + required this.onConfirm, + }); + + @override + State<_AddExistingDialog> createState() => _AddExistingDialogState(); +} + +class _AddExistingDialogState extends State<_AddExistingDialog> { + String _filter = ''; + final _ctrl = TextEditingController(); + + @override + void dispose() { + _ctrl.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final filtered = _filter.isEmpty + ? widget.rooms + : widget.rooms + .where((r) => r + .getLocalizedDisplayname() + .toLowerCase() + .contains(_filter.toLowerCase())) + .toList(); + + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rLg)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400, maxHeight: 520), + child: Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 20, 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text('Raum hinzufügen', + style: TextStyle( + color: pt.fg, + fontSize: 17, + fontWeight: FontWeight.w700)), + ), + IconButton( + icon: Icon(Icons.close, color: pt.fgDim, size: 20), + onPressed: () => Navigator.pop(context), + ), + ], + ), + const SizedBox(height: 12), + _SearchField( + controller: _ctrl, + hint: 'Raum suchen…', + pt: pt, + onChanged: (v) => setState(() => _filter = v), + ), + ], + ), + ), + const Divider(height: 1), + if (filtered.isEmpty) + Expanded( + child: Center( + child: Text('Keine Räume gefunden', + style: TextStyle(color: pt.fgDim, fontSize: 13)), + ), + ) + else + Expanded( + child: ListView.builder( + padding: const EdgeInsets.symmetric( + horizontal: 8, vertical: 4), + itemCount: filtered.length, + itemBuilder: (context, i) { + final room = filtered[i]; + final name = room.getLocalizedDisplayname(); + final letter = + name.isNotEmpty ? name[0].toUpperCase() : '?'; + final avatarUri = room.avatar; + final createContent = + room.getState('m.room.create')?.content; + final isVoice = + createContent?['type'] == _kVoiceChannelType; + return ListTile( + dense: true, + leading: avatarUri != null + ? MxcAvatar( + mxcUri: avatarUri, + client: widget.client, + size: 32, + borderRadius: BorderRadius.circular(pt.rSm), + placeholder: (_) => _InitialAvatar( + letter: letter, pt: pt, size: 32), + ) + : _InitialAvatar(letter: letter, pt: pt, size: 32), + title: Text(name, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + subtitle: Text( + isVoice ? 'Sprachkanal' : 'Textkanal', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + trailing: + Icon(isVoice ? Icons.volume_up_outlined : Icons.tag, + color: pt.fgDim, size: 16), + onTap: () { + Navigator.pop(context); + widget.onConfirm(room.id); + }, + ); + }, + ), + ), + ], + ), + ), + ); + } +} + +// ─── Shared helpers ─────────────────────────────────────────────────────────── + +class _SectionLabel extends StatelessWidget { + final String text; + final PyramidTheme pt; + const _SectionLabel(this.text, this.pt); + + @override + Widget build(BuildContext context) { + return Text(text, + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w700, + letterSpacing: 0.8)); + } +} + +class _Field extends StatelessWidget { + final TextEditingController controller; + final String hint; + final int maxLines; + final PyramidTheme pt; + + const _Field({ + required this.controller, + required this.hint, + this.maxLines = 1, + required this.pt, + }); + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + maxLines: maxLines, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + hintText: hint, + hintStyle: TextStyle(color: pt.fgDim), + filled: true, + fillColor: pt.bg0, + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.accent), + ), + ), + ); + } +} + +class _SearchField extends StatelessWidget { + final TextEditingController controller; + final String hint; + final PyramidTheme pt; + final ValueChanged onChanged; + + const _SearchField({ + required this.controller, + required this.hint, + required this.pt, + required this.onChanged, + }); + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + onChanged: onChanged, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + hintText: hint, + hintStyle: TextStyle(color: pt.fgDim), + prefixIcon: Icon(Icons.search, color: pt.fgDim, size: 18), + filled: true, + fillColor: pt.bg0, + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + isDense: true, + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rSm), + borderSide: BorderSide(color: pt.accent), + ), + ), + ); + } +} + +// ─── Avatar Editor ─────────────────────────────────────────────────────────── + +class _AvatarEditor extends StatelessWidget { + final Room space; + final Uint8List? pendingAvatar; + final bool canEdit; + final VoidCallback onPick; + final VoidCallback onRemove; + final PyramidTheme pt; + final dynamic client; + + const _AvatarEditor({ + required this.space, + required this.pendingAvatar, + required this.canEdit, + required this.onPick, + required this.onRemove, + required this.pt, + required this.client, + }); + + @override + Widget build(BuildContext context) { + final letter = space.getLocalizedDisplayname().isNotEmpty + ? space.getLocalizedDisplayname()[0].toUpperCase() + : '?'; + final avatarUri = space.avatar; + final hasAvatar = pendingAvatar != null || avatarUri != null; + + Widget avatarWidget; + if (pendingAvatar != null) { + avatarWidget = Image.memory(pendingAvatar!, fit: BoxFit.cover, + width: 64, height: 64); + } else if (avatarUri != null && client != null) { + avatarWidget = MxcAvatar( + mxcUri: avatarUri, + client: client, + size: 64, + borderRadius: BorderRadius.circular(32), + placeholder: (_) => _InitialAvatar(letter: letter, pt: pt, size: 64), + ); + } else { + avatarWidget = _InitialAvatar(letter: letter, pt: pt, size: 64); + } + + return Row( + children: [ + GestureDetector( + onTap: canEdit ? onPick : null, + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 64, + height: 64, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: avatarWidget, + ), + if (canEdit) + Positioned( + right: -2, + bottom: -2, + child: Container( + padding: const EdgeInsets.all(4), + decoration: BoxDecoration( + color: pt.accent, + shape: BoxShape.circle, + border: Border.all(color: pt.bg1, width: 2), + ), + child: const Icon(Icons.edit, size: 10, color: Colors.white), + ), + ), + ], + ), + ), + const SizedBox(width: 12), + Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + canEdit ? 'Klicken zum Ändern' : 'Serverbild', + style: TextStyle(color: pt.fg, fontSize: 13, + fontWeight: FontWeight.w500), + ), + if (canEdit && hasAvatar) + GestureDetector( + onTap: onRemove, + child: Text('Entfernen', + style: TextStyle( + color: const Color(0xFFED4245), fontSize: 12)), + ), + ], + ), + ], + ); + } +} + +class _InitialAvatar extends StatelessWidget { + final String letter; + final PyramidTheme pt; + final double size; + const _InitialAvatar( + {required this.letter, required this.pt, required this.size}); + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(size / 2), + ), + child: Center( + child: Text(letter, + style: TextStyle( + color: pt.fg, + fontSize: size * 0.4, + fontWeight: FontWeight.w700)), + ), + ); + } +} diff --git a/lib/features/spaces/spaces_rail.dart b/lib/features/spaces/spaces_rail.dart new file mode 100644 index 0000000..19d0eb7 --- /dev/null +++ b/lib/features/spaces/spaces_rail.dart @@ -0,0 +1,535 @@ +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/rooms/rooms_provider.dart'; +import 'package:pyramid/widgets/create_join_dialog.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; +import 'package:pyramid/widgets/pyramid_logo.dart'; + +class SpacesRail extends ConsumerWidget { + const SpacesRail({super.key}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final pt = PyramidTheme.of(context); + final spaces = ref.watch(spacesProvider).valueOrNull ?? []; + final activeSpaceId = ref.watch(activeSpaceIdProvider); + final forceJoined = ref.watch(forceJoinedSpacesProvider); + + final dmUnread = ref.watch(dmUnreadCountProvider).valueOrNull ?? 0; + + void selectSpace(String? id) { + // Save current room for the space we're leaving + final currentRoom = ref.read(activeRoomIdProvider); + final currentSpace = ref.read(activeSpaceIdProvider); + if (currentRoom != null) { + final updated = Map.from(ref.read(lastRoomPerSpaceProvider)); + updated[currentSpace] = currentRoom; + ref.read(lastRoomPerSpaceProvider.notifier).state = updated; + } + // Switch space and restore last visited room for the new space + ref.read(activeSpaceIdProvider.notifier).state = id; + ref.read(activeRoomIdProvider.notifier).state = + ref.read(lastRoomPerSpaceProvider)[id]; + final scaffold = Scaffold.maybeOf(context); + if (scaffold != null && scaffold.isDrawerOpen) { + scaffold.closeDrawer(); + } + } + + return Container( + width: 72, + color: pt.bg0, + child: Column( + children: [ + const SizedBox(height: 12), + _HomeButton( + pt: pt, + active: activeSpaceId == 'dms' || activeSpaceId == null, + unreadCount: dmUnread, + onTap: () => selectSpace('dms'), + ), + Padding( + padding: const EdgeInsets.symmetric(vertical: 8), + child: Container( + width: 32, + height: 2, + decoration: BoxDecoration( + color: pt.border, + borderRadius: BorderRadius.circular(2), + ), + ), + ), + Expanded( + child: ListView( + padding: EdgeInsets.zero, + children: [ + _VirtualSpaceItem( + id: 'rooms', + label: 'R', + color: const Color(0xFFF59E0B), + name: 'Rooms', + active: activeSpaceId == 'rooms', + unread: 0, + pt: pt, + onTap: () => selectSpace('rooms'), + ), + ...spaces.map((space) => Padding( + padding: const EdgeInsets.only(top: 6), + child: _SpaceItem( + space: space, + active: activeSpaceId == space.id, + isInvite: space.membership == Membership.invite && + !forceJoined.contains(space.id), + pt: pt, + onTap: () => selectSpace(space.id), + ), + )), + const SizedBox(height: 8), + _AddButton(pt: pt), + const SizedBox(height: 8), + ], + ), + ), + const SizedBox(height: 8), + _SettingsButton(pt: pt), + const SizedBox(height: 12), + ], + ), + ); + } +} + +class _SettingsButton extends ConsumerWidget { + final PyramidTheme pt; + const _SettingsButton({required this.pt}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Center( + child: IconButton( + icon: Icon(Icons.settings_outlined, color: pt.fgDim), + onPressed: () { + ref.read(activeModalProvider.notifier).state = ModalKind.settings; + final scaffold = Scaffold.maybeOf(context); + if (scaffold != null && scaffold.isDrawerOpen) { + scaffold.closeDrawer(); + } + }, + ), + ); + } +} + +class _HomeButton extends StatefulWidget { + final PyramidTheme pt; + final bool active; + final int unreadCount; + final VoidCallback onTap; + + const _HomeButton({ + required this.pt, + required this.active, + required this.unreadCount, + required this.onTap, + }); + + @override + State<_HomeButton> createState() => _HomeButtonState(); +} + +class _HomeButtonState extends State<_HomeButton> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Stack( + clipBehavior: Clip.none, + children: [ + if (widget.active) + Positioned( + left: -12, + top: 10, + child: Container( + width: 4, + height: 28, + decoration: BoxDecoration( + color: pt.accent, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(3), + bottomRight: Radius.circular(3), + ), + ), + ), + ), + MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutBack, + transform: _hovered + ? (Matrix4.translationValues(0, -2, 0)..rotateZ(-0.05)) + : Matrix4.identity(), + child: Tooltip( + message: 'Direct Messages', + waitDuration: const Duration(milliseconds: 400), + preferBelow: false, + child: Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 48, + height: 48, + decoration: BoxDecoration( + gradient: LinearGradient( + begin: Alignment.topLeft, + end: Alignment.bottomRight, + colors: [pt.accent, Color.fromARGB(255, + (pt.accent.r * 255 * 0.85).round().clamp(0, 255), + (pt.accent.g * 255 * 0.85).round().clamp(0, 255), + (pt.accent.b * 255 * 0.7).round().clamp(0, 255), + )], + ), + borderRadius: BorderRadius.circular( + widget.active ? pt.rLg * 0.6 : pt.rLg, + ), + boxShadow: widget.active + ? [BoxShadow(color: pt.accentGlow, blurRadius: 16, offset: const Offset(0, 4))] + : null, + ), + child: Center(child: PyramidLogo(size: 28, color: Colors.white)), + ), + if (widget.unreadCount > 0) + Positioned( + right: -4, + top: -4, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 5), + constraints: const BoxConstraints(minWidth: 18, minHeight: 18), + decoration: BoxDecoration( + color: pt.danger, + borderRadius: BorderRadius.circular(999), + border: Border.all(color: pt.bg0, width: 1.5), + ), + child: Center( + child: Text( + widget.unreadCount > 99 ? '99+' : '${widget.unreadCount}', + style: const TextStyle(color: Colors.white, fontSize: 10, fontWeight: FontWeight.w700), + ), + ), + ), + ), + ], + ), + ), + ), + ), + ), + ], + ); + } +} + +class _VirtualSpaceItem extends StatefulWidget { + final String id; + final String label; + final Color color; + final String name; + final bool active; + final int unread; + final PyramidTheme pt; + final VoidCallback onTap; + + const _VirtualSpaceItem({ + required this.id, + required this.label, + required this.color, + required this.name, + required this.active, + required this.unread, + required this.pt, + required this.onTap, + }); + + @override + State<_VirtualSpaceItem> createState() => _VirtualSpaceItemState(); +} + +class _VirtualSpaceItemState extends State<_VirtualSpaceItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final active = widget.active; + final radius = active + ? pt.rLg * 0.6 + : _hovered ? pt.rLg * 0.7 : pt.rLg; + + return Center( + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: Stack( + clipBehavior: Clip.none, + children: [ + // Active indicator + if (active) + Positioned( + left: -18, + top: 10, + child: Container( + width: 4, + height: 28, + decoration: BoxDecoration( + color: pt.accent, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(3), + bottomRight: Radius.circular(3), + ), + ), + ), + ), + Tooltip( + message: widget.name, + waitDuration: const Duration(milliseconds: 400), + preferBelow: false, + child: AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutBack, + width: 48, + height: 48, + decoration: BoxDecoration( + color: _hovered ? pt.bg3 : pt.bg2, + borderRadius: BorderRadius.circular(radius), + ), + child: Center( + child: PyramidGlyph( + size: 30, + color: widget.color, + label: widget.label, + ), + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +class _SpaceItem extends ConsumerStatefulWidget { + final Room space; + final bool active; + final bool isInvite; + final PyramidTheme pt; + final VoidCallback onTap; + + const _SpaceItem({ + required this.space, + required this.active, + this.isInvite = false, + required this.pt, + required this.onTap, + }); + + @override + ConsumerState<_SpaceItem> createState() => _SpaceItemState(); +} + +class _SpaceItemState extends ConsumerState<_SpaceItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final active = widget.active; + final name = widget.space.getLocalizedDisplayname(); + final letter = name.isNotEmpty ? name[0].toUpperCase() : '?'; + final radius = active ? pt.rLg * 0.6 : _hovered ? pt.rLg * 0.7 : pt.rLg; + final client = ref.watch(matrixClientProvider).valueOrNull; + final avatarUri = widget.space.avatar; + + Widget avatarChild; + if (client != null && avatarUri != null) { + avatarChild = MxcAvatar( + mxcUri: avatarUri, + client: client, + size: 48, + borderRadius: BorderRadius.circular(radius), + placeholder: (_) => _SpaceInitial(letter: letter, pt: pt, radius: radius), + ); + } else { + avatarChild = _SpaceInitial(letter: letter, pt: pt, radius: radius); + } + + return Center( + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + onSecondaryTap: widget.isInvite + ? null + : () => showDialog( + context: context, + builder: (_) => SpaceEditDialog(space: widget.space), + ), + onLongPress: widget.isInvite + ? null + : () => showDialog( + context: context, + builder: (_) => SpaceEditDialog(space: widget.space), + ), + child: Stack( + clipBehavior: Clip.none, + children: [ + if (active) + Positioned( + left: -18, + top: 10, + child: Container( + width: 4, + height: 28, + decoration: BoxDecoration( + color: pt.accent, + borderRadius: const BorderRadius.only( + topRight: Radius.circular(3), + bottomRight: Radius.circular(3), + ), + ), + ), + ), + Tooltip( + message: name, + waitDuration: const Duration(milliseconds: 400), + preferBelow: false, + child: AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutBack, + width: 48, + height: 48, + decoration: BoxDecoration( + color: _hovered ? pt.bg3 : pt.bg2, + borderRadius: BorderRadius.circular(radius), + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(radius), + child: avatarChild, + ), + ), + ), + if (widget.isInvite) + Positioned( + right: -2, + top: -2, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 4, vertical: 1), + decoration: BoxDecoration( + color: pt.accent, + borderRadius: BorderRadius.circular(999), + border: Border.all(color: pt.bg0, width: 1.5), + ), + child: const Text( + 'NEU', + style: TextStyle( + color: Colors.white, + fontSize: 8, + fontWeight: FontWeight.w800, + letterSpacing: 0.3), + ), + ), + ), + ], + ), + ), + ), + ); + } +} + +class _SpaceInitial extends StatelessWidget { + final String letter; + final PyramidTheme pt; + final double radius; + const _SpaceInitial({required this.letter, required this.pt, required this.radius}); + + @override + Widget build(BuildContext context) { + return Center( + child: Text(letter, style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + ); + } +} + +class _AddButton extends StatefulWidget { + final PyramidTheme pt; + const _AddButton({required this.pt}); + + @override + State<_AddButton> createState() => _AddButtonState(); +} + +class _AddButtonState extends State<_AddButton> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Center( + child: MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: () => showDialog( + context: context, + builder: (_) => const CreateJoinDialog(), + ), + child: Tooltip( + message: 'Create · Join · Discover', + waitDuration: const Duration(milliseconds: 400), + preferBelow: false, + child: AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutBack, + width: 48, + height: 48, + decoration: BoxDecoration( + color: _hovered ? pt.accentSoft : pt.bg2, + borderRadius: BorderRadius.circular(_hovered ? pt.rLg * 0.7 : pt.rLg), + border: Border.all( + color: _hovered ? pt.accent : pt.borderStrong, + width: 1.5, + style: BorderStyle.solid, + ), + ), + child: Center( + child: AnimatedRotation( + turns: _hovered ? 0.25 : 0, + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutBack, + child: Icon(Icons.add, color: pt.accent, size: 22), + ), + ), + ), + ), + ), + ), + ); + } +} diff --git a/lib/layout/app_shell.dart b/lib/layout/app_shell.dart new file mode 100644 index 0000000..538ddd0 --- /dev/null +++ b/lib/layout/app_shell.dart @@ -0,0 +1,1073 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/encryption/utils/key_verification.dart' show KeyVerification, KeyVerificationEmoji, KeyVerificationState; +import 'package:matrix/matrix.dart'; +import 'package:pretty_qr_code/pretty_qr_code.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/core/voip_manager.dart'; +import 'package:pyramid/features/auth/bootstrap_dialog.dart'; +import 'package:pyramid/features/call/voice_channel.dart'; +import 'package:pyramid/features/chat/chat_view.dart'; +import 'package:pyramid/features/members/members_panel.dart'; +import 'package:pyramid/features/rooms/rooms_panel.dart'; +import 'package:pyramid/features/spaces/spaces_rail.dart'; +import 'package:pyramid/widgets/search_modal.dart'; +import 'package:pyramid/widgets/settings_modal.dart'; +import 'package:pyramid/widgets/share_target_dialog.dart'; +import 'package:pyramid/core/notification_service.dart'; +import 'package:pyramid/widgets/update_banner.dart'; + +class AppShell extends ConsumerStatefulWidget { + const AppShell({super.key}); + + @override + ConsumerState createState() => _AppShellState(); +} + +class _AppShellState extends ConsumerState + with WidgetsBindingObserver { + double _sidebarWidth = 260; + bool _bootstrapTriggered = false; + // Flankenerkennung für die Auto-Switch-Listener (siehe build). + bool _wasVoipConnected = false; + bool _wasLiveKitActive = false; + StreamSubscription? _verificationSub; + Timer? _presenceTimer; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addObserver(this); + WidgetsBinding.instance.addPostFrameCallback((_) { + _triggerBootstrap(); + _subscribeVerification(); + initNotifications(ref); + _startPresenceHeartbeat(); + }); + } + + @override + void dispose() { + WidgetsBinding.instance.removeObserver(this); + _verificationSub?.cancel(); + _presenceTimer?.cancel(); + super.dispose(); + } + + /// Sends `setPresence(online)` every 55 seconds while the app is active. + /// This prevents the server from marking us offline due to inactivity timeout. + void _startPresenceHeartbeat() async { + _presenceTimer?.cancel(); + final client = await ref.read(matrixClientProvider.future); + if (!mounted) return; + _sendPresence(client, true); + _presenceTimer = Timer.periodic(const Duration(seconds: 55), (_) { + _sendPresence(client, true); + }); + } + + void _sendPresence(Client client, bool online) { + client + .setPresence( + client.userID!, + online ? PresenceType.online : PresenceType.unavailable, + ) + .catchError((_) {}); + } + + @override + void didChangeAppLifecycleState(AppLifecycleState state) { + super.didChangeAppLifecycleState(state); + // Update focus state immediately — used by notification suppression logic. + ref.read(windowFocusedProvider.notifier).state = + state == AppLifecycleState.resumed; + ref.read(matrixClientProvider.future).then((client) { + if (!mounted) return; + if (state == AppLifecycleState.resumed) { + _sendPresence(client, true); + // Restart heartbeat timer after coming back from background. + _presenceTimer?.cancel(); + _presenceTimer = Timer.periodic(const Duration(seconds: 55), (_) { + _sendPresence(client, true); + }); + // Advance the notification watch time so catch-up events from the initial + // sync (already shown by the FCM background handler) are not shown again. + resetNotificationStartTime(); + // Send any inline reply stored by the background notification handler. + checkPendingReply(ref); + } else if (state == AppLifecycleState.paused || + state == AppLifecycleState.detached) { + _presenceTimer?.cancel(); + _sendPresence(client, false); + } + }).catchError((_) {}); + } + + void _triggerBootstrap() async { + if (_bootstrapTriggered) return; + final client = await ref.read(matrixClientProvider.future); + if (client.encryption?.crossSigning.enabled != true) { + if (mounted) { + setState(() => _bootstrapTriggered = true); + showBootstrapDialog(context, client); + } + } + } + + void _subscribeVerification() async { + final client = await ref.read(matrixClientProvider.future); + if (!mounted) return; + _verificationSub = client.onKeyVerificationRequest.stream.listen((request) { + if (!mounted) return; + // Only show dialog if it's in askAccept state (incoming request not yet handled) + if (request.state == KeyVerificationState.askAccept) { + showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => _IncomingVerificationDialog( + request: request, + pt: PyramidTheme.of(context), + ), + ); + } + }); + } + + void onSidebarResize(double delta) { + setState(() { + _sidebarWidth = (_sidebarWidth + delta).clamp(200.0, 500.0); + }); + } + + void onCloseModal() { + ref.read(activeModalProvider.notifier).state = ModalKind.none; + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + + // Activate notification watcher (no-op after first call) + ref.watch(notificationWatcherProvider); + + // Auto-switch to voice view when call is connected — but only on the + // transition into the connected state. The provider feuert bei jedem + // notifyListeners (u.a. Render-Timer im Sekundentakt); ohne Flankenerkennung + // würde der Nutzer permanent zurück in die Call-UI gezwungen und könnte + // sie nie minimieren. + ref.listen(voipStateProvider, (prev, next) { + final wasConnected = _wasVoipConnected; + final isConnected = next.currentCall != null && + next.currentCall!.state == CallState.kConnected; + _wasVoipConnected = isConnected; + if (isConnected && !wasConnected) { + if (ref.read(viewModeProvider) != ViewMode.voice) { + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + } + } + }); + + ref.listen(callStateProvider, (prev, next) { + // Only auto-switch to voice view for video/audio calls, NOT voice channels + // (voice channels should stay in background with a mini bar) + final wasActive = _wasLiveKitActive; + final isActiveCall = next.isActive && !next.isConnecting && !next.isVoiceChannel; + _wasLiveKitActive = isActiveCall; + if (isActiveCall && !wasActive) { + if (ref.read(viewModeProvider) != ViewMode.voice) { + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + } + } + }); + + // "Teilen nach Pyramid" (Android): geteilte Inhalte → Raum-Picker zeigen. + ref.listen(pendingShareProvider, (prev, next) { + if (next != null && !next.isEmpty) { + ref.read(pendingShareProvider.notifier).state = null; + ShareTargetDialog.show(context, ref, next); + } + }); + + final sidebarWidth = _sidebarWidth; + final railCollapsed = ref.watch(railCollapsedProvider); + final activeRoomId = ref.watch(activeRoomIdProvider); + final viewMode = ref.watch(viewModeProvider); + final activeModal = ref.watch(activeModalProvider); + final membersOpen = ref.watch(membersPanelOpenProvider); + final innerPt = PyramidTheme.of(context); + final voip = ref.watch(voipStateProvider); + + final size = MediaQuery.sizeOf(context); + final isMobile = size.width < 900 || size.height < 500; + + // Auto-close members panel if screen gets too small + if (!isMobile && size.width < 1100 && membersOpen) { + WidgetsBinding.instance.addPostFrameCallback((_) { + ref.read(membersPanelOpenProvider.notifier).state = false; + }); + } + + if (isMobile) { + return _MobileShell( + pt: innerPt, + activeRoomId: activeRoomId, + viewMode: viewMode, + activeModal: activeModal, + membersOpen: membersOpen, + onCloseModal: onCloseModal, + ); + } + + return Scaffold( + backgroundColor: pt.bg1, + body: PopScope( + canPop: false, + onPopInvokedWithResult: (didPop, _) { + if (activeModal != ModalKind.none) { + onCloseModal(); + } + }, + child: Column( + children: [ + const UpdateBanner(), + const _NotificationBlockedBanner(), + Expanded(child: Stack( + children: [ + Row( + children: [ + // Spaces rail + AnimatedContainer( + duration: const Duration(milliseconds: 250), + curve: Curves.easeOutCubic, + width: railCollapsed ? 0 : 72, + clipBehavior: Clip.hardEdge, + decoration: const BoxDecoration(), + child: const SpacesRail(), + ), + // Rooms panel with resizable divider + SizedBox( + width: sidebarWidth.clamp(200.0, size.width * 0.4), + child: const RoomsPanel(), + ), + _ResizeDivider( + pt: innerPt, + onDrag: onSidebarResize, + ), + // Main content + Expanded( + child: viewMode == ViewMode.voice + ? const VoiceChannelView() + : activeRoomId != null + ? ChatView(roomId: activeRoomId) + : const NoChatSelected(), + ), + // Members panel — only if enough space (min 1100px total width) + if (membersOpen && activeRoomId != null && viewMode != ViewMode.voice && size.width >= 1100) + MembersPanel(roomId: activeRoomId), + ], + ), + // Incoming Call Popup for Desktop + if (voip.currentCall != null && voip.currentCall!.state == CallState.kRinging) + _IncomingCallOverlay(call: voip.currentCall!, voip: voip, pt: pt), + + // Modal overlays + if (activeModal == ModalKind.settings) + SettingsModal(onClose: onCloseModal), + if (activeModal == ModalKind.search) + SearchModal(onClose: onCloseModal), + + // Members panel as overlay if screen is narrow but requested + if (membersOpen && activeRoomId != null && viewMode != ViewMode.voice && size.width < 1100) ...[ + Positioned.fill( + child: GestureDetector( + onTap: () => ref.read(membersPanelOpenProvider.notifier).state = false, + child: Container(color: Colors.black.withAlpha(110)), + ), + ), + Positioned( + right: 0, + top: 0, + bottom: 0, + child: Container( + decoration: BoxDecoration( + boxShadow: [BoxShadow(color: Colors.black45, blurRadius: 16)], + ), + child: MembersPanel( + roomId: activeRoomId, + onClose: () => ref.read(membersPanelOpenProvider.notifier).state = false, + ), + ), + ), + ], + ], + )), // end Stack + Expanded + ], + ), // end Column + ), + ); + } +} + +class _MobileShell extends ConsumerWidget { + final PyramidTheme pt; + final String? activeRoomId; + final ViewMode viewMode; + final ModalKind activeModal; + final bool membersOpen; + final VoidCallback onCloseModal; + + const _MobileShell({ + required this.pt, + required this.activeRoomId, + required this.viewMode, + required this.activeModal, + required this.membersOpen, + required this.onCloseModal, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final voip = ref.watch(voipStateProvider); + + Widget body; + if (viewMode == ViewMode.voice) { + body = const VoiceChannelView(); + } else if (activeRoomId != null) { + body = ChatView(roomId: activeRoomId!); + } else { + body = const RoomsPanel(); + } + + return PopScope( + canPop: activeRoomId == null && viewMode == ViewMode.chat && !membersOpen, + onPopInvokedWithResult: (didPop, _) { + if (!didPop) { + if (membersOpen) { + ref.read(membersPanelOpenProvider.notifier).state = false; + } else if (viewMode == ViewMode.voice) { + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + } else if (activeRoomId != null) { + ref.read(activeRoomIdProvider.notifier).state = null; + } + } + }, + child: Scaffold( + backgroundColor: pt.bg0, + drawer: Drawer( + width: 80, + backgroundColor: pt.bg0, + child: const SpacesRail(), + ), + body: Stack( + children: [ + body, + if (membersOpen && activeRoomId != null && viewMode != ViewMode.voice) ...[ + // Tap-outside scrim closes the panel + Positioned.fill( + child: GestureDetector( + onTap: () => ref.read(membersPanelOpenProvider.notifier).state = false, + child: Container(color: Colors.black.withAlpha(110)), + ), + ), + Positioned( + right: 0, + top: 0, + bottom: 0, + child: Builder(builder: (ctx) { + final w = MediaQuery.sizeOf(ctx).width; + return MembersPanel( + roomId: activeRoomId!, + width: (w * 0.82).clamp(240.0, 320.0), + onClose: () => ref.read(membersPanelOpenProvider.notifier).state = false, + ); + }), + ), + ], + if (voip.currentCall != null && voip.currentCall!.state == CallState.kRinging) + _IncomingCallOverlay(call: voip.currentCall!, voip: voip, pt: pt), + if (activeModal == ModalKind.settings) + SettingsModal(onClose: onCloseModal), + if (activeModal == ModalKind.search) + SearchModal(onClose: onCloseModal), + const Positioned( + top: 0, left: 0, right: 0, + child: _NotificationBlockedBanner(), + ), + ], + ), + ), + ); + } +} + +class _NotificationBlockedBanner extends ConsumerWidget { + const _NotificationBlockedBanner(); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final blocked = ref.watch(notificationsBlockedProvider); + if (!blocked) return const SizedBox.shrink(); + + return Material( + color: Colors.transparent, + child: Container( + color: const Color(0xFFF5A623), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + child: Row( + children: [ + const Icon(Icons.notifications_off, size: 16, color: Colors.white), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Benachrichtigungen sind deaktiviert', + style: TextStyle(color: Colors.white, fontSize: 12, fontWeight: FontWeight.w500), + ), + ), + TextButton( + onPressed: () { + openNotificationSettings(); + ref.read(notificationsBlockedProvider.notifier).state = false; + }, + style: TextButton.styleFrom( + foregroundColor: Colors.white, + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + child: const Text('Einstellungen', style: TextStyle(fontSize: 12, decoration: TextDecoration.underline)), + ), + IconButton( + icon: const Icon(Icons.close, size: 14, color: Colors.white), + padding: const EdgeInsets.all(4), + constraints: const BoxConstraints(), + onPressed: () => ref.read(notificationsBlockedProvider.notifier).state = false, + ), + ], + ), + ), + ); + } +} + +class _IncomingCallOverlay extends ConsumerWidget { + final CallSession call; + final PyramidVoipManager voip; + final PyramidTheme pt; + + const _IncomingCallOverlay({ + required this.call, + required this.voip, + required this.pt, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + return Container( + color: Colors.black.withAlpha(180), + child: Center( + child: Container( + width: 320, + padding: const EdgeInsets.all(32), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rXl), + border: Border.all(color: pt.border), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 80, + height: 80, + decoration: BoxDecoration( + color: pt.accent, + shape: BoxShape.circle, + ), + child: const Icon(Icons.person_rounded, size: 40, color: Colors.white), + ), + const SizedBox(height: 24), + Text( + 'Eingehender Anruf', + style: TextStyle(color: pt.fgDim, fontSize: 13), + ), + const SizedBox(height: 8), + Text( + call.room.getLocalizedDisplayname(), + style: TextStyle(color: pt.fg, fontSize: 18, fontWeight: FontWeight.w700), + textAlign: TextAlign.center, + ), + const SizedBox(height: 32), + Row( + mainAxisAlignment: MainAxisAlignment.spaceEvenly, + children: [ + FloatingActionButton( + heroTag: 'reject_call', + onPressed: () => voip.safeAction(() async => await call.reject()), + backgroundColor: pt.danger, + child: const Icon(Icons.call_end_rounded, color: Colors.white), + ), + FloatingActionButton( + heroTag: 'answer_call', + onPressed: () { + ref.read(viewModeProvider.notifier).state = ViewMode.voice; + voip.safeAction(() async => await call.answer()); + }, + backgroundColor: pt.online, + child: const Icon(Icons.call_rounded, color: Colors.white), + ), + ], + ), + ], + ), + ), + ), + ); + } +} + +class _ResizeDivider extends StatefulWidget { + final PyramidTheme pt; + final ValueChanged onDrag; + + const _ResizeDivider({required this.pt, required this.onDrag}); + + @override + State<_ResizeDivider> createState() => _ResizeDividerState(); +} + +class _ResizeDividerState extends State<_ResizeDivider> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: SystemMouseCursors.resizeColumn, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + behavior: HitTestBehavior.translucent, + onHorizontalDragUpdate: (d) => widget.onDrag(d.delta.dx), + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: 6, + color: _hovered ? widget.pt.accent.withAlpha(80) : widget.pt.border, + ), + ), + ); + } +} + +class NoChatSelected extends StatelessWidget { + const NoChatSelected({super.key}); + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.chat_bubble_outline_rounded, size: 64, color: pt.fgDim.withAlpha(50)), + const SizedBox(height: 16), + Text( + 'Select a chat to start messaging', + style: TextStyle(color: pt.fgMuted, fontSize: 15), + ), + ], + ), + ); + } +} + +// ─── Incoming Key Verification Dialog ─────────────────────────────────────── + +class _IncomingVerificationDialog extends StatefulWidget { + final KeyVerification request; + final PyramidTheme pt; + + const _IncomingVerificationDialog({ + required this.request, + required this.pt, + }); + + @override + State<_IncomingVerificationDialog> createState() => + _IncomingVerificationDialogState(); +} + +class _IncomingVerificationDialogState + extends State<_IncomingVerificationDialog> { + late KeyVerificationState _state; + + @override + void initState() { + super.initState(); + _state = widget.request.state; + widget.request.onUpdate = () { + if (mounted) setState(() => _state = widget.request.state); + }; + } + + @override + void dispose() { + if (!widget.request.isDone) { + widget.request.cancel('m.user').catchError((_) {}); + } + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final req = widget.request; + + return AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(16), + side: BorderSide(color: pt.border)), + contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0), + title: Row( + children: [ + Icon(Icons.verified_user_outlined, size: 20, color: pt.accent), + const SizedBox(width: 10), + Expanded( + child: Text( + 'Verifikationsanfrage', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700), + ), + ), + ], + ), + content: SizedBox( + width: 380, + child: _buildContent(pt, req), + ), + actions: _buildActions(pt, req), + ); + } + + Widget _buildContent(PyramidTheme pt, KeyVerification req) { + return switch (_state) { + KeyVerificationState.askAccept => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _VerifInfoRow( + icon: Icons.devices_rounded, + label: (req.deviceId?.isNotEmpty == true) ? req.deviceId! : 'Unbekanntes Gerät', + pt: pt, + ), + const SizedBox(height: 6), + _VerifInfoRow( + icon: Icons.person_outline_rounded, + label: req.userId, + pt: pt, + ), + const SizedBox(height: 12), + Text( + 'Dieses Gerät möchte sich mit deinem Konto verifizieren.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + ], + ), + ), + KeyVerificationState.waitingAccept => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 16), + Text('Bereite Verifikation vor…', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ]), + ), + KeyVerificationState.askChoice => Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + 'Wähle eine Verifikationsmethode:', + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 16), + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () => req.continueVerification('m.sas.v1').catchError((_) {}), + icon: const Icon(Icons.tag_faces_rounded, size: 18), + label: const Text('Emoji-Verifikation'), + ), + const SizedBox(height: 8), + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: pt.bg3, + foregroundColor: pt.fg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () => req.continueVerification('m.qr_code.show.v1').catchError((_) {}), + icon: const Icon(Icons.qr_code_rounded, size: 18), + label: const Text('QR-Code anzeigen'), + ), + const SizedBox(height: 8), + ], + ), + ), + KeyVerificationState.confirmQRScan => _QrCodeDisplay(pt: pt, request: req), + KeyVerificationState.showQRSuccess => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _InfoCard( + pt: pt, + icon: Icons.verified_rounded, + color: const Color(0xFF22C55E), + text: 'QR-Code erfolgreich gescannt. Verifikation abgeschlossen.'), + ), + KeyVerificationState.askSas => _SasView(request: req, pt: pt, onClose: () => Navigator.pop(context)), + KeyVerificationState.waitingSas => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 16), + Text('Warte auf Bestätigung der anderen Seite…', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ]), + ), + KeyVerificationState.done => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _InfoCard( + pt: pt, + icon: Icons.verified_rounded, + color: const Color(0xFF22C55E), + text: 'Gerät erfolgreich verifiziert.'), + ), + _ => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _InfoCard( + pt: pt, + icon: Icons.error_outline_rounded, + color: pt.danger, + text: 'Verifizierung fehlgeschlagen oder abgebrochen.'), + ), + }; + } + + List _buildActions(PyramidTheme pt, KeyVerification req) { + if (_state == KeyVerificationState.askAccept) { + return [ + TextButton( + onPressed: () { + req.cancel('m.user').catchError((_) {}); + Navigator.pop(context); + }, + child: Text('Ablehnen', style: TextStyle(color: pt.danger)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => req.acceptVerification().catchError((_) {}), + child: const Text('Annehmen'), + ), + ]; + } + if (_state == KeyVerificationState.confirmQRScan) { + return [ + TextButton( + onPressed: () { + req.cancel('m.user').catchError((_) {}); + Navigator.pop(context); + }, + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF22C55E), + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => req.acceptQRScanConfirmation().catchError((_) {}), + child: const Text('Gescannt bestätigen'), + ), + ]; + } + if (_state == KeyVerificationState.done || + _state == KeyVerificationState.showQRSuccess || + _state == KeyVerificationState.error) { + return [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(context), + child: const Text('Schließen'), + ), + ]; + } + if (_state == KeyVerificationState.askSas || _state == KeyVerificationState.askChoice) return []; + return [ + TextButton( + onPressed: () { + req.cancel('m.user').catchError((_) {}); + Navigator.pop(context); + }, + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ]; + } +} + +class _SasView extends StatelessWidget { + final KeyVerification request; + final PyramidTheme pt; + final VoidCallback onClose; + + const _SasView({required this.request, required this.pt, required this.onClose}); + + @override + Widget build(BuildContext context) { + final emojis = request.sasEmojis; + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Vergleiche die Emojis auf beiden Geräten', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 20), + if (emojis.isNotEmpty) + Wrap( + spacing: 10, + runSpacing: 10, + alignment: WrapAlignment.center, + children: emojis.map((e) => _EmojiChip(emoji: e, pt: pt)).toList(), + ) + else + Text('Keine Emojis verfügbar', style: TextStyle(color: pt.fgDim, fontSize: 13)), + const SizedBox(height: 24), + Text( + 'Stimmen alle Emojis überein?', + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: OutlinedButton.icon( + style: OutlinedButton.styleFrom( + foregroundColor: pt.danger, + side: BorderSide(color: pt.danger.withAlpha(120)), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () { + request.rejectSas().catchError((_) {}); + onClose(); + }, + icon: const Icon(Icons.close_rounded, size: 16), + label: const Text('Stimmt nicht'), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF22C55E), + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () => request.acceptSas().catchError((_) {}), + icon: const Icon(Icons.check_rounded, size: 16), + label: const Text('Stimmt überein'), + ), + ), + ], + ), + const SizedBox(height: 8), + ], + ), + ); + } +} + +class _EmojiChip extends StatelessWidget { + final KeyVerificationEmoji emoji; + final PyramidTheme pt; + const _EmojiChip({required this.emoji, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + width: 64, + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: pt.border), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(emoji.emoji, style: const TextStyle(fontSize: 24)), + const SizedBox(height: 4), + Text( + emoji.name, + style: TextStyle(color: pt.fgMuted, fontSize: 9), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + } +} + +class _VerifInfoRow extends StatelessWidget { + final IconData icon; + final String label; + final PyramidTheme pt; + const _VerifInfoRow({required this.icon, required this.label, required this.pt}); + + @override + Widget build(BuildContext context) { + return Row( + children: [ + Icon(icon, size: 14, color: pt.fgDim), + const SizedBox(width: 8), + Expanded( + child: Text( + label, + style: TextStyle(color: pt.fg, fontSize: 12, fontFamily: 'monospace'), + overflow: TextOverflow.ellipsis, + ), + ), + ], + ); + } +} + +class _InfoCard extends StatelessWidget { + final PyramidTheme pt; + final IconData icon; + final Color color; + final String text; + const _InfoCard({required this.pt, required this.icon, required this.color, required this.text}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Icon(icon, color: color, size: 18), + const SizedBox(width: 10), + Expanded(child: Text(text, style: TextStyle(color: pt.fgMuted, fontSize: 13))), + ], + ), + ); + } +} + +class _QrCodeDisplay extends StatelessWidget { + final PyramidTheme pt; + final KeyVerification request; + + const _QrCodeDisplay({required this.pt, required this.request}); + + @override + Widget build(BuildContext context) { + final qrCode = request.qrCode; + if (qrCode == null) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 12), + Text('QR-Code wird generiert…', style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ], + ), + ); + } + + try { + final rawBytes = Uint8List.fromList(qrCode.qrDataRawBytes.toList()); + final qr = QrCode.fromUint8List(data: rawBytes, errorCorrectLevel: QrErrorCorrectLevel.L); + final qrImage = QrImage(qr); + + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Scanne diesen QR-Code mit dem anderen Gerät', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 16), + Center( + child: Container( + width: 220, + height: 220, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: PrettyQrView(qrImage: qrImage), + ), + ), + const SizedBox(height: 12), + Text( + 'Sobald das andere Gerät den Code gescannt hat, tippe auf „Gescannt bestätigen".', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + const SizedBox(height: 8), + ], + ), + ); + } catch (_) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _InfoCard( + pt: pt, + icon: Icons.error_outline_rounded, + color: pt.danger, + text: 'QR-Code konnte nicht generiert werden.', + ), + ); + } + } +} diff --git a/lib/layout/panel_layout.dart b/lib/layout/panel_layout.dart deleted file mode 100644 index 8975162..0000000 --- a/lib/layout/panel_layout.dart +++ /dev/null @@ -1,52 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pyramid/features/rooms/rooms_page.dart'; - -final sidebarWidthProvider = StateProvider((ref) => 280); - -class PanelLayout extends ConsumerWidget { - final Widget mainContent; - const PanelLayout({super.key, required this.mainContent}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final sidebarWidth = ref.watch(sidebarWidthProvider); - - return Row( - children: [ - SizedBox( - width: sidebarWidth, - child: const RoomsPage(), - ), - _ResizeDivider( - onDrag: (delta) { - final notifier = ref.read(sidebarWidthProvider.notifier); - notifier.state = - (notifier.state + delta).clamp(180.0, 480.0); - }, - ), - Expanded(child: mainContent), - ], - ); - } -} - -class _ResizeDivider extends StatelessWidget { - final ValueChanged onDrag; - const _ResizeDivider({required this.onDrag}); - - @override - Widget build(BuildContext context) { - return GestureDetector( - behavior: HitTestBehavior.translucent, - onHorizontalDragUpdate: (d) => onDrag(d.delta.dx), - child: MouseRegion( - cursor: SystemMouseCursors.resizeColumn, - child: Container( - width: 6, - color: Theme.of(context).dividerColor, - ), - ), - ); - } -} diff --git a/lib/layout/shell_page.dart b/lib/layout/shell_page.dart deleted file mode 100644 index ae01d3b..0000000 --- a/lib/layout/shell_page.dart +++ /dev/null @@ -1,19 +0,0 @@ -import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; -import 'package:pyramid/layout/panel_layout.dart'; - -class ShellPage extends ConsumerWidget { - final Widget child; - const ShellPage({super.key, required this.child}); - - @override - Widget build(BuildContext context, WidgetRef ref) { - final isWide = MediaQuery.sizeOf(context).width >= 700; - - return Scaffold( - body: isWide - ? PanelLayout(mainContent: child) - : child, - ); - } -} diff --git a/lib/main.dart b/lib/main.dart index e2067a2..850a682 100644 --- a/lib/main.dart +++ b/lib/main.dart @@ -1,11 +1,41 @@ +import 'dart:io'; + +import 'package:firebase_core/firebase_core.dart'; +import 'package:firebase_messaging/firebase_messaging.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_vodozemac/flutter_vodozemac.dart' as vod; +import 'package:media_kit/media_kit.dart'; import 'package:pyramid/core/app.dart'; +import 'package:pyramid/core/background_push.dart'; import 'package:pyramid/core/matrix_client.dart'; import 'package:pyramid/features/auth/login_notifier.dart'; +import 'package:pyramid/widgets/pyramid_loader.dart'; void main() async { WidgetsFlutterBinding.ensureInitialized(); + MediaKit.ensureInitialized(); + + if (Platform.isAndroid) { + // Firebase must be initialised first, then the background handler registered. + try { await Firebase.initializeApp(); } catch (_) {} + FirebaseMessaging.onBackgroundMessage(handleBackgroundMessage); + // Store the background-engine callback handle so PushService.kt / + // ReplyReceiver can decrypt + send encrypted replies when the app is killed. + await registerBgEngineHandle(); + } + + // Catch unhandled async exceptions to prevent silent crashes + FlutterError.onError = (details) { + FlutterError.presentError(details); + }; + + await vod.init(); + + // Hide status bar and navigation bar for immersive feel + await SystemChrome.setEnabledSystemUIMode(SystemUiMode.immersiveSticky); + runApp(const ProviderScope(child: PyramidBootstrap())); } @@ -18,7 +48,7 @@ class PyramidBootstrap extends ConsumerWidget { return clientAsync.when( loading: () => const MaterialApp( - home: Scaffold(body: Center(child: CircularProgressIndicator())), + home: Scaffold(body: Center(child: PyramidLoader(size: 80))), ), error: (e, _) => MaterialApp( home: Scaffold(body: Center(child: Text('Fehler: $e'))), diff --git a/lib/utils/clipboard_image.dart b/lib/utils/clipboard_image.dart new file mode 100644 index 0000000..df00b9d --- /dev/null +++ b/lib/utils/clipboard_image.dart @@ -0,0 +1,182 @@ +import 'dart:ffi'; +import 'dart:io'; +import 'dart:typed_data'; + +import 'package:ffi/ffi.dart'; +import 'package:image/image.dart' as img; + +// ── Windows constants ──────────────────────────────────────────────────────── + +const _CF_DIB = 8; +const _CF_DIBV4 = 20; + +// ── Native function typedefs ───────────────────────────────────────────────── + +typedef _OpenClipboardNative = Int32 Function(IntPtr hwnd); +typedef _OpenClipboard = int Function(int hwnd); + +typedef _CloseClipboardNative = Int32 Function(); +typedef _CloseClipboard = int Function(); + +typedef _IsFormatAvailableNative = Int32 Function(Uint32 format); +typedef _IsFormatAvailable = int Function(int format); + +typedef _GetClipboardDataNative = IntPtr Function(Uint32 format); +typedef _GetClipboardData = int Function(int format); + +typedef _GlobalSizeNative = IntPtr Function(IntPtr hMem); +typedef _GlobalSize = int Function(int hMem); + +typedef _GlobalLockNative = Pointer Function(IntPtr hMem); +typedef _GlobalLock = Pointer Function(int hMem); + +typedef _GlobalUnlockNative = Int32 Function(IntPtr hMem); +typedef _GlobalUnlock = int Function(int hMem); + +typedef _RegisterFormatNative = Uint32 Function(Pointer name); +typedef _RegisterFormat = int Function(Pointer name); + +// ── Public API ─────────────────────────────────────────────────────────────── + +/// Returns image bytes (PNG) from the Windows clipboard, or null if there is +/// no image or the platform is not Windows. +/// +/// Checks the following formats in order: +/// 1. "PNG" – custom registered format used by browsers / screenshot tools +/// 2. CF_DIBV4 / CF_DIB – Device-Independent Bitmap (Win+Shift+S, etc.) +Uint8List? getClipboardImageBytes() { + if (!Platform.isWindows) return null; + try { + return _readClipboardImage(); + } catch (_) { + return null; + } +} + +// ── Implementation ─────────────────────────────────────────────────────────── + +Uint8List? _readClipboardImage() { + final user32 = DynamicLibrary.open('user32.dll'); + final kernel32 = DynamicLibrary.open('kernel32.dll'); + + final openClipboard = + user32.lookupFunction<_OpenClipboardNative, _OpenClipboard>('OpenClipboard'); + final closeClipboard = + user32.lookupFunction<_CloseClipboardNative, _CloseClipboard>('CloseClipboard'); + final isFormatAvailable = + user32.lookupFunction<_IsFormatAvailableNative, _IsFormatAvailable>( + 'IsClipboardFormatAvailable'); + final getClipboardData = + user32.lookupFunction<_GetClipboardDataNative, _GetClipboardData>('GetClipboardData'); + final registerFormat = + user32.lookupFunction<_RegisterFormatNative, _RegisterFormat>( + 'RegisterClipboardFormatW'); + final globalSize = + kernel32.lookupFunction<_GlobalSizeNative, _GlobalSize>('GlobalSize'); + final globalLock = + kernel32.lookupFunction<_GlobalLockNative, _GlobalLock>('GlobalLock'); + final globalUnlock = + kernel32.lookupFunction<_GlobalUnlockNative, _GlobalUnlock>('GlobalUnlock'); + + // Register custom "PNG" format (Chrome, Edge, Firefox, Snipping Tool export) + final pngNamePtr = 'PNG'.toNativeUtf16(); + final pngFormat = registerFormat(pngNamePtr); + malloc.free(pngNamePtr); + + if (openClipboard(0) == 0) return null; + + try { + // 1. Try custom PNG format — bytes are ready-to-use PNG + if (pngFormat != 0 && isFormatAvailable(pngFormat) != 0) { + final bytes = _readGlobalBytes( + getClipboardData(pngFormat), globalSize, globalLock, globalUnlock); + if (bytes != null && bytes.isNotEmpty) return bytes; + } + + // 2. Try CF_DIBV4 then CF_DIB — convert DIB to PNG via the image package + for (final fmt in [_CF_DIBV4, _CF_DIB]) { + if (isFormatAvailable(fmt) != 0) { + final dibBytes = _readGlobalBytes( + getClipboardData(fmt), globalSize, globalLock, globalUnlock); + if (dibBytes != null && dibBytes.isNotEmpty) { + final png = _dibToPng(dibBytes); + if (png != null) return png; + } + } + } + + return null; + } finally { + closeClipboard(); + } +} + +/// Copy the bytes pointed to by a global memory handle. +Uint8List? _readGlobalBytes( + int handle, + _GlobalSize globalSize, + _GlobalLock globalLock, + _GlobalUnlock globalUnlock, +) { + if (handle == 0) return null; + final size = globalSize(handle); + if (size == 0) return null; + final ptr = globalLock(handle); + if (ptr.address == 0) return null; + try { + return Uint8List.fromList(ptr.asTypedList(size)); + } finally { + globalUnlock(handle); + } +} + +/// Convert a CF_DIB / CF_DIBV4 block to PNG bytes using the `image` package. +/// +/// A DIB is essentially a BMP without the 14-byte file header. We prepend the +/// header and let the `image` package decode it. +Uint8List? _dibToPng(Uint8List dib) { + if (dib.length < 40) return null; // minimum BITMAPINFOHEADER size + + final bd = ByteData.sublistView(dib); + + final headerSize = bd.getUint32(0, Endian.little); // biSize + final bitCount = bd.getUint16(14, Endian.little); // biBitCount + final compression = bd.getUint32(16, Endian.little); // biCompression + final clrUsed = bd.getUint32(32, Endian.little); // biClrUsed + + // Calculate color table size (in bytes, each entry = 4 bytes RGBQUAD) + int colorTableEntries; + if (bitCount <= 8) { + colorTableEntries = clrUsed != 0 ? clrUsed : (1 << bitCount); + } else if (compression == 3 /* BI_BITFIELDS */ || compression == 6 /* BI_ALPHABITFIELDS */) { + colorTableEntries = 0; + } else { + colorTableEntries = clrUsed; + } + final colorTableBytes = colorTableEntries * 4; + + // Offset to pixel data from start of FILE (= 14 file header bytes + DIB) + final pixelOffset = 14 + headerSize + colorTableBytes; + + // Build the 14-byte BITMAPFILEHEADER + final fileSize = 14 + dib.length; + final fileHeader = Uint8List(14); + final fh = ByteData.sublistView(fileHeader); + fileHeader[0] = 0x42; // 'B' + fileHeader[1] = 0x4D; // 'M' + fh.setUint32(2, fileSize, Endian.little); + fh.setUint32(6, 0, Endian.little); + fh.setUint32(10, pixelOffset, Endian.little); + + final bmp = Uint8List(fileHeader.length + dib.length); + bmp.setRange(0, fileHeader.length, fileHeader); + bmp.setRange(fileHeader.length, bmp.length, dib); + + try { + final decoded = img.decodeBmp(bmp); + if (decoded == null) return null; + return Uint8List.fromList(img.encodePng(decoded)); + } catch (_) { + return null; + } +} diff --git a/lib/utils/gif_favorite_service.dart b/lib/utils/gif_favorite_service.dart new file mode 100644 index 0000000..c7f0294 --- /dev/null +++ b/lib/utils/gif_favorite_service.dart @@ -0,0 +1,444 @@ +import 'dart:convert'; +import 'dart:typed_data'; +import 'package:http/http.dart' as http; + +const _stickerServerUrl = 'https://stickers.steggi-matrix.work'; + +class GifFavoriteService { + // ── GIF Favorites cache ───────────────────────────────────────────────── + static final List> _cache = []; + static bool _loaded = false; + + // ── Sticker Favorites cache ────────────────────────────────────────────── + static final List> _stickerCache = []; + static bool _stickerLoaded = false; + + static Future>> load() async { + if (_loaded) return _cache; + try { + final res = await http.get(Uri.parse('$_stickerServerUrl/gif-favorites')); + final data = jsonDecode(res.body) as List; + _cache + ..clear() + ..addAll(data.cast>()); + _loaded = true; + } catch (_) {} + return _cache; + } + + static List> get cache => List.unmodifiable(_cache); + + /// True if the given https:// URL is already a favorite. + static bool isFavorite(String url) => + _cache.any((f) => f['url'] == url); + + /// True if a favorite was created from this mxc:// source URL. + static bool isFavoriteByMxc(String mxcUrl) => + _cache.any((f) => f['mxc_source'] == mxcUrl); + + /// Upload raw GIF/WebP bytes to the Pi server. + /// Returns the public https:// URL on success, null on failure. + static Future uploadToPi(Uint8List bytes, String mimeType) async { + try { + final res = await http.post( + Uri.parse('$_stickerServerUrl/gif-file-upload'), + headers: {'Content-Type': mimeType}, + body: bytes, + ); + if (res.statusCode == 200) { + final data = jsonDecode(res.body); + return data['url'] as String?; + } + } catch (_) {} + return null; + } + + /// Toggle a plain external GIF (Giphy etc.). + static Future toggle( + String url, + String previewUrl, + String title, + ) async { + final removing = isFavorite(url); + if (removing) { + _cache.removeWhere((f) => f['url'] == url); + } else { + _cache.add({'url': url, 'preview_url': previewUrl, 'title': title}); + } + try { + await http.post( + Uri.parse('$_stickerServerUrl/gif-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'action': removing ? 'remove' : 'add', + 'url': url, + 'preview_url': previewUrl, + 'title': title, + }), + ); + } catch (_) { + // Revert on error + if (removing) { + _cache.add({'url': url, 'preview_url': previewUrl, 'title': title}); + } else { + _cache.removeWhere((f) => f['url'] == url); + } + } + } + + /// Add a favorite that was uploaded from an mxc:// source. + /// [url] is the Pi-hosted https:// URL; [mxcSource] is the original mxc:// URL. + static Future addWithMxcSource( + String url, + String previewUrl, + String title, + String mxcSource, + ) async { + final entry = { + 'url': url, + 'preview_url': previewUrl, + 'title': title, + 'mxc_source': mxcSource, + }; + _cache.add(entry); + try { + await http.post( + Uri.parse('$_stickerServerUrl/gif-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'action': 'add', + 'url': url, + 'preview_url': previewUrl, + 'title': title, + 'mxc_source': mxcSource, + }), + ); + } catch (_) { + _cache.removeWhere((f) => f['mxc_source'] == mxcSource); + } + } + + /// Remove a favorite that was originally added from an mxc:// source. + static Future removeByMxc(String mxcSource) async { + _cache.removeWhere((f) => f['mxc_source'] == mxcSource); + try { + await http.post( + Uri.parse('$_stickerServerUrl/gif-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'action': 'remove', + 'url': '', + 'mxc_source': mxcSource, + }), + ); + } catch (_) {} + } + + /// Extracts the URL logic from a matrix event to easily toggle favoriting globally. + static Future toggleEventFavorites(dynamic event) async { + await load(); + String rawUrl = ''; + final url = event.content['url'] as String?; + if (url != null && url.isNotEmpty) { + rawUrl = url; + } else { + final fileObj = event.content['file']; + if (fileObj is Map) { + final fileUrl = fileObj['url']; + if (fileUrl is String && fileUrl.isNotEmpty) rawUrl = fileUrl; + } + } + + if (rawUrl.isEmpty) return false; + + final u = Uri.tryParse(rawUrl); + final isExternal = u != null && (u.scheme == 'https' || u.scheme == 'http'); + final title = event.content['body'] as String? ?? 'Sticker'; + final isFav = isExternal ? isFavorite(rawUrl) : isFavoriteByMxc(rawUrl); + + if (isExternal) { + await toggle(rawUrl, rawUrl, title); + return true; + } else if (rawUrl.startsWith('mxc://')) { + if (isFav) { + await removeByMxc(rawUrl); + return true; + } else { + try { + final matrixFile = await event.downloadAndDecryptAttachment(getThumbnail: false); + final mimeType = event.infoMap['mimetype'] as String? ?? 'image/webp'; + final piUrl = await uploadToPi(matrixFile.bytes, mimeType); + if (piUrl != null) { + await addWithMxcSource(piUrl, piUrl, title, rawUrl); + return true; + } + } catch (e) { + return false; + } + } + } + return false; + } + + // ── Sticker Favorites ──────────────────────────────────────────────────── + + /// Load sticker favorites from the server into the sticker cache. + static Future>> loadStickers() async { + if (_stickerLoaded) return _stickerCache; + try { + final res = await http.get(Uri.parse('$_stickerServerUrl/sticker-favorites')); + final data = jsonDecode(res.body) as List; + _stickerCache + ..clear() + ..addAll(data.cast>()); + _stickerLoaded = true; + } catch (_) {} + return _stickerCache; + } + + static List> get stickerCache => List.unmodifiable(_stickerCache); + + /// All user-created stickers (saved from images). Shown in "Meine Sticker". + static List> get userStickerItems => + List.unmodifiable( + _stickerCache.where((s) => s['user_sticker'] == true).toList(), + ); + + /// Explicitly favorited stickers. Includes: + /// - User stickers with favorited == true + /// - Pack sticker favorites (entries without user_sticker == true) + static List> get stickerFavoritesItems => + List.unmodifiable( + _stickerCache.where((s) { + if (s['user_sticker'] == true) return s['favorited'] == true; + return true; + }).toList(), + ); + + /// Remove a sticker from the local cache immediately (without a server round-trip). + /// Call this after successfully posting a remove action to the server. + static void removeSticker(String mxcUrl) { + _stickerCache.removeWhere((s) => s['mxc_source'] == mxcUrl); + } + + /// True if this mxc:// URL is in the effective favorites list. + static bool isStickerFavorite(String mxcUrl) => + stickerFavoritesItems.any((s) => s['mxc_source'] == mxcUrl); + + /// Toggle the favorited flag on a user sticker. Returns true on success. + static Future setUserStickerFavorited(String mxcSource, bool favorited) async { + final idx = _stickerCache.indexWhere((s) => s['mxc_source'] == mxcSource); + if (idx == -1) return false; + _stickerCache[idx]['favorited'] = favorited; + try { + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({ + 'action': 'set_favorited', + 'mxc_source': mxcSource, + 'favorited': favorited, + }), + ); + return true; + } catch (_) { + _stickerCache[idx]['favorited'] = !favorited; + return false; + } + } + + /// Add or remove any image/sticker event from sticker favorites. + /// Handles both unencrypted (content['url']) and encrypted (content['file']['url']) events. + /// For encrypted events, re-uploads the decrypted bytes to Matrix so the + /// stored mxc:// URL can be sent as a sticker without decryption keys. + static Future addImageAsStickerFavorite(dynamic event) async { + await loadStickers(); + + // Resolve original mxc URL (used as deduplication key) + String rawMxc = event.content['url'] as String? ?? ''; + final bool isEncrypted = event.content['file'] != null; + if (rawMxc.isEmpty && isEncrypted) { + final fileObj = event.content['file']; + if (fileObj is Map) rawMxc = fileObj['url'] as String? ?? ''; + } + if (rawMxc.isEmpty) return false; + + final title = event.content['body'] as String? ?? 'Sticker'; + + // Check if ALREADY in cache (by mxc_source), regardless of favorited status. + // This prevents duplicates when user taps "Als Sticker speichern" on an already-saved sticker. + final existingIdx = _stickerCache.indexWhere((s) => s['mxc_source'] == rawMxc); + if (existingIdx != -1) { + // Toggle: remove the existing user sticker + final backup = Map.from(_stickerCache[existingIdx]); + _stickerCache.removeAt(existingIdx); + try { + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'remove', 'mxc_source': rawMxc}), + ); + return true; + } catch (_) { + _stickerCache.insert(existingIdx, backup); + return false; + } + } else { + try { + final matrixFile = await event.downloadAndDecryptAttachment(getThumbnail: false); + final mimeType = (event.infoMap['mimetype'] as String?) ?? 'image/png'; + + // For encrypted events the original mxc:// points to ciphertext. + // Re-upload the decrypted bytes to get a plain, sendable mxc:// URL. + String stickerMxc; + if (isEncrypted) { + final dynamic uploadedUri = await event.room.client.uploadContent( + matrixFile.bytes, + filename: 'sticker', + contentType: mimeType, + ); + stickerMxc = uploadedUri.toString(); + } else { + stickerMxc = rawMxc; + } + + // Also upload to Pi server for the picker preview thumbnail + final piUrl = await uploadToPi(matrixFile.bytes, mimeType); + if (piUrl == null) return false; + + final entry = { + 'mxc_source': rawMxc, // deduplication key (original encrypted or plain mxc) + 'mxc': stickerMxc, // sendable unencrypted mxc:// URL + 'url': piUrl, // Pi preview URL shown in the picker + 'title': title, + 'mimetype': mimeType, + 'user_sticker': true, // created from an image, shown in "Meine Sticker" + 'favorited': false, // not in favorites until explicitly hearted + }; + _stickerCache.add(entry); + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'add', ...entry}), + ); + return true; + } catch (_) { + _stickerCache.removeWhere((s) => s['mxc_source'] == rawMxc); + return false; + } + } + } + + /// Add or remove a pack sticker from favorites using its already-accessible + /// thumbnail URL — no download or re-upload needed. + static Future togglePackStickerFavorite({ + required String mxcUrl, + required String thumbUrl, + required String title, + String mimetype = 'image/webp', + }) async { + await loadStickers(); + + final isFav = isStickerFavorite(mxcUrl); + + if (isFav) { + _stickerCache.removeWhere((s) => s['mxc_source'] == mxcUrl); + try { + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'remove', 'mxc_source': mxcUrl}), + ); + return true; + } catch (_) { + _stickerCache.add({'mxc_source': mxcUrl, 'mxc': mxcUrl, 'url': thumbUrl, 'title': title}); + return false; + } + } else { + final entry = { + 'mxc_source': mxcUrl, + 'mxc': mxcUrl, + 'url': thumbUrl, + 'title': title, + 'mimetype': mimetype, + 'user_sticker': false, + 'favorited': false, + }; + _stickerCache.add(entry); + try { + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'add', ...entry}), + ); + return true; + } catch (_) { + _stickerCache.removeWhere((s) => s['mxc_source'] == mxcUrl); + return false; + } + } + } + + /// Toggle a sticker event into/out of the sticker favorites. + /// For user-created stickers, only the favorited flag is toggled. + /// For pack stickers, the sticker is added/removed from the favorites list. + static Future toggleStickerFavorite(dynamic event) async { + await loadStickers(); + final rawMxc = event.content['url'] as String? ?? ''; + if (rawMxc.isEmpty) return false; + final title = event.content['body'] as String? ?? 'Sticker'; + + // If it's a user-created sticker, toggle its favorited flag only + final userIdx = _stickerCache.indexWhere( + (s) => s['mxc_source'] == rawMxc && s['user_sticker'] == true, + ); + if (userIdx != -1) { + final currentFav = _stickerCache[userIdx]['favorited'] == true; + return setUserStickerFavorited(rawMxc, !currentFav); + } + + final isFav = isStickerFavorite(rawMxc); + + if (isFav) { + _stickerCache.removeWhere((s) => s['mxc_source'] == rawMxc); + try { + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'remove', 'mxc_source': rawMxc}), + ); + return true; + } catch (_) { + _stickerCache.add({'mxc_source': rawMxc, 'title': title}); + return false; + } + } else { + // Upload thumbnail bytes to Pi for preview + try { + final matrixFile = await event.downloadAndDecryptAttachment(getThumbnail: false); + final mimeType = event.infoMap['mimetype'] as String? ?? 'image/webp'; + final piUrl = await uploadToPi(matrixFile.bytes, mimeType); + if (piUrl == null) return false; + final entry = { + 'mxc_source': rawMxc, + 'mxc': rawMxc, + 'url': piUrl, + 'title': title, + 'mimetype': mimeType, + 'user_sticker': false, + 'favorited': false, + }; + _stickerCache.add(entry); + await http.post( + Uri.parse('$_stickerServerUrl/sticker-favorites'), + headers: {'Content-Type': 'application/json'}, + body: jsonEncode({'action': 'add', ...entry}), + ); + return true; + } catch (_) { + _stickerCache.removeWhere((s) => s['mxc_source'] == rawMxc); + return false; + } + } + } +} diff --git a/lib/widgets/banner_crop_dialog.dart b/lib/widgets/banner_crop_dialog.dart new file mode 100644 index 0000000..f76a744 --- /dev/null +++ b/lib/widgets/banner_crop_dialog.dart @@ -0,0 +1,184 @@ +import 'dart:typed_data'; +import 'dart:ui' as ui; + +import 'package:flutter/material.dart'; +import 'package:flutter/rendering.dart'; +import 'package:pyramid/core/theme.dart'; + +class BannerCropDialog extends StatefulWidget { + final Uint8List imageBytes; + // Width-to-height ratio for the crop frame (e.g. 2.4 = 2.4× wider than tall) + final double aspectRatio; + + const BannerCropDialog({ + super.key, + required this.imageBytes, + this.aspectRatio = 2.4, + }); + + @override + State createState() => _BannerCropDialogState(); +} + +class _BannerCropDialogState extends State { + final _transformController = TransformationController(); + final _repaintKey = GlobalKey(); + bool _exporting = false; + + @override + void dispose() { + _transformController.dispose(); + super.dispose(); + } + + Future _confirm() async { + setState(() => _exporting = true); + try { + final boundary = _repaintKey.currentContext!.findRenderObject() + as RenderRepaintBoundary; + // pixelRatio 2 gives enough resolution for a banner + final image = await boundary.toImage(pixelRatio: 2.0); + final byteData = + await image.toByteData(format: ui.ImageByteFormat.png); + if (byteData == null || !mounted) return; + Navigator.of(context).pop(byteData.buffer.asUint8List()); + } catch (e) { + if (mounted) { + ScaffoldMessenger.of(context).showSnackBar( + SnackBar(content: Text('Fehler beim Zuschneiden: $e'))); + setState(() => _exporting = false); + } + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rLg)), + insetPadding: const EdgeInsets.symmetric(horizontal: 24, vertical: 40), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 520), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // ── Header ──────────────────────────────────────────────────── + Padding( + padding: const EdgeInsets.fromLTRB(20, 20, 12, 12), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Banner zuschneiden', + style: TextStyle( + color: pt.fg, + fontSize: 16, + fontWeight: FontWeight.w700)), + Text( + 'Ziehe und zoome das Bild zum gewünschten Ausschnitt', + style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + IconButton( + icon: Icon(Icons.close, color: pt.fgDim, size: 20), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ), + ), + // ── Crop frame ──────────────────────────────────────────────── + Padding( + padding: const EdgeInsets.symmetric(horizontal: 20), + child: AspectRatio( + aspectRatio: widget.aspectRatio, + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rBase), + child: RepaintBoundary( + key: _repaintKey, + child: Container( + color: Colors.black, + child: InteractiveViewer( + transformationController: _transformController, + minScale: 0.25, + maxScale: 8.0, + child: Image.memory( + widget.imageBytes, + fit: BoxFit.cover, + width: double.infinity, + height: double.infinity, + ), + ), + ), + ), + ), + ), + ), + // ── Hint ────────────────────────────────────────────────────── + Padding( + padding: const EdgeInsets.fromLTRB(20, 10, 20, 0), + child: Row( + children: [ + Icon(Icons.info_outline, size: 13, color: pt.fgDim), + const SizedBox(width: 6), + Expanded( + child: Text( + 'Pinch/Scroll zum Zoomen, Drag zum Positionieren', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + ), + TextButton( + onPressed: () { + _transformController.value = Matrix4.identity(); + }, + child: + Text('Zurücksetzen', style: TextStyle(color: pt.fgDim, fontSize: 11)), + ), + ], + ), + ), + // ── Actions ─────────────────────────────────────────────────── + Padding( + padding: const EdgeInsets.fromLTRB(20, 12, 20, 20), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: _exporting + ? null + : () => Navigator.of(context).pop(), + child: const Text('Abbrechen'), + ), + const SizedBox(width: 8), + FilledButton( + onPressed: _exporting ? null : _confirm, + style: FilledButton.styleFrom( + backgroundColor: pt.accent, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rBase)), + ), + child: _exporting + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.bg0)) + : const Text('Übernehmen', + style: TextStyle( + color: Colors.white, + fontWeight: FontWeight.w600)), + ), + ], + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/create_join_dialog.dart b/lib/widgets/create_join_dialog.dart new file mode 100644 index 0000000..87c88fa --- /dev/null +++ b/lib/widgets/create_join_dialog.dart @@ -0,0 +1,1047 @@ +import 'dart:async'; + +import 'package:flutter/material.dart' hide Visibility; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +enum CreateJoinTab { create, join, discover } +enum _CreateType { room, voice, space } + +class CreateJoinDialog extends ConsumerStatefulWidget { + final CreateJoinTab initialTab; + const CreateJoinDialog({super.key, this.initialTab = CreateJoinTab.create}); + + @override + ConsumerState createState() => _CreateJoinDialogState(); +} + +class _CreateJoinDialogState extends ConsumerState { + late CreateJoinTab _tab; + _CreateType _createType = _CreateType.room; + + // Create + final _nameCtrl = TextEditingController(); + final _topicCtrl = TextEditingController(); + final _aliasCtrl = TextEditingController(); + bool _isPublic = false; + bool _isEncrypted = true; + bool _creating = false; + String? _createError; + + // Join + final _joinCtrl = TextEditingController(); + bool _joining = false; + String? _joinError; + + // Discover + final _discoverServerCtrl = TextEditingController(); + final _discoverSearchCtrl = TextEditingController(); + List _publicRooms = []; + String? _nextBatch; + bool _discoverLoading = false; + bool _discoverLoadingMore = false; + String? _discoverError; + Timer? _searchDebounce; + final Set _joiningRooms = {}; + + @override + void initState() { + super.initState(); + _tab = widget.initialTab; + WidgetsBinding.instance.addPostFrameCallback((_) { + if (_tab == CreateJoinTab.discover) _discover(); + }); + } + + @override + void dispose() { + _nameCtrl.dispose(); + _topicCtrl.dispose(); + _aliasCtrl.dispose(); + _joinCtrl.dispose(); + _discoverServerCtrl.dispose(); + _discoverSearchCtrl.dispose(); + _searchDebounce?.cancel(); + super.dispose(); + } + + Future _create() async { + final name = _nameCtrl.text.trim(); + if (name.isEmpty) { + setState(() => _createError = 'Bitte einen Namen eingeben.'); + return; + } + setState(() { _creating = true; _createError = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + String roomId; + if (_createType == _CreateType.space) { + roomId = await client.createSpace( + name: name, + topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(), + visibility: _isPublic ? Visibility.public : Visibility.private, + spaceAliasName: _aliasCtrl.text.trim().isEmpty ? null : _aliasCtrl.text.trim(), + ); + } else if (_createType == _CreateType.voice) { + roomId = await client.createRoom( + name: name, + topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(), + visibility: Visibility.private, + preset: CreateRoomPreset.privateChat, + creationContent: {'type': 'io.pyramid.voice_channel'}, + ); + // Voice-Presence (io.pyramid.voice.presence) muss von JEDEM Mitglied + // schreibbar sein (state_default ist 50, normale Mitglieder haben 0) — + // sonst sieht man nur den Raum-Ersteller im Kanal. Nachträglich setzen, + // weil Continuwuity power_level_content_override beim createRoom + // ignoriert. + try { + final plRaw = await client.getRoomStateWithKey( + roomId, EventTypes.RoomPowerLevels, ''); + final pl = Map.from(plRaw); + final events = + Map.from(pl['events'] as Map? ?? {}); + events['io.pyramid.voice.presence'] = 0; + pl['events'] = events; + await client.setRoomStateWithKey( + roomId, EventTypes.RoomPowerLevels, '', pl); + } catch (_) { + // Nicht kritisch — Presence-Anzeige funktioniert dann nur für Admins. + } + } else { + roomId = await client.createRoom( + name: name, + topic: _topicCtrl.text.trim().isEmpty ? null : _topicCtrl.text.trim(), + visibility: _isPublic ? Visibility.public : Visibility.private, + roomAliasName: _aliasCtrl.text.trim().isEmpty ? null : _aliasCtrl.text.trim(), + preset: _isPublic ? CreateRoomPreset.publicChat : CreateRoomPreset.privateChat, + initialState: _isEncrypted && !_isPublic + ? [StateEvent(content: {'algorithm': 'm.megolm.v1.aes-sha2'}, type: EventTypes.Encryption)] + : null, + ); + } + if (mounted) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + Navigator.of(context).pop(); + } + } on MatrixException catch (e) { + if (mounted) setState(() { _creating = false; _createError = e.errorMessage; }); + } catch (e) { + if (mounted) setState(() { _creating = false; _createError = e.toString().split('\n').first; }); + } + } + + Future _join() async { + final addr = _joinCtrl.text.trim(); + if (addr.isEmpty) { + setState(() => _joinError = 'Bitte eine Raum-Adresse eingeben.'); + return; + } + setState(() { _joining = true; _joinError = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + final roomId = await client.joinRoom(addr); + if (mounted) { + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + Navigator.of(context).pop(); + } + } on MatrixException catch (e) { + if (mounted) setState(() { _joining = false; _joinError = e.errorMessage; }); + } catch (e) { + if (mounted) setState(() { _joining = false; _joinError = e.toString().split('\n').first; }); + } + } + + Future _discover({bool loadMore = false}) async { + if (loadMore) { + if (_nextBatch == null) return; + setState(() => _discoverLoadingMore = true); + } else { + setState(() { _discoverLoading = true; _discoverError = null; }); + } + try { + final client = await ref.read(matrixClientProvider.future); + final server = _discoverServerCtrl.text.trim().isEmpty ? null : _discoverServerCtrl.text.trim(); + final search = _discoverSearchCtrl.text.trim(); + final res = await client.queryPublicRooms( + server: server, + limit: 30, + since: loadMore ? _nextBatch : null, + filter: search.isEmpty ? null : PublicRoomQueryFilter(genericSearchTerm: search), + ); + if (mounted) { + setState(() { + if (loadMore) { + _publicRooms.addAll(res.chunk); + } else { + _publicRooms = res.chunk; + } + _nextBatch = res.nextBatch; + _discoverLoading = false; + _discoverLoadingMore = false; + }); + } + } catch (e) { + if (mounted) setState(() { + _discoverLoading = false; + _discoverLoadingMore = false; + _discoverError = e.toString().split('\n').first; + }); + } + } + + void _onSearchChanged(String _) { + _searchDebounce?.cancel(); + _searchDebounce = Timer(const Duration(milliseconds: 500), _discover); + } + + Future _joinPublicRoom(String roomId, List? via) async { + setState(() => _joiningRooms.add(roomId)); + try { + final client = await ref.read(matrixClientProvider.future); + final id = await client.joinRoom(roomId, via: via); + if (mounted) { + ref.read(activeRoomIdProvider.notifier).state = id; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + Navigator.of(context).pop(); + } + } catch (_) { + if (mounted) setState(() => _joiningRooms.remove(roomId)); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final size = MediaQuery.sizeOf(context); + final isNarrow = size.width < 600; + + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: isNarrow ? size.width * 0.97 : 580, + maxHeight: size.height * 0.85, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + _buildTabs(pt), + Divider(color: pt.border, height: 1), + Flexible(child: _buildBody(pt)), + ], + ), + ), + ); + } + + Widget _buildTabs(PyramidTheme pt) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 12, 12), + child: Row( + children: [ + Expanded( + child: Row( + children: [ + _Tab(label: 'Erstellen', icon: Icons.add_rounded, active: _tab == CreateJoinTab.create, + pt: pt, onTap: () => setState(() => _tab = CreateJoinTab.create)), + const SizedBox(width: 4), + _Tab(label: 'Beitreten', icon: Icons.login_rounded, active: _tab == CreateJoinTab.join, + pt: pt, onTap: () => setState(() => _tab = CreateJoinTab.join)), + const SizedBox(width: 4), + _Tab(label: 'Entdecken', icon: Icons.explore_rounded, active: _tab == CreateJoinTab.discover, + pt: pt, onTap: () { + setState(() => _tab = CreateJoinTab.discover); + if (_publicRooms.isEmpty) _discover(); + }), + ], + ), + ), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ], + ), + ); + } + + Widget _buildBody(PyramidTheme pt) { + return switch (_tab) { + CreateJoinTab.create => _buildCreate(pt), + CreateJoinTab.join => _buildJoin(pt), + CreateJoinTab.discover => _buildDiscover(pt), + }; + } + + Widget _buildCreate(PyramidTheme pt) { + return SingleChildScrollView( + padding: const EdgeInsets.fromLTRB(20, 4, 20, 20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Type toggle + Row(children: [ + _TypeToggle( + label: 'Raum', + icon: Icons.tag_rounded, + active: _createType == _CreateType.room, + pt: pt, + onTap: () => setState(() { _createType = _CreateType.room; _isPublic = false; }), + ), + const SizedBox(width: 8), + _TypeToggle( + label: 'Voice', + icon: Icons.mic_rounded, + active: _createType == _CreateType.voice, + pt: pt, + onTap: () => setState(() { _createType = _CreateType.voice; _isPublic = false; }), + ), + const SizedBox(width: 8), + _TypeToggle( + label: 'Space', + icon: Icons.workspaces_rounded, + active: _createType == _CreateType.space, + pt: pt, + onTap: () => setState(() => _createType = _CreateType.space), + ), + ]), + const SizedBox(height: 16), + _Field(ctrl: _nameCtrl, label: 'Name *', pt: pt, autofocus: true), + const SizedBox(height: 10), + _Field(ctrl: _topicCtrl, label: 'Thema / Beschreibung (optional)', pt: pt, maxLines: 2), + const SizedBox(height: 14), + // Options + if (_createType == _CreateType.voice) + Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Row( + children: [ + Icon(Icons.info_outline, size: 14, color: pt.fgDim), + const SizedBox(width: 6), + Expanded( + child: Text( + 'Voice-Kanäle sind privat. Mitglieder können beitreten und direkt sprechen.', + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + ), + ], + ), + ), + if (_createType != _CreateType.voice) ...[ + _OptionRow( + label: 'Öffentlich', + desc: 'Im Verzeichnis sichtbar, jeder kann beitreten', + pt: pt, + value: _isPublic, + onChanged: (v) => setState(() => _isPublic = v), + ), + if (_createType == _CreateType.room) ...[ + const SizedBox(height: 8), + _OptionRow( + label: 'Verschlüsselt', + desc: 'Ende-zu-Ende-Verschlüsselung aktivieren', + pt: pt, + value: _isEncrypted, + onChanged: (v) => setState(() => _isEncrypted = v), + ), + ], + if (_isPublic) ...[ + const SizedBox(height: 10), + _Field( + ctrl: _aliasCtrl, + label: 'Alias (optional)', + pt: pt, + hint: 'mein-raum → #mein-raum:server', + ), + ], + ], + if (_createError != null) ...[ + const SizedBox(height: 10), + _ErrorCard(text: _createError!, pt: pt), + ], + const SizedBox(height: 16), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: _creating ? null : _create, + child: _creating + ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + : Text(_createType == _CreateType.space ? 'Space erstellen' : 'Raum erstellen'), + ), + ), + ], + ), + ); + } + + Widget _buildJoin(PyramidTheme pt) { + return Padding( + padding: const EdgeInsets.fromLTRB(20, 8, 20, 20), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text('Raum-Adresse oder ID eingeben', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5)), + const SizedBox(height: 12), + _Field( + ctrl: _joinCtrl, + label: 'Adresse oder ID', + hint: '#kanal:server.de oder !abc123:server.de', + pt: pt, + autofocus: true, + onSubmitted: (_) => _join(), + ), + const SizedBox(height: 6), + Text('Tipp: Matrix-Räume, Spaces und Gruppen werden alle unterstützt.', + style: TextStyle(color: pt.fgDim, fontSize: 11)), + if (_joinError != null) ...[ + const SizedBox(height: 10), + _ErrorCard(text: _joinError!, pt: pt), + ], + const SizedBox(height: 16), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: _joining ? null : _join, + child: _joining + ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + : const Text('Beitreten'), + ), + ), + ], + ), + ); + } + + Widget _buildDiscover(PyramidTheme pt) { + return Column( + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 8), + child: Row(children: [ + Expanded( + child: _Field( + ctrl: _discoverSearchCtrl, + label: 'Suchen', + pt: pt, + onChanged: _onSearchChanged, + prefixIcon: Icon(Icons.search_rounded, size: 16, color: pt.fgDim), + ), + ), + const SizedBox(width: 8), + SizedBox( + width: 140, + child: _Field( + ctrl: _discoverServerCtrl, + label: 'Server', + hint: 'matrix.org', + pt: pt, + onSubmitted: (_) => _discover(), + ), + ), + ]), + ), + Divider(color: pt.border, height: 1), + Flexible( + child: _discoverLoading + ? const Center(child: CircularProgressIndicator.adaptive()) + : _discoverError != null + ? Center(child: _ErrorCard(text: _discoverError!, pt: pt)) + : _publicRooms.isEmpty + ? Center(child: Text('Keine Räume gefunden.', style: TextStyle(color: pt.fgMuted, fontSize: 13))) + : ListView.builder( + itemCount: _publicRooms.length + (_nextBatch != null ? 1 : 0), + itemBuilder: (ctx, i) { + if (i == _publicRooms.length) { + return Padding( + padding: const EdgeInsets.all(12), + child: Center( + child: _discoverLoadingMore + ? const CircularProgressIndicator.adaptive() + : TextButton( + onPressed: () => _discover(loadMore: true), + child: Text('Mehr laden', style: TextStyle(color: pt.accent)), + ), + ), + ); + } + final room = _publicRooms[i]; + return _PublicRoomItem( + room: room, + pt: pt, + isJoining: _joiningRooms.contains(room.roomId), + onJoin: () => _joinPublicRoom(room.roomId, null), + ); + }, + ), + ), + ], + ); + } +} + +// ── Space / Room editor dialog ───────────────────────────────────────────────── + +class SpaceEditDialog extends ConsumerStatefulWidget { + final Room space; + const SpaceEditDialog({super.key, required this.space}); + + @override + ConsumerState createState() => _SpaceEditDialogState(); +} + +class _SpaceEditDialogState extends ConsumerState { + late TextEditingController _nameCtrl; + late TextEditingController _topicCtrl; + bool _saving = false; + String? _error; + bool _saved = false; + + @override + void initState() { + super.initState(); + _nameCtrl = TextEditingController(text: widget.space.getLocalizedDisplayname()); + _topicCtrl = TextEditingController(text: widget.space.topic ?? ''); + } + + @override + void dispose() { + _nameCtrl.dispose(); + _topicCtrl.dispose(); + super.dispose(); + } + + Future _save() async { + setState(() { _saving = true; _error = null; _saved = false; }); + try { + final name = _nameCtrl.text.trim(); + final topic = _topicCtrl.text.trim(); + if (name.isNotEmpty && name != widget.space.getLocalizedDisplayname()) { + await widget.space.setName(name); + } + if (topic != (widget.space.topic ?? '')) { + await widget.space.setDescription(topic); + } + if (mounted) setState(() { _saving = false; _saved = true; }); + await Future.delayed(const Duration(seconds: 1)); + if (mounted) Navigator.of(context).pop(true); + } catch (e) { + if (mounted) setState(() { _saving = false; _error = e.toString().split('\n').first; }); + } + } + + Future _leave() async { + final pt = PyramidTheme.of(context); + final confirmed = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + title: Text('Space verlassen?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text('Du verlässt "${widget.space.getLocalizedDisplayname()}".', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.danger, foregroundColor: Colors.white, + elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Verlassen'), + ), + ], + ), + ); + if (confirmed != true || !mounted) return; + try { + await widget.space.leave(); + if (mounted) { + ref.read(activeSpaceIdProvider.notifier).state = 'rooms'; + Navigator.of(context).pop(true); + } + } catch (e) { + if (mounted) setState(() => _error = e.toString().split('\n').first); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + return Dialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 420), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.workspaces_rounded, size: 18, color: pt.accent), + const SizedBox(width: 8), + Expanded(child: Text('Space bearbeiten', + style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600))), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ]), + const SizedBox(height: 16), + _Field(ctrl: _nameCtrl, label: 'Name', pt: pt), + const SizedBox(height: 10), + _Field(ctrl: _topicCtrl, label: 'Beschreibung', pt: pt, maxLines: 2), + if (_error != null) ...[ + const SizedBox(height: 10), + _ErrorCard(text: _error!, pt: pt), + ], + const SizedBox(height: 16), + Row(children: [ + Expanded(child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: pt.danger, side: BorderSide(color: pt.danger.withAlpha(80)), + padding: const EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _leave, + child: const Text('Verlassen'), + )), + const SizedBox(width: 10), + Expanded(child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _saving ? null : _save, + child: _saving + ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + : const Text('Speichern'), + )), + ]), + ], + ), + ), + ), + ); + } +} + +// ── Room settings dialog ─────────────────────────────────────────────────────── + +class RoomSettingsDialog extends ConsumerStatefulWidget { + final Room room; + const RoomSettingsDialog({super.key, required this.room}); + + @override + ConsumerState createState() => _RoomSettingsDialogState(); +} + +class _RoomSettingsDialogState extends ConsumerState { + late TextEditingController _nameCtrl; + late TextEditingController _topicCtrl; + bool _saving = false; + String? _error; + + @override + void initState() { + super.initState(); + _nameCtrl = TextEditingController(text: widget.room.getLocalizedDisplayname()); + _topicCtrl = TextEditingController(text: widget.room.topic ?? ''); + } + + @override + void dispose() { + _nameCtrl.dispose(); + _topicCtrl.dispose(); + super.dispose(); + } + + Future _save() async { + setState(() { _saving = true; _error = null; }); + try { + if (_nameCtrl.text.trim() != widget.room.getLocalizedDisplayname()) { + await widget.room.setName(_nameCtrl.text.trim()); + } + final newTopic = _topicCtrl.text.trim(); + if (newTopic != (widget.room.topic ?? '')) { + await widget.room.setDescription(newTopic); + } + if (mounted) Navigator.of(context).pop(); + } catch (e) { + if (mounted) setState(() { _saving = false; _error = e.toString().split('\n').first; }); + } + } + + Future _leaveRoom() async { + final pt = PyramidTheme.of(context); + final confirmed = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + title: Text('Raum verlassen?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text('"${widget.room.getLocalizedDisplayname()}" verlassen.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.danger, foregroundColor: Colors.white, + elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Verlassen'), + ), + ], + ), + ); + if (confirmed != true || !mounted) return; + try { + final roomId = widget.room.id; + await widget.room.leave(); + if (mounted) { + final current = ref.read(activeRoomIdProvider); + if (current == roomId) ref.read(activeRoomIdProvider.notifier).state = null; + Navigator.of(context).pop(); + } + } catch (e) { + if (mounted) setState(() => _error = e.toString().split('\n').first); + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final canEdit = widget.room.canSendEvent(EventTypes.RoomName); + + return Dialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 400), + child: Padding( + padding: const EdgeInsets.all(24), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.settings_rounded, size: 18, color: pt.accent), + const SizedBox(width: 8), + Expanded(child: Text('Raum-Einstellungen', + style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600))), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ]), + const SizedBox(height: 6), + SelectableText(widget.room.id, + style: TextStyle(color: pt.fgDim, fontSize: 11, fontFamily: 'monospace')), + const SizedBox(height: 16), + if (canEdit) ...[ + _Field(ctrl: _nameCtrl, label: 'Name', pt: pt), + const SizedBox(height: 10), + _Field(ctrl: _topicCtrl, label: 'Thema', pt: pt, maxLines: 2), + ] else + Text('Du hast keine Berechtigung, diesen Raum zu bearbeiten.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + if (_error != null) ...[ + const SizedBox(height: 10), + _ErrorCard(text: _error!, pt: pt), + ], + const SizedBox(height: 16), + Row(children: [ + Expanded(child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: pt.danger, side: BorderSide(color: pt.danger.withAlpha(80)), + padding: const EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _leaveRoom, + child: const Text('Verlassen'), + )), + if (canEdit) ...[ + const SizedBox(width: 10), + Expanded(child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _saving ? null : _save, + child: _saving + ? const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + : const Text('Speichern'), + )), + ], + ]), + ], + ), + ), + ), + ); + } +} + +// ── Helper widgets ───────────────────────────────────────────────────────────── + +class _Tab extends StatefulWidget { + final String label; + final IconData icon; + final bool active; + final PyramidTheme pt; + final VoidCallback onTap; + const _Tab({required this.label, required this.icon, required this.active, required this.pt, required this.onTap}); + + @override + State<_Tab> createState() => _TabState(); +} + +class _TabState extends State<_Tab> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 6), + decoration: BoxDecoration( + color: widget.active ? pt.accentSoft : (_hovered ? pt.bgHover : Colors.transparent), + borderRadius: BorderRadius.circular(6), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Icon(widget.icon, size: 14, color: widget.active ? pt.accent : pt.fgMuted), + const SizedBox(width: 6), + Text(widget.label, style: TextStyle( + color: widget.active ? pt.fg : pt.fgMuted, + fontSize: 13, fontWeight: widget.active ? FontWeight.w600 : FontWeight.w400, + )), + ]), + ), + ), + ); + } +} + +class _TypeToggle extends StatelessWidget { + final String label; + final IconData icon; + final bool active; + final PyramidTheme pt; + final VoidCallback onTap; + const _TypeToggle({required this.label, required this.icon, required this.active, required this.pt, required this.onTap}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 8), + decoration: BoxDecoration( + color: active ? pt.accent : pt.bg3, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: active ? pt.accent : pt.border), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Icon(icon, size: 14, color: active ? pt.accentFg : pt.fgMuted), + const SizedBox(width: 6), + Text(label, style: TextStyle( + color: active ? pt.accentFg : pt.fgMuted, + fontSize: 13, fontWeight: FontWeight.w500, + )), + ]), + ), + ); + } +} + +class _OptionRow extends StatelessWidget { + final String label; + final String desc; + final bool value; + final ValueChanged onChanged; + final PyramidTheme pt; + const _OptionRow({required this.label, required this.desc, required this.value, required this.onChanged, required this.pt}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => onChanged(!value), + child: Row(children: [ + Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(label, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500)), + Text(desc, style: TextStyle(color: pt.fgDim, fontSize: 11)), + ])), + Switch(value: value, onChanged: onChanged, activeColor: pt.accent), + ]), + ); + } +} + +class _Field extends StatelessWidget { + final TextEditingController ctrl; + final String label; + final String? hint; + final PyramidTheme pt; + final bool autofocus; + final int maxLines; + final Widget? prefixIcon; + final ValueChanged? onChanged; + final ValueChanged? onSubmitted; + + const _Field({ + required this.ctrl, required this.label, required this.pt, + this.hint, this.autofocus = false, this.maxLines = 1, + this.prefixIcon, this.onChanged, this.onSubmitted, + }); + + @override + Widget build(BuildContext context) => TextField( + controller: ctrl, + autofocus: autofocus, + maxLines: maxLines, + style: TextStyle(color: pt.fg, fontSize: 13), + onChanged: onChanged, + onSubmitted: onSubmitted, + decoration: InputDecoration( + labelText: label, + hintText: hint, + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + hintStyle: TextStyle(color: pt.fgDim, fontSize: 12), + prefixIcon: prefixIcon, + filled: true, fillColor: pt.bg3, + isDense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + ), + cursorColor: pt.accent, + ); +} + +class _ErrorCard extends StatelessWidget { + final String text; + final PyramidTheme pt; + const _ErrorCard({required this.text, required this.pt}); + + @override + Widget build(BuildContext context) => Container( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: pt.danger.withAlpha(20), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.danger.withAlpha(60)), + ), + child: Row(children: [ + Icon(Icons.error_outline_rounded, size: 14, color: pt.danger), + const SizedBox(width: 8), + Expanded(child: Text(text, style: TextStyle(color: pt.danger, fontSize: 12))), + ]), + ); +} + +class _PublicRoomItem extends ConsumerWidget { + final PublicRoomsChunk room; + final PyramidTheme pt; + final bool isJoining; + final VoidCallback onJoin; + const _PublicRoomItem({required this.room, required this.pt, required this.isJoining, required this.onJoin}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final client = ref.watch(matrixClientProvider).valueOrNull; + final name = room.name ?? room.canonicalAlias ?? room.roomId; + final avatarUrl = room.avatarUrl; + final alreadyJoined = client?.getRoomById(room.roomId) != null; + + return Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 4), + child: Row(children: [ + // Avatar + Container( + width: 36, height: 36, + decoration: BoxDecoration(color: pt.bg3, borderRadius: BorderRadius.circular(8)), + child: (client != null && avatarUrl != null) + ? ClipRRect( + borderRadius: BorderRadius.circular(8), + child: MxcImage(mxcUri: avatarUrl.toString(), client: client, fit: BoxFit.cover), + ) + : Center(child: Text( + name.isNotEmpty ? name[0].toUpperCase() : '?', + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w700), + )), + ), + const SizedBox(width: 10), + Expanded(child: Column(crossAxisAlignment: CrossAxisAlignment.start, children: [ + Text(name, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + if (room.topic != null) + Text(room.topic!, style: TextStyle(color: pt.fgDim, fontSize: 11), + overflow: TextOverflow.ellipsis, maxLines: 1), + Text('${room.numJoinedMembers} Mitglieder', + style: TextStyle(color: pt.fgDim, fontSize: 11)), + ])), + const SizedBox(width: 8), + if (alreadyJoined) + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration(color: pt.accentSoft, borderRadius: BorderRadius.circular(6)), + child: Text('Beigetreten', style: TextStyle(color: pt.accent, fontSize: 11, fontWeight: FontWeight.w600)), + ) + else if (isJoining) + const SizedBox(width: 20, height: 20, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + else + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + minimumSize: Size.zero, tapTargetSize: MaterialTapTargetSize.shrinkWrap, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(6)), + ), + onPressed: onJoin, + child: const Text('Beitreten', style: TextStyle(fontSize: 12)), + ), + ]), + ); + } +} diff --git a/lib/widgets/hover_region.dart b/lib/widgets/hover_region.dart new file mode 100644 index 0000000..23d0550 --- /dev/null +++ b/lib/widgets/hover_region.dart @@ -0,0 +1,117 @@ +import 'package:flutter/material.dart'; + +// Simple hover-aware widget for desktop hover effects +class HoverRegion extends StatefulWidget { + final Widget Function(BuildContext context, bool hovered) builder; + final MouseCursor cursor; + + const HoverRegion({ + super.key, + required this.builder, + this.cursor = SystemMouseCursors.click, + }); + + @override + State createState() => _HoverRegionState(); +} + +class _HoverRegionState extends State { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + return MouseRegion( + cursor: widget.cursor, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: widget.builder(context, _hovered), + ); + } +} + +// Icon button styled to match Pyramid's .icon-btn +class PyrIconBtn extends StatefulWidget { + final Widget icon; + final VoidCallback? onPressed; + final String? tooltip; + final bool active; + final Color? activeColor; + final Color? dangerColor; + final double size; + + const PyrIconBtn({ + super.key, + required this.icon, + this.onPressed, + this.tooltip, + this.active = false, + this.activeColor, + this.dangerColor, + this.size = 32, + }); + + @override + State createState() => _PyrIconBtnState(); +} + +class _PyrIconBtnState extends State { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final theme = Theme.of(context); + final isDark = theme.brightness == Brightness.dark; + final fgMuted = isDark ? const Color(0xFFA4A4B0) : const Color(0xFF54545E); + final fg = isDark ? const Color(0xFFECECF0) : const Color(0xFF1A1A1F); + final bgHover = isDark ? const Color(0xFF232330) : const Color(0xFFE9E7E1); + + final color = widget.active + ? (widget.activeColor ?? const Color(0xFFF5A614)) + : _hovered ? fg : fgMuted; + + final platform = Theme.of(context).platform; + final isMobile = platform == TargetPlatform.android || platform == TargetPlatform.iOS; + // On mobile, use a slightly larger touch target, but respect the requested size + final touchSize = isMobile ? (widget.size + 8).clamp(32.0, 48.0) : widget.size; + + final btn = MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onPressed, + child: SizedBox( + width: touchSize, + height: touchSize, + child: Center( + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + curve: Curves.easeOutCubic, + width: widget.size, + height: widget.size, + decoration: BoxDecoration( + color: _hovered ? bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(7), + ), + child: Center( + child: IconTheme( + data: IconThemeData(color: color, size: 16), + child: widget.icon, + ), + ), + ), + ), + ), + ), + ); + + if (widget.tooltip != null) { + return Tooltip( + message: widget.tooltip!, + waitDuration: const Duration(milliseconds: 500), + child: btn, + ); + } + return btn; + } +} diff --git a/lib/widgets/mxc_image.dart b/lib/widgets/mxc_image.dart index ef0a585..809818f 100644 --- a/lib/widgets/mxc_image.dart +++ b/lib/widgets/mxc_image.dart @@ -1,53 +1,205 @@ +import 'dart:typed_data'; import 'package:flutter/material.dart'; -import 'package:flutter_riverpod/flutter_riverpod.dart'; import 'package:matrix/matrix.dart'; -import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/media_cache.dart'; -class MxcImage extends ConsumerWidget { +class MxcAvatar extends StatefulWidget { final Uri? mxcUri; + final Client client; + final double size; + final BorderRadius? borderRadius; + final Widget Function(BuildContext) placeholder; + + const MxcAvatar({ + super.key, + required this.mxcUri, + required this.client, + required this.size, + required this.placeholder, + this.borderRadius, + }); + + @override + State createState() => _MxcAvatarState(); +} + +class _MxcAvatarState extends State { + late Future _future; + + @override + void initState() { + super.initState(); + _future = _load(); + } + + @override + void didUpdateWidget(MxcAvatar old) { + super.didUpdateWidget(old); + if (old.mxcUri != widget.mxcUri) _future = _load(); + } + + Future _load() async { + final mxc = widget.mxcUri; + if (mxc == null) return null; + + final key = 'avatar:${mxc}_${widget.size.round()}'; + // Memory → Disk → Netzwerk. Disk-Treffer machen Avatare nach einem + // App-Neustart sofort sichtbar statt nachzuladen. + final hit = await MediaCache.instance.getPersistent(key); + if (hit != null) return hit; + + final headers = {'authorization': 'Bearer ${widget.client.accessToken}'}; + + try { + // Try thumbnail first; fall back to full download if 404 (server + // doesn't support on-the-fly thumbnailing, e.g. Continuwuity). + final thumbUri = await mxc.getThumbnailUri( + widget.client, + width: widget.size.round(), + height: widget.size.round(), + method: ThumbnailMethod.crop, + ); + final thumbResp = await widget.client.httpClient.get(thumbUri, headers: headers); + if (thumbResp.statusCode == 200) { + await MediaCache.instance.putPersistent(key, thumbResp.bodyBytes); + return thumbResp.bodyBytes; + } + + // Thumbnail not available — download full image. + final dlUri = await mxc.getDownloadUri(widget.client); + final dlResp = await widget.client.httpClient.get(dlUri, headers: headers); + if (dlResp.statusCode != 200) return null; + await MediaCache.instance.putPersistent(key, dlResp.bodyBytes); + return dlResp.bodyBytes; + } catch (_) { + return null; + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _future, + builder: (context, snap) { + if (snap.hasData && snap.data != null) { + return ClipRRect( + borderRadius: widget.borderRadius ?? + BorderRadius.circular(widget.size / 2), + child: Image.memory( + snap.data!, + width: widget.size, + height: widget.size, + fit: BoxFit.cover, + errorBuilder: (_, __, ___) => widget.placeholder(context), + ), + ); + } + return widget.placeholder(context); + }, + ); + } +} + +// Rectangular MXC image (no fixed size, fills parent) +class MxcImage extends StatefulWidget { + final String mxcUri; + final Client client; + final BoxFit fit; final double? width; final double? height; - final Widget Function(BuildContext)? placeholder; + final Widget? placeholder; const MxcImage({ super.key, required this.mxcUri, + required this.client, + this.fit = BoxFit.cover, this.width, this.height, this.placeholder, }); @override - Widget build(BuildContext context, WidgetRef ref) { - final clientAsync = ref.watch(matrixClientProvider); - final uri = mxcUri; + State createState() => _MxcImageState(); +} - if (uri == null) return _fallback(context); +class _MxcImageState extends State { + late Future _future; - return clientAsync.when( - loading: () => _fallback(context), - error: (e, st) => _fallback(context), - data: (client) => FutureBuilder( - future: uri.getThumbnailUri( - client, - width: width != null ? (width! * 2).toInt() : 64, - height: height != null ? (height! * 2).toInt() : 64, - method: ThumbnailMethod.crop, - ), - builder: (context, snap) { - if (!snap.hasData) return _fallback(context); - return Image.network( - snap.data!.toString(), - width: width, - height: height, - fit: BoxFit.cover, - errorBuilder: (ctx, err, st) => _fallback(context), - ); - }, - ), - ); + @override + void initState() { + super.initState(); + _future = _load(); } - Widget _fallback(BuildContext context) => - placeholder?.call(context) ?? SizedBox(width: width, height: height); + @override + void didUpdateWidget(MxcImage old) { + super.didUpdateWidget(old); + if (old.mxcUri != widget.mxcUri) { + // Block-Body: die Closure darf KEIN Future zurückgeben, sonst wirft + // Flutter "setState() callback returned a Future". + setState(() { + _future = _load(); + }); + } + } + + Future _load() async { + final key = 'img:${widget.mxcUri}'; + final hit = await MediaCache.instance.getPersistent(key); + if (hit != null) return hit; + try { + final uri = Uri.parse(widget.mxcUri); + final headers = { + 'authorization': 'Bearer ${widget.client.accessToken}', + }; + // Erst Thumbnail versuchen (spart Bandbreite, v.a. mobil) — Fallback + // auf Volldownload für Server ohne Thumbnail-Support (Continuwuity). + try { + final thumbUri = await uri.getThumbnailUri( + widget.client, + width: 800, + height: 600, + method: ThumbnailMethod.scale, + ); + final res = await widget.client.httpClient.get(thumbUri, headers: headers); + if (res.statusCode == 200) { + await MediaCache.instance.putPersistent(key, res.bodyBytes); + return res.bodyBytes; + } + } catch (_) {} + final httpUri = await uri.getDownloadUri(widget.client); + final res = await widget.client.httpClient.get(httpUri, headers: headers); + if (res.statusCode != 200) return null; + final bytes = res.bodyBytes; + await MediaCache.instance.putPersistent(key, bytes); + return bytes; + } catch (_) { + return null; + } + } + + @override + Widget build(BuildContext context) { + return FutureBuilder( + future: _future, + builder: (_, snap) { + if (snap.connectionState == ConnectionState.waiting) { + return widget.placeholder ?? const SizedBox.shrink(); + } + if (snap.hasData && snap.data != null) { + return Image.memory( + snap.data!, + fit: widget.fit, + width: widget.width, + height: widget.height, + gaplessPlayback: true, + errorBuilder: (_, __, ___) => + widget.placeholder ?? const SizedBox.shrink(), + ); + } + return widget.placeholder ?? const SizedBox.shrink(); + }, + ); + } } diff --git a/lib/widgets/new_dm_dialog.dart b/lib/widgets/new_dm_dialog.dart new file mode 100644 index 0000000..33801a0 --- /dev/null +++ b/lib/widgets/new_dm_dialog.dart @@ -0,0 +1,346 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +class NewDmDialog extends ConsumerStatefulWidget { + const NewDmDialog({super.key}); + + @override + ConsumerState createState() => _NewDmDialogState(); +} + +class _NewDmDialogState extends ConsumerState { + final _searchCtrl = TextEditingController(); + List _results = []; + bool _searching = false; + String? _error; + Timer? _debounce; + final Set _starting = {}; + + @override + void dispose() { + _searchCtrl.dispose(); + _debounce?.cancel(); + super.dispose(); + } + + void _onSearchChanged(String query) { + _debounce?.cancel(); + if (query.trim().length < 2) { + setState(() { + _results = []; + _searching = false; + _error = null; + }); + return; + } + setState(() => _searching = true); + _debounce = Timer(const Duration(milliseconds: 500), () => _search(query.trim())); + } + + Future _search(String query) async { + try { + final client = await ref.read(matrixClientProvider.future); + final res = await client.searchUserDirectory(query, limit: 20); + if (mounted) { + setState(() { + _results = res.results; + _searching = false; + _error = null; + }); + } + } catch (e) { + if (mounted) { + setState(() { + _searching = false; + _error = e.toString().split('\n').first; + }); + } + } + } + + Future _startDm(String userId) async { + setState(() => _starting.add(userId)); + try { + final client = await ref.read(matrixClientProvider.future); + final roomId = await client.startDirectChat(userId); + if (mounted) { + ref.read(activeSpaceIdProvider.notifier).state = 'dms'; + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + Navigator.of(context).pop(); + } + } catch (e) { + if (mounted) { + setState(() { + _starting.remove(userId); + _error = e.toString().split('\n').first; + }); + } + } + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final size = MediaQuery.sizeOf(context); + final isNarrow = size.width < 600; + + return Dialog( + backgroundColor: pt.bg1, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: BoxConstraints( + maxWidth: isNarrow ? size.width * 0.97 : 480, + maxHeight: size.height * 0.75, + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 12, 12), + child: Row(children: [ + Icon(Icons.chat_bubble_outline_rounded, size: 16, color: pt.accent), + const SizedBox(width: 8), + Expanded( + child: Text('Neue Unterhaltung', + style: TextStyle( + color: pt.fg, + fontSize: 15, + fontWeight: FontWeight.w600)), + ), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ]), + ), + Divider(color: pt.border, height: 1), + Padding( + padding: const EdgeInsets.fromLTRB(16, 12, 16, 8), + child: TextField( + controller: _searchCtrl, + autofocus: true, + style: TextStyle(color: pt.fg, fontSize: 13), + onChanged: _onSearchChanged, + decoration: InputDecoration( + hintText: 'Name oder @nutzer:server suchen', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 13), + prefixIcon: Padding( + padding: const EdgeInsets.only(left: 10, right: 8), + child: Icon(Icons.search_rounded, size: 16, color: pt.fgDim), + ), + prefixIconConstraints: + const BoxConstraints(minWidth: 0, minHeight: 0), + filled: true, + fillColor: pt.bg2, + isDense: true, + contentPadding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.accent)), + ), + cursorColor: pt.accent, + ), + ), + if (_error != null) + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 8), + child: _DmErrorBanner(text: _error!, pt: pt), + ), + Flexible( + child: _searching + ? const Padding( + padding: EdgeInsets.all(24), + child: + Center(child: CircularProgressIndicator.adaptive()), + ) + : _results.isEmpty + ? Padding( + padding: const EdgeInsets.all(24), + child: Center( + child: Text( + _searchCtrl.text.trim().length < 2 + ? 'Mindestens 2 Zeichen eingeben.' + : 'Keine Nutzer gefunden.', + style: TextStyle( + color: pt.fgMuted, fontSize: 13), + ), + ), + ) + : ListView.builder( + shrinkWrap: true, + padding: + const EdgeInsets.fromLTRB(8, 0, 8, 12), + itemCount: _results.length, + itemBuilder: (ctx, i) { + final user = _results[i]; + return _UserResultItem( + profile: user, + pt: pt, + isStarting: + _starting.contains(user.userId), + onTap: () => _startDm(user.userId), + ); + }, + ), + ), + ], + ), + ), + ); + } +} + +class _UserResultItem extends ConsumerWidget { + final Profile profile; + final PyramidTheme pt; + final bool isStarting; + final VoidCallback onTap; + + const _UserResultItem({ + required this.profile, + required this.pt, + required this.isStarting, + required this.onTap, + }); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final client = ref.watch(matrixClientProvider).valueOrNull; + final name = profile.displayName ?? profile.userId; + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + + Widget avatar; + if (client != null && profile.avatarUrl != null) { + avatar = MxcAvatar( + mxcUri: profile.avatarUrl, + client: client, + size: 36, + borderRadius: BorderRadius.circular(18), + placeholder: (_) => + _DmInitialCircle(initial: initial, size: 36, name: name), + ); + } else { + avatar = _DmInitialCircle(initial: initial, size: 36, name: name); + } + + return Material( + color: Colors.transparent, + child: InkWell( + borderRadius: BorderRadius.circular(8), + onTap: isStarting ? null : onTap, + child: Padding( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 6), + child: Row(children: [ + avatar, + const SizedBox(width: 10), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(name, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis), + Text(profile.userId, + style: + TextStyle(color: pt.fgDim, fontSize: 11), + overflow: TextOverflow.ellipsis), + ]), + ), + const SizedBox(width: 8), + if (isStarting) + const SizedBox( + width: 20, + height: 20, + child: CircularProgressIndicator.adaptive( + strokeWidth: 2)) + else + Icon(Icons.arrow_forward_rounded, + size: 14, color: pt.fgDim), + ]), + ), + ), + ); + } +} + +class _DmInitialCircle extends StatelessWidget { + final String initial; + final double size; + final String name; + + const _DmInitialCircle( + {required this.initial, required this.size, required this.name}); + + Color _color() { + const colors = [ + Color(0xFF06B6D4), Color(0xFFA855F7), Color(0xFF10B981), + Color(0xFFF43F5E), Color(0xFF3B82F6), Color(0xFFF59E0B), + ]; + if (name.isEmpty) return colors[0]; + return colors[name.codeUnitAt(0) % colors.length]; + } + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration(color: _color(), shape: BoxShape.circle), + child: Center( + child: Text(initial, + style: const TextStyle( + color: Colors.white, + fontSize: 14, + fontWeight: FontWeight.w600)), + ), + ); + } +} + +class _DmErrorBanner extends StatelessWidget { + final String text; + final PyramidTheme pt; + const _DmErrorBanner({required this.text, required this.pt}); + + @override + Widget build(BuildContext context) => Container( + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: pt.danger.withAlpha(20), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.danger.withAlpha(60)), + ), + child: Row(children: [ + Icon(Icons.error_outline_rounded, size: 14, color: pt.danger), + const SizedBox(width: 8), + Expanded( + child: Text(text, + style: + TextStyle(color: pt.danger, fontSize: 12))), + ]), + ); +} diff --git a/lib/widgets/profile_popover.dart b/lib/widgets/profile_popover.dart new file mode 100644 index 0000000..fded0d5 --- /dev/null +++ b/lib/widgets/profile_popover.dart @@ -0,0 +1,442 @@ +import 'dart:convert'; + +import 'package:flutter/material.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +class ProfilePopover extends StatefulWidget { + final String userId; + final Room room; + final Offset globalPos; + final VoidCallback onClose; + + const ProfilePopover({ + super.key, + required this.userId, + required this.room, + required this.globalPos, + required this.onClose, + }); + + @override + State createState() => _ProfilePopoverState(); +} + +class _ProfilePopoverState extends State { + Profile? _profile; + PresenceType? _presence; + String? _bannerMxcUri; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + try { + final p = await widget.room.client.getProfileFromUserId(widget.userId); + if (mounted) setState(() => _profile = p); + } catch (_) {} + try { + final p = await widget.room.client.fetchCurrentPresence(widget.userId); + // Veraltete "online"-Presence herabstufen, wenn die letzte Aktivität + // nicht frisch ist (Server meldet sonst dauerhaft online). + final last = p.lastActiveTimestamp; + final fresh = p.currentlyActive == true || + (last != null && + DateTime.now().difference(last) < const Duration(minutes: 5)); + final effective = (p.presence == PresenceType.online && !fresh) + ? PresenceType.offline + : p.presence; + if (mounted) setState(() => _presence = effective); + } catch (_) {} + // Load banner from Matrix profile custom field (works for any user) + try { + final client = widget.room.client; + final apiUri = client.homeserver!.replace( + path: '/_matrix/client/v3/profile/${Uri.encodeComponent(widget.userId)}', + ); + final resp = await client.httpClient.get( + apiUri, + headers: {'Authorization': 'Bearer ${client.accessToken}'}, + ); + if (resp.statusCode == 200) { + final data = jsonDecode(resp.body) as Map; + final url = data['io.pyramid.profile.banner_url'] as String?; + if (url != null && mounted) setState(() => _bannerMxcUri = url); + } + } catch (_) {} + // Legacy fallback: account data (only own user) + if (_bannerMxcUri == null && widget.userId == widget.room.client.userID) { + try { + final bannerData = + widget.room.client.accountData['com.pyramid.profile.banner']; + final url = bannerData?.content['url'] as String?; + if (url != null && mounted) setState(() => _bannerMxcUri = url); + } catch (_) {} + } + } + + @override + Widget build(BuildContext context) { + final size = MediaQuery.sizeOf(context); + final member = widget.room.unsafeGetUserFromMemoryOrFallback(widget.userId); + final displayName = _profile?.displayName ?? member.displayName ?? widget.userId.split(':').first.replaceAll('@', ''); + final avatarUrl = _profile?.avatarUrl ?? member.avatarUrl; + final handle = widget.userId; + final initials = displayName.isNotEmpty ? displayName[0].toUpperCase() : '?'; + final color = _colorForName(displayName); + final powerLevel = widget.room.getPowerLevelByUserId(widget.userId); + final joinDate = _formatJoinDate(widget.room, widget.userId); + + const popoverW = 300.0; + const popoverH = 380.0; + final left = (widget.globalPos.dx + 16).clamp(8.0, size.width - popoverW - 8); + final top = (widget.globalPos.dy - 80).clamp(8.0, size.height - popoverH - 8); + + return Positioned( + left: left, + top: top, + child: Material( + color: Colors.transparent, + child: Container( + width: popoverW, + decoration: BoxDecoration( + color: PyramidColors.bg0, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: PyramidColors.border), + boxShadow: const [ + BoxShadow(color: Color(0x60000000), blurRadius: 24, offset: Offset(0, 8)) + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(12), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Banner — real image for own profile, color gradient for others + SizedBox( + height: 64, + child: _bannerMxcUri != null + ? MxcImage( + mxcUri: _bannerMxcUri!, + client: widget.room.client, + fit: BoxFit.cover, + width: double.infinity, + height: 64, + placeholder: Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withValues(alpha: 0.6), + color.withValues(alpha: 0.3) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + ), + ) + : Container( + decoration: BoxDecoration( + gradient: LinearGradient( + colors: [ + color.withValues(alpha: 0.6), + color.withValues(alpha: 0.3) + ], + begin: Alignment.topLeft, + end: Alignment.bottomRight, + ), + ), + ), + ), + Padding( + padding: const EdgeInsets.fromLTRB(16, 0, 16, 16), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + // Avatar row + Transform.translate( + offset: const Offset(0, -28), + child: Row( + children: [ + Stack( + clipBehavior: Clip.none, + children: [ + Container( + width: 56, + height: 56, + decoration: BoxDecoration( + color: color, + borderRadius: BorderRadius.circular(16), + border: Border.all(color: PyramidColors.bg0, width: 3), + ), + clipBehavior: Clip.antiAlias, + child: avatarUrl != null + ? MxcImage( + mxcUri: avatarUrl.toString(), + client: widget.room.client, + width: 56, + height: 56, + placeholder: Center( + child: Text(initials, + style: const TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w700)), + ), + ) + : Center( + child: Text(initials, + style: const TextStyle( + color: Colors.white, + fontSize: 22, + fontWeight: FontWeight.w700))), + ), + Positioned( + right: -2, + bottom: -2, + child: _PresenceDot(presence: _presence, size: 14), + ), + ], + ), + ], + ), + ), + Transform.translate( + offset: const Offset(0, -20), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(displayName, + style: const TextStyle( + color: PyramidColors.fg, + fontSize: 17, + fontWeight: FontWeight.w700)), + const SizedBox(height: 2), + Text(handle, + style: const TextStyle( + color: PyramidColors.fgMuted, fontSize: 12)), + const SizedBox(height: 12), + // Action buttons + Row( + children: [ + _ProfileBtn( + label: 'Nachricht', + icon: Icons.send_outlined, + primary: true, + onTap: () { + widget.onClose(); + // TODO: open DM + }, + ), + const SizedBox(width: 8), + _ProfileBtn( + label: 'Anrufen', + icon: Icons.call_outlined, + onTap: () {}, + ), + const SizedBox(width: 8), + _ProfileBtn( + icon: Icons.more_vert, + onTap: () {}, + ), + ], + ), + if (powerLevel > 0) ...[ + const SizedBox(height: 14), + const Text('Rollen', + style: TextStyle( + color: PyramidColors.fgDim, + fontSize: 10, + fontWeight: FontWeight.w700, + letterSpacing: 0.8)), + const SizedBox(height: 6), + Wrap( + spacing: 6, + runSpacing: 4, + children: [ + _RoleBadge( + label: powerLevel >= 100 ? 'Admin' : 'Moderator', + color: powerLevel >= 100 + ? const Color(0xFFF59E0B) + : const Color(0xFF06B6D4), + ), + ], + ), + ], + if (joinDate != null) ...[ + const SizedBox(height: 14), + const Text('Mitglied seit', + style: TextStyle( + color: PyramidColors.fgDim, + fontSize: 10, + fontWeight: FontWeight.w700, + letterSpacing: 0.8)), + const SizedBox(height: 4), + Text(joinDate, + style: const TextStyle( + color: PyramidColors.fgMuted, fontSize: 12)), + ], + ], + ), + ), + ], + ), + ), + ], + ), + ), + ), + ), + ); + } + + String? _formatJoinDate(Room room, String userId) { + try { + final member = room.unsafeGetUserFromMemoryOrFallback(userId); + // User joined if membership is join + if (member.membership != Membership.join) return null; + // No timestamp available from StrippedStateEvent; show server domain hint + final server = userId.contains(':') ? userId.split(':').last : null; + return server != null ? 'via $server' : null; + } catch (_) { + return null; + } + } + + Color _colorForName(String name) { + const colors = [ + Color(0xFF06B6D4), Color(0xFFA855F7), Color(0xFFFF6B9D), + Color(0xFF10B981), Color(0xFFF59E0B), Color(0xFF3B82F6), + Color(0xFFF43F5E), + ]; + final hash = name.codeUnits.fold(0, (a, b) => a + b); + return colors[hash % colors.length]; + } +} + +class _PresenceDot extends StatelessWidget { + final PresenceType? presence; + final double size; + const _PresenceDot({required this.presence, required this.size}); + + @override + Widget build(BuildContext context) { + final color = switch (presence) { + PresenceType.online => const Color(0xFF23A55A), + PresenceType.unavailable => const Color(0xFFF0B232), + _ => const Color(0xFF7C7C8A), + }; + return Container( + width: size, + height: size, + decoration: BoxDecoration( + color: color, + shape: BoxShape.circle, + border: Border.all(color: PyramidColors.bg0, width: 2), + ), + ); + } +} + +class _ProfileBtn extends StatefulWidget { + final String? label; + final IconData icon; + final bool primary; + final VoidCallback onTap; + + const _ProfileBtn({ + required this.icon, + required this.onTap, + this.label, + this.primary = false, + }); + + @override + State<_ProfileBtn> createState() => _ProfileBtnState(); +} + +class _ProfileBtnState extends State<_ProfileBtn> { + bool _hover = false; + + @override + Widget build(BuildContext context) { + final hasLabel = widget.label != null; + return MouseRegion( + onEnter: (_) => setState(() => _hover = true), + onExit: (_) => setState(() => _hover = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 120), + padding: EdgeInsets.symmetric( + horizontal: hasLabel ? 12 : 9, vertical: 7), + decoration: BoxDecoration( + color: widget.primary + ? (_hover + ? PyramidTheme.of(context).accent.withAlpha(200) + : PyramidTheme.of(context).accent) + : (_hover ? PyramidColors.bgHover : PyramidColors.bg2), + borderRadius: BorderRadius.circular(8), + border: Border.all( + color: widget.primary ? Colors.transparent : PyramidColors.border, + ), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(widget.icon, + size: 14, + color: widget.primary + ? PyramidColors.accentFg + : PyramidColors.fg), + if (hasLabel) ...[ + const SizedBox(width: 6), + Text(widget.label!, + style: TextStyle( + color: widget.primary + ? PyramidColors.accentFg + : PyramidColors.fg, + fontSize: 13, + fontWeight: FontWeight.w500)), + ], + ], + ), + ), + ), + ); + } +} + +class _RoleBadge extends StatelessWidget { + final String label; + final Color color; + const _RoleBadge({required this.label, required this.color}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: color.withValues(alpha: 0.15), + borderRadius: BorderRadius.circular(999), + border: Border.all(color: color.withValues(alpha: 0.4)), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Container( + width: 6, height: 6, + decoration: BoxDecoration(color: color, shape: BoxShape.circle)), + const SizedBox(width: 5), + Text(label, + style: TextStyle(color: color, fontSize: 11, fontWeight: FontWeight.w500)), + ], + ), + ); + } +} diff --git a/lib/widgets/pyramid_loader.dart b/lib/widgets/pyramid_loader.dart new file mode 100644 index 0000000..e78431e --- /dev/null +++ b/lib/widgets/pyramid_loader.dart @@ -0,0 +1,202 @@ +import 'dart:math'; +import 'package:flutter/material.dart'; +import 'package:lottie/lottie.dart'; +import 'package:pyramid/core/theme.dart'; + +class PyramidLoader extends StatefulWidget { + final double size; + final bool useLottie; + + const PyramidLoader({super.key, this.size = 60, this.useLottie = false}); + + @override + State createState() => _PyramidLoaderState(); +} + +class _PyramidLoaderState extends State + with SingleTickerProviderStateMixin { + late AnimationController _ctrl; + + // Mirror the JS constants exactly + static const _hold = 0.2; + static const _curveExp = 3.0; + static const _tiltDeg = 20.0; + + double _ease(double t, double exp) => + t < 0.5 ? 0.5 * pow(2 * t, exp) : 1 - 0.5 * pow(2 * (1 - t), exp); + + double _yawAt(double t) { + final a = 1.0 - _hold; + if (t >= a) return pi / 4; + return _ease(t / a, _curveExp) * 2 * pi + pi / 4; + } + + @override + void initState() { + super.initState(); + _ctrl = AnimationController( + vsync: this, + duration: const Duration(milliseconds: 2000), + )..repeat(); + } + + @override + void dispose() { + _ctrl.dispose(); + super.dispose(); + } + + Color _accent(BuildContext ctx) { + try { + return PyramidTheme.of(ctx).accent; + } catch (_) { + return const Color(0xFFF5A524); + } + } + + @override + Widget build(BuildContext context) { + final accent = _accent(context); + + final painter = AnimatedBuilder( + animation: _ctrl, + builder: (_, __) => CustomPaint( + painter: _PyramidPainter( + yaw: _yawAt(_ctrl.value), + accent: accent, + tiltDeg: _tiltDeg, + ), + size: Size(widget.size, widget.size), + ), + ); + + if (widget.useLottie) { + return Center( + child: SizedBox( + width: widget.size, + height: widget.size, + child: ColorFiltered( + colorFilter: ColorFilter.mode(accent, BlendMode.srcIn), + child: Lottie.asset( + 'assets/pyramid-loader.json', + fit: BoxFit.contain, + repeat: true, + animate: true, + errorBuilder: (_, __, ___) => painter, + ), + ), + ), + ); + } + + return Center(child: painter); + } +} + +class _PyramidPainter extends CustomPainter { + final double yaw; + final Color accent; + final double tiltDeg; + + const _PyramidPainter({ + required this.yaw, + required this.accent, + required this.tiltDeg, + }); + + List _rotY(List v, double a) { + final c = cos(a), s = sin(a); + return [v[0] * c + v[2] * s, v[1], -v[0] * s + v[2] * c]; + } + + List> _clipZ(List> poly) { + final out = >[]; + for (var i = 0; i < poly.length; i++) { + final a = poly[i]; + final b = poly[(i + 1) % poly.length]; + final ai = a[2] >= 0, bi = b[2] >= 0; + if (ai) out.add(a); + if (ai != bi) { + final t = a[2] / (a[2] - b[2]); + out.add([a[0] + t * (b[0] - a[0]), a[1] + t * (b[1] - a[1]), 0.0]); + } + } + return out; + } + + Offset _proj(List v, double sc, double cx, double cy, double tr) => + Offset(cx + v[0] * sc, cy + (v[1] * cos(tr) + v[2] * sin(tr)) * sc); + + double _frontness(List> verts) { + final a = verts[0], b = verts[1], c = verts[2]; + final ux = b[0]-a[0], uy = b[1]-a[1], uz = b[2]-a[2]; + final vx = c[0]-a[0], vy = c[1]-a[1], vz = c[2]-a[2]; + final nz = ux * vy - uy * vx; + final nLen = sqrt( + pow(uy * vz - uz * vy, 2) + pow(uz * vx - ux * vz, 2) + nz * nz, + ); + return nLen == 0 ? 0 : max(0.0, -nz / nLen); + } + + Color _darken(Color c, double amount) => Color.fromARGB( + c.alpha, + max(0, (c.red * (1 - amount)).round()), + max(0, (c.green * (1 - amount)).round()), + max(0, (c.blue * (1 - amount)).round()), + ); + + @override + void paint(Canvas canvas, Size size) { + final sc = size.width * 0.38; + final cx = size.width / 2; + final cy = size.height / 2; + final tr = -tiltDeg * pi / 180; + + const base = 0.7; + final faces = [ + [[0.0, -1.0, 0.0], [base, 1.0, base], [base, 1.0, -base]], + [[0.0, -1.0, 0.0], [base, 1.0, -base], [-base, 1.0, -base]], + [[0.0, -1.0, 0.0], [-base, 1.0, -base],[-base, 1.0, base]], + [[0.0, -1.0, 0.0], [-base, 1.0, base], [base, 1.0, base]], + ]; + + final items = <({List pts, double depth})>[]; + + for (final face in faces) { + final rot = face.map((v) => _rotY(v, yaw)).toList(); + final cl = _clipZ(rot); + if (cl.length < 3) continue; + final depth = cl.fold(0.0, (s, v) => s + v[2]) / cl.length; + items.add(( + pts: cl.map((v) => _proj(v, sc, cx, cy, tr)).toList(), + depth: depth, + )); + } + + items.sort((a, b) => a.depth.compareTo(b.depth)); + + final fillPaint = Paint() + ..color = _darken(accent, 0.45) + ..style = PaintingStyle.fill; + final strokePaint = Paint() + ..color = accent + ..style = PaintingStyle.stroke + ..strokeWidth = 1.4 * (size.width / 96) + ..strokeJoin = StrokeJoin.round + ..strokeCap = StrokeCap.round; + + for (final item in items) { + final path = Path()..moveTo(item.pts[0].dx, item.pts[0].dy); + for (var i = 1; i < item.pts.length; i++) { + path.lineTo(item.pts[i].dx, item.pts[i].dy); + } + path.close(); + canvas.drawPath(path, fillPaint); + canvas.drawPath(path, strokePaint); + } + } + + @override + bool shouldRepaint(_PyramidPainter old) => + old.yaw != yaw || old.accent != accent; +} diff --git a/lib/widgets/pyramid_logo.dart b/lib/widgets/pyramid_logo.dart new file mode 100644 index 0000000..c1a344b --- /dev/null +++ b/lib/widgets/pyramid_logo.dart @@ -0,0 +1,187 @@ +import 'dart:math' as math; +import 'dart:ui' as ui; +import 'package:flutter/material.dart'; + +// 3D Pyramid logo — two faces + base outline + spine +class PyramidLogo extends StatelessWidget { + final double size; + final Color color; + const PyramidLogo({super.key, this.size = 36, this.color = Colors.white}); + + @override + Widget build(BuildContext context) => + CustomPaint(size: Size(size, size), painter: _PyramidLogoPainter(color: color)); +} + +class _PyramidLogoPainter extends CustomPainter { + final Color color; + const _PyramidLogoPainter({required this.color}); + + @override + void paint(Canvas canvas, Size size) { + final w = size.width; + final h = size.height; + final sx = w / 48; + final sy = h / 48; + Offset p(double x, double y) => Offset(x * sx, y * sy); + + final apex = p(24, 6); + final baseL = p(6, 40); + final baseR = p(42, 40); + final baseM = p(24, 34); + + // Left face — full opacity → 55% + final leftPath = Path()..moveTo(apex.dx, apex.dy)..lineTo(baseL.dx, baseL.dy)..lineTo(baseM.dx, baseM.dy)..close(); + canvas.drawPath(leftPath, Paint()..shader = ui.Gradient.linear( + Offset(0, apex.dy), Offset(0, baseL.dy), + [color.withAlpha(255), color.withAlpha(140)], + )); + + // Right face — 85% → 25% + final rightPath = Path()..moveTo(apex.dx, apex.dy)..lineTo(baseR.dx, baseR.dy)..lineTo(baseM.dx, baseM.dy)..close(); + canvas.drawPath(rightPath, Paint()..shader = ui.Gradient.linear( + Offset(apex.dx, apex.dy), Offset(baseR.dx, baseR.dy), + [color.withAlpha(217), color.withAlpha(64)], + )); + + // Base outline + canvas.drawPath( + Path()..moveTo(baseL.dx, baseL.dy)..lineTo(baseM.dx, baseM.dy)..lineTo(baseR.dx, baseR.dy), + Paint()..color = color.withAlpha(102)..style = PaintingStyle.stroke + ..strokeWidth = math.max(sx, 0.7)..strokeJoin = StrokeJoin.round, + ); + + // Spine + canvas.drawLine(apex, baseM, Paint()..color = color.withAlpha(230) + ..strokeWidth = math.max(sx * 0.8, 0.6)); + } + + @override + bool shouldRepaint(_PyramidLogoPainter old) => old.color != color; +} + +// Pyramid mark — stylised stacked triangles +class PyramidMark extends StatelessWidget { + final double size; + final Color? color; + + const PyramidMark({super.key, this.size = 30, this.color}); + + @override + Widget build(BuildContext context) { + final c = color ?? Colors.white; + return SizedBox( + width: size, + height: size, + child: CustomPaint(painter: _PyramidPainter(c)), + ); + } +} + +class _PyramidPainter extends CustomPainter { + final Color color; + _PyramidPainter(this.color); + + @override + void paint(Canvas canvas, Size size) { + final paint = Paint()..color = color..style = PaintingStyle.fill; + final w = size.width; + final h = size.height; + + // bottom big triangle + final big = Path() + ..moveTo(w * 0.5, h * 0.1) + ..lineTo(w * 0.92, h * 0.88) + ..lineTo(w * 0.08, h * 0.88) + ..close(); + canvas.drawPath(big, paint); + + // inner cutout (dark) to create layered look + final cut = Paint() + ..color = Colors.black.withAlpha(80) + ..style = PaintingStyle.fill; + final inner = Path() + ..moveTo(w * 0.5, h * 0.28) + ..lineTo(w * 0.74, h * 0.72) + ..lineTo(w * 0.26, h * 0.72) + ..close(); + canvas.drawPath(inner, cut); + } + + @override + bool shouldRepaint(_PyramidPainter old) => old.color != color; +} + +// Pyramid space glyph (letter + triangle overlay) +class PyramidGlyph extends StatelessWidget { + final double size; + final Color color; + final String label; + + const PyramidGlyph({ + super.key, + this.size = 30, + required this.color, + required this.label, + }); + + @override + Widget build(BuildContext context) { + return SizedBox( + width: size, + height: size, + child: Stack( + alignment: Alignment.center, + children: [ + CustomPaint( + size: Size(size, size), + painter: _PyramidPainter(color), + ), + Text( + label.isNotEmpty ? label[0].toUpperCase() : '?', + style: TextStyle( + color: Colors.white, + fontSize: size * 0.38, + fontWeight: FontWeight.bold, + height: 1, + ), + ), + ], + ), + ); + } +} + +// Presence indicator dot +class PresenceDot extends StatelessWidget { + final String status; // online, away, busy, offline + final double size; + final Color borderColor; + + const PresenceDot({ + super.key, + required this.status, + this.size = 10, + this.borderColor = const Color(0xFF111114), + }); + + Color get _color => switch (status) { + 'online' => const Color(0xFF4ADE80), + 'away' => const Color(0xFFFACC15), + 'busy' => const Color(0xFFF87171), + _ => const Color(0xFF6F6F7D), + }; + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + decoration: BoxDecoration( + color: _color, + shape: BoxShape.circle, + border: Border.all(color: borderColor, width: 2), + ), + ); + } +} diff --git a/lib/widgets/screen_share_picker.dart b/lib/widgets/screen_share_picker.dart new file mode 100644 index 0000000..03704f4 --- /dev/null +++ b/lib/widgets/screen_share_picker.dart @@ -0,0 +1,233 @@ +import 'dart:typed_data'; +import 'package:flutter/material.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart'; +import 'package:pyramid/core/theme.dart'; + +class ScreenSharePicker extends StatefulWidget { + const ScreenSharePicker({super.key}); + + static Future show(BuildContext context) async { + return showDialog( + context: context, + builder: (context) => const ScreenSharePicker(), + ); + } + + @override + State createState() => _ScreenSharePickerState(); +} + +class _ScreenSharePickerState extends State with SingleTickerProviderStateMixin { + late TabController _tabController; + List _sources = []; + bool _loading = true; + + @override + void initState() { + super.initState(); + _tabController = TabController(length: 2, vsync: this); + _loadSources(); + } + + Future _loadSources() async { + try { + // FluffyChat Fix: Get both types at once to avoid native crashes on Windows + final sources = await desktopCapturer.getSources(types: [ + SourceType.Screen, + SourceType.Window, + ]); + if (mounted) { + setState(() { + _sources = sources; + _loading = false; + }); + } + } catch (e) { + print('[Picker] Error loading sources: $e'); + if (mounted) setState(() => _loading = false); + } + } + + @override + void dispose() { + _tabController.dispose(); + super.dispose(); + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final screens = _sources.where((s) => s.type == SourceType.Screen).toList(); + final windows = _sources.where((s) => s.type == SourceType.Window).toList(); + + final screenSize = MediaQuery.sizeOf(context); + return Center( + child: Container( + // Auf kleinen Bildschirmen (Mobile, Quer- wie Hochformat) einpassen. + width: (screenSize.width - 32).clamp(280.0, 600.0), + height: (screenSize.height - 48).clamp(320.0, 520.0), + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rXl), + border: Border.all(color: pt.border), + boxShadow: [BoxShadow(color: Colors.black54, blurRadius: 40)], + ), + child: Column( + children: [ + // Header + Padding( + padding: const EdgeInsets.fromLTRB(24, 20, 16, 8), + child: Row( + children: [ + Text('Share your screen', + style: TextStyle(color: pt.fg, fontSize: 20, fontWeight: FontWeight.w700)), + const Spacer(), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim), + onPressed: () => Navigator.pop(context), + ), + ], + ), + ), + + // Tabs + TabBar( + controller: _tabController, + indicatorColor: pt.accent, + labelColor: pt.accent, + unselectedLabelColor: pt.fgMuted, + dividerColor: pt.border, + tabs: const [ + Tab(text: 'Screens'), + Tab(text: 'Windows'), + ], + ), + + // Content + Expanded( + child: _loading + ? Center(child: CircularProgressIndicator(color: pt.accent)) + : TabBarView( + controller: _tabController, + children: [ + _SourceGrid(sources: screens, pt: pt), + _SourceGrid(sources: windows, pt: pt), + ], + ), + ), + + // Footer + Container( + padding: const EdgeInsets.all(16), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.vertical(bottom: Radius.circular(pt.rXl)), + border: Border(top: BorderSide(color: pt.border)), + ), + child: Row( + mainAxisAlignment: MainAxisAlignment.end, + children: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Cancel', style: TextStyle(color: pt.fgMuted)), + ), + ], + ), + ), + ], + ), + ), + ); + } +} + +class _SourceGrid extends StatelessWidget { + final List sources; + final PyramidTheme pt; + + const _SourceGrid({required this.sources, required this.pt}); + + @override + Widget build(BuildContext context) { + if (sources.isEmpty) { + return Center(child: Text('No sources found', style: TextStyle(color: pt.fgDim))); + } + + return GridView.builder( + padding: const EdgeInsets.all(16), + gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount( + crossAxisCount: 2, + crossAxisSpacing: 12, + mainAxisSpacing: 16, + childAspectRatio: 1.4, + ), + itemCount: sources.length, + itemBuilder: (context, i) { + final s = sources[i]; + return _SourceTile(source: s, pt: pt); + }, + ); + } +} + +class _SourceTile extends StatefulWidget { + final DesktopCapturerSource source; + final PyramidTheme pt; + + const _SourceTile({required this.source, required this.pt}); + + @override + State<_SourceTile> createState() => _SourceTileState(); +} + +class _SourceTileState extends State<_SourceTile> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + cursor: SystemMouseCursors.click, + child: GestureDetector( + onTap: () => Navigator.pop(context, widget.source), + child: Column( + children: [ + Expanded( + child: Container( + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all( + color: _hovered ? pt.accent : pt.border, + width: _hovered ? 2 : 1, + ), + ), + clipBehavior: Clip.antiAlias, + child: widget.source.thumbnail != null + ? Image.memory( + widget.source.thumbnail!, + fit: BoxFit.cover, + width: double.infinity, + ) + : Center(child: Icon(Icons.monitor_rounded, color: pt.fgDim, size: 32)), + ), + ), + const SizedBox(height: 6), + Text( + widget.source.name, + maxLines: 1, + overflow: TextOverflow.ellipsis, + style: TextStyle( + color: _hovered ? pt.fg : pt.fgMuted, + fontSize: 12, + fontWeight: _hovered ? FontWeight.w600 : FontWeight.w400, + ), + ), + ], + ), + ), + ); + } +} diff --git a/lib/widgets/search_modal.dart b/lib/widgets/search_modal.dart new file mode 100644 index 0000000..3679c05 --- /dev/null +++ b/lib/widgets/search_modal.dart @@ -0,0 +1,840 @@ +import 'dart:async'; + +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +// ─── State ──────────────────────────────────────────────────────────────────── + +enum _Filter { all, media, people } + +class _SearchState { + final bool loading; + final List messageResults; + final List roomResults; + final String? error; + + const _SearchState({ + this.loading = false, + this.messageResults = const [], + this.roomResults = const [], + this.error, + }); + + _SearchState copyWith({ + bool? loading, + List? messageResults, + List? roomResults, + String? error, + }) => _SearchState( + loading: loading ?? this.loading, + messageResults: messageResults ?? this.messageResults, + roomResults: roomResults ?? this.roomResults, + error: error, + ); +} + +// ─── Widget ─────────────────────────────────────────────────────────────────── + +class SearchModal extends ConsumerStatefulWidget { + final VoidCallback onClose; + const SearchModal({super.key, required this.onClose}); + + @override + ConsumerState createState() => _SearchModalState(); +} + +class _SearchModalState extends ConsumerState { + final _ctrl = TextEditingController(); + final _focusNode = FocusNode(); + _Filter _filter = _Filter.all; + String _query = ''; + int _selected = 0; + _SearchState _state = const _SearchState(); + Timer? _debounce; + + @override + void initState() { + super.initState(); + WidgetsBinding.instance.addPostFrameCallback((_) => _focusNode.requestFocus()); + } + + @override + void dispose() { + _debounce?.cancel(); + _ctrl.dispose(); + _focusNode.dispose(); + super.dispose(); + } + + void _onQueryChanged(String q) { + setState(() { + _query = q; + _selected = 0; + }); + _debounce?.cancel(); + if (q.trim().isEmpty) { + setState(() => _state = const _SearchState()); + return; + } + _debounce = Timer(const Duration(milliseconds: 400), () => _runSearch(q.trim())); + } + + Future _runSearch(String q) async { + final client = ref.read(matrixClientProvider).valueOrNull; + if (client == null) return; + setState(() => _state = _state.copyWith(loading: true, error: null)); + + // Room/people filter: purely local + final allRooms = client.rooms.where((r) => !r.isSpace).toList(); + final roomResults = _filter == _Filter.media + ? [] + : allRooms + .where((r) { + if (_filter == _Filter.people && !r.isDirectChat) return false; + if (_filter == _Filter.all && r.isDirectChat) return false; + return r.getLocalizedDisplayname().toLowerCase().contains(q.toLowerCase()); + }) + .take(5) + .toList(); + + // Message/media search: LOCAL over decrypted events. The server-side + // /search API can't see E2EE message content (only ciphertext), so it + // returns nothing for encrypted rooms — we search the local database + // (which holds decrypted events) instead, like Element does. + List messageResults = []; + if (_filter != _Filter.people) { + try { + messageResults = await _localMessageSearch(client, q); + } catch (e) { + setState(() => _state = _state.copyWith( + loading: false, + error: 'Suche fehlgeschlagen: $e', + )); + return; + } + } + + if (mounted) { + setState(() => _state = _SearchState( + loading: false, + messageResults: messageResults, + roomResults: roomResults, + )); + } + } + + // Scans the local (decrypted) event database across all rooms for messages + // whose body matches the query. For the media filter, only media messages + // whose filename/caption matches are returned. + Future> _localMessageSearch(Client client, String q) async { + final db = client.database; + final lower = q.toLowerCase(); + final media = _filter == _Filter.media; + const mediaTypes = {'m.image', 'm.video', 'm.file', 'm.audio'}; + const perRoomScanCap = 1500; + const totalCap = 60; + const chunk = 500; + + final results = []; + for (final room in client.rooms.where((r) => !r.isSpace)) { + var start = 0; + var scanned = 0; + try { + while (scanned < perRoomScanCap) { + final events = await db.getEventList(room, start: start, limit: chunk); + if (events.isEmpty) break; + for (final e in events) { + if (e.type != EventTypes.Message || e.redacted) continue; + final msgtype = e.content.tryGet('msgtype') ?? ''; + if (media && !mediaTypes.contains(msgtype)) continue; + if (!e.body.toLowerCase().contains(lower)) continue; + results.add(e); + } + start += chunk; + scanned += events.length; + if (events.length < chunk || results.length >= totalCap) break; + } + } catch (_) {} + if (results.length >= totalCap) break; + } + + results.sort((a, b) => b.originServerTs.compareTo(a.originServerTs)); + return results.take(totalCap).toList(); + } + + void _openRoom(String roomId, {String? eventId}) { + widget.onClose(); + ref.read(activeRoomIdProvider.notifier).state = roomId; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + if (eventId != null) { + ref.read(pendingJumpEventProvider.notifier).state = eventId; + } + } + + int get _totalResults => + _state.roomResults.length + _state.messageResults.length; + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final client = ref.watch(matrixClientProvider).valueOrNull; + + final filters = [ + (_Filter.all, 'Alle', Icons.auto_awesome_rounded), + (_Filter.media, 'Medien', Icons.image_rounded), + (_Filter.people, 'Personen & Räume', Icons.group_rounded), + ]; + + return KeyboardListener( + focusNode: FocusNode(), + onKeyEvent: (e) { + if (e is! KeyDownEvent) return; + if (e.logicalKey == LogicalKeyboardKey.escape) widget.onClose(); + if (e.logicalKey == LogicalKeyboardKey.arrowDown) { + setState(() => _selected = (_selected + 1) % _totalResults.clamp(1, 999)); + } + if (e.logicalKey == LogicalKeyboardKey.arrowUp) { + setState(() => _selected = (_selected - 1).clamp(0, _totalResults - 1)); + } + if (e.logicalKey == LogicalKeyboardKey.enter) { + _activateSelected(client); + } + }, + child: GestureDetector( + onTap: widget.onClose, + child: Container( + color: Colors.black.withAlpha(150), + alignment: Alignment.topCenter, + padding: const EdgeInsets.only(top: 80), + child: GestureDetector( + onTap: () {}, + child: Container( + width: 640, + constraints: const BoxConstraints(maxHeight: 560), + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rXl), + border: Border.all(color: pt.border), + boxShadow: [ + BoxShadow(color: Colors.black.withAlpha(180), blurRadius: 60, offset: const Offset(0, 20)), + ], + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + // Input + _SearchBar(ctrl: _ctrl, focusNode: _focusNode, onChanged: _onQueryChanged, pt: pt), + // Filters + _FilterRow( + filters: filters, + active: _filter, + pt: pt, + onSelect: (f) { + setState(() { _filter = f; _selected = 0; }); + if (_query.trim().isNotEmpty) _runSearch(_query.trim()); + }, + ), + // Results + Flexible(child: _ResultsPane( + state: _state, + query: _query, + filter: _filter, + selected: _selected, + pt: pt, + client: client, + onOpenRoom: _openRoom, + )), + // Footer + _Footer( + count: _totalResults, + loading: _state.loading, + pt: pt, + ), + ], + ), + ), + ), + ), + ), + ); + } + + void _activateSelected(Client? client) { + final roomCount = _state.roomResults.length; + if (_selected < roomCount) { + _openRoom(_state.roomResults[_selected].id); + } else { + final idx = _selected - roomCount; + if (idx < _state.messageResults.length) { + final e = _state.messageResults[idx]; + final rid = e.roomId; + if (rid != null) _openRoom(rid, eventId: e.eventId); + } + } + } +} + +// ─── Search bar ─────────────────────────────────────────────────────────────── + +class _SearchBar extends StatelessWidget { + final TextEditingController ctrl; + final FocusNode focusNode; + final ValueChanged onChanged; + final PyramidTheme pt; + const _SearchBar({required this.ctrl, required this.focusNode, required this.onChanged, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 12), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: pt.border))), + child: Row( + children: [ + Icon(Icons.search_rounded, size: 20, color: pt.fgDim), + const SizedBox(width: 10), + Expanded( + child: TextField( + controller: ctrl, + focusNode: focusNode, + style: TextStyle(color: pt.fg, fontSize: 15), + cursorColor: pt.accent, + decoration: InputDecoration( + hintText: 'Nachrichten, Medien, Personen, Räume suchen…', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 15), + border: InputBorder.none, + contentPadding: EdgeInsets.zero, + isDense: true, + ), + onChanged: onChanged, + ), + ), + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 3), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(4), + border: Border.all(color: pt.border), + ), + child: Text('esc', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ), + ], + ), + ); + } +} + +// ─── Filter row ─────────────────────────────────────────────────────────────── + +class _FilterRow extends StatelessWidget { + final List<(_Filter, String, IconData)> filters; + final _Filter active; + final PyramidTheme pt; + final ValueChanged<_Filter> onSelect; + const _FilterRow({required this.filters, required this.active, required this.pt, required this.onSelect}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(vertical: 8), + decoration: BoxDecoration(border: Border(bottom: BorderSide(color: pt.border))), + child: SingleChildScrollView( + scrollDirection: Axis.horizontal, + padding: const EdgeInsets.symmetric(horizontal: 12), + child: Row( + children: filters.map((f) => Padding( + padding: const EdgeInsets.only(right: 6), + child: _Chip(label: f.$2, icon: f.$3, active: active == f.$1, pt: pt, onTap: () => onSelect(f.$1)), + )).toList(), + ), + ), + ); + } +} + +// ─── Results pane ───────────────────────────────────────────────────────────── + +class _ResultsPane extends StatelessWidget { + final _SearchState state; + final String query; + final _Filter filter; + final int selected; + final PyramidTheme pt; + final Client? client; + final void Function(String roomId, {String? eventId}) onOpenRoom; + + const _ResultsPane({ + required this.state, + required this.query, + required this.filter, + required this.selected, + required this.pt, + required this.client, + required this.onOpenRoom, + }); + + @override + Widget build(BuildContext context) { + if (query.isEmpty) { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Column(mainAxisSize: MainAxisSize.min, children: [ + Icon(Icons.search_rounded, size: 36, color: pt.fgDim), + const SizedBox(height: 10), + Text('Tippe um zu suchen', style: TextStyle(color: pt.fgMuted, fontSize: 14)), + ]), + ), + ); + } + + if (state.loading) { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: SizedBox(width: 24, height: 24, child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent)), + ), + ); + } + + if (state.error != null) { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Text(state.error!, style: TextStyle(color: pt.danger, fontSize: 13)), + ), + ); + } + + final hasRooms = state.roomResults.isNotEmpty; + final hasMessages = state.messageResults.isNotEmpty; + + if (!hasRooms && !hasMessages) { + return Center( + child: Padding( + padding: const EdgeInsets.all(32), + child: Text('Keine Ergebnisse für "$query"', style: TextStyle(color: pt.fgMuted, fontSize: 14)), + ), + ); + } + + int itemIndex = 0; + final items = []; + + if (hasRooms) { + items.add(_SectionHeader(label: filter == _Filter.people ? 'Personen & Räume' : 'Räume', pt: pt)); + for (final room in state.roomResults) { + final idx = itemIndex++; + items.add(_RoomItem(room: room, selected: selected == idx, pt: pt, onTap: () => onOpenRoom(room.id))); + } + } + + if (hasMessages) { + items.add(_SectionHeader(label: filter == _Filter.media ? 'Medien' : 'Nachrichten', pt: pt)); + for (final event in state.messageResults) { + final idx = itemIndex++; + final room = client?.getRoomById(event.roomId ?? '') ?? event.room; + items.add(_MessageItem( + event: event, + room: room, + selected: selected == idx, + pt: pt, + onTap: () => onOpenRoom(event.roomId ?? '', eventId: event.eventId), + )); + } + } + + return ListView( + padding: const EdgeInsets.symmetric(vertical: 4), + shrinkWrap: true, + children: items, + ); + } +} + +// ─── Section header ─────────────────────────────────────────────────────────── + +class _SectionHeader extends StatelessWidget { + final String label; + final PyramidTheme pt; + const _SectionHeader({required this.label, required this.pt}); + @override + Widget build(BuildContext context) => Padding( + padding: const EdgeInsets.fromLTRB(14, 10, 14, 4), + child: Text(label.toUpperCase(), style: TextStyle(color: pt.fgDim, fontSize: 10, fontWeight: FontWeight.w700, letterSpacing: 0.8)), + ); +} + +// ─── Room result item ───────────────────────────────────────────────────────── + +class _RoomItem extends StatefulWidget { + final Room room; + final bool selected; + final PyramidTheme pt; + final VoidCallback onTap; + const _RoomItem({required this.room, required this.selected, required this.pt, required this.onTap}); + @override + State<_RoomItem> createState() => _RoomItemState(); +} + +class _RoomItemState extends State<_RoomItem> { + bool _hovered = false; + + Color _colorForName(String n) { + const c = [Color(0xFF06B6D4), Color(0xFFA855F7), Color(0xFFFF6B9D), Color(0xFF10B981), Color(0xFFF59E0B), Color(0xFF3B82F6)]; + return c[n.codeUnits.fold(0, (a, b) => a + b) % c.length]; + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final room = widget.room; + final name = room.getLocalizedDisplayname(); + final avatarUrl = room.avatar; + final isDm = room.isDirectChat; + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 100), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + margin: const EdgeInsets.symmetric(horizontal: 6), + decoration: BoxDecoration( + color: widget.selected || _hovered ? pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + children: [ + SizedBox(width: 32, height: 32, + child: avatarUrl != null + ? ClipRRect( + borderRadius: BorderRadius.circular(isDm ? 16 : pt.rSm), + child: MxcImage(mxcUri: avatarUrl.toString(), client: room.client, width: 32, height: 32), + ) + : Container( + decoration: BoxDecoration( + color: _colorForName(name), + borderRadius: BorderRadius.circular(isDm ? 16 : pt.rSm), + ), + child: Center(child: Text(name.isEmpty ? '?' : name[0].toUpperCase(), + style: const TextStyle(color: Colors.white, fontWeight: FontWeight.w600, fontSize: 14))), + ), + ), + const SizedBox(width: 10), + Expanded(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(isDm ? Icons.person_rounded : Icons.tag_rounded, size: 11, color: pt.fgDim), + const SizedBox(width: 3), + Expanded(child: Text(name, style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w600), overflow: TextOverflow.ellipsis)), + ]), + if (room.lastEvent != null) + Text(room.lastEvent!.body, style: TextStyle(color: pt.fgMuted, fontSize: 12), overflow: TextOverflow.ellipsis, maxLines: 1), + ], + )), + if (room.notificationCount > 0) + Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration(color: pt.accent, borderRadius: BorderRadius.circular(999)), + child: Text('${room.notificationCount}', style: const TextStyle(color: Colors.white, fontSize: 11, fontWeight: FontWeight.w600)), + ), + ], + ), + ), + ), + ); + } +} + +// ─── Message result item ────────────────────────────────────────────────────── + +class _MessageItem extends StatefulWidget { + final Event event; + final Room? room; + final bool selected; + final PyramidTheme pt; + final VoidCallback onTap; + const _MessageItem({required this.event, required this.room, required this.selected, required this.pt, required this.onTap}); + @override + State<_MessageItem> createState() => _MessageItemState(); +} + +class _MessageItemState extends State<_MessageItem> { + bool _hovered = false; + + String _senderName() { + final event = widget.event; + final room = widget.room; + if (room != null) { + final member = room.unsafeGetUserFromMemoryOrFallback(event.senderId); + return member.displayName ?? event.senderId.split(':').first.replaceFirst('@', ''); + } + return event.senderId.split(':').first.replaceFirst('@', ''); + } + + String _timeLabel() { + final ts = widget.event.originServerTs; + final now = DateTime.now(); + final diff = now.difference(ts); + if (diff.inDays == 0) return '${ts.hour.toString().padLeft(2, '0')}:${ts.minute.toString().padLeft(2, '0')}'; + if (diff.inDays < 7) return _weekday(ts.weekday); + return '${ts.day}.${ts.month}.${ts.year}'; + } + + String _weekday(int d) => ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'][d - 1]; + + String _msgBody() { + final content = widget.event.content; + final msgtype = content.tryGet('msgtype') ?? ''; + if (msgtype == 'm.image') return '📷 Bild'; + if (msgtype == 'm.video') return '🎬 Video'; + if (msgtype == 'm.audio') return '🎵 Audio'; + if (msgtype == 'm.file') return '📎 ${content.tryGet('body') ?? 'Datei'}'; + return content.tryGet('body') ?? ''; + } + + IconData _roomIcon() { + final room = widget.room; + if (room == null) return Icons.tag_rounded; + return room.isDirectChat ? Icons.person_rounded : Icons.tag_rounded; + } + + bool get _isVisualMedia { + final t = widget.event.content.tryGet('msgtype') ?? ''; + return t == 'm.image' || t == 'm.video'; + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final roomName = widget.room?.getLocalizedDisplayname() ?? widget.event.roomId ?? ''; + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 100), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 8), + margin: const EdgeInsets.symmetric(horizontal: 6, vertical: 1), + decoration: BoxDecoration( + color: widget.selected || _hovered ? pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + if (_isVisualMedia) + Padding( + padding: const EdgeInsets.only(top: 1, right: 8), + child: _SearchThumb(event: widget.event, pt: pt), + ) + else ...[ + Padding( + padding: const EdgeInsets.only(top: 2), + child: Icon(_roomIcon(), size: 14, color: pt.fgDim), + ), + const SizedBox(width: 8), + ], + Expanded(child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Expanded(child: Text(roomName, style: TextStyle(color: pt.fgMuted, fontSize: 11), overflow: TextOverflow.ellipsis)), + Text(_timeLabel(), style: TextStyle(color: pt.fgDim, fontSize: 11)), + ]), + const SizedBox(height: 1), + RichText( + maxLines: 2, + overflow: TextOverflow.ellipsis, + text: TextSpan(children: [ + TextSpan(text: '${_senderName()}: ', style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w600)), + TextSpan(text: _msgBody(), style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ]), + ), + ], + )), + ], + ), + ), + ), + ); + } +} + +// ─── Search media thumbnail ─────────────────────────────────────────────────── +// Loads (and decrypts, if needed) a small thumbnail for image/video results. + +class _SearchThumb extends StatefulWidget { + final Event event; + final PyramidTheme pt; + const _SearchThumb({required this.event, required this.pt}); + @override + State<_SearchThumb> createState() => _SearchThumbState(); +} + +class _SearchThumbState extends State<_SearchThumb> { + static final Map _cache = {}; + Uint8List? _bytes; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + final id = widget.event.eventId; + if (_cache.containsKey(id)) { + setState(() => _bytes = _cache[id]); + return; + } + try { + final file = await widget.event + .downloadAndDecryptAttachment(getThumbnail: true) + .timeout(const Duration(seconds: 10)); + _cache[id] = file.bytes; + if (mounted) setState(() => _bytes = file.bytes); + } catch (_) { + _cache[id] = null; + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + const size = 38.0; + return ClipRRect( + borderRadius: BorderRadius.circular(pt.rSm), + child: SizedBox( + width: size, + height: size, + child: _bytes != null + ? Image.memory(_bytes!, fit: BoxFit.cover, + errorBuilder: (_, __, ___) => _placeholder(pt)) + : _placeholder(pt), + ), + ); + } + + Widget _placeholder(PyramidTheme pt) => Container( + color: pt.bg3, + child: Icon( + (widget.event.content.tryGet('msgtype') ?? '') == 'm.video' + ? Icons.videocam_rounded + : Icons.image_rounded, + size: 18, + color: pt.fgDim, + ), + ); +} + +// ─── Shared chips / footer ──────────────────────────────────────────────────── + +class _Chip extends StatefulWidget { + final String label; + final IconData icon; + final bool active; + final PyramidTheme pt; + final VoidCallback onTap; + const _Chip({required this.label, required this.icon, required this.active, required this.pt, required this.onTap}); + @override + State<_Chip> createState() => _ChipState(); +} + +class _ChipState extends State<_Chip> { + bool _h = false; + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _h = true), + onExit: (_) => setState(() => _h = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 5), + decoration: BoxDecoration( + color: widget.active ? pt.accentSoft : _h ? pt.bgHover : Colors.transparent, + borderRadius: BorderRadius.circular(999), + border: Border.all(color: widget.active ? pt.accent : pt.border), + ), + child: Row(mainAxisSize: MainAxisSize.min, children: [ + Icon(widget.icon, size: 11, color: widget.active ? pt.accent : pt.fgMuted), + const SizedBox(width: 4), + Text(widget.label, style: TextStyle( + color: widget.active ? pt.accent : pt.fgMuted, + fontSize: 12, + fontWeight: widget.active ? FontWeight.w600 : FontWeight.w400, + )), + ]), + ), + ), + ); + } +} + +class _Footer extends StatelessWidget { + final int count; + final bool loading; + final PyramidTheme pt; + const _Footer({required this.count, required this.loading, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 10), + decoration: BoxDecoration( + color: pt.bg2, + border: Border(top: BorderSide(color: pt.border)), + borderRadius: BorderRadius.only(bottomLeft: Radius.circular(pt.rXl), bottomRight: Radius.circular(pt.rXl)), + ), + child: Row( + children: [ + _Hint('↑↓', 'navigieren', pt), + const SizedBox(width: 16), + _Hint('↵', 'öffnen', pt), + const Spacer(), + if (loading) + SizedBox(width: 12, height: 12, child: CircularProgressIndicator(strokeWidth: 1.5, color: pt.fgDim)) + else + Text( + '$count Ergebnis${count == 1 ? '' : 'se'}', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + ], + ), + ); + } +} + +class _Hint extends StatelessWidget { + final String key_; + final String label; + final PyramidTheme pt; + const _Hint(this.key_, this.label, this.pt); + @override + Widget build(BuildContext context) => Row(children: [ + Container( + padding: const EdgeInsets.symmetric(horizontal: 5, vertical: 2), + decoration: BoxDecoration(color: pt.bg3, borderRadius: BorderRadius.circular(4), border: Border.all(color: pt.border)), + child: Text(key_, style: TextStyle(color: pt.fgMuted, fontSize: 11, fontFamily: 'monospace')), + ), + const SizedBox(width: 4), + Text(label, style: TextStyle(color: pt.fgDim, fontSize: 11)), + ]); +} diff --git a/lib/widgets/settings_modal.dart b/lib/widgets/settings_modal.dart new file mode 100644 index 0000000..031ea3d --- /dev/null +++ b/lib/widgets/settings_modal.dart @@ -0,0 +1,5517 @@ +import 'dart:async'; +import 'dart:convert'; +import 'dart:io'; +import 'dart:math'; +import 'dart:typed_data'; + +import 'package:crypto/crypto.dart' as mcrypto; +import 'package:pyramid/core/fcm_push_service.dart'; +import 'package:pyramid/core/notification_service.dart' show openBatteryOptimizationSettings; +import 'package:file_picker/file_picker.dart'; +import 'package:flutter/foundation.dart' show compute; +import 'package:flutter/material.dart'; +import 'package:flutter/services.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:flutter_webrtc/flutter_webrtc.dart'; +import 'package:http/http.dart' as http; +import 'package:matrix/encryption/ssss.dart'; +import 'package:matrix/encryption/utils/bootstrap.dart'; +import 'package:matrix/encryption/utils/key_verification.dart' show KeyVerification, KeyVerificationEmoji, KeyVerificationState; +import 'package:matrix/matrix.dart'; +import 'package:pretty_qr_code/pretty_qr_code.dart'; +import 'package:path_provider/path_provider.dart'; +import 'package:pointycastle/export.dart' as pc; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/e2ee_diagnostics.dart'; +import 'package:pyramid/core/livekit_call_manager.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/voip_manager.dart'; +import 'package:pyramid/core/settings_prefs.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/core/update_checker.dart'; +import 'package:pyramid/widgets/update_download_dialog.dart'; +import 'package:url_launcher/url_launcher.dart'; +import 'package:pyramid/widgets/banner_crop_dialog.dart'; +import 'package:pyramid/widgets/hover_region.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; +import 'package:pyramid/widgets/pyramid_loader.dart'; +import 'package:shared_preferences/shared_preferences.dart'; + +// ── Megolm key export / import – top-level so compute() can use them ───────── + +const _kMegolmHeader = '-----BEGIN MEGOLM SESSION DATA-----'; +const _kMegolmFooter = '-----END MEGOLM SESSION DATA-----'; + +// PBKDF2-HMAC-SHA512. args: {pass: Uint8List, salt: Uint8List, iter: int} +Uint8List _runPbkdf2(Map args) { + final pass = args['pass'] as Uint8List; + final salt = args['salt'] as Uint8List; + final iterations = args['iter'] as int; + const blockLen = 64; // SHA-512 digest size + const dkLen = 64; + + final hmac = mcrypto.Hmac(mcrypto.sha512, pass); + final blockCount = (dkLen / blockLen).ceil(); + final dk = Uint8List(blockCount * blockLen); + + for (var i = 1; i <= blockCount; i++) { + final saltI = Uint8List(salt.length + 4); + saltI.setRange(0, salt.length, salt); + ByteData.sublistView(saltI, salt.length).setUint32(0, i); + + var u = Uint8List.fromList(hmac.convert(saltI).bytes); + final block = Uint8List.fromList(u); + + for (var j = 1; j < iterations; j++) { + u = Uint8List.fromList(hmac.convert(u).bytes); + for (var k = 0; k < blockLen; k++) { block[k] ^= u[k]; } + } + dk.setRange((i - 1) * blockLen, i * blockLen, block); + } + return dk.sublist(0, dkLen); +} + +Uint8List _aesCtr(Uint8List key, Uint8List iv, Uint8List data) { + final cipher = pc.SICStreamCipher(pc.AESEngine()) + ..init(true, pc.ParametersWithIV(pc.KeyParameter(key), iv)); + final out = Uint8List(data.length); + cipher.processBytes(data, 0, data.length, out, 0); + return out; +} + +// args: {passphrase: String, sessions: List} → encrypted String +String _encryptMegolmKeys(Map args) { + final pass = args['passphrase'] as String; + final sessions = args['sessions'] as List; + + final rng = Random.secure(); + final salt = Uint8List.fromList(List.generate(16, (_) => rng.nextInt(256))); + // IV: 8 random bytes as nonce, last 8 bytes 0x00 (counter starts at 0) + final iv = Uint8List(16); + for (var i = 0; i < 8; i++) { iv[i] = rng.nextInt(256); } + + const iterations = 100000; + final dk = _runPbkdf2({ + 'pass': Uint8List.fromList(utf8.encode(pass)), + 'salt': salt, + 'iter': iterations, + }); + final aesKey = dk.sublist(0, 32); + final hmacKey = dk.sublist(32, 64); + + final plaintext = Uint8List.fromList(utf8.encode(jsonEncode(sessions))); + final encrypted = _aesCtr(aesKey, iv, plaintext); + + final iterBe = Uint8List(4)..buffer.asByteData().setUint32(0, iterations); + + // header bytes: 0x01 | salt(16) | iv(16) | iterBe(4) | encrypted(n) + final header = Uint8List(1 + 16 + 16 + 4 + encrypted.length); + var off = 0; + header[off++] = 0x01; + header.setRange(off, off += 16, salt); + header.setRange(off, off += 16, iv); + header.setRange(off, off += 4, iterBe); + header.setRange(off, off + encrypted.length, encrypted); + + final mac = Uint8List.fromList( + mcrypto.Hmac(mcrypto.sha256, hmacKey).convert(header).bytes, + ); + + final full = Uint8List(header.length + 32); + full.setRange(0, header.length, header); + full.setRange(header.length, full.length, mac); + + return '$_kMegolmHeader\n${base64.encode(full)}\n$_kMegolmFooter'; +} + +// args: {passphrase: String, data: List} → List sessions +List _decryptMegolmKeys(Map args) { + final pass = args['passphrase'] as String; + final raw = Uint8List.fromList(args['data'] as List); + + if (raw.length < 1 + 16 + 16 + 4 + 32 || raw[0] != 0x01) { + throw Exception('Ungültiges Dateiformat (Version ${raw.isEmpty ? "?" : raw[0]}).'); + } + + final salt = raw.sublist(1, 17); + final iv = raw.sublist(17, 33); + final iterations = raw.buffer.asByteData().getUint32(33); + final encrypted = raw.sublist(37, raw.length - 32); + final storedMac = raw.sublist(raw.length - 32); + + if (iterations < 1 || iterations > 10000000) { + throw Exception('Iterationsanzahl außerhalb des erlaubten Bereichs.'); + } + + final dk = _runPbkdf2({ + 'pass': Uint8List.fromList(utf8.encode(pass)), + 'salt': Uint8List.fromList(salt), + 'iter': iterations, + }); + final aesKey = dk.sublist(0, 32); + final hmacKey = dk.sublist(32, 64); + + // Verify MAC over all bytes except the appended MAC itself + final toMac = raw.sublist(0, raw.length - 32); + final expectedMac = mcrypto.Hmac(mcrypto.sha256, hmacKey).convert(toMac).bytes; + var macOk = true; + for (var i = 0; i < 32; i++) { + if (expectedMac[i] != storedMac[i]) { macOk = false; break; } + } + if (!macOk) throw Exception('Falsches Passwort oder beschädigte Datei.'); + + final decrypted = _aesCtr(aesKey, Uint8List.fromList(iv), Uint8List.fromList(encrypted)); + return jsonDecode(utf8.decode(decrypted)) as List; +} + +// ───────────────────────────────────────────────────────────────────────────── + +class SettingsModal extends ConsumerStatefulWidget { + final VoidCallback onClose; + const SettingsModal({super.key, required this.onClose}); + + @override + ConsumerState createState() => _SettingsModalState(); +} + +class _SettingsModalState extends ConsumerState { + // null = show the category list (mobile). On desktop it falls back to the + // first section so content is always visible. + String? _section; + + // Categories shared by the desktop sidebar and the mobile list/detail. + static const List<(String, String, IconData)> _categories = [ + ('profile', 'Mein Profil', Icons.person_outline_rounded), + ('notifications', 'Benachrichtigungen', Icons.notifications_none_rounded), + ('appearance', 'Erscheinungsbild', Icons.palette_outlined), + ('voice', 'Sprache & Video', Icons.headphones_rounded), + ('keys', 'Tastaturkürzel', Icons.keyboard_rounded), + ('privacy', 'Datenschutz', Icons.lock_outline_rounded), + ('sessions', 'Sitzungen', Icons.devices_rounded), + ('encryption', 'Verschlüsselung', Icons.shield_outlined), + ('about', 'Über Pyramid', Icons.info_outline_rounded), + ]; + + String _titleFor(String id) => + _categories.firstWhere((c) => c.$1 == id, orElse: () => (id, id, Icons.settings)).$2; + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final isDark = ref.watch(themeModeProvider); + final accentIdx = ref.watch(accentProvider); + final radius = ref.watch(radiusProvider); + final density = ref.watch(densityProvider); + final motion = ref.watch(motionProvider); + + final size = MediaQuery.sizeOf(context); + final isMobile = size.width < 700; + + return GestureDetector( + onTap: widget.onClose, + child: Container( + color: Colors.black.withAlpha(150), + child: Center( + child: GestureDetector( + onTap: () {}, + child: Container( + constraints: const BoxConstraints(maxWidth: 820, maxHeight: 660), + width: isMobile ? size.width * 0.97 : 740, + height: isMobile ? size.height * 0.92 : 560, + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rXl), + border: Border.all(color: pt.border), + boxShadow: [ + BoxShadow( + color: Colors.black.withAlpha(130), + blurRadius: 40, + offset: const Offset(0, 12), + ), + ], + ), + child: ClipRRect( + borderRadius: BorderRadius.circular(pt.rXl), + child: isMobile + ? _mobileLayout(pt, isDark, accentIdx, radius, density, motion) + : _desktopLayout(pt, isDark, accentIdx, radius, density, motion), + ), + ), + ), + ), + ), + ); + } + + // ── Desktop: sidebar + content side by side ────────────────────────────── + Widget _desktopLayout(PyramidTheme pt, bool isDark, int accentIdx, + double radius, double density, double motion) { + final active = _section ?? 'appearance'; + return Row( + children: [ + Container( + width: 200, + decoration: BoxDecoration( + color: pt.bg2, + border: Border(right: BorderSide(color: pt.border)), + ), + child: SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + const SizedBox(height: 16), + _NavSection('Account', pt), + _NavItem('profile', 'Mein Profil', Icons.person_outline_rounded, active, pt, () => setState(() => _section = 'profile')), + _NavItem('notifications', 'Benachrichtigungen', Icons.notifications_none_rounded, active, pt, () => setState(() => _section = 'notifications')), + const SizedBox(height: 14), + _NavSection('App', pt), + _NavItem('appearance', 'Erscheinungsbild', Icons.palette_outlined, active, pt, () => setState(() => _section = 'appearance')), + _NavItem('voice', 'Sprache & Video', Icons.headphones_rounded, active, pt, () => setState(() => _section = 'voice')), + _NavItem('keys', 'Tastaturkürzel', Icons.keyboard_rounded, active, pt, () => setState(() => _section = 'keys')), + const SizedBox(height: 14), + _NavSection('Sicherheit', pt), + _NavItem('privacy', 'Datenschutz', Icons.lock_outline_rounded, active, pt, () => setState(() => _section = 'privacy')), + _NavItem('sessions', 'Sitzungen', Icons.devices_rounded, active, pt, () => setState(() => _section = 'sessions')), + _NavItem('encryption', 'Verschlüsselung', Icons.shield_outlined, active, pt, () => setState(() => _section = 'encryption')), + const SizedBox(height: 14), + _NavItem('about', 'Über Pyramid', Icons.info_outline_rounded, active, pt, () => setState(() => _section = 'about')), + const Divider(height: 24, indent: 12, endIndent: 12), + _LogoutNavButton(pt: pt, isMobile: false, onClose: widget.onClose), + const SizedBox(height: 16), + ], + ), + ), + ), + Expanded( + child: Stack( + children: [ + Padding( + padding: const EdgeInsets.all(28), + child: _buildContent(pt, isDark, accentIdx, radius, density, motion, active), + ), + Positioned( + top: 8, + right: 8, + child: PyrIconBtn( + icon: const Icon(Icons.close_rounded, size: 20), + tooltip: 'Schließen', + onPressed: widget.onClose, + ), + ), + ], + ), + ), + ], + ); + } + + // ── Mobile: full-width category list → detail with a back arrow ─────────── + Widget _mobileLayout(PyramidTheme pt, bool isDark, int accentIdx, + double radius, double density, double motion) { + final section = _section; + if (section == null) { + // Category list + return Column( + children: [ + _MobileHeader(title: 'Einstellungen', pt: pt, onClose: widget.onClose), + Expanded( + child: ListView( + padding: const EdgeInsets.symmetric(vertical: 8), + children: [ + for (final c in _categories) + _MobileCategoryTile( + label: c.$2, + icon: c.$3, + pt: pt, + onTap: () => setState(() => _section = c.$1), + ), + const Divider(height: 24, indent: 16, endIndent: 16), + _LogoutNavButton(pt: pt, isMobile: false, onClose: widget.onClose), + const SizedBox(height: 16), + ], + ), + ), + ], + ); + } + // Detail view with a back arrow + return Column( + children: [ + _MobileHeader( + title: _titleFor(section), + pt: pt, + onBack: () => setState(() => _section = null), + onClose: widget.onClose, + ), + Expanded( + child: Padding( + padding: const EdgeInsets.fromLTRB(16, 8, 16, 16), + child: _buildContent(pt, isDark, accentIdx, radius, density, motion, section), + ), + ), + ], + ); + } + + Widget _buildContent(PyramidTheme pt, bool isDark, int accentIdx, + double radius, double density, double motion, String section) { + return switch (section) { + 'appearance' => _AppearanceSection( + pt: pt, + isDark: isDark, + accentIdx: accentIdx, + radius: radius, + density: density, + motion: motion, + ref: ref), + 'profile' => _ProfileSection(pt: pt), + 'notifications' => _NotificationsSection(pt: pt), + 'voice' => _VoiceSection(pt: pt), + 'keys' => _KeysSection(pt: pt), + 'privacy' => _PrivacySection(pt: pt), + 'sessions' => _SessionsSection(pt: pt), + 'encryption' => _EncryptionSection(pt: pt, ref: ref), + 'about' => _AboutSection(pt: pt), + _ => _AppearanceSection( + pt: pt, + isDark: isDark, + accentIdx: accentIdx, + radius: radius, + density: density, + motion: motion, + ref: ref), + }; + } +} + +// ── Mobile helpers ────────────────────────────────────────────────────────── + +class _MobileHeader extends StatelessWidget { + final String title; + final PyramidTheme pt; + final VoidCallback? onBack; + final VoidCallback onClose; + const _MobileHeader({required this.title, required this.pt, this.onBack, required this.onClose}); + + @override + Widget build(BuildContext context) { + return Container( + height: 52, + padding: const EdgeInsets.symmetric(horizontal: 8), + decoration: BoxDecoration( + color: pt.bg2, + border: Border(bottom: BorderSide(color: pt.border)), + ), + child: Row( + children: [ + if (onBack != null) + IconButton( + onPressed: onBack, + icon: Icon(Icons.arrow_back_rounded, size: 20, color: pt.fg), + tooltip: 'Zurück', + ) + else + const SizedBox(width: 8), + Expanded( + child: Text( + title, + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w600), + overflow: TextOverflow.ellipsis, + ), + ), + IconButton( + onPressed: onClose, + icon: Icon(Icons.close_rounded, size: 20, color: pt.fgMuted), + tooltip: 'Schließen', + ), + ], + ), + ); + } +} + +class _MobileCategoryTile extends StatelessWidget { + final String label; + final IconData icon; + final PyramidTheme pt; + final VoidCallback onTap; + const _MobileCategoryTile({required this.label, required this.icon, required this.pt, required this.onTap}); + + @override + Widget build(BuildContext context) { + return InkWell( + onTap: onTap, + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 15), + child: Row( + children: [ + Icon(icon, size: 21, color: pt.fgMuted), + const SizedBox(width: 16), + Expanded( + child: Text(label, style: TextStyle(color: pt.fg, fontSize: 15)), + ), + Icon(Icons.chevron_right_rounded, size: 20, color: pt.fgDim), + ], + ), + ), + ); + } +} + +// ── Nav helpers ─────────────────────────────────────────────────────────────── + +class _NavSection extends StatelessWidget { + final String title; + final PyramidTheme pt; + const _NavSection(this.title, this.pt); + + @override + Widget build(BuildContext context) { + return Padding( + padding: const EdgeInsets.fromLTRB(12, 0, 12, 4), + child: Text( + title.toUpperCase(), + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 0.04 * 11, + ), + ), + ); + } +} + +class _NavItem extends StatefulWidget { + final String id; + final String label; + final IconData icon; + final String active; + final PyramidTheme pt; + final VoidCallback onTap; + + const _NavItem(this.id, this.label, this.icon, this.active, this.pt, this.onTap); + + @override + State<_NavItem> createState() => _NavItemState(); +} + +class _NavItemState extends State<_NavItem> { + bool _hovered = false; + + @override + Widget build(BuildContext context) { + final isActive = widget.id == widget.active; + final pt = widget.pt; + + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: widget.onTap, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + margin: const EdgeInsets.fromLTRB(8, 1, 8, 1), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + decoration: BoxDecoration( + color: isActive + ? pt.accentSoft + : _hovered + ? pt.bgHover + : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + mainAxisAlignment: widget.label.isEmpty + ? MainAxisAlignment.center + : MainAxisAlignment.start, + children: [ + Icon( + widget.icon, + size: 14, + color: isActive ? pt.accent : _hovered ? pt.fg : pt.fgMuted, + ), + if (widget.label.isNotEmpty) ...[ + const SizedBox(width: 8), + Text( + widget.label, + style: TextStyle( + color: isActive ? pt.fg : _hovered ? pt.fg : pt.fgMuted, + fontSize: 13, + fontWeight: isActive ? FontWeight.w600 : FontWeight.w400, + ), + ), + ], + ], + ), + ), + ), + ); + } +} + +class _LogoutNavButton extends ConsumerStatefulWidget { + final PyramidTheme pt; + final bool isMobile; + final VoidCallback onClose; + const _LogoutNavButton({required this.pt, required this.isMobile, required this.onClose}); + + @override + ConsumerState<_LogoutNavButton> createState() => _LogoutNavButtonState(); +} + +class _LogoutNavButtonState extends ConsumerState<_LogoutNavButton> { + bool _hovered = false; + bool _loading = false; + + Future _logout() async { + final pt = widget.pt; + final confirmed = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + title: Text('Abmelden?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text('Du wirst von diesem Gerät abgemeldet.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.danger, foregroundColor: Colors.white, + elevation: 0, shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Abmelden'), + ), + ], + ), + ); + if (confirmed != true || !mounted) return; + setState(() => _loading = true); + try { + widget.onClose(); + final client = await ref.read(matrixClientProvider.future); + await client.logout(); + } catch (_) {} + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return MouseRegion( + cursor: SystemMouseCursors.click, + onEnter: (_) => setState(() => _hovered = true), + onExit: (_) => setState(() => _hovered = false), + child: GestureDetector( + onTap: _loading ? null : _logout, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + margin: const EdgeInsets.fromLTRB(8, 1, 8, 1), + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 7), + decoration: BoxDecoration( + color: _hovered ? pt.danger.withAlpha(30) : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + mainAxisAlignment: widget.isMobile ? MainAxisAlignment.center : MainAxisAlignment.start, + children: [ + _loading + ? SizedBox(width: 14, height: 14, child: CircularProgressIndicator(strokeWidth: 2, color: pt.danger)) + : Icon(Icons.logout_rounded, size: 14, color: pt.danger), + if (!widget.isMobile) ...[ + const SizedBox(width: 8), + Text('Abmelden', style: TextStyle(color: pt.danger, fontSize: 13)), + ], + ], + ), + ), + ), + ); + } +} + +// ── Shared UI primitives ────────────────────────────────────────────────────── + +class _SectionTitle extends StatelessWidget { + final String title; + final String subtitle; + final PyramidTheme pt; + const _SectionTitle({required this.title, required this.subtitle, required this.pt}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text(title, + style: TextStyle(color: pt.fg, fontSize: 20, fontWeight: FontWeight.w700)), + const SizedBox(height: 4), + Text(subtitle, style: TextStyle(color: pt.fgMuted, fontSize: 13)), + const SizedBox(height: 24), + ], + ); + } +} + +class _SettingsGroup extends StatelessWidget { + final String title; + final PyramidTheme pt; + final List children; + + const _SettingsGroup({required this.title, required this.pt, required this.children}); + + @override + Widget build(BuildContext context) { + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title.toUpperCase(), + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontWeight: FontWeight.w600, + letterSpacing: 0.04 * 11), + ), + const SizedBox(height: 10), + Container( + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: pt.border), + ), + child: Column(children: children), + ), + ], + ); + } +} + +class _SettingsRow extends StatelessWidget { + final String title; + final String? desc; + final PyramidTheme pt; + final Widget? control; + final VoidCallback? onTap; + final bool destructive; + final bool showArrow; + + const _SettingsRow({ + required this.title, + required this.pt, + this.desc, + this.control, + this.onTap, + this.destructive = false, + this.showArrow = false, + }); + + @override + Widget build(BuildContext context) { + Widget content = Padding( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 12), + child: Row( + children: [ + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + title, + style: TextStyle( + color: destructive ? pt.danger : pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + ), + if (desc != null) ...[ + const SizedBox(height: 2), + Text(desc!, style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ], + ), + ), + ?control, + if (showArrow) + Icon(Icons.chevron_right_rounded, size: 16, color: pt.fgDim), + ], + ), + ); + + if (onTap != null) { + return Material( + color: Colors.transparent, + child: InkWell( + onTap: onTap, + borderRadius: BorderRadius.circular(10), + child: content, + ), + ); + } + return content; + } +} + +class _Divider extends StatelessWidget { + final PyramidTheme pt; + const _Divider({required this.pt}); + + @override + Widget build(BuildContext context) { + return Container(height: 1, color: pt.border, margin: const EdgeInsets.only(left: 14)); + } +} + +class _Toggle extends StatelessWidget { + final bool value; + final ValueChanged onChanged; + final PyramidTheme pt; + const _Toggle({required this.value, required this.onChanged, required this.pt}); + + @override + Widget build(BuildContext context) { + return GestureDetector( + onTap: () => onChanged(!value), + child: AnimatedContainer( + duration: const Duration(milliseconds: 200), + width: 42, + height: 24, + decoration: BoxDecoration( + color: value ? pt.accent : pt.bg3, + borderRadius: BorderRadius.circular(12), + border: Border.all(color: value ? pt.accent : pt.borderStrong), + ), + child: Padding( + padding: const EdgeInsets.all(2), + child: AnimatedAlign( + duration: const Duration(milliseconds: 200), + alignment: value ? Alignment.centerRight : Alignment.centerLeft, + child: Container( + width: 18, + height: 18, + decoration: BoxDecoration( + color: Colors.white, + shape: BoxShape.circle, + boxShadow: [BoxShadow(color: Colors.black.withAlpha(60), blurRadius: 4)], + ), + ), + ), + ), + ), + ); + } +} + +class _SegControl extends StatelessWidget { + final List options; + final int selected; + final PyramidTheme pt; + final ValueChanged onSelect; + + const _SegControl( + {required this.options, required this.selected, required this.pt, required this.onSelect}); + + @override + Widget build(BuildContext context) { + return Container( + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rSm), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: options.asMap().entries.map((e) { + final isActive = e.key == selected; + return GestureDetector( + onTap: () => onSelect(e.key), + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 6), + decoration: BoxDecoration( + color: isActive ? pt.accent : Colors.transparent, + borderRadius: BorderRadius.circular(pt.rSm - 2), + ), + child: Text( + e.value, + style: TextStyle( + color: isActive ? pt.accentFg : pt.fgMuted, + fontSize: 13, + fontWeight: isActive ? FontWeight.w600 : FontWeight.w400, + ), + ), + ), + ); + }).toList(), + ), + ); + } +} + +class _PrimaryBtn extends StatelessWidget { + final String label; + final IconData? icon; + final VoidCallback? onPressed; + final PyramidTheme pt; + final bool loading; + final bool destructive; + + const _PrimaryBtn({ + required this.label, + required this.pt, + this.icon, + this.onPressed, + this.loading = false, + this.destructive = false, + }); + + @override + Widget build(BuildContext context) { + final bg = destructive ? pt.danger : pt.accent; + final fg = destructive ? Colors.white : pt.accentFg; + return ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: bg, + foregroundColor: fg, + disabledBackgroundColor: bg.withAlpha(100), + padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 10), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + elevation: 0, + ), + onPressed: loading ? null : onPressed, + icon: loading + ? SizedBox( + width: 14, height: 14, child: CircularProgressIndicator(color: fg, strokeWidth: 2)) + : (icon != null ? Icon(icon, size: 16) : const SizedBox.shrink()), + label: Text(label), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// PROFILE +// ───────────────────────────────────────────────────────────────────────────── + +class _ProfileSection extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _ProfileSection({required this.pt}); + + @override + ConsumerState<_ProfileSection> createState() => _ProfileSectionState(); +} + +class _ProfileSectionState extends ConsumerState<_ProfileSection> { + late TextEditingController _nameCtrl; + late TextEditingController _statusCtrl; + bool _saving = false; + bool _saved = false; + String? _error; + Uint8List? _pendingAvatar; + Uri? _avatarUri; + Uint8List? _pendingBanner; + String? _bannerMxcUri; + Uint8List? _pendingServerBanner; + bool _serverBannerSaving = false; + + @override + void initState() { + super.initState(); + _nameCtrl = TextEditingController(); + _statusCtrl = TextEditingController(); + _loadProfile(); + } + + @override + void dispose() { + _nameCtrl.dispose(); + _statusCtrl.dispose(); + super.dispose(); + } + + Future _loadProfile() async { + final client = await ref.read(matrixClientProvider.future); + if (!mounted) return; + + // 1) SOFORT aus dem lokalen Cache füllen — kein Warten auf den Server. + _nameCtrl.text = client.userID ?? ''; + for (final room in client.rooms) { + final u = room.unsafeGetUserFromMemoryOrFallback(client.userID!); + if (u.displayName != null || u.avatarUrl != null) { + if (u.displayName != null) _nameCtrl.text = u.displayName!; + _avatarUri = u.avatarUrl; + break; + } + } + try { + final bannerData = client.accountData['com.pyramid.profile.banner']; + _bannerMxcUri = bannerData?.content['url'] as String?; + } catch (_) {} + setState(() {}); + + // 2) Server-Daten PARALLEL nachladen, UI aktualisiert sich pro Antwort. + client + .getProfileFromUserId(client.userID!) + .then((profile) { + if (!mounted) return; + setState(() { + if (profile.displayName != null) _nameCtrl.text = profile.displayName!; + _avatarUri = profile.avatarUrl ?? _avatarUri; + }); + }).catchError((_) {}); + + () async { + try { + final apiUri = client.homeserver!.replace( + path: + '/_matrix/client/v3/profile/${Uri.encodeComponent(client.userID!)}', + ); + final resp = await client.httpClient.get( + apiUri, + headers: {'Authorization': 'Bearer ${client.accessToken}'}, + ); + if (resp.statusCode == 200 && mounted) { + final data = jsonDecode(resp.body) as Map; + final url = data['io.pyramid.profile.banner_url'] as String?; + if (url != null) setState(() => _bannerMxcUri = url); + } + } catch (_) {} + }(); + } + + Future _pickAvatar() async { + final result = await FilePicker.platform.pickFiles(type: FileType.image, withData: true); + final file = result?.files.first; + if (file == null) return; + final bytes = file.bytes ?? await file.xFile.readAsBytes(); + setState(() => _pendingAvatar = bytes); + } + + Future _pickBanner() async { + final result = await FilePicker.platform.pickFiles(type: FileType.image, withData: true); + final file = result?.files.first; + if (file == null) return; + final raw = file.bytes ?? await file.xFile.readAsBytes(); + if (!mounted) return; + final cropped = await showDialog( + context: context, + builder: (_) => BannerCropDialog(imageBytes: raw, aspectRatio: 3.0), + ); + if (cropped == null || !mounted) return; + setState(() => _pendingBanner = cropped); + } + + Future _pickServerBanner() async { + final result = await FilePicker.platform.pickFiles(type: FileType.image, withData: true); + final file = result?.files.first; + if (file == null) return; + final raw = file.bytes ?? await file.xFile.readAsBytes(); + if (!mounted) return; + final cropped = await showDialog( + context: context, + builder: (_) => BannerCropDialog(imageBytes: raw, aspectRatio: 2.4), + ); + if (cropped == null || !mounted) return; + setState(() => _serverBannerSaving = true); + try { + final client = await ref.read(matrixClientProvider.future); + final uri = await client.uploadContent(cropped, filename: 'server_banner.png', contentType: 'image/png'); + await ref.read(serverBannerProvider.notifier).set(client.homeserver.toString(), uri.toString()); + if (mounted) setState(() { _pendingServerBanner = cropped; _serverBannerSaving = false; }); + } catch (_) { + if (mounted) setState(() => _serverBannerSaving = false); + } + } + + Future _removeServerBanner() async { + final client = ref.read(matrixClientProvider).valueOrNull; + if (client == null) return; + await ref.read(serverBannerProvider.notifier).set(client.homeserver.toString(), null); + if (mounted) setState(() => _pendingServerBanner = null); + } + + Future _save() async { + setState(() { _saving = true; _error = null; _saved = false; }); + try { + final client = await ref.read(matrixClientProvider.future); + final name = _nameCtrl.text.trim(); + if (name.isNotEmpty) { + await client.setProfileField( + client.userID!, + 'displayname', + {'displayname': name}, + ); + } + if (_pendingAvatar != null) { + await client.setAvatar(MatrixFile( + bytes: _pendingAvatar!, + name: 'avatar.jpg', + mimeType: 'image/jpeg', + )); + setState(() => _pendingAvatar = null); + } + if (_pendingBanner != null) { + final uri = await client.uploadContent( + _pendingBanner!, filename: 'banner.png', contentType: 'image/png'); + final uriStr = uri.toString(); + // Store as a profile custom field so other users can see it + await client.setProfileField( + client.userID!, + 'io.pyramid.profile.banner_url', + {'io.pyramid.profile.banner_url': uriStr}, + ); + // Also keep in account data as legacy fallback + await client.setAccountData(client.userID!, 'com.pyramid.profile.banner', + {'url': uriStr}); + setState(() { _bannerMxcUri = uriStr; _pendingBanner = null; }); + } + final status = _statusCtrl.text.trim(); + await client.setPresence( + client.userID!, + PresenceType.online, + statusMsg: status.isEmpty ? null : status, + ); + if (mounted) setState(() { _saving = false; _saved = true; }); + await Future.delayed(const Duration(seconds: 2)); + if (mounted) setState(() => _saved = false); + } catch (e) { + if (mounted) setState(() { _saving = false; _error = e.toString().split('\n').first; }); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final clientAsync = ref.watch(matrixClientProvider); + final client = clientAsync.valueOrNull; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Mein Profil', + subtitle: 'Wie du in Pyramid erscheinst.', + pt: pt), + // Banner + GestureDetector( + onTap: _pickBanner, + child: Stack( + children: [ + Container( + height: 100, + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: _pendingBanner != null + ? Image.memory(_pendingBanner!, fit: BoxFit.cover, width: double.infinity) + : (client != null && _bannerMxcUri != null + ? MxcImage( + mxcUri: _bannerMxcUri!, + client: client, + fit: BoxFit.cover, + width: double.infinity, + ) + : Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.add_photo_alternate_outlined, size: 28, color: pt.fgDim), + const SizedBox(height: 4), + Text('Profilbanner auswählen', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + )), + ), + Positioned( + right: 8, + bottom: 8, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: pt.bg0.withAlpha(200), + borderRadius: BorderRadius.circular(6), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_rounded, size: 11, color: pt.fgMuted), + const SizedBox(width: 4), + Text('Banner ändern', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ], + ), + ), + ), + ], + ), + ), + const SizedBox(height: 16), + // Avatar row + Row( + children: [ + GestureDetector( + onTap: _pickAvatar, + child: Stack( + children: [ + Container( + width: 72, + height: 72, + decoration: BoxDecoration( + shape: BoxShape.circle, + border: Border.all(color: pt.border, width: 2), + ), + child: ClipOval( + child: _pendingAvatar != null + ? Image.memory(_pendingAvatar!, fit: BoxFit.cover) + : (client != null && _avatarUri != null + ? MxcAvatar( + mxcUri: _avatarUri, + client: client, + size: 72, + placeholder: (_) => _AvatarFallback( + name: _nameCtrl.text, size: 72, pt: pt), + ) + : _AvatarFallback( + name: _nameCtrl.text, size: 72, pt: pt)), + ), + ), + Positioned( + right: 0, + bottom: 0, + child: Container( + width: 24, + height: 24, + decoration: BoxDecoration( + color: pt.accent, + shape: BoxShape.circle, + border: Border.all(color: pt.bg1, width: 2), + ), + child: Icon(Icons.edit_rounded, size: 12, color: pt.accentFg), + ), + ), + ], + ), + ), + const SizedBox(width: 20), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + _nameCtrl.text.isNotEmpty ? _nameCtrl.text : (client?.userID ?? ''), + style: TextStyle( + color: pt.fg, fontSize: 16, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 2), + SelectableText( + client?.userID ?? '', + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + const SizedBox(height: 6), + if (_pendingAvatar != null) + Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: pt.accent.withAlpha(40), + borderRadius: BorderRadius.circular(6), + ), + child: Text('Neues Bild ausgewählt', + style: TextStyle(color: pt.accent, fontSize: 11)), + ), + ], + ), + ), + ], + ), + const SizedBox(height: 24), + _SettingsGroup(title: 'Name & Status', pt: pt, children: [ + Padding( + padding: const EdgeInsets.fromLTRB(14, 14, 14, 4), + child: _PrefTextField( + controller: _nameCtrl, + label: 'Anzeigename', + pt: pt, + ), + ), + const SizedBox(height: 2), + Padding( + padding: const EdgeInsets.fromLTRB(14, 4, 14, 14), + child: _PrefTextField( + controller: _statusCtrl, + label: 'Statusnachricht (optional)', + pt: pt, + maxLength: 120, + ), + ), + ]), + const SizedBox(height: 20), + if (_error != null) + Padding( + padding: const EdgeInsets.only(bottom: 12), + child: _StatusCard( + pt: pt, color: pt.danger, icon: Icons.error_outline_rounded, text: _error!), + ), + if (_saved) + Padding( + padding: const EdgeInsets.only(bottom: 12), + child: _StatusCard( + pt: pt, + color: PyramidColors.success, + icon: Icons.check_circle_outline_rounded, + text: 'Profil gespeichert.'), + ), + _PrimaryBtn( + label: _saving ? 'Speichern…' : 'Speichern', + icon: Icons.save_outlined, + pt: pt, + loading: _saving, + onPressed: _save, + ), + const SizedBox(height: 24), + + // ── Server-Banner ───────────────────────────────────────────────── + _SectionTitle( + title: 'Server-Darstellung', + subtitle: 'Banner für ${client?.homeserver?.host ?? 'diesen Server'}', + pt: pt, + ), + Consumer(builder: (context, ref, _) { + final serverBanners = ref.watch(serverBannerProvider).valueOrNull ?? {}; + final homeserver = client?.homeserver.toString(); + final existingMxc = homeserver != null ? serverBanners[homeserver] : null; + final hasBanner = _pendingServerBanner != null || existingMxc != null; + + return Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + GestureDetector( + onTap: _serverBannerSaving ? null : _pickServerBanner, + child: Container( + height: 90, + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + clipBehavior: Clip.hardEdge, + child: Stack( + fit: StackFit.expand, + children: [ + if (_pendingServerBanner != null) + Image.memory(_pendingServerBanner!, fit: BoxFit.cover, + errorBuilder: (_, __, ___) => const SizedBox.shrink()) + else if (existingMxc != null && client != null) + MxcImage(mxcUri: existingMxc, client: client, fit: BoxFit.cover) + else + Center( + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.add_photo_alternate_outlined, size: 24, color: pt.fgDim), + const SizedBox(height: 4), + Text('Server-Banner auswählen', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ), + if (_serverBannerSaving) + Container( + color: Colors.black38, + child: const Center(child: CircularProgressIndicator(strokeWidth: 2)), + ), + if (hasBanner) + Positioned( + right: 8, + bottom: 8, + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 4), + decoration: BoxDecoration( + color: pt.bg0.withAlpha(200), + borderRadius: BorderRadius.circular(6), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.edit_rounded, size: 11, color: pt.fgMuted), + const SizedBox(width: 4), + Text('Banner ändern', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ], + ), + ), + ), + ], + ), + ), + ), + if (hasBanner) ...[ + const SizedBox(height: 8), + GestureDetector( + onTap: _removeServerBanner, + child: Text( + 'Banner entfernen', + style: TextStyle(color: pt.danger, fontSize: 12), + ), + ), + ], + ], + ); + }), + + const SizedBox(height: 24), + _SettingsGroup(title: 'Konto', pt: pt, children: [ + _SettingsRow( + title: 'Passwort ändern', + desc: 'Aktuelles Passwort zum Ändern erforderlich', + pt: pt, + showArrow: true, + onTap: _changePassword, + ), + ]), + const SizedBox(height: 12), + _SettingsGroup(title: 'Gefahrenbereich', pt: pt, children: [ + _SettingsRow( + title: 'Konto löschen', + desc: 'Konto dauerhaft deaktivieren – nicht rückgängig zu machen', + pt: pt, + showArrow: true, + destructive: true, + onTap: _deleteAccount, + ), + ]), + ], + ), + ); + } + + Future _changePassword() async { + await showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => _ChangePasswordDialog(pt: widget.pt), + ); + } + + Future _deleteAccount() async { + await showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => _DeleteAccountDialog(pt: widget.pt), + ); + } +} + +class _AvatarFallback extends StatelessWidget { + final String name; + final double size; + final PyramidTheme pt; + const _AvatarFallback({required this.name, required this.size, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + width: size, + height: size, + color: pt.accent, + child: Center( + child: Text( + name.isNotEmpty ? name[0].toUpperCase() : '?', + style: + TextStyle(color: pt.accentFg, fontSize: size * 0.4, fontWeight: FontWeight.w700), + ), + ), + ); + } +} + +class _PrefTextField extends StatelessWidget { + final TextEditingController controller; + final String label; + final PyramidTheme pt; + final int? maxLength; + + const _PrefTextField({ + required this.controller, + required this.label, + required this.pt, + this.maxLength, + }); + + @override + Widget build(BuildContext context) { + return TextField( + controller: controller, + maxLength: maxLength, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + labelText: label, + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + counterText: '', + filled: true, + fillColor: pt.bg3, + isDense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + ), + cursorColor: pt.accent, + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// NOTIFICATIONS +// ───────────────────────────────────────────────────────────────────────────── + +class _NotificationsSection extends ConsumerWidget { + final PyramidTheme pt; + const _NotificationsSection({required this.pt}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final desktop = ref.watch(notifDesktopProvider); + final sound = ref.watch(notifSoundProvider); + final preview = ref.watch(notifPreviewProvider); + final dmMentionOnly = ref.watch(notifMentionOnlyDmProvider); + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Benachrichtigungen', + subtitle: 'Bestimme, wann und wie du benachrichtigt wirst.', + pt: pt), + _SettingsGroup(title: 'Desktop', pt: pt, children: [ + _SettingsRow( + title: 'Desktop-Benachrichtigungen', + desc: 'Zeige Systembenachrichtigungen bei neuen Nachrichten', + pt: pt, + control: _Toggle( + value: desktop, + pt: pt, + onChanged: (v) => ref.read(notifDesktopProvider.notifier).set(v), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Benachrichtigungston', + desc: 'Sound abspielen wenn eine Nachricht eingeht', + pt: pt, + control: _Toggle( + value: sound, + pt: pt, + onChanged: (v) => ref.read(notifSoundProvider.notifier).set(v), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Nachrichtenvorschau', + desc: 'Nachrichteninhalt in Benachrichtigung anzeigen', + pt: pt, + control: _Toggle( + value: preview, + pt: pt, + onChanged: (v) => ref.read(notifPreviewProvider.notifier).set(v), + ), + ), + ]), + const SizedBox(height: 20), + _SettingsGroup(title: 'Filter', pt: pt, children: [ + _SettingsRow( + title: 'Nur Erwähnungen (DMs)', + desc: 'Benachrichtigung nur bei direkten @Erwähnungen', + pt: pt, + control: _Toggle( + value: dmMentionOnly, + pt: pt, + onChanged: (v) => ref.read(notifMentionOnlyDmProvider.notifier).set(v), + ), + ), + ]), + const SizedBox(height: 20), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Icon(Icons.info_outline_rounded, size: 16, color: pt.fgDim), + const SizedBox(width: 10), + Expanded( + child: Text( + 'Push-Benachrichtigungen für Android/iOS sind in Vorbereitung.', + style: TextStyle(color: pt.fgMuted, fontSize: 12), + ), + ), + ], + ), + ), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// APPEARANCE +// ───────────────────────────────────────────────────────────────────────────── + +class _AppearanceSection extends StatelessWidget { + final PyramidTheme pt; + final bool isDark; + final int accentIdx; + final double radius; + final double density; + final double motion; + final WidgetRef ref; + + const _AppearanceSection({ + required this.pt, + required this.isDark, + required this.accentIdx, + required this.radius, + required this.density, + required this.motion, + required this.ref, + }); + + @override + Widget build(BuildContext context) { + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Erscheinungsbild', + subtitle: 'Gestalte Pyramid nach deinem Geschmack.', + pt: pt), + _SettingsGroup(title: 'Theme', pt: pt, children: [ + _SettingsRow( + title: 'Farbmodus', + desc: 'Hell oder dunkel', + pt: pt, + control: _SegControl( + options: const ['Dunkel', 'Hell'], + selected: isDark ? 0 : 1, + pt: pt, + onSelect: (i) { + final dark = i == 0; + ref.read(themeModeProvider.notifier).state = dark; + saveThemePrefs(isDark: dark); + }, + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Akzentfarbe', + desc: 'Farbe für Hervorhebungen und Buttons', + pt: pt, + control: Row( + children: accentPresets.asMap().entries.map((e) { + final i = e.key; + final preset = e.value; + final isActive = accentIdx == i; + return GestureDetector( + onTap: () { + ref.read(accentProvider.notifier).state = i; + saveThemePrefs(accentIdx: i); + }, + child: AnimatedContainer( + duration: const Duration(milliseconds: 150), + width: 22, + height: 22, + margin: const EdgeInsets.only(right: 6), + decoration: BoxDecoration( + color: preset.color, + shape: BoxShape.circle, + border: isActive ? Border.all(color: Colors.white, width: 2) : null, + boxShadow: isActive + ? [BoxShadow(color: preset.color.withAlpha(100), blurRadius: 8)] + : null, + ), + ), + ); + }).toList(), + ), + ), + ]), + const SizedBox(height: 20), + _SettingsGroup(title: 'Form & Bewegung', pt: pt, children: [ + _SettingsRow( + title: 'Eckenrundung', + desc: '${radius.round()} px', + pt: pt, + control: SizedBox( + width: 150, + child: SliderTheme( + data: SliderThemeData( + activeTrackColor: pt.accent, + thumbColor: pt.accent, + inactiveTrackColor: pt.border, + trackHeight: 3, + thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6), + ), + child: Slider( + value: radius, + min: 4, + max: 20, + onChanged: (v) { + ref.read(radiusProvider.notifier).state = v; + saveThemePrefs(radius: v); + }, + ), + ), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Animationen', + desc: '${(motion * 100).round()}%', + pt: pt, + control: SizedBox( + width: 150, + child: SliderTheme( + data: SliderThemeData( + activeTrackColor: pt.accent, + thumbColor: pt.accent, + inactiveTrackColor: pt.border, + trackHeight: 3, + thumbShape: const RoundSliderThumbShape(enabledThumbRadius: 6), + ), + child: Slider( + value: motion, + min: 0, + max: 1, + onChanged: (v) { + ref.read(motionProvider.notifier).state = v; + saveThemePrefs(motion: v); + }, + ), + ), + ), + ), + ]), + const SizedBox(height: 20), + _SettingsGroup(title: 'Vorschau', pt: pt, children: [ + Padding( + padding: const EdgeInsets.all(16), + child: Row( + children: [ + Expanded( + child: Column( + children: [ + Container( + height: 100, + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: const Center(child: PyramidLoader(size: 70, useLottie: true)), + ), + const SizedBox(height: 6), + Text('Lottie', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ], + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + children: [ + Container( + height: 100, + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: const Center(child: PyramidLoader(size: 70, useLottie: false)), + ), + const SizedBox(height: 6), + Text('SVG', style: TextStyle(color: pt.fgMuted, fontSize: 11)), + ], + ), + ), + ], + ), + ), + ]), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// VOICE & VIDEO +// ───────────────────────────────────────────────────────────────────────────── + +class _VoiceSection extends StatefulWidget { + final PyramidTheme pt; + const _VoiceSection({required this.pt}); + + @override + State<_VoiceSection> createState() => _VoiceSectionState(); +} + +class _VoiceSectionState extends State<_VoiceSection> { + List _audioInputs = []; + List _audioOutputs = []; + List _videoInputs = []; + String? _selectedMic; + String? _selectedSpeaker; + String? _selectedCamera; + double _outputVolume = 1.0; + bool _loading = true; + String? _loadError; + + static const _kMic = 'voice_mic_device'; + static const _kSpeaker = 'voice_speaker_device'; + static const _kCamera = 'voice_camera_device'; + static const _kOutputVolume = 'voice_output_volume'; + + @override + void initState() { + super.initState(); + _init(); + } + + Future _init() async { + final prefs = await SharedPreferences.getInstance(); + List devices = []; + String? loadError; + try { + devices = await navigator.mediaDevices.enumerateDevices(); + } catch (_) { + devices = []; + } + // Windows (und teils Android) liefert eine LEERE Liste ohne Fehler, + // solange in diesem Prozess noch nie ein Media-Stream geöffnet wurde. + // Deshalb nicht nur bei Exception, sondern auch bei leerer Liste einmal + // kurz getUserMedia anfordern und erneut enumerieren — und zwar SOLANGE + // der Stream noch offen ist (nach stop() melden manche Systeme wieder 0). + final hasAudioInput = + devices.any((d) => d.kind?.toLowerCase() == 'audioinput'); + if (devices.isEmpty || !hasAudioInput) { + try { + final stream = await navigator.mediaDevices + .getUserMedia({'audio': true, 'video': false}); + try { + devices = await navigator.mediaDevices.enumerateDevices(); + } finally { + for (final t in stream.getTracks()) { + t.stop(); + } + await stream.dispose(); + } + if (devices.isEmpty) { + // Bekanntes libwebrtc-Problem auf manchen Windows-Systemen: das + // Audio-Device-Module meldet 0 Geräte, obwohl Aufnahme/Wiedergabe + // über das Standardgerät einwandfrei funktionieren. + loadError = + 'Die Audiotreiber melden keine Geräteliste an WebRTC ' + '(bekanntes libwebrtc-Problem auf manchen Windows-Systemen). ' + 'Anrufe funktionieren trotzdem — es wird das Windows-Standardgerät verwendet.'; + } + } catch (e2) { + loadError = 'getUserMedia: ${e2.toString().split('\n').first}'; + } + } + if (!mounted) return; + setState(() { + _audioInputs = devices.where((d) => d.kind?.toLowerCase() == 'audioinput').toList(); + _audioOutputs = devices.where((d) => d.kind?.toLowerCase() == 'audiooutput').toList(); + _videoInputs = devices.where((d) => d.kind?.toLowerCase() == 'videoinput').toList(); + _selectedMic = prefs.getString(_kMic); + _selectedSpeaker = prefs.getString(_kSpeaker); + _selectedCamera = prefs.getString(_kCamera); + _outputVolume = prefs.getDouble(_kOutputVolume) ?? 1.0; + _loadError = loadError; + _loading = false; + }); + } + + Future _setOutputVolume(double v) async { + setState(() => _outputVolume = v); + final prefs = await SharedPreferences.getInstance(); + await prefs.setDouble(_kOutputVolume, v); + // Live auf laufende Calls anwenden. + LiveKitCallManager.instance.setOutputVolume(v).catchError((_) {}); + try { + PyramidVoipManager.instance.applyOutputVolume(v).catchError((_) {}); + } catch (_) {} // Instanz existiert evtl. noch nicht + } + + Future _save(String key, String? value) async { + final prefs = await SharedPreferences.getInstance(); + if (value == null || value.isEmpty) { + await prefs.remove(key); + } else { + await prefs.setString(key, value); + } + } + + Widget _deviceDropdown({ + required List devices, + required String? selected, + required String placeholder, + required IconData icon, + required ValueChanged onChanged, + }) { + final pt = widget.pt; + if (devices.isEmpty) { + return Container( + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 6), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(6), + border: Border.all(color: pt.border), + ), + child: Row( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(icon, size: 13, color: pt.fgDim), + const SizedBox(width: 6), + Text('Kein Gerät', style: TextStyle(color: pt.fgDim, fontSize: 12)), + ], + ), + ); + } + + final validSelected = devices.any((d) => d.deviceId == selected) ? selected : null; + + return ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 220), + child: Container( + padding: const EdgeInsets.symmetric(horizontal: 10), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(6), + border: Border.all(color: pt.border), + ), + child: DropdownButtonHideUnderline( + child: DropdownButton( + value: validSelected, + hint: Row(children: [ + Icon(icon, size: 13, color: pt.fgDim), + const SizedBox(width: 6), + Text(placeholder, style: TextStyle(color: pt.fgDim, fontSize: 12)), + ]), + dropdownColor: pt.bg2, + iconEnabledColor: pt.fgDim, + isDense: true, + style: TextStyle(color: pt.fg, fontSize: 12), + onChanged: onChanged, + items: devices.map((d) { + final label = d.label.isNotEmpty ? d.label : 'Gerät ${d.deviceId.substring(0, 6)}'; + return DropdownMenuItem( + value: d.deviceId, + child: Text(label, overflow: TextOverflow.ellipsis), + ); + }).toList(), + ), + ), + ), + ); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Sprache & Video', + subtitle: 'Mikrofon, Kamera und Anrufeinstellungen.', + pt: pt), + if (_loading) + const Center(child: Padding(padding: EdgeInsets.all(32), child: CircularProgressIndicator.adaptive())) + else ...[ + if (_loadError != null) + Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.border), + ), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.warning_amber_rounded, size: 16, color: pt.away), + const SizedBox(width: 8), + Text('Geräteliste nicht verfügbar', + style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500)), + ]), + const SizedBox(height: 6), + Text(_loadError!, style: TextStyle(color: pt.fgDim, fontSize: 11)), + const SizedBox(height: 6), + Text( + 'Mikrofon und Lautsprecher legst du in diesem Fall über die ' + 'Windows-Soundeinstellungen (Standardgerät) fest. ' + 'Falls dort alles stimmt: Windows-Einstellungen → Datenschutz → Mikrofon prüfen.', + style: TextStyle(color: pt.fgMuted, fontSize: 11), + ), + ], + ), + ), + ), + _SettingsGroup(title: 'Geräte', pt: pt, children: [ + _SettingsRow( + title: 'Mikrofon', + desc: _audioInputs.isEmpty ? 'Kein Gerät gefunden' : '${_audioInputs.length} Gerät(e) gefunden', + pt: pt, + control: _deviceDropdown( + devices: _audioInputs, + selected: _selectedMic, + placeholder: 'Standard', + icon: Icons.mic_rounded, + onChanged: (v) { + setState(() => _selectedMic = v); + _save(_kMic, v); + }, + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Lautsprecher', + desc: _audioOutputs.isEmpty ? 'Kein Gerät gefunden' : '${_audioOutputs.length} Gerät(e) gefunden', + pt: pt, + control: _deviceDropdown( + devices: _audioOutputs, + selected: _selectedSpeaker, + placeholder: 'Standard', + icon: Icons.volume_up_rounded, + onChanged: (v) { + setState(() => _selectedSpeaker = v); + _save(_kSpeaker, v); + }, + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Kamera', + desc: _videoInputs.isEmpty ? 'Kein Gerät gefunden' : '${_videoInputs.length} Gerät(e) gefunden', + pt: pt, + control: _deviceDropdown( + devices: _videoInputs, + selected: _selectedCamera, + placeholder: 'Standard', + icon: Icons.videocam_rounded, + onChanged: (v) { + setState(() => _selectedCamera = v); + _save(_kCamera, v); + }, + ), + ), + ]), + const SizedBox(height: 16), + _SettingsGroup(title: 'Pegel', pt: pt, children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Icon(Icons.volume_up_rounded, size: 15, color: pt.fgMuted), + const SizedBox(width: 8), + Text('Ausgabelautstärke', + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500)), + const Spacer(), + Text('${(_outputVolume * 100).round()} %', + style: TextStyle( + color: pt.fgMuted, + fontSize: 12, + fontFamily: 'monospace')), + ], + ), + SliderTheme( + data: SliderThemeData( + activeTrackColor: pt.accent, + inactiveTrackColor: pt.bg3, + thumbColor: pt.accent, + overlayColor: pt.accent.withAlpha(30), + trackHeight: 3, + thumbShape: const RoundSliderThumbShape( + enabledThumbRadius: 7), + ), + child: Slider( + value: _outputVolume.clamp(0.0, 1.5), + min: 0.0, + max: 1.5, + divisions: 30, + onChanged: _setOutputVolume, + ), + ), + Text( + 'Lautstärke der anderen Teilnehmer in Calls. ' + 'Wirkt sofort auf laufende Anrufe.', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + ], + ), + ), + ]), + const SizedBox(height: 16), + _TurnUsageCard(pt: pt), + const SizedBox(height: 12), + TextButton.icon( + style: TextButton.styleFrom( + foregroundColor: pt.fgMuted, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + ), + onPressed: () { setState(() { _loading = true; _loadError = null; }); _init(); }, + icon: const Icon(Icons.refresh_rounded, size: 14), + label: const Text('Geräte neu laden', style: TextStyle(fontSize: 12)), + ), + ], + ], + ), + ); + } +} + +// ── TURN-Verbrauch (Cloudflare Free Tier, vom Pi überwacht) ────────────────── + +/// Zeigt den TURN-Relay-Verbrauch des laufenden Monats an. Die Daten kommen +/// aus der turn-status.json, die der Guard-Cron auf dem Pi stündlich schreibt. +/// Solange der Endpoint nicht existiert (Analytics-Token fehlt), bleibt die +/// Karte unsichtbar. +class _TurnUsageCard extends StatefulWidget { + final PyramidTheme pt; + const _TurnUsageCard({required this.pt}); + + @override + State<_TurnUsageCard> createState() => _TurnUsageCardState(); +} + +class _TurnUsageCardState extends State<_TurnUsageCard> { + Map? _status; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + try { + final resp = await http + .get(Uri.parse( + 'https://steggi-matrix.work/.well-known/pyramid/turn-status.json')) + .timeout(const Duration(seconds: 5)); + if (resp.statusCode == 200 && mounted) { + setState( + () => _status = jsonDecode(resp.body) as Map); + } + } catch (_) { + // Endpoint (noch) nicht vorhanden — Karte einfach nicht anzeigen. + } + } + + @override + Widget build(BuildContext context) { + final s = _status; + if (s == null) return const SizedBox.shrink(); + final pt = widget.pt; + final used = (s['egress_gb'] as num?)?.toDouble() ?? 0; + final limit = (s['limit_gb'] as num?)?.toDouble() ?? 990; + final pct = limit > 0 ? (used / limit).clamp(0.0, 1.0) : 0.0; + final active = s['turn_active'] != false; + final barColor = !active + ? pt.danger + : pct > 0.8 + ? pt.away + : pt.accent; + + return _SettingsGroup(title: 'Call-Relay (TURN)', pt: pt, children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(active ? Icons.cloud_done_rounded : Icons.cloud_off_rounded, + size: 15, color: active ? pt.online : pt.danger), + const SizedBox(width: 8), + Text( + active + ? 'Relay aktiv' + : 'Relay deaktiviert (Limit erreicht)', + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500)), + const Spacer(), + Text( + '${used.toStringAsFixed(1)} / ${limit.toStringAsFixed(0)} GB', + style: TextStyle( + color: pt.fgMuted, + fontSize: 12, + fontFamily: 'monospace')), + ]), + const SizedBox(height: 8), + ClipRRect( + borderRadius: BorderRadius.circular(99), + child: LinearProgressIndicator( + value: pct, + minHeight: 5, + backgroundColor: pt.bg3, + color: barColor, + ), + ), + const SizedBox(height: 6), + Text( + active + ? 'Cloudflare-TURN-Traffic diesen Monat (Free Tier: ${limit.toStringAsFixed(0)} GB). ' + 'Bei Erreichen des Limits laufen Calls bis Monatsende ohne Relay weiter.' + : 'Monatslimit erreicht — Calls nutzen bis Monatsende nur direkte Verbindungen (STUN).', + style: TextStyle(color: pt.fgDim, fontSize: 11), + ), + ], + ), + ), + ]); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// KEYBINDS +// ───────────────────────────────────────────────────────────────────────────── + +class _KeysSection extends StatelessWidget { + final PyramidTheme pt; + const _KeysSection({required this.pt}); + + @override + Widget build(BuildContext context) { + final keys = [ + ('Schnellsuche', 'Strg+K'), + ('Raum als gelesen markieren', 'Shift+Esc'), + ('Zu ungelesen springen', 'Strg+J'), + ('Linke Leiste ein-/ausblenden', 'Strg+B'), + ('Mitglieder ein-/ausblenden', 'Strg+Shift+U'), + ('Nachrichten durchsuchen', 'Strg+F'), + ('Antworten', 'R'), + ('Auswahl aufheben', 'Esc'), + ]; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Tastaturkürzel', + subtitle: 'Schnelle Aktionen per Tastatur.', + pt: pt), + _SettingsGroup( + title: 'Navigieren', + pt: pt, + children: keys.asMap().entries.map((entry) { + final (action, binding) = entry.value; + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + child: Row( + children: [ + Expanded( + child: Text(action, + style: TextStyle(color: pt.fg, fontSize: 13))), + Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(6), + border: Border.all(color: pt.border), + ), + child: Text(binding, + style: TextStyle( + color: pt.fgMuted, + fontSize: 12, + fontFamily: 'monospace')), + ), + ], + ), + ), + if (entry.key < keys.length - 1) _Divider(pt: pt), + ], + ); + }).toList(), + ), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// PRIVACY +// ───────────────────────────────────────────────────────────────────────────── + +class _PrivacySection extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _PrivacySection({required this.pt}); + + @override + ConsumerState<_PrivacySection> createState() => _PrivacySectionState(); +} + +class _PrivacySectionState extends ConsumerState<_PrivacySection> { + List _ignoredUsers = []; + final Set _unblocking = {}; + + @override + void initState() { + super.initState(); + _loadIgnoredUsers(); + } + + Future _loadIgnoredUsers() async { + final client = await ref.read(matrixClientProvider.future); + if (mounted) setState(() => _ignoredUsers = List.from(client.ignoredUsers)); + } + + Future _unblockUser(String userId) async { + setState(() => _unblocking.add(userId)); + try { + final client = await ref.read(matrixClientProvider.future); + await client.unignoreUser(userId); + await _loadIgnoredUsers(); + } catch (e) { + // ignore — list will be stale but not crash + } finally { + if (mounted) setState(() => _unblocking.remove(userId)); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final presence = ref.watch(privacyPresenceProvider); + final readReceipts = ref.watch(privacyReadReceiptsProvider); + final typing = ref.watch(privacyTypingProvider); + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Datenschutz', + subtitle: 'Steuere, was andere über dich erfahren.', + pt: pt), + _SettingsGroup(title: 'Sichtbarkeit', pt: pt, children: [ + _SettingsRow( + title: 'Online-Status anzeigen', + desc: 'Anderen anzeigen, wenn du aktiv bist', + pt: pt, + control: _Toggle( + value: presence, + pt: pt, + onChanged: (v) async { + ref.read(privacyPresenceProvider.notifier).set(v); + final client = await ref.read(matrixClientProvider.future); + await client.setPresence( + client.userID!, + v ? PresenceType.online : PresenceType.offline, + ).catchError((_) {}); + }, + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Lesebestätigungen senden', + desc: 'Anderen zeigen, dass du ihre Nachrichten gelesen hast', + pt: pt, + control: _Toggle( + value: readReceipts, + pt: pt, + onChanged: (v) => ref.read(privacyReadReceiptsProvider.notifier).set(v), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Tipp-Indikator senden', + desc: '„schreibt…" Anzeige aktivieren', + pt: pt, + control: _Toggle( + value: typing, + pt: pt, + onChanged: (v) => ref.read(privacyTypingProvider.notifier).set(v), + ), + ), + ]), + const SizedBox(height: 20), + // ── Blocked users ────────────────────────────────────────────────── + _SettingsGroup(title: 'Blockierte Nutzer (${_ignoredUsers.length})', pt: pt, children: [ + if (_ignoredUsers.isEmpty) + Padding( + padding: const EdgeInsets.all(14), + child: Text('Keine blockierten Nutzer.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ) + else + ..._ignoredUsers.asMap().entries.map((entry) { + final i = entry.key; + final userId = entry.value; + final isUnblocking = _unblocking.contains(userId); + return Column(children: [ + Padding( + padding: const EdgeInsets.symmetric(horizontal: 14, vertical: 10), + child: Row(children: [ + Expanded( + child: Text(userId, + style: TextStyle(color: pt.fg, fontSize: 13), + overflow: TextOverflow.ellipsis), + ), + if (isUnblocking) + const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + else + TextButton( + style: TextButton.styleFrom( + foregroundColor: pt.accent, + padding: const EdgeInsets.symmetric(horizontal: 10, vertical: 4), + minimumSize: Size.zero, + tapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + onPressed: () => _unblockUser(userId), + child: const Text('Entblocken', style: TextStyle(fontSize: 12)), + ), + ]), + ), + if (i < _ignoredUsers.length - 1) _Divider(pt: pt), + ]); + }), + ]), + const SizedBox(height: 20), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.accentSoft, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: pt.accent.withAlpha(60)), + ), + child: Row( + children: [ + Icon(Icons.shield_outlined, size: 16, color: pt.accent), + const SizedBox(width: 10), + Expanded( + child: Text( + 'Alle Nachrichten sind Ende-zu-Ende-verschlüsselt.', + style: TextStyle(color: pt.fg, fontSize: 12), + ), + ), + ], + ), + ), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// SESSIONS +// ───────────────────────────────────────────────────────────────────────────── + +class _SessionsSection extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _SessionsSection({required this.pt}); + + @override + ConsumerState<_SessionsSection> createState() => _SessionsSectionState(); +} + +class _SessionsSectionState extends ConsumerState<_SessionsSection> { + List _devices = []; + bool _loading = true; + String? _currentDeviceId; + final Set _revoking = {}; + bool _logoutAllLoading = false; + String? _error; + + @override + void initState() { + super.initState(); + _load(); + } + + Future _load() async { + setState(() { _loading = true; _error = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + _currentDeviceId = client.deviceID; + await client.updateUserDeviceKeys(additionalUsers: {client.userID!}); + final keys = client.userDeviceKeys[client.userID]; + if (mounted) { + setState(() { + _devices = keys?.deviceKeys.values.toList() ?? []; + _loading = false; + }); + } + } catch (e) { + if (mounted) { + setState(() { + _loading = false; + _error = e.toString().split('\n').first; + }); + } + } + } + + Future _revokeDevice(String deviceId) async { + setState(() => _revoking.add(deviceId)); + try { + final client = await ref.read(matrixClientProvider.future); + await client.deleteDevice(deviceId); + await _load(); + } catch (e) { + if (mounted) { + setState(() { + _revoking.remove(deviceId); + _error = 'Abmelden fehlgeschlagen: ${e.toString().split('\n').first}'; + }); + } + } + } + + Future _renameCurrentDevice(BuildContext context) async { + final client = await ref.read(matrixClientProvider.future); + final currentName = _devices + .where((d) => d.deviceId == _currentDeviceId) + .map((d) => d.unsigned?['device_display_name'] as String? ?? d.deviceId ?? '') + .firstOrNull ?? ''; + + final ctrl = TextEditingController(text: currentName); + final pt = widget.pt; + final confirmed = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + title: Text('Gerät umbenennen', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: TextField( + controller: ctrl, + autofocus: true, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + labelText: 'Gerätename', + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + filled: true, fillColor: pt.bg3, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + ), + cursorColor: pt.accent, + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.accent, foregroundColor: pt.accentFg, elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Umbenennen'), + ), + ], + ), + ); + ctrl.dispose(); + if (confirmed != true || _currentDeviceId == null) return; + try { + await client.updateDevice(_currentDeviceId!, displayName: ctrl.text.trim()); + await _load(); + } catch (e) { + if (mounted) setState(() => _error = 'Umbenennen fehlgeschlagen: ${e.toString().split('\n').first}'); + } + } + + Future _logoutAllOtherDevices(BuildContext context) async { + final pt = widget.pt; + final otherIds = _devices + .where((d) => d.deviceId != _currentDeviceId && d.deviceId != null) + .map((d) => d.deviceId!) + .toList(); + if (otherIds.isEmpty) return; + + final confirm = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + title: Text('Alle anderen Sitzungen abmelden?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text( + '${otherIds.length} Gerät${otherIds.length == 1 ? '' : 'e'} werden abgemeldet. Nicht gespeicherte Nachrichten auf diesen Geräten können verloren gehen.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx, false), child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.danger, foregroundColor: Colors.white, elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Alle abmelden'), + ), + ], + ), + ); + if (confirm != true || !mounted) return; + setState(() { _logoutAllLoading = true; _error = null; }); + + final client = await ref.read(matrixClientProvider.future); + try { + await client.deleteDevices(otherIds); + } on MatrixException catch (e) { + if (e.requireAdditionalAuthentication && mounted) { + final password = await _askPassword(context, pt); + if (password == null || !mounted) { setState(() => _logoutAllLoading = false); return; } + try { + await client.deleteDevices(otherIds, auth: AuthenticationData( + type: AuthenticationTypes.password, + session: e.session, + additionalFields: { + 'identifier': {'type': 'm.id.user', 'user': client.userID}, + 'password': password, + }, + )); + } catch (e2) { + if (mounted) setState(() { _logoutAllLoading = false; _error = 'Abmelden fehlgeschlagen: ${e2.toString().split('\n').first}'; }); + return; + } + } else { + if (mounted) setState(() { _logoutAllLoading = false; _error = 'Abmelden fehlgeschlagen: ${e.toString().split('\n').first}'; }); + return; + } + } catch (e) { + if (mounted) setState(() { _logoutAllLoading = false; _error = 'Abmelden fehlgeschlagen: ${e.toString().split('\n').first}'; }); + return; + } + await _load(); + if (mounted) setState(() => _logoutAllLoading = false); + } + + Future _askPassword(BuildContext context, PyramidTheme pt) { + final ctrl = TextEditingController(); + return showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + title: Text('Passwort bestätigen', style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w700)), + content: TextField( + controller: ctrl, + autofocus: true, + obscureText: true, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + labelText: 'Passwort', + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + filled: true, fillColor: pt.bg3, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + ), + cursorColor: pt.accent, + onSubmitted: (_) => Navigator.pop(ctx, ctrl.text), + ), + actions: [ + TextButton(onPressed: () => Navigator.pop(ctx, null), child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted))), + ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.accent, foregroundColor: pt.accentFg, elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, ctrl.text), + child: const Text('Bestätigen'), + ), + ], + ), + ).then((v) { ctrl.dispose(); return v; }); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Sitzungen', + subtitle: 'Geräte, auf denen du angemeldet bist.', + pt: pt), + if (_loading) + const Center( + child: Padding(padding: EdgeInsets.all(32), child: CircularProgressIndicator.adaptive())) + else if (_error != null) + _StatusCard( + pt: pt, color: pt.danger, icon: Icons.error_outline_rounded, text: _error!) + else ...[ + _SettingsGroup( + title: 'Aktive Sitzungen (${_devices.length})', + pt: pt, + children: _devices.isEmpty + ? [ + Padding( + padding: const EdgeInsets.all(16), + child: Text('Keine Sitzungen gefunden.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ) + ] + : _devices.asMap().entries.map((entry) { + final i = entry.key; + final device = entry.value; + final isCurrent = device.deviceId == _currentDeviceId; + final isRevoking = _revoking.contains(device.deviceId); + final isVerified = device.verified; + final displayName = device.unsigned?['device_display_name'] as String? ?? + device.deviceId ?? + 'Unbekanntes Gerät'; + + return Column( + children: [ + Padding( + padding: const EdgeInsets.symmetric( + horizontal: 14, vertical: 12), + child: Row( + children: [ + Container( + width: 36, + height: 36, + decoration: BoxDecoration( + color: isCurrent + ? pt.accentSoft + : pt.bg3, + borderRadius: BorderRadius.circular(8), + ), + child: Icon( + Icons.devices_rounded, + size: 18, + color: isCurrent ? pt.accent : pt.fgMuted, + ), + ), + const SizedBox(width: 12), + Expanded( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Expanded( + child: Text( + displayName, + style: TextStyle( + color: pt.fg, + fontSize: 13, + fontWeight: FontWeight.w500, + ), + ), + ), + if (isCurrent) ...[ + Container( + padding: const EdgeInsets.symmetric( + horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: pt.accentSoft, + borderRadius: BorderRadius.circular(4), + ), + child: Text('Dieses Gerät', + style: TextStyle( + color: pt.accent, + fontSize: 10, + fontWeight: FontWeight.w600)), + ), + const SizedBox(width: 4), + GestureDetector( + onTap: () => _renameCurrentDevice(context), + child: Tooltip( + message: 'Gerät umbenennen', + child: Icon(Icons.edit_rounded, size: 13, color: pt.fgDim), + ), + ), + ], + if (isVerified == true && !isCurrent) + Icon(Icons.verified_rounded, + size: 14, color: PyramidColors.success), + if (isVerified == false && !isCurrent) + Icon(Icons.warning_amber_rounded, + size: 14, color: pt.away), + ], + ), + const SizedBox(height: 2), + SelectableText( + device.deviceId ?? '', + style: TextStyle( + color: pt.fgDim, + fontSize: 11, + fontFamily: 'monospace'), + ), + ], + ), + ), + if (!isCurrent) ...[ + const SizedBox(width: 8), + if (isVerified == false) + GestureDetector( + onTap: () => _verifyDevice(context, device, displayName), + child: Tooltip( + message: 'Verifizieren', + child: Icon(Icons.verified_user_outlined, + size: 16, color: pt.accent), + ), + ), + const SizedBox(width: 6), + if (isRevoking) + SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.danger), + ) + else + GestureDetector( + onTap: () => _confirmRevoke(context, device, displayName), + child: Tooltip( + message: 'Abmelden', + child: Icon(Icons.logout_rounded, + size: 16, color: pt.fgDim), + ), + ), + ], + ], + ), + ), + if (i < _devices.length - 1) _Divider(pt: pt), + ], + ); + }).toList(), + ), + const SizedBox(height: 12), + Row( + children: [ + TextButton.icon( + style: TextButton.styleFrom( + foregroundColor: pt.fgMuted, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + ), + onPressed: _load, + icon: const Icon(Icons.refresh_rounded, size: 14), + label: const Text('Aktualisieren', style: TextStyle(fontSize: 12)), + ), + const Spacer(), + if (_logoutAllLoading) + const SizedBox(width: 16, height: 16, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + else if (_devices.where((d) => d.deviceId != _currentDeviceId).isNotEmpty) + TextButton.icon( + style: TextButton.styleFrom( + foregroundColor: pt.danger, + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + ), + onPressed: () => _logoutAllOtherDevices(context), + icon: const Icon(Icons.logout_rounded, size: 14), + label: const Text('Alle anderen abmelden', style: TextStyle(fontSize: 12)), + ), + ], + ), + ], + ], + ), + ); + } + + Future _verifyDevice( + BuildContext context, DeviceKeys device, String displayName) async { + await showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => _SasVerificationDialog( + pt: widget.pt, + deviceName: displayName, + device: device, + ), + ); + await _load(); + } + + Future _confirmRevoke( + BuildContext context, DeviceKeys device, String displayName) async { + final confirm = await showDialog( + context: context, + builder: (ctx) { + final pt = widget.pt; + return AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + title: Text('Gerät abmelden?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text( + '"$displayName" wird abgemeldet und alle lokalen Schlüssel werden gelöscht.', + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.danger, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Abmelden'), + ), + ], + ); + }, + ); + if (confirm == true && device.deviceId != null) { + await _revokeDevice(device.deviceId!); + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// SAS VERIFICATION DIALOG +// ───────────────────────────────────────────────────────────────────────────── + +class _SasVerificationDialog extends ConsumerStatefulWidget { + final PyramidTheme pt; + final String deviceName; + final DeviceKeys device; + + const _SasVerificationDialog({ + required this.pt, + required this.deviceName, + required this.device, + }); + + @override + ConsumerState<_SasVerificationDialog> createState() => _SasVerificationDialogState(); +} + +class _SasVerificationDialogState extends ConsumerState<_SasVerificationDialog> { + KeyVerification? _verification; + KeyVerificationState _state = KeyVerificationState.waitingAccept; + bool _starting = true; + String? _error; + + @override + void initState() { + super.initState(); + _startVerification(); + } + + @override + void dispose() { + final v = _verification; + if (v != null && !v.isDone) { + v.cancel('m.user').catchError((_) {}); + } + super.dispose(); + } + + Future _startVerification() async { + try { + final client = await ref.read(matrixClientProvider.future); + final deviceId = widget.device.deviceId; + if (deviceId == null) throw Exception('Keine Geräte-ID'); + + final deviceKeys = client.userDeviceKeys[client.userID]?.deviceKeys[deviceId]; + if (deviceKeys == null) throw Exception('Gerät nicht gefunden'); + + final verification = await deviceKeys.startVerification(); + _verification = verification; + + verification.onUpdate = () { + if (!mounted) return; + setState(() => _state = verification.state); + }; + + if (mounted) { + setState(() { + _state = verification.state; + _starting = false; + }); + } + } catch (e) { + if (mounted) { + setState(() { + _error = e.toString().split('\n').first; + _starting = false; + }); + } + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + + return AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + contentPadding: const EdgeInsets.fromLTRB(24, 20, 24, 0), + title: Row( + children: [ + Icon(Icons.verified_user_outlined, size: 20, color: pt.accent), + const SizedBox(width: 10), + Expanded( + child: Text( + 'Gerät verifizieren', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700), + ), + ), + ], + ), + content: SizedBox( + width: 380, + child: _buildContent(pt), + ), + actions: _buildActions(pt), + ); + } + + Widget _buildContent(PyramidTheme pt) { + if (_error != null) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _StatusCard( + pt: pt, + icon: Icons.error_outline_rounded, + color: pt.danger, + text: _error!), + ); + } + + if (_starting) { + return const Padding( + padding: EdgeInsets.symmetric(vertical: 24), + child: Center(child: CircularProgressIndicator.adaptive()), + ); + } + + final v = _verification; + + return switch (_state) { + KeyVerificationState.waitingAccept || KeyVerificationState.askAccept => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 16), + Text( + 'Warte auf Bestätigung von „${widget.deviceName}"…', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 8), + Text( + 'Öffne Pyramid auf dem anderen Gerät und bestätige die Verifikationsanfrage.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + ], + ), + ), + KeyVerificationState.askChoice => Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Text( + 'Das andere Gerät hat die Anfrage akzeptiert.\nWähle eine Verifikationsmethode:', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 16), + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () => v?.continueVerification('m.sas.v1').catchError((_) {}), + icon: const Icon(Icons.tag_faces_rounded, size: 18), + label: const Text('Emoji-Verifikation'), + ), + const SizedBox(height: 8), + ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: pt.bg3, + foregroundColor: pt.fg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: () => v?.continueVerification('m.qr_code.show.v1').catchError((_) {}), + icon: const Icon(Icons.qr_code_rounded, size: 18), + label: const Text('QR-Code anzeigen'), + ), + const SizedBox(height: 8), + ], + ), + ), + KeyVerificationState.confirmQRScan => _OutgoingQrCodeDisplay( + pt: pt, + request: v, + ), + KeyVerificationState.showQRSuccess => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _StatusCard( + pt: pt, + icon: Icons.verified_rounded, + color: PyramidColors.success, + text: 'QR-Code erfolgreich gescannt. Verifikation abgeschlossen.'), + ), + KeyVerificationState.askSas => _SasEmojiContent( + pt: pt, + verification: v!, + onConfirm: () => v.acceptSas().catchError((_) {}), + onReject: () { + v.rejectSas().catchError((_) {}); + Navigator.of(context).pop(); + }, + ), + KeyVerificationState.waitingSas => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 16), + Text( + 'Warte auf Bestätigung des anderen Geräts…', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + ], + ), + ), + KeyVerificationState.done => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _StatusCard( + pt: pt, + icon: Icons.verified_rounded, + color: PyramidColors.success, + text: '„${widget.deviceName}" wurde erfolgreich verifiziert.'), + ), + _ => Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _StatusCard( + pt: pt, + icon: Icons.error_outline_rounded, + color: pt.danger, + text: 'Verifizierung fehlgeschlagen oder abgebrochen.'), + ), + }; + } + + List _buildActions(PyramidTheme pt) { + if (_state == KeyVerificationState.done || + _state == KeyVerificationState.showQRSuccess || + _error != null || + _state == KeyVerificationState.error) { + return [ + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(context), + child: const Text('Schließen'), + ), + ]; + } + if (_state == KeyVerificationState.confirmQRScan) { + return [ + TextButton( + onPressed: () { + _verification?.cancel('m.user').catchError((_) {}); + Navigator.pop(context); + }, + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: const Color(0xFF22C55E), + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => _verification?.acceptQRScanConfirmation().catchError((_) {}), + child: const Text('Gescannt bestätigen'), + ), + ]; + } + if (_state == KeyVerificationState.askSas || _state == KeyVerificationState.askChoice) { + return []; + } + return [ + TextButton( + onPressed: () { + _verification?.cancel('m.user').catchError((_) {}); + Navigator.pop(context); + }, + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ]; + } +} + +class _OutgoingQrCodeDisplay extends StatelessWidget { + final PyramidTheme pt; + final KeyVerification? request; + + const _OutgoingQrCodeDisplay({required this.pt, required this.request}); + + @override + Widget build(BuildContext context) { + final qrCode = request?.qrCode; + if (qrCode == null) { + return Padding( + padding: const EdgeInsets.symmetric(vertical: 24), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 12), + Text('QR-Code wird generiert…', style: TextStyle(color: pt.fgMuted, fontSize: 13)), + ], + ), + ); + } + + try { + final rawBytes = Uint8List.fromList(qrCode.qrDataRawBytes.toList()); + final qr = QrCode.fromUint8List(data: rawBytes, errorCorrectLevel: QrErrorCorrectLevel.L); + final qrImage = QrImage(qr); + + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Scanne diesen QR-Code mit dem anderen Gerät', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 16), + Center( + child: Container( + width: 220, + height: 220, + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: Colors.white, + borderRadius: BorderRadius.circular(12), + ), + child: PrettyQrView(qrImage: qrImage), + ), + ), + const SizedBox(height: 12), + Text( + 'Sobald das andere Gerät den Code gescannt hat, tippe auf „Gescannt bestätigen".', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgDim, fontSize: 12), + ), + const SizedBox(height: 8), + ], + ), + ); + } catch (_) { + return Padding( + padding: const EdgeInsets.only(bottom: 16), + child: _StatusCard( + pt: pt, + icon: Icons.error_outline_rounded, + color: pt.danger, + text: 'QR-Code konnte nicht generiert werden.', + ), + ); + } + } +} + +class _SasEmojiContent extends StatelessWidget { + final PyramidTheme pt; + final KeyVerification verification; // ignore: library_private_types_in_public_api + final VoidCallback onConfirm; + final VoidCallback onReject; + + const _SasEmojiContent({ + required this.pt, + required this.verification, + required this.onConfirm, + required this.onReject, + }); + + @override + Widget build(BuildContext context) { + final emojis = verification.sasEmojis; + + return Padding( + padding: const EdgeInsets.only(bottom: 8), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text( + 'Vergleiche die Emojis auf beiden Geräten', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 20), + if (emojis.isNotEmpty) + Wrap( + spacing: 12, + runSpacing: 12, + alignment: WrapAlignment.center, + children: emojis.map((e) => _SasEmojiChip(emoji: e, pt: pt)).toList(), + ) + else + Text('Keine Emojis verfügbar.', style: TextStyle(color: pt.fgDim, fontSize: 13)), + const SizedBox(height: 24), + Text( + 'Stimmen alle Emojis überein?', + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 16), + Row( + children: [ + Expanded( + child: OutlinedButton.icon( + style: OutlinedButton.styleFrom( + foregroundColor: pt.danger, + side: BorderSide(color: pt.danger.withAlpha(120)), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: onReject, + icon: const Icon(Icons.close_rounded, size: 16), + label: const Text('Stimmt nicht überein'), + ), + ), + const SizedBox(width: 12), + Expanded( + child: ElevatedButton.icon( + style: ElevatedButton.styleFrom( + backgroundColor: PyramidColors.success, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + padding: const EdgeInsets.symmetric(vertical: 12), + ), + onPressed: onConfirm, + icon: const Icon(Icons.check_rounded, size: 16), + label: const Text('Stimmt überein'), + ), + ), + ], + ), + const SizedBox(height: 8), + ], + ), + ); + } +} + +class _SasEmojiChip extends StatelessWidget { + final KeyVerificationEmoji emoji; + final PyramidTheme pt; + + const _SasEmojiChip({required this.emoji, required this.pt}); + + @override + Widget build(BuildContext context) { + return Container( + width: 68, + padding: const EdgeInsets.symmetric(vertical: 8, horizontal: 4), + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(10), + border: Border.all(color: pt.border), + ), + child: Column( + mainAxisSize: MainAxisSize.min, + children: [ + Text(emoji.emoji, style: const TextStyle(fontSize: 26)), + const SizedBox(height: 4), + Text( + emoji.name, + style: TextStyle(color: pt.fgMuted, fontSize: 10), + textAlign: TextAlign.center, + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// ENCRYPTION +// ───────────────────────────────────────────────────────────────────────────── + +enum _EncState { idle, loading, needsKey, unlocking, done, error } +enum _RecoveryStep { loading, showKey, confirmKey, applying, done, error } + +class _EncryptionSection extends ConsumerStatefulWidget { + final PyramidTheme pt; + final WidgetRef ref; + const _EncryptionSection({required this.pt, required this.ref}); + + @override + ConsumerState<_EncryptionSection> createState() => _EncryptionSectionState(); +} + +class _EncryptionSectionState extends ConsumerState<_EncryptionSection> { + _EncState _state = _EncState.idle; + Bootstrap? _bootstrap; + final _keyCtrl = TextEditingController(); + String? _error; + + // Status loaded from encryption object + bool? _crossSigningEnabled; + bool? _crossSigningCached; + bool? _keyBackupEnabled; + bool _statusLoaded = false; + + // Key file export / import + bool _exportLoading = false; + bool _importLoading = false; + String? _keyFileMsg; + bool _keyFileMsgIsError = false; + bool _diagUploading = false; + String? _diagMsg; + bool _diagMsgIsError = false; + + @override + void initState() { + super.initState(); + _loadStatus(); + } + + @override + void dispose() { + _keyCtrl.dispose(); + super.dispose(); + } + + Future _loadStatus() async { + try { + final client = await ref.read(matrixClientProvider.future); + final enc = client.encryption; + if (enc == null) return; + final cached = await enc.crossSigning.isCached().catchError((_) => false); + if (!mounted) return; + setState(() { + _crossSigningEnabled = enc.crossSigning.enabled; + _crossSigningCached = cached; + _keyBackupEnabled = enc.keyManager.enabled; + _statusLoaded = true; + }); + } catch (_) {} + } + + Future _start() async { + setState(() { _state = _EncState.loading; _error = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + if (client.encryption == null) { + setState(() { _state = _EncState.error; _error = 'Verschlüsselung nicht verfügbar.'; }); + return; + } + final enc = client.encryption!; + final cached = await enc.keyManager.isCached().catchError((_) => false); + if (cached) { + await enc.keyManager.loadAllKeys().catchError((_) {}); + if (mounted) setState(() { _state = _EncState.done; _error = null; }); + await _loadStatus(); + return; + } + + await client.roomsLoading; + await client.accountDataLoading; + await client.userDeviceKeysLoading; + + final completer = Completer(); + _bootstrap = enc.bootstrap(onUpdate: (bs) { + if (!mounted) return; + switch (bs.state) { + case BootstrapState.askWipeSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.wipeSsss(false)); + case BootstrapState.askBadSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.ignoreBadSecrets(true)); + case BootstrapState.askUseExistingSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.useExistingSsss(true)); + case BootstrapState.openExistingSsss: + if (!completer.isCompleted) completer.complete(true); + case BootstrapState.askNewSsss: + if (!completer.isCompleted) completer.complete(false); + case BootstrapState.error: + if (!completer.isCompleted) completer.complete(false); + if (mounted) setState(() { _state = _EncState.error; _error = 'Bootstrap-Fehler.'; }); + default: + break; + } + }); + + final needsKey = await completer.future + .timeout(const Duration(seconds: 30), onTimeout: () => false); + if (!mounted) return; + setState(() => _state = needsKey ? _EncState.needsKey : _EncState.done); + await _loadStatus(); + } catch (e) { + if (mounted) setState(() { _state = _EncState.error; _error = e.toString().split('\n').first; }); + } + } + + Future _unlock() async { + final bs = _bootstrap; + if (bs == null || bs.newSsssKey == null) return; + final key = _keyCtrl.text.trim(); + if (key.isEmpty) { setState(() => _error = 'Bitte Wiederherstellungsschlüssel eingeben.'); return; } + setState(() { _state = _EncState.unlocking; _error = null; }); + try { + await bs.newSsssKey!.unlock(keyOrPassphrase: key); + await bs.openExistingSsss(); + final client = await ref.read(matrixClientProvider.future); + if (bs.encryption.crossSigning.enabled) { + await client.encryption!.crossSigning.selfSign(recoveryKey: key); + } + await client.encryption!.keyManager.loadAllKeys(); + if (mounted) setState(() => _state = _EncState.done); + await _loadStatus(); + } on InvalidPassphraseException catch (_) { + if (mounted) setState(() { _state = _EncState.needsKey; _error = 'Falscher Schlüssel.'; }); + } on FormatException catch (_) { + if (mounted) setState(() { _state = _EncState.needsKey; _error = 'Ungültiges Format.'; }); + } catch (e) { + if (mounted) setState(() { _state = _EncState.error; _error = e.toString().split('\n').first; }); + } + } + + Future _resetSecurity() async { + final confirm = await showDialog( + context: context, + builder: (ctx) { + final pt = widget.pt; + return AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + title: Text('Sicherheit zurücksetzen?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text( + 'Dies löscht deine aktuellen Cross-Signing-Schlüssel und den Online-Schlüssel-Backup. Nicht gesicherte Sitzungen können Nachrichten möglicherweise nicht mehr entschlüsseln.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.danger, foregroundColor: Colors.white, elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Zurücksetzen'), + ), + ], + ); + }, + ); + if (confirm != true || !mounted) return; + setState(() { _state = _EncState.loading; _error = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + final enc = client.encryption; + if (enc == null) throw Exception('Verschlüsselung nicht verfügbar'); + await client.roomsLoading; + await client.accountDataLoading; + await client.userDeviceKeysLoading; + final completer = Completer(); + enc.bootstrap(onUpdate: (bs) { + if (!mounted) return; + switch (bs.state) { + case BootstrapState.askWipeSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.wipeSsss(true)); + case BootstrapState.askBadSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.ignoreBadSecrets(true)); + case BootstrapState.askUseExistingSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.useExistingSsss(false)); + case BootstrapState.askNewSsss: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.newSsss()); + case BootstrapState.askWipeCrossSigning: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.wipeCrossSigning(true)); + case BootstrapState.askSetupCrossSigning: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.askSetupCrossSigning( + setupMasterKey: true, setupSelfSigningKey: true, setupUserSigningKey: true)); + case BootstrapState.askWipeOnlineKeyBackup: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.wipeOnlineKeyBackup(true)); + case BootstrapState.askSetupOnlineKeyBackup: + WidgetsBinding.instance.addPostFrameCallback((_) => bs.askSetupOnlineKeyBackup(true)); + case BootstrapState.done: + if (!completer.isCompleted) completer.complete(); + case BootstrapState.error: + if (!completer.isCompleted) completer.completeError('Bootstrap-Fehler'); + default: + break; + } + }); + await completer.future.timeout(const Duration(seconds: 60)); + if (mounted) setState(() => _state = _EncState.done); + await _loadStatus(); + } catch (e) { + if (mounted) setState(() { _state = _EncState.error; _error = e.toString().split('\n').first; }); + } + } + + Future _showPassphraseDialog({required bool forExport}) { + return showDialog( + context: context, + builder: (ctx) => _PassphraseDialog(pt: widget.pt, forExport: forExport), + ); + } + + Future _exportKeys() async { + final passphrase = await _showPassphraseDialog(forExport: true); + if (passphrase == null || !mounted) return; + + setState(() { _exportLoading = true; _keyFileMsg = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + final db = client.database; + if (db == null) throw Exception('Datenbank nicht verfügbar.'); + + final stored = await db.getAllInboundGroupSessions(); + final sessions = >[]; + + for (final s in stored) { + try { + final content = jsonDecode(s.content) as Map; + final sessionKey = content['session_key'] as String?; + if (sessionKey == null || sessionKey.isEmpty) continue; + + final claimedKeys = s.senderClaimedKeys.isNotEmpty + ? (jsonDecode(s.senderClaimedKeys) as Map) + .map((k, v) => MapEntry(k, v.toString())) + : {}; + + sessions.add({ + 'algorithm': 'm.megolm.v1.aes-sha2', + 'forwarding_curve25519_key_chain': [], + 'room_id': s.roomId, + 'sender_key': s.senderKey, + 'sender_claimed_keys': claimedKeys, + 'session_id': s.sessionId, + 'session_key': sessionKey, + }); + } catch (_) { continue; } + } + + if (sessions.isEmpty) throw Exception('Keine exportierbaren Sitzungsschlüssel gefunden.'); + + final encrypted = await compute(_encryptMegolmKeys, { + 'passphrase': passphrase, + 'sessions': sessions, + }); + + final dir = await getApplicationDocumentsDirectory(); + final now = DateTime.now(); + final stamp = '${now.year}' + '${now.month.toString().padLeft(2, '0')}' + '${now.day.toString().padLeft(2, '0')}'; + final file = File('${dir.path}/pyramid_keys_$stamp.txt'); + await file.writeAsString(encrypted); + + if (mounted) setState(() { + _exportLoading = false; + _keyFileMsgIsError = false; + _keyFileMsg = '${sessions.length} Schlüssel exportiert → ${file.path}'; + }); + } catch (e) { + if (mounted) setState(() { + _exportLoading = false; + _keyFileMsgIsError = true; + _keyFileMsg = 'Export fehlgeschlagen: ${e.toString().split('\n').first}'; + }); + } + } + + Future _uploadDiagnostics() async { + setState(() { _diagUploading = true; _diagMsg = null; }); + try { + final notifier = ref.read(e2eeDiagnosticsProvider.notifier); + final msg = await notifier.upload( + serverUrl: 'https://dashboard.steggi-matrix.work', + token: 'J5laxTz5Zte9oRB5x8QsyYRQ6b0hAuXI', + ); + if (mounted) setState(() { _diagUploading = false; _diagMsgIsError = false; _diagMsg = msg; }); + } catch (e) { + if (mounted) setState(() { _diagUploading = false; _diagMsgIsError = true; _diagMsg = e.toString(); }); + } + } + + Future _importKeys() async { + final result = await FilePicker.platform.pickFiles( + type: FileType.custom, + allowedExtensions: ['txt', 'key', 'keys'], + allowMultiple: false, + ); + if (result == null || result.files.isEmpty || result.files.first.path == null) return; + if (!mounted) return; + + final passphrase = await _showPassphraseDialog(forExport: false); + if (passphrase == null || !mounted) return; + + setState(() { _importLoading = true; _keyFileMsg = null; }); + try { + final fileContent = await File(result.files.first.path!).readAsString(); + final trimmed = fileContent.trim(); + + if (!trimmed.startsWith(_kMegolmHeader) || !trimmed.endsWith(_kMegolmFooter)) { + throw Exception('Ungültiges Dateiformat – kein Megolm-Schlüsseldatei-Header.'); + } + + final lines = trimmed.split('\n'); + // Strip \r so Windows line endings (\r\n) don't corrupt the base64 string. + final b64 = lines.skip(1).take(lines.length - 2).join('').replaceAll(RegExp(r'\s'), ''); + final padded = b64 + '=' * ((4 - b64.length % 4) % 4); + final dataBytes = base64.decode(padded); + + final sessions = await compute(_decryptMegolmKeys, { + 'passphrase': passphrase, + 'data': dataBytes.toList(), + }); + + final client = await ref.read(matrixClientProvider.future); + final km = client.encryption?.keyManager; + if (km == null) throw Exception('Verschlüsselung nicht initialisiert.'); + + var imported = 0; + for (final raw in sessions) { + try { + final session = raw as Map; + final roomId = session['room_id'] as String?; + final sessionId = session['session_id'] as String?; + final senderKey = session['sender_key'] as String?; + if (roomId == null || sessionId == null || senderKey == null) continue; + + final claimedKeys = (session['sender_claimed_keys'] as Map?) + ?.map((k, v) => MapEntry(k.toString(), v.toString())) ?? + {}; + + await km.setInboundGroupSession( + roomId, sessionId, senderKey, + Map.from(session), + forwarded: true, + senderClaimedKeys: claimedKeys, + ); + imported++; + } catch (_) { continue; } + } + + if (mounted) setState(() { + _importLoading = false; + _keyFileMsgIsError = false; + _keyFileMsg = '$imported von ${sessions.length} Schlüssel importiert.'; + }); + } catch (e) { + if (mounted) setState(() { + _importLoading = false; + _keyFileMsgIsError = true; + _keyFileMsg = 'Import fehlgeschlagen: ${e.toString().split('\n').first}'; + }); + } + } + + Future _changeRecoveryKey() async { + final changed = await showDialog( + context: context, + barrierDismissible: false, + builder: (ctx) => _ChangeRecoveryKeyDialog(pt: widget.pt), + ); + if (changed == true && mounted) { + await _loadStatus(); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle( + title: 'Verschlüsselung', + subtitle: 'Ende-zu-Ende-Verschlüsselung & Sicherheit verwalten.', + pt: pt), + + // ── Status overview ─────────────────────────────────────────────── + if (_statusLoaded) ...[ + _SettingsGroup(title: 'Sicherheitsstatus', pt: pt, children: [ + _SettingsRow( + title: 'Cross-Signing', + desc: _crossSigningEnabled == true + ? (_crossSigningCached == true ? 'Eingerichtet & verifiziert' : 'Eingerichtet, Schlüssel nicht im Cache') + : 'Nicht eingerichtet', + pt: pt, + control: Icon( + _crossSigningEnabled == true && _crossSigningCached == true + ? Icons.verified_rounded + : (_crossSigningEnabled == true ? Icons.warning_amber_rounded : Icons.cancel_outlined), + size: 16, + color: _crossSigningEnabled == true && _crossSigningCached == true + ? PyramidColors.success + : (_crossSigningEnabled == true ? pt.away : pt.danger), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Online-Schlüsselbackup', + desc: _keyBackupEnabled == true ? 'Aktiv – Sitzungsschlüssel gesichert' : 'Nicht aktiviert', + pt: pt, + control: Icon( + _keyBackupEnabled == true ? Icons.cloud_done_rounded : Icons.cloud_off_rounded, + size: 16, + color: _keyBackupEnabled == true ? PyramidColors.success : pt.fgDim, + ), + ), + ]), + const SizedBox(height: 20), + _FingerprintGroup(pt: pt), + const SizedBox(height: 20), + ], + + // ── Key recovery / unlock ───────────────────────────────────────── + _SettingsGroup(title: 'Wiederherstellung', pt: pt, children: [ + _SettingsRow( + title: 'Schlüssel wiederherstellen', + desc: 'Nachrichten mit dem Wiederherstellungsschlüssel entschlüsseln', + pt: pt, + showArrow: true, + onTap: _state == _EncState.loading ? null : _start, + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Wiederherstellungsschlüssel ändern', + desc: 'Neuen Schlüssel generieren, notieren und aktivieren', + pt: pt, + showArrow: true, + onTap: _state == _EncState.loading ? null : _changeRecoveryKey, + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Sicherheit neu einrichten', + desc: 'Cross-Signing & Backup zurücksetzen und neu aufsetzen', + pt: pt, + showArrow: true, + destructive: true, + onTap: _state == _EncState.loading ? null : _resetSecurity, + ), + ]), + const SizedBox(height: 20), + + // ── Key file export / import ─────────────────────────────────────── + _SettingsGroup(title: 'Schlüsseldatei', pt: pt, children: [ + _SettingsRow( + title: 'Schlüssel exportieren', + desc: 'Sitzungsschlüssel als verschlüsselte Datei sichern (kompatibel mit Element)', + pt: pt, + showArrow: !_exportLoading, + control: _exportLoading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive(strokeWidth: 2), + ) + : null, + onTap: (_exportLoading || _importLoading) ? null : _exportKeys, + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Schlüssel importieren', + desc: 'Sitzungsschlüssel aus exportierter Datei laden', + pt: pt, + showArrow: !_importLoading, + control: _importLoading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive(strokeWidth: 2), + ) + : null, + onTap: (_exportLoading || _importLoading) ? null : _importKeys, + ), + ]), + + if (_keyFileMsg != null) ...[ + const SizedBox(height: 12), + _StatusCard( + pt: pt, + icon: _keyFileMsgIsError + ? Icons.error_outline_rounded + : Icons.check_circle_outline_rounded, + color: _keyFileMsgIsError ? pt.danger : PyramidColors.success, + text: _keyFileMsg!, + ), + ], + const SizedBox(height: 20), + + // ── E2EE Diagnostics ────────────────────────────────────────────── + Consumer(builder: (context, ref, _) { + final count = ref.watch(e2eeDiagnosticsProvider).length; + return _SettingsGroup(title: 'Diagnose', pt: pt, children: [ + _SettingsRow( + title: 'Entschlüsselungsfehler hochladen', + desc: count == 0 + ? 'Keine Fehler gesammelt' + : '$count Fehler gesammelt – zum Server hochladen', + pt: pt, + showArrow: !_diagUploading && count > 0, + control: _diagUploading + ? const SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator.adaptive(strokeWidth: 2), + ) + : count > 0 + ? Container( + padding: const EdgeInsets.symmetric(horizontal: 6, vertical: 2), + decoration: BoxDecoration( + color: pt.danger.withAlpha(30), + borderRadius: BorderRadius.circular(10), + ), + child: Text('$count', style: TextStyle(color: pt.danger, fontSize: 12)), + ) + : null, + onTap: (_diagUploading || count == 0) ? null : _uploadDiagnostics, + ), + ]); + }), + + if (_diagMsg != null) ...[ + const SizedBox(height: 12), + _StatusCard( + pt: pt, + icon: _diagMsgIsError + ? Icons.error_outline_rounded + : Icons.cloud_done_rounded, + color: _diagMsgIsError ? pt.danger : PyramidColors.success, + text: _diagMsg!, + ), + ], + const SizedBox(height: 20), + + // ── Inline state UI ─────────────────────────────────────────────── + if (_state == _EncState.loading) + const Center(child: Padding(padding: EdgeInsets.all(24), child: CircularProgressIndicator.adaptive())), + + if (_state == _EncState.done) ...[ + _StatusCard( + pt: pt, + icon: Icons.check_circle_outline_rounded, + color: PyramidColors.success, + text: 'Alle Schlüssel importiert. Nachrichten werden entschlüsselt.'), + const SizedBox(height: 12), + ], + + if (_state == _EncState.needsKey || _state == _EncState.unlocking) ...[ + _StatusCard( + pt: pt, + icon: Icons.lock_outline_rounded, + color: pt.accent, + text: 'Wiederherstellungsschlüssel erforderlich.'), + const SizedBox(height: 16), + TextField( + controller: _keyCtrl, + readOnly: _state == _EncState.unlocking, + autofocus: true, + autocorrect: false, + style: TextStyle(color: pt.fg, fontSize: 13, fontFamily: 'monospace'), + decoration: InputDecoration( + hintText: 'EsXX XXXX XXXX XXXX …', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 12), + labelText: 'Wiederherstellungsschlüssel', + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + errorText: _error, + errorMaxLines: 2, + filled: true, + fillColor: pt.bg2, + prefixIcon: Icon(Icons.vpn_key_outlined, color: pt.fgDim, size: 18), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + isDense: true, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 12), + ), + cursorColor: pt.accent, + onSubmitted: (_) => _unlock(), + ), + const SizedBox(height: 12), + SizedBox( + width: double.infinity, + child: _PrimaryBtn( + label: _state == _EncState.unlocking ? 'Entschlüssele…' : 'Nachrichten entschlüsseln', + icon: Icons.lock_open_outlined, + pt: pt, + loading: _state == _EncState.unlocking, + onPressed: _unlock, + ), + ), + const SizedBox(height: 12), + ], + + if (_state == _EncState.error) ...[ + _StatusCard( + pt: pt, icon: Icons.error_outline_rounded, color: PyramidColors.danger, + text: _error ?? 'Unbekannter Fehler.'), + const SizedBox(height: 12), + OutlinedButton.icon( + style: OutlinedButton.styleFrom( + foregroundColor: pt.fg, + side: BorderSide(color: pt.border), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: _start, + icon: const Icon(Icons.refresh_rounded, size: 16), + label: const Text('Erneut versuchen'), + ), + ], + + if (_state == _EncState.idle && !_statusLoaded) + _StatusCard( + pt: pt, + icon: Icons.shield_outlined, + color: pt.fgMuted, + text: 'Lade Sicherheitsstatus…'), + ], + ), + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// CHANGE RECOVERY KEY DIALOG +// ───────────────────────────────────────────────────────────────────────────── + +class _ChangeRecoveryKeyDialog extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _ChangeRecoveryKeyDialog({required this.pt}); + + @override + ConsumerState<_ChangeRecoveryKeyDialog> createState() => + _ChangeRecoveryKeyDialogState(); +} + +class _ChangeRecoveryKeyDialogState + extends ConsumerState<_ChangeRecoveryKeyDialog> { + _RecoveryStep _step = _RecoveryStep.loading; + String? _generatedKey; + String? _error; + bool _copied = false; + // Completer signals when bootstrap reaches `done` + final _doneCompleter = Completer(); + + @override + void initState() { + super.initState(); + _startBootstrap(); + } + + Future _startBootstrap() async { + try { + final client = await ref.read(matrixClientProvider.future); + final enc = client.encryption; + if (enc == null) throw Exception('Verschlüsselung nicht verfügbar.'); + await client.roomsLoading; + await client.accountDataLoading; + await client.userDeviceKeysLoading; + enc.bootstrap(onUpdate: (bs) { + if (!mounted) return; + _onBootstrapUpdate(bs); + }); + } catch (e) { + if (mounted) { + setState(() { + _step = _RecoveryStep.error; + _error = e.toString().split('\n').first; + }); + } + } + } + + // After newSsss() calls checkCrossSigning(), the bootstrap immediately + // transitions to askWipeCrossSigning (or askSetupCrossSigning). All post- + // newSsss states must therefore auto-advance unconditionally — guarding on + // _step would leave them stuck. + void _onBootstrapUpdate(Bootstrap bs) { + switch (bs.state) { + case BootstrapState.askWipeSsss: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askWipeSsss) bs.wipeSsss(true); + }); + case BootstrapState.askBadSsss: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askBadSsss) bs.ignoreBadSecrets(true); + }); + case BootstrapState.askUseExistingSsss: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askUseExistingSsss) bs.useExistingSsss(false); + }); + case BootstrapState.askUnlockSsss: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askUnlockSsss) bs.unlockedSsss(); + }); + case BootstrapState.askNewSsss: + // Only generate once + if (_step == _RecoveryStep.loading) { + WidgetsBinding.instance.addPostFrameCallback((_) async { + if (bs.state != BootstrapState.askNewSsss) return; + try { + await bs.newSsss(); + // newSsss() internally calls checkCrossSigning() which already + // transitions to askWipeCrossSigning; capture key after it returns. + final key = bs.newSsssKey?.recoveryKey; + if (mounted) setState(() { _generatedKey = key; _step = _RecoveryStep.showKey; }); + } catch (e) { + if (mounted) setState(() { _step = _RecoveryStep.error; _error = e.toString().split('\n').first; }); + } + }); + } + case BootstrapState.askWipeCrossSigning: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askWipeCrossSigning) bs.wipeCrossSigning(false); + }); + case BootstrapState.askSetupCrossSigning: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askSetupCrossSigning) { + bs.askSetupCrossSigning( + setupMasterKey: true, + setupSelfSigningKey: true, + setupUserSigningKey: true, + ); + } + }); + case BootstrapState.askWipeOnlineKeyBackup: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askWipeOnlineKeyBackup) bs.wipeOnlineKeyBackup(true); + }); + case BootstrapState.askSetupOnlineKeyBackup: + WidgetsBinding.instance.addPostFrameCallback((_) { + if (bs.state == BootstrapState.askSetupOnlineKeyBackup) bs.askSetupOnlineKeyBackup(true); + }); + case BootstrapState.done: + if (!_doneCompleter.isCompleted) _doneCompleter.complete(); + // Only auto-advance to done if user already clicked through (applying). + // If still on showKey/confirmKey, the user must finish reading first. + if (mounted && _step == _RecoveryStep.applying) { + setState(() => _step = _RecoveryStep.done); + } + case BootstrapState.error: + if (!_doneCompleter.isCompleted) _doneCompleter.completeError('Bootstrap-Fehler'); + if (mounted) setState(() { _step = _RecoveryStep.error; _error = 'Fehler bei der Schlüsselgenerierung.'; }); + default: + break; + } + } + + // Called when user taps "Schlüssel gespeichert – weiter" on the showKey screen. + void _onKeySaved() { + setState(() => _step = _RecoveryStep.confirmKey); + } + + // Called when user submits the correct key confirmation. + // Bootstrap may still be running (cross-signing + key backup); wait for done. + Future _onKeyConfirmed() async { + setState(() => _step = _RecoveryStep.applying); + try { + await _doneCompleter.future.timeout(const Duration(seconds: 90)); + if (mounted) setState(() => _step = _RecoveryStep.done); + } catch (e) { + if (mounted) setState(() { _step = _RecoveryStep.error; _error = 'Timeout: Bootstrap abgebrochen.'; }); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final canClose = _step != _RecoveryStep.loading && _step != _RecoveryStep.applying && _step != _RecoveryStep.confirmKey; + + return Dialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border), + ), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 440, minWidth: 320), + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.stretch, + children: [ + Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 12, 12), + child: Row( + children: [ + Icon(Icons.key_rounded, size: 18, color: pt.accent), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Wiederherstellungsschlüssel', + style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600), + ), + ), + if (canClose) + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(_step == _RecoveryStep.done), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ], + ), + ), + Divider(color: pt.border, height: 1), + Padding( + padding: const EdgeInsets.all(20), + child: _buildBody(pt), + ), + ], + ), + ), + ); + } + + Widget _buildBody(PyramidTheme pt) { + return switch (_step) { + _RecoveryStep.loading => const Center( + child: Padding(padding: EdgeInsets.all(24), child: CircularProgressIndicator.adaptive()), + ), + _RecoveryStep.showKey => _ShowKeyBody( + pt: pt, + generatedKey: _generatedKey ?? '', + copied: _copied, + onCopy: () { + Clipboard.setData(ClipboardData(text: _generatedKey ?? '')); + setState(() => _copied = true); + }, + onKeySaved: _onKeySaved, + ), + _RecoveryStep.confirmKey => _ConfirmKeyBody( + pt: pt, + expectedKey: _generatedKey ?? '', + onConfirmed: _onKeyConfirmed, + ), + _RecoveryStep.applying => Column( + mainAxisSize: MainAxisSize.min, + children: [ + const CircularProgressIndicator.adaptive(), + const SizedBox(height: 16), + Text( + 'Schlüssel wird aktiviert…\nCross-Signing und Backup werden eingerichtet.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + ], + ), + _RecoveryStep.done => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.check_circle_outline_rounded, color: PyramidColors.success, size: 52), + const SizedBox(height: 12), + Text( + 'Wiederherstellungsschlüssel wurde erfolgreich geändert.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w500), + ), + const SizedBox(height: 6), + Text( + 'Bewahre deinen Schlüssel sicher auf – du brauchst ihn bei Geräteverlust.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.4), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: () => Navigator.of(context).pop(true), + child: const Text('Fertig'), + ), + ), + ], + ), + _RecoveryStep.error => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline_rounded, color: PyramidColors.danger, size: 48), + const SizedBox(height: 12), + Text( + _error ?? 'Ein unbekannter Fehler ist aufgetreten.', + textAlign: TextAlign.center, + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: OutlinedButton( + style: OutlinedButton.styleFrom( + foregroundColor: pt.fg, side: BorderSide(color: pt.border), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: () => Navigator.of(context).pop(false), + child: const Text('Schließen'), + ), + ), + ], + ), + }; + } +} + +class _ShowKeyBody extends StatelessWidget { + final PyramidTheme pt; + final String generatedKey; + final bool copied; + final VoidCallback onCopy; + final VoidCallback onKeySaved; + + const _ShowKeyBody({ + required this.pt, + required this.generatedKey, + required this.copied, + required this.onCopy, + required this.onKeySaved, + }); + + @override + Widget build(BuildContext context) { + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Dein neuer Wiederherstellungsschlüssel', + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 8), + Text( + 'Speichere diesen Schlüssel sicher – du brauchst ihn, wenn du den Zugang zu allen Geräten verlierst.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + const SizedBox(height: 16), + Container( + decoration: BoxDecoration( + color: pt.bg3, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Expanded( + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + child: SelectableText( + generatedKey, + style: TextStyle( + color: pt.accent, fontSize: 13, + fontFamily: 'monospace', letterSpacing: 0.5, height: 1.6, + ), + ), + ), + ), + IconButton( + onPressed: onCopy, + icon: Icon( + copied ? Icons.check_rounded : Icons.copy_rounded, + size: 18, + color: copied ? PyramidColors.success : pt.fgDim, + ), + tooltip: copied ? 'Kopiert!' : 'In Zwischenablage kopieren', + ), + ], + ), + ), + const SizedBox(height: 12), + Container( + padding: const EdgeInsets.all(10), + decoration: BoxDecoration( + color: Colors.orange.withAlpha(28), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: Colors.orange.withAlpha(80)), + ), + child: Row( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Icon(Icons.warning_amber_rounded, size: 16, color: Colors.orange.shade700), + const SizedBox(width: 8), + Expanded( + child: Text( + 'Schreibe diesen Schlüssel auf oder speichere ihn in einem Passwort-Manager. Er kann nicht wiederhergestellt werden.', + style: TextStyle(color: Colors.orange.shade800, fontSize: 12, height: 1.4), + ), + ), + ], + ), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: onKeySaved, + child: const Text('Schlüssel gespeichert – weiter'), + ), + ), + ], + ); + } +} + +class _ConfirmKeyBody extends StatefulWidget { + final PyramidTheme pt; + final String expectedKey; + final VoidCallback onConfirmed; + + const _ConfirmKeyBody({ + required this.pt, + required this.expectedKey, + required this.onConfirmed, + }); + + @override + State<_ConfirmKeyBody> createState() => _ConfirmKeyBodyState(); +} + +class _ConfirmKeyBodyState extends State<_ConfirmKeyBody> { + final _controller = TextEditingController(); + bool _mismatch = false; + + @override + void dispose() { + _controller.dispose(); + super.dispose(); + } + + void _submit() { + final entered = _controller.text.trim(); + if (entered == widget.expectedKey) { + widget.onConfirmed(); + } else { + setState(() => _mismatch = true); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + 'Schlüssel bestätigen', + style: TextStyle(color: pt.fg, fontSize: 14, fontWeight: FontWeight.w600), + ), + const SizedBox(height: 8), + Text( + 'Gib deinen neuen Wiederherstellungsschlüssel zur Bestätigung ein.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + const SizedBox(height: 16), + TextField( + controller: _controller, + autofocus: true, + style: TextStyle( + color: pt.fg, fontSize: 13, + fontFamily: 'monospace', letterSpacing: 0.4, + ), + decoration: InputDecoration( + hintText: 'EsTX XXXX XXXX …', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 13), + filled: true, + fillColor: pt.bg3, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: _mismatch ? PyramidColors.danger : pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), + borderSide: BorderSide(color: _mismatch ? PyramidColors.danger : pt.accent, width: 1.5), + ), + errorText: _mismatch ? 'Schlüssel stimmt nicht überein.' : null, + ), + onChanged: (_) { if (_mismatch) setState(() => _mismatch = false); }, + onSubmitted: (_) => _submit(), + ), + const SizedBox(height: 20), + SizedBox( + width: double.infinity, + child: ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: _submit, + child: const Text('Aktivieren'), + ), + ), + ], + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// FINGERPRINT GROUP +// ───────────────────────────────────────────────────────────────────────────── + +class _FingerprintGroup extends ConsumerWidget { + final PyramidTheme pt; + const _FingerprintGroup({required this.pt}); + + static String _fmt(String key) { + final clean = key.replaceAll(RegExp(r'\s'), ''); + final groups = []; + for (var i = 0; i < clean.length; i += 4) { + groups.add(clean.substring(i, (i + 4).clamp(0, clean.length))); + } + return groups.join(' '); + } + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clientAsync = ref.watch(matrixClientProvider); + final client = clientAsync.valueOrNull; + if (client == null) return const SizedBox.shrink(); + + final fingerprint = _fmt(client.fingerprintKey); + final deviceId = client.deviceID ?? ''; + + return _SettingsGroup(title: 'Dieses Gerät', pt: pt, children: [ + _SettingsRow( + title: 'Geräte-ID', + desc: deviceId, + pt: pt, + control: IconButton( + icon: Icon(Icons.copy_rounded, size: 14, color: pt.fgDim), + tooltip: 'Kopieren', + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + onPressed: () => Clipboard.setData(ClipboardData(text: deviceId)), + ), + ), + _Divider(pt: pt), + Padding( + padding: const EdgeInsets.fromLTRB(14, 12, 14, 12), + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row( + children: [ + Text('Ed25519-Fingerabdruck', + style: TextStyle(color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500)), + const Spacer(), + IconButton( + icon: Icon(Icons.copy_rounded, size: 14, color: pt.fgDim), + tooltip: 'Fingerabdruck kopieren', + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + onPressed: () => Clipboard.setData(ClipboardData(text: client.fingerprintKey)), + ), + ], + ), + const SizedBox(height: 4), + SelectableText( + fingerprint, + style: TextStyle( + color: pt.fgMuted, fontSize: 11, + fontFamily: 'monospace', letterSpacing: 0.5, height: 1.6, + ), + ), + ], + ), + ), + ]); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// CHANGE PASSWORD DIALOG +// ───────────────────────────────────────────────────────────────────────────── + +class _ChangePasswordDialog extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _ChangePasswordDialog({required this.pt}); + + @override + ConsumerState<_ChangePasswordDialog> createState() => _ChangePasswordDialogState(); +} + +class _ChangePasswordDialogState extends ConsumerState<_ChangePasswordDialog> { + final _oldCtrl = TextEditingController(); + final _newCtrl = TextEditingController(); + final _confirmCtrl = TextEditingController(); + bool _oldVisible = false; + bool _newVisible = false; + bool _loading = false; + String? _error; + bool _done = false; + + @override + void dispose() { + _oldCtrl.dispose(); + _newCtrl.dispose(); + _confirmCtrl.dispose(); + super.dispose(); + } + + Future _submit() async { + final oldPw = _oldCtrl.text; + final newPw = _newCtrl.text; + final confirm = _confirmCtrl.text; + if (oldPw.isEmpty || newPw.isEmpty) { + setState(() => _error = 'Bitte alle Felder ausfüllen.'); + return; + } + if (newPw != confirm) { + setState(() => _error = 'Die neuen Passwörter stimmen nicht überein.'); + return; + } + if (newPw.length < 8) { + setState(() => _error = 'Das neue Passwort muss mindestens 8 Zeichen lang sein.'); + return; + } + setState(() { _loading = true; _error = null; }); + try { + final client = await ref.read(matrixClientProvider.future); + await client.changePassword(newPw, oldPassword: oldPw); + if (mounted) setState(() { _loading = false; _done = true; }); + } on MatrixException catch (e) { + if (mounted) setState(() { _loading = false; _error = e.errorMessage; }); + } catch (e) { + if (mounted) setState(() { _loading = false; _error = e.toString().split('\n').first; }); + } + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Dialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 420, minWidth: 300), + child: Padding( + padding: const EdgeInsets.all(24), + child: _done ? _buildDone(pt) : _buildForm(pt), + ), + ), + ); + } + + Widget _buildDone(PyramidTheme pt) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.check_circle_outline_rounded, color: PyramidColors.success, size: 52), + const SizedBox(height: 12), + Text('Passwort geändert', style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600)), + const SizedBox(height: 6), + Text('Dein Passwort wurde erfolgreich aktualisiert.', + textAlign: TextAlign.center, style: TextStyle(color: pt.fgMuted, fontSize: 13)), + const SizedBox(height: 20), + SizedBox(width: double.infinity, child: ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.of(context).pop(), + child: const Text('Schließen'), + )), + ], + ); + + Widget _buildForm(PyramidTheme pt) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.lock_outline_rounded, size: 18, color: pt.accent), + const SizedBox(width: 8), + Text('Passwort ändern', style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600)), + const Spacer(), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ]), + const SizedBox(height: 20), + _PwField(ctrl: _oldCtrl, label: 'Aktuelles Passwort', pt: pt, + visible: _oldVisible, onToggle: () => setState(() => _oldVisible = !_oldVisible)), + const SizedBox(height: 12), + _PwField(ctrl: _newCtrl, label: 'Neues Passwort', pt: pt, + visible: _newVisible, onToggle: () => setState(() => _newVisible = !_newVisible)), + const SizedBox(height: 12), + _PwField(ctrl: _confirmCtrl, label: 'Neues Passwort bestätigen', pt: pt, + visible: _newVisible, onToggle: null, + onSubmitted: (_) => _submit()), + if (_error != null) ...[ + const SizedBox(height: 10), + _StatusCard(pt: pt, color: pt.danger, icon: Icons.error_outline_rounded, text: _error!), + ], + const SizedBox(height: 20), + SizedBox(width: double.infinity, child: ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.accent, foregroundColor: pt.accentFg, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _loading ? null : _submit, + child: _loading + ? const SizedBox(width: 18, height: 18, child: CircularProgressIndicator.adaptive(strokeWidth: 2)) + : const Text('Passwort ändern'), + )), + ], + ); +} + +class _PwField extends StatelessWidget { + final TextEditingController ctrl; + final String label; + final PyramidTheme pt; + final bool visible; + final VoidCallback? onToggle; + final ValueChanged? onSubmitted; + + const _PwField({ + required this.ctrl, required this.label, required this.pt, + required this.visible, required this.onToggle, this.onSubmitted, + }); + + @override + Widget build(BuildContext context) => TextField( + controller: ctrl, + obscureText: !visible, + onSubmitted: onSubmitted, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + labelText: label, + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + filled: true, fillColor: pt.bg3, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + suffixIcon: onToggle != null + ? IconButton( + icon: Icon(visible ? Icons.visibility_off_rounded : Icons.visibility_rounded, size: 16, color: pt.fgDim), + onPressed: onToggle, + ) + : null, + ), + cursorColor: pt.accent, + ); +} + +// ───────────────────────────────────────────────────────────────────────────── +// DELETE ACCOUNT DIALOG +// ───────────────────────────────────────────────────────────────────────────── + +class _DeleteAccountDialog extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _DeleteAccountDialog({required this.pt}); + + @override + ConsumerState<_DeleteAccountDialog> createState() => _DeleteAccountDialogState(); +} + +enum _DeleteStep { confirm, auth, deleting, error } + +class _DeleteAccountDialogState extends ConsumerState<_DeleteAccountDialog> { + _DeleteStep _step = _DeleteStep.confirm; + final _pwCtrl = TextEditingController(); + bool _pwVisible = false; + bool _eraseData = true; + String? _error; + + @override + void dispose() { _pwCtrl.dispose(); super.dispose(); } + + Future _proceed() async { + setState(() { _step = _DeleteStep.deleting; _error = null; }); + final client = await ref.read(matrixClientProvider.future); + try { + await client.deactivateAccount(erase: _eraseData); + } on MatrixException catch (e) { + if (e.requireAdditionalAuthentication && mounted) { + // UIA required — try with password + try { + await client.deactivateAccount( + erase: _eraseData, + auth: AuthenticationData( + type: AuthenticationTypes.password, + session: e.session, + additionalFields: { + 'identifier': {'type': 'm.id.user', 'user': client.userID}, + 'password': _pwCtrl.text, + }, + ), + ); + } on MatrixException catch (e2) { + if (mounted) setState(() { _step = _DeleteStep.error; _error = e2.errorMessage; }); + return; + } catch (e2) { + if (mounted) setState(() { _step = _DeleteStep.error; _error = e2.toString().split('\n').first; }); + return; + } + } else { + if (mounted) setState(() { _step = _DeleteStep.error; _error = e.errorMessage; }); + return; + } + } catch (e) { + if (mounted) setState(() { _step = _DeleteStep.error; _error = e.toString().split('\n').first; }); + return; + } + // Konto wurde gelöscht — ausloggen + try { await client.logout(); } catch (_) {} + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return Dialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), side: BorderSide(color: pt.border)), + child: ConstrainedBox( + constraints: const BoxConstraints(maxWidth: 440, minWidth: 300), + child: Padding( + padding: const EdgeInsets.all(24), + child: switch (_step) { + _DeleteStep.confirm => _buildConfirm(pt), + _DeleteStep.auth => _buildAuth(pt), + _DeleteStep.deleting => const Center( + child: Padding(padding: EdgeInsets.all(32), child: CircularProgressIndicator.adaptive()), + ), + _DeleteStep.error => _buildError(pt), + }, + ), + ), + ); + } + + Widget _buildConfirm(PyramidTheme pt) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.warning_rounded, size: 20, color: pt.danger), + const SizedBox(width: 8), + Text('Konto löschen', style: TextStyle(color: pt.danger, fontSize: 15, fontWeight: FontWeight.w700)), + const Spacer(), + IconButton( + icon: Icon(Icons.close_rounded, color: pt.fgDim, size: 16), + onPressed: () => Navigator.of(context).pop(), + padding: EdgeInsets.zero, + constraints: const BoxConstraints(maxWidth: 28, maxHeight: 28), + ), + ]), + const SizedBox(height: 16), + Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.danger.withAlpha(20), + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.danger.withAlpha(60)), + ), + child: Text( + 'Diese Aktion ist unwiderruflich. Dein Konto, alle Sitzungen und ' + 'deine Mitgliedschaft in Räumen werden dauerhaft gelöscht.', + style: TextStyle(color: pt.fg, fontSize: 13, height: 1.5), + ), + ), + const SizedBox(height: 16), + GestureDetector( + onTap: () => setState(() => _eraseData = !_eraseData), + child: Row(children: [ + SizedBox( + width: 18, height: 18, + child: Checkbox( + value: _eraseData, + onChanged: (v) => setState(() => _eraseData = v ?? true), + activeColor: pt.accent, + side: BorderSide(color: pt.border), + materialTapTargetSize: MaterialTapTargetSize.shrinkWrap, + ), + ), + const SizedBox(width: 8), + Expanded(child: Text('Nachrichten und Daten vom Server löschen', + style: TextStyle(color: pt.fg, fontSize: 13))), + ]), + ), + const SizedBox(height: 20), + Row(children: [ + Expanded(child: OutlinedButton( + style: OutlinedButton.styleFrom(foregroundColor: pt.fg, side: BorderSide(color: pt.border), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.of(context).pop(), + child: const Text('Abbrechen'), + )), + const SizedBox(width: 12), + Expanded(child: ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.danger, foregroundColor: Colors.white, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => setState(() => _step = _DeleteStep.auth), + child: const Text('Weiter'), + )), + ]), + ], + ); + + Widget _buildAuth(PyramidTheme pt) => Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Row(children: [ + Icon(Icons.lock_outline_rounded, size: 18, color: pt.danger), + const SizedBox(width: 8), + Text('Konto löschen bestätigen', style: TextStyle(color: pt.fg, fontSize: 15, fontWeight: FontWeight.w600)), + ]), + const SizedBox(height: 16), + Text('Gib dein Passwort ein, um die Löschung zu bestätigen.', + style: TextStyle(color: pt.fgMuted, fontSize: 13)), + const SizedBox(height: 16), + TextField( + controller: _pwCtrl, + autofocus: true, + obscureText: !_pwVisible, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + labelText: 'Passwort', + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + filled: true, fillColor: pt.bg3, + contentPadding: const EdgeInsets.symmetric(horizontal: 12, vertical: 10), + border: OutlineInputBorder(borderRadius: BorderRadius.circular(8)), + enabledBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder(borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.danger)), + suffixIcon: IconButton( + icon: Icon(_pwVisible ? Icons.visibility_off_rounded : Icons.visibility_rounded, size: 16, color: pt.fgDim), + onPressed: () => setState(() => _pwVisible = !_pwVisible), + ), + ), + cursorColor: pt.danger, + onSubmitted: (_) => _proceed(), + ), + const SizedBox(height: 20), + Row(children: [ + Expanded(child: OutlinedButton( + style: OutlinedButton.styleFrom(foregroundColor: pt.fg, side: BorderSide(color: pt.border), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => setState(() => _step = _DeleteStep.confirm), + child: const Text('Zurück'), + )), + const SizedBox(width: 12), + Expanded(child: ElevatedButton( + style: ElevatedButton.styleFrom(backgroundColor: pt.danger, foregroundColor: Colors.white, + elevation: 0, padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: _proceed, + child: const Text('Konto endgültig löschen'), + )), + ]), + ], + ); + + Widget _buildError(PyramidTheme pt) => Column( + mainAxisSize: MainAxisSize.min, + children: [ + Icon(Icons.error_outline_rounded, color: pt.danger, size: 48), + const SizedBox(height: 12), + Text(_error ?? 'Ein Fehler ist aufgetreten.', + textAlign: TextAlign.center, style: TextStyle(color: pt.fgMuted, fontSize: 13)), + const SizedBox(height: 20), + SizedBox(width: double.infinity, child: OutlinedButton( + style: OutlinedButton.styleFrom(foregroundColor: pt.fg, side: BorderSide(color: pt.border), + padding: const EdgeInsets.symmetric(vertical: 12), + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.of(context).pop(), + child: const Text('Schließen'), + )), + ], + ); +} + +// ───────────────────────────────────────────────────────────────────────────── +// ABOUT +// ───────────────────────────────────────────────────────────────────────────── + +class _AboutSection extends ConsumerWidget { + final PyramidTheme pt; + const _AboutSection({required this.pt}); + + @override + Widget build(BuildContext context, WidgetRef ref) { + final clientAsync = ref.watch(matrixClientProvider); + final client = clientAsync.valueOrNull; + + return SingleChildScrollView( + child: Column( + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + _SectionTitle(title: 'Über Pyramid', subtitle: 'Version & Konto-Infos.', pt: pt), + _SettingsGroup(title: 'Version', pt: pt, children: [ + _SettingsRow( + title: 'Pyramid', + desc: '0.1.0 · Flutter · Matrix SDK', + pt: pt, + control: Container( + padding: const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: pt.accentSoft, + borderRadius: BorderRadius.circular(6)), + child: Text('Beta', + style: TextStyle( + color: pt.accent, fontSize: 10, fontWeight: FontWeight.w700)), + )), + _Divider(pt: pt), + _SettingsRow( + title: 'Matrix SDK', + desc: 'matrix-dart-sdk ^6.2.0', + pt: pt), + ]), + const SizedBox(height: 20), + _UpdatesSettingsGroup(pt: pt), + const SizedBox(height: 20), + _NotificationsSettingsGroup(pt: pt), + const SizedBox(height: 20), + if (client != null) + _SettingsGroup(title: 'Konto', pt: pt, children: [ + _SettingsRow( + title: 'Matrix-ID', + desc: client.userID ?? '', + pt: pt, + control: GestureDetector( + onTap: () => Clipboard.setData(ClipboardData(text: client.userID ?? '')), + child: Tooltip( + message: 'Kopieren', + child: Icon(Icons.copy_rounded, size: 14, color: pt.fgDim), + ), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Homeserver', + desc: client.homeserver?.toString() ?? '', + pt: pt, + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Gerät', + desc: client.deviceID ?? '', + pt: pt, + control: GestureDetector( + onTap: () => + Clipboard.setData(ClipboardData(text: client.deviceID ?? '')), + child: Tooltip( + message: 'Kopieren', + child: Icon(Icons.copy_rounded, size: 14, color: pt.fgDim), + ), + ), + ), + ]), + const SizedBox(height: 20), + _SettingsGroup(title: 'Konto-Aktionen', pt: pt, children: [ + _SettingsRow( + title: 'Abmelden', + desc: 'Auf diesem Gerät ausloggen', + pt: pt, + destructive: true, + showArrow: true, + onTap: () => _confirmLogout(context, ref), + ), + ]), + ], + ), + ); + } + + Future _confirmLogout(BuildContext context, WidgetRef ref) async { + final confirm = await showDialog( + context: context, + builder: (ctx) => AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border)), + title: Text('Abmelden?', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700)), + content: Text( + 'Du wirst auf diesem Gerät abgemeldet. Deine Nachrichten bleiben erhalten.', + style: TextStyle(color: pt.fgMuted, fontSize: 13), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(ctx, false), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.danger, + foregroundColor: Colors.white, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8))), + onPressed: () => Navigator.pop(ctx, true), + child: const Text('Abmelden'), + ), + ], + ), + ); + if (confirm == true) { + final client = await ref.read(matrixClientProvider.future); + await client.logout().catchError((_) {}); + } + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// NOTIFICATIONS SETTINGS GROUP +// ───────────────────────────────────────────────────────────────────────────── + +class _NotificationsSettingsGroup extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _NotificationsSettingsGroup({required this.pt}); + @override + ConsumerState<_NotificationsSettingsGroup> createState() => + _NotificationsSettingsGroupState(); +} + +class _NotificationsSettingsGroupState + extends ConsumerState<_NotificationsSettingsGroup> { + bool _running = false; + String? _result; + bool _retryRunning = false; + String? _retryResult; + + Future _runDiag() async { + setState(() { _running = true; _result = null; }); + final client = await ref.read(matrixClientProvider.future); + final diag = await fcmDiagnostics(client); + if (mounted) setState(() { _running = false; _result = diag; }); + } + + Future _runRetry() async { + setState(() { _retryRunning = true; _retryResult = null; }); + final client = await ref.read(matrixClientProvider.future); + final result = await retryPusherRegistration(client); + if (mounted) setState(() { _retryRunning = false; _retryResult = result; }); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + if (!Platform.isAndroid) return const SizedBox.shrink(); + return _SettingsGroup(title: 'Push-Benachrichtigungen', pt: pt, children: [ + _SettingsRow( + title: 'Akku-Optimierung deaktivieren', + desc: 'Samsung / andere OEMs unterdrücken sonst Benachrichtigungen bei geschlossener App.', + pt: pt, + showArrow: true, + onTap: openBatteryOptimizationSettings, + control: Icon(Icons.battery_saver_outlined, size: 16, color: pt.fgDim), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'FCM Diagnose', + desc: _result ?? 'Prüft ob FCM-Token & Pusher korrekt registriert sind.', + pt: pt, + onTap: _running ? null : _runDiag, + control: _running + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent), + ) + : Icon(Icons.bug_report_outlined, size: 16, color: pt.fgDim), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Pusher neu registrieren', + desc: _retryResult ?? 'Pusher beim Homeserver erneut anmelden.', + pt: pt, + onTap: _retryRunning ? null : _runRetry, + control: _retryRunning + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator(strokeWidth: 2, color: pt.accent), + ) + : Icon(Icons.sync_outlined, size: 16, color: pt.fgDim), + ), + ]); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// UPDATE SETTINGS GROUP +// ───────────────────────────────────────────────────────────────────────────── + +class _UpdatesSettingsGroup extends ConsumerStatefulWidget { + final PyramidTheme pt; + const _UpdatesSettingsGroup({required this.pt}); + + @override + ConsumerState<_UpdatesSettingsGroup> createState() => + _UpdatesSettingsGroupState(); +} + +class _UpdatesSettingsGroupState extends ConsumerState<_UpdatesSettingsGroup> { + bool _checking = false; + + Future _checkNow() async { + setState(() => _checking = true); + await resetUpdateCheckTimer(); + ref.invalidate(updateInfoProvider); + // Give the async provider a moment to resolve before resetting the spinner. + await Future.delayed(const Duration(seconds: 2)); + if (mounted) setState(() => _checking = false); + } + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + final updateAsync = ref.watch(updateInfoProvider); + + return _SettingsGroup(title: 'Updates', pt: pt, children: [ + updateAsync.when( + loading: () => _SettingsRow( + title: 'Nach Updates suchen…', + desc: 'Gitea Releases wird geprüft', + pt: pt, + control: SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, + color: pt.accent, + ), + ), + ), + error: (e, _) => _SettingsRow( + title: 'Update-Prüfung fehlgeschlagen', + desc: 'Keine Verbindung oder Gitea nicht erreichbar (nur im Heimnetz).', + pt: pt, + control: _checking + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.accent), + ) + : GestureDetector( + onTap: _checkNow, + child: Tooltip( + message: 'Erneut prüfen', + child: Icon(Icons.refresh_rounded, + size: 16, color: pt.fgDim), + ), + ), + ), + data: (info) { + if (info == null) { + return _SettingsRow( + title: 'Pyramid ist aktuell', + desc: 'Du verwendest die neueste Version.', + pt: pt, + onTap: _checking ? null : _checkNow, + control: _checking + ? SizedBox( + width: 16, + height: 16, + child: CircularProgressIndicator( + strokeWidth: 2, color: pt.accent), + ) + : Icon(Icons.refresh_rounded, size: 16, color: pt.fgDim), + ); + } + // New version available + return Column( + children: [ + _SettingsRow( + title: 'Update verfügbar: ${info.tagName}', + desc: info.releaseName, + pt: pt, + showArrow: true, + onTap: () async { + if (info.canDownload) { + await showUpdateDownloadDialog(context, info); + } else { + final uri = Uri.parse(info.htmlUrl); + if (await canLaunchUrl(uri)) { + await launchUrl(uri, mode: LaunchMode.externalApplication); + } + } + }, + control: Container( + padding: + const EdgeInsets.symmetric(horizontal: 8, vertical: 3), + decoration: BoxDecoration( + color: pt.accent, + borderRadius: BorderRadius.circular(6)), + child: Text( + 'Neu', + style: TextStyle( + color: pt.accentFg, + fontSize: 10, + fontWeight: FontWeight.w700), + ), + ), + ), + _Divider(pt: pt), + _SettingsRow( + title: 'Diese Version überspringen', + desc: '${info.tagName} nicht mehr anzeigen', + pt: pt, + onTap: () async { + await skipUpdateVersion(info.tagName); + ref.invalidate(updateInfoProvider); + }, + ), + ], + ); + }, + ), + ]); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Passphrase dialog (for key export/import) +// ───────────────────────────────────────────────────────────────────────────── + +class _PassphraseDialog extends StatefulWidget { + final PyramidTheme pt; + final bool forExport; + const _PassphraseDialog({required this.pt, required this.forExport}); + + @override + State<_PassphraseDialog> createState() => _PassphraseDialogState(); +} + +class _PassphraseDialogState extends State<_PassphraseDialog> { + final _ctrl1 = TextEditingController(); + final _ctrl2 = TextEditingController(); + bool _obscure = true; + String? _error; + + @override + void dispose() { + _ctrl1.dispose(); + _ctrl2.dispose(); + super.dispose(); + } + + void _submit() { + final pass = _ctrl1.text.trim(); + if (pass.isEmpty) { + setState(() => _error = 'Bitte ein Passwort eingeben.'); + return; + } + if (widget.forExport && pass != _ctrl2.text.trim()) { + setState(() => _error = 'Passwörter stimmen nicht überein.'); + return; + } + Navigator.pop(context, pass); + } + + InputDecoration _inputDeco(String label, PyramidTheme pt) => InputDecoration( + labelText: label, + labelStyle: TextStyle(color: pt.fgMuted, fontSize: 13), + errorText: _error, + filled: true, + fillColor: pt.bg3, + prefixIcon: Icon(Icons.lock_outline_rounded, color: pt.fgDim, size: 18), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.border)), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(8), borderSide: BorderSide(color: pt.accent)), + isDense: true, + errorMaxLines: 2, + suffixIcon: IconButton( + icon: Icon( + _obscure ? Icons.visibility_off_outlined : Icons.visibility_outlined, + size: 18, + color: pt.fgDim, + ), + onPressed: () => setState(() => _obscure = !_obscure), + ), + ); + + @override + Widget build(BuildContext context) { + final pt = widget.pt; + return AlertDialog( + backgroundColor: pt.bg2, + shape: RoundedRectangleBorder( + borderRadius: BorderRadius.circular(pt.rXl), + side: BorderSide(color: pt.border), + ), + title: Text( + widget.forExport ? 'Schlüssel exportieren' : 'Schlüssel importieren', + style: TextStyle(color: pt.fg, fontSize: 16, fontWeight: FontWeight.w700), + ), + content: SizedBox( + width: 340, + child: Column( + mainAxisSize: MainAxisSize.min, + crossAxisAlignment: CrossAxisAlignment.start, + children: [ + Text( + widget.forExport + ? 'Wähle ein Passwort zum Verschlüsseln der Schlüsseldatei.' + : 'Gib das Passwort ein, mit dem die Datei verschlüsselt wurde.', + style: TextStyle(color: pt.fgMuted, fontSize: 13, height: 1.5), + ), + const SizedBox(height: 16), + TextField( + controller: _ctrl1, + obscureText: _obscure, + autofocus: true, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: _inputDeco('Passwort', pt).copyWith( + // Only show error on confirm field if export, else here + errorText: widget.forExport ? null : _error, + ), + cursorColor: pt.accent, + onSubmitted: widget.forExport ? null : (_) => _submit(), + ), + if (widget.forExport) ...[ + const SizedBox(height: 12), + TextField( + controller: _ctrl2, + obscureText: _obscure, + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: _inputDeco('Passwort bestätigen', pt), + cursorColor: pt.accent, + onSubmitted: (_) => _submit(), + ), + ], + ], + ), + ), + actions: [ + TextButton( + onPressed: () => Navigator.pop(context), + child: Text('Abbrechen', style: TextStyle(color: pt.fgMuted)), + ), + ElevatedButton( + style: ElevatedButton.styleFrom( + backgroundColor: pt.accent, + foregroundColor: pt.accentFg, + elevation: 0, + shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8)), + ), + onPressed: _submit, + child: Text(widget.forExport ? 'Exportieren' : 'Importieren'), + ), + ], + ); + } +} + +// ───────────────────────────────────────────────────────────────────────────── +// Shared small widgets +// ───────────────────────────────────────────────────────────────────────────── + +class _StatusCard extends StatelessWidget { + final PyramidTheme pt; + final IconData icon; + final Color color; + final String text; + const _StatusCard( + {required this.pt, required this.icon, required this.color, required this.text}); + + @override + Widget build(BuildContext context) { + return Container( + padding: const EdgeInsets.all(12), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(8), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Icon(icon, color: color, size: 18), + const SizedBox(width: 10), + Expanded(child: Text(text, style: TextStyle(color: pt.fgMuted, fontSize: 13))), + ], + ), + ); + } +} diff --git a/lib/widgets/share_target_dialog.dart b/lib/widgets/share_target_dialog.dart new file mode 100644 index 0000000..ae76319 --- /dev/null +++ b/lib/widgets/share_target_dialog.dart @@ -0,0 +1,297 @@ +import 'dart:io'; + +import 'package:flutter/material.dart'; +import 'package:flutter_riverpod/flutter_riverpod.dart'; +import 'package:matrix/matrix.dart'; +import 'package:pyramid/core/app_state.dart'; +import 'package:pyramid/core/matrix_client.dart'; +import 'package:pyramid/core/theme.dart'; +import 'package:pyramid/features/chat/attachment_dialog.dart'; +import 'package:pyramid/widgets/mxc_image.dart'; + +/// "Teilen nach Pyramid": Raum-Picker für geteilte Inhalte (Text/Dateien). +/// Nach Auswahl wird der Raum geöffnet; Dateien laufen durch den +/// AttachmentDialog (mit Vorschau), Text wird direkt gesendet. +class ShareTargetDialog { + static Future show( + BuildContext context, + WidgetRef ref, + PendingShare share, + ) async { + final client = await ref.read(matrixClientProvider.future); + if (!context.mounted) return; + + final room = await showGeneralDialog( + context: context, + barrierDismissible: true, + barrierLabel: 'Teilen', + barrierColor: Colors.black54, + transitionDuration: const Duration(milliseconds: 180), + pageBuilder: (_, __, ___) => _ShareTargetPicker(client: client, share: share), + transitionBuilder: (_, anim, __, child) { + final curved = CurvedAnimation(parent: anim, curve: Curves.easeOutBack); + return FadeTransition( + opacity: anim, + child: ScaleTransition( + scale: Tween(begin: 0.94, end: 1.0).animate(curved), + child: child, + ), + ); + }, + ); + if (room == null || !context.mounted) return; + + // Zielraum öffnen. + ref.read(activeRoomIdProvider.notifier).state = room.id; + ref.read(viewModeProvider.notifier).state = ViewMode.chat; + + var filesSent = false; + if (share.paths.isNotEmpty) { + final files = share.paths + .map(File.new) + .where((f) => f.existsSync()) + .toList(); + if (files.isNotEmpty) { + filesSent = await AttachmentDialog.show(context, files, room); + for (final f in files) { + f.delete().catchError((_) => f); + } + } + } + final text = share.text?.trim() ?? ''; + if (text.isNotEmpty && (share.paths.isEmpty || filesSent)) { + try { + await room.sendTextEvent(text); + } catch (_) {} + } + } +} + +class _ShareTargetPicker extends StatefulWidget { + final Client client; + final PendingShare share; + const _ShareTargetPicker({required this.client, required this.share}); + + @override + State<_ShareTargetPicker> createState() => _ShareTargetPickerState(); +} + +class _ShareTargetPickerState extends State<_ShareTargetPicker> { + String _filter = ''; + + List get _rooms { + final rooms = widget.client.rooms + .where((r) => + r.membership == Membership.join && + !r.isSpace && + (_filter.isEmpty || + r + .getLocalizedDisplayname() + .toLowerCase() + .contains(_filter.toLowerCase()))) + .toList() + // Zuletzt aktive Chats zuerst — wie bei Discord/WhatsApp-Share. + ..sort((a, b) => (b.lastEvent?.originServerTs ?? + DateTime.fromMillisecondsSinceEpoch(0)) + .compareTo(a.lastEvent?.originServerTs ?? + DateTime.fromMillisecondsSinceEpoch(0))); + return rooms; + } + + @override + Widget build(BuildContext context) { + final pt = PyramidTheme.of(context); + final size = MediaQuery.sizeOf(context); + final rooms = _rooms; + final share = widget.share; + final fileCount = share.paths.length; + + return Center( + child: Material( + color: Colors.transparent, + child: Container( + width: (size.width - 32).clamp(280.0, 440.0), + height: (size.height - 80).clamp(320.0, 560.0), + decoration: BoxDecoration( + color: pt.bg1, + borderRadius: BorderRadius.circular(pt.rXl), + border: Border.all(color: pt.border), + boxShadow: const [BoxShadow(color: Colors.black54, blurRadius: 40)], + ), + child: Column( + children: [ + // Header + Padding( + padding: const EdgeInsets.fromLTRB(20, 16, 12, 4), + child: Row( + children: [ + Icon(Icons.share_rounded, size: 18, color: pt.accent), + const SizedBox(width: 10), + Expanded( + child: Text( + 'Teilen nach…', + style: TextStyle( + color: pt.fg, + fontSize: 16, + fontWeight: FontWeight.w700), + ), + ), + IconButton( + icon: Icon(Icons.close_rounded, size: 18, color: pt.fgDim), + onPressed: () => Navigator.of(context).pop(), + ), + ], + ), + ), + // Vorschau des geteilten Inhalts + Padding( + padding: const EdgeInsets.fromLTRB(20, 4, 20, 10), + child: Container( + width: double.infinity, + padding: + const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + decoration: BoxDecoration( + color: pt.bg2, + borderRadius: BorderRadius.circular(pt.rBase), + border: Border.all(color: pt.border), + ), + child: Row( + children: [ + Icon( + fileCount > 0 + ? Icons.attach_file_rounded + : Icons.notes_rounded, + size: 14, + color: pt.fgMuted, + ), + const SizedBox(width: 8), + Expanded( + child: Text( + fileCount > 0 + ? '$fileCount Datei${fileCount == 1 ? '' : 'en'}' + '${(share.text?.isNotEmpty ?? false) ? ' + Text' : ''}' + : (share.text ?? ''), + style: TextStyle(color: pt.fgMuted, fontSize: 12), + maxLines: 2, + overflow: TextOverflow.ellipsis, + ), + ), + ], + ), + ), + ), + // Suche + Padding( + padding: const EdgeInsets.fromLTRB(20, 0, 20, 8), + child: TextField( + autofocus: false, + onChanged: (v) => setState(() => _filter = v), + style: TextStyle(color: pt.fg, fontSize: 13), + decoration: InputDecoration( + hintText: 'Chat suchen…', + hintStyle: TextStyle(color: pt.fgDim, fontSize: 13), + prefixIcon: + Icon(Icons.search_rounded, size: 16, color: pt.fgDim), + isDense: true, + filled: true, + fillColor: pt.bg2, + contentPadding: const EdgeInsets.symmetric(vertical: 8), + border: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.border), + ), + enabledBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.border), + ), + focusedBorder: OutlineInputBorder( + borderRadius: BorderRadius.circular(pt.rBase), + borderSide: BorderSide(color: pt.accent), + ), + ), + ), + ), + // Raumliste + Expanded( + child: rooms.isEmpty + ? Center( + child: Text('Keine Chats gefunden', + style: TextStyle(color: pt.fgDim, fontSize: 13)), + ) + : ListView.builder( + padding: const EdgeInsets.fromLTRB(8, 0, 8, 8), + itemCount: rooms.length, + itemBuilder: (_, i) => + _RoomRow(room: rooms[i], pt: pt, client: widget.client), + ), + ), + ], + ), + ), + ), + ); + } +} + +class _RoomRow extends StatelessWidget { + final Room room; + final PyramidTheme pt; + final Client client; + const _RoomRow({required this.room, required this.pt, required this.client}); + + @override + Widget build(BuildContext context) { + final name = room.getLocalizedDisplayname(); + final initial = name.isNotEmpty ? name[0].toUpperCase() : '?'; + return InkWell( + borderRadius: BorderRadius.circular(pt.rBase), + onTap: () => Navigator.of(context).pop(room), + child: Padding( + padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8), + child: Row( + children: [ + if (room.avatar != null) + MxcAvatar( + mxcUri: room.avatar, + client: client, + size: 30, + borderRadius: BorderRadius.circular(15), + placeholder: (_) => _initialCircle(initial), + ) + else + _initialCircle(initial), + const SizedBox(width: 12), + Expanded( + child: Text( + name, + style: TextStyle( + color: pt.fg, fontSize: 13, fontWeight: FontWeight.w500), + overflow: TextOverflow.ellipsis, + ), + ), + if (room.isDirectChat) + Icon(Icons.person_outline_rounded, size: 14, color: pt.fgDim) + else + Icon(Icons.tag_rounded, size: 14, color: pt.fgDim), + ], + ), + ), + ); + } + + Widget _initialCircle(String initial) => Container( + width: 30, + height: 30, + decoration: BoxDecoration( + color: pt.accent.withAlpha(60), + shape: BoxShape.circle, + ), + child: Center( + child: Text( + initial, + style: TextStyle( + color: pt.fg, fontSize: 13, fontWeight: FontWeight.w600), + ), + ), + ); +} diff --git a/lib/widgets/update_download_dialog.dart b/lib/widgets/update_download_dialog.dart index c04fe93..7e127c6 100644 --- a/lib/widgets/update_download_dialog.dart +++ b/lib/widgets/update_download_dialog.dart @@ -8,7 +8,7 @@ import 'package:path/path.dart' as p; import 'package:path_provider/path_provider.dart'; import 'package:pyramid/core/theme.dart'; import 'package:pyramid/core/update_checker.dart'; -import 'package:pyramid/widgets/pyramid_logo.dart'; +import 'package:pyramid/widgets/pyramid_loader.dart'; // ─── Entry point ────────────────────────────────────────────────────────────── @@ -36,10 +36,7 @@ class _UpdateDownloadDialog extends ConsumerStatefulWidget { _UpdateDownloadDialogState(); } -class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> - with SingleTickerProviderStateMixin { - late final AnimationController _spinCtrl; - +class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> { _DownloadState _state = _DownloadState.idle; double _progress = 0.0; int _received = 0; @@ -49,19 +46,9 @@ class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> @override void initState() { super.initState(); - _spinCtrl = AnimationController( - vsync: this, - duration: const Duration(seconds: 3), - )..repeat(); _startDownload(); } - @override - void dispose() { - _spinCtrl.dispose(); - super.dispose(); - } - // ─── Download ─────────────────────────────────────────────────────────────── Future _startDownload() async { @@ -127,6 +114,22 @@ class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> .invokeMethod('installApk', {'path': file.path}); if (mounted) setState(() => _state = _DownloadState.done); } + } on PlatformException catch (e) { + if (e.code == 'PERMISSION_REQUIRED') { + if (mounted) { + setState(() { + _state = _DownloadState.error; + _errorMsg = 'Bitte "Unbekannte Apps installieren" für Pyramid erlauben (Einstellungen geöffnet) — dann erneut versuchen.'; + }); + } + } else { + if (mounted) { + setState(() { + _state = _DownloadState.error; + _errorMsg = e.message ?? e.toString(); + }); + } + } } catch (e) { if (mounted) { setState(() { @@ -170,21 +173,24 @@ class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> child: Column( mainAxisSize: MainAxisSize.min, children: [ - // ── Animated Pyramid ── - _AnimatedPyramid(ctrl: _spinCtrl, pt: pt), + // ── Loading animation ── + const PyramidLoader(size: 72), const SizedBox(height: 24), - // ── Title ── - Text( - _titleText(), - style: TextStyle( - color: pt.fg, - fontSize: 16, - fontWeight: FontWeight.w700, + // ── Title (hidden while actively downloading) ── + if (_state != _DownloadState.downloading && + _state != _DownloadState.installing) ...[ + Text( + _titleText(), + style: TextStyle( + color: pt.fg, + fontSize: 16, + fontWeight: FontWeight.w700, + ), + textAlign: TextAlign.center, ), - textAlign: TextAlign.center, - ), - const SizedBox(height: 6), + const SizedBox(height: 6), + ], Text( widget.info.tagName, style: TextStyle(color: pt.accent, fontSize: 13), @@ -285,28 +291,6 @@ class _UpdateDownloadDialogState extends ConsumerState<_UpdateDownloadDialog> } } -// ─── Animated pyramid ───────────────────────────────────────────────────────── - -class _AnimatedPyramid extends StatelessWidget { - final AnimationController ctrl; - final PyramidTheme pt; - const _AnimatedPyramid({required this.ctrl, required this.pt}); - - @override - Widget build(BuildContext context) { - return AnimatedBuilder( - animation: ctrl, - builder: (context, _) { - final pulse = 0.9 + 0.1 * (0.5 - (ctrl.value - 0.5).abs()) * 2; - return Transform.scale( - scale: pulse, - child: PyramidLogo(size: 72, color: pt.accent), - ); - }, - ); - } -} - // ─── Progress bar ───────────────────────────────────────────────────────────── class _ProgressBar extends StatelessWidget { diff --git a/linux/flutter/generated_plugin_registrant.cc b/linux/flutter/generated_plugin_registrant.cc index aa44afe..331f998 100644 --- a/linux/flutter/generated_plugin_registrant.cc +++ b/linux/flutter/generated_plugin_registrant.cc @@ -6,16 +6,21 @@ #include "generated_plugin_registrant.h" -#include +#include #include #include #include +#include +#include +#include #include +#include +#include void fl_register_plugins(FlPluginRegistry* registry) { - g_autoptr(FlPluginRegistrar) dynamic_color_registrar = - fl_plugin_registry_get_registrar_for_plugin(registry, "DynamicColorPlugin"); - dynamic_color_plugin_register_with_registrar(dynamic_color_registrar); + g_autoptr(FlPluginRegistrar) desktop_drop_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "DesktopDropPlugin"); + desktop_drop_plugin_register_with_registrar(desktop_drop_registrar); g_autoptr(FlPluginRegistrar) flutter_secure_storage_linux_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "FlutterSecureStorageLinuxPlugin"); flutter_secure_storage_linux_plugin_register_with_registrar(flutter_secure_storage_linux_registrar); @@ -25,7 +30,22 @@ void fl_register_plugins(FlPluginRegistry* registry) { g_autoptr(FlPluginRegistrar) livekit_client_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "LiveKitPlugin"); live_kit_plugin_register_with_registrar(livekit_client_registrar); + g_autoptr(FlPluginRegistrar) local_notifier_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "LocalNotifierPlugin"); + local_notifier_plugin_register_with_registrar(local_notifier_registrar); + g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin"); + media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar); + g_autoptr(FlPluginRegistrar) media_kit_video_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitVideoPlugin"); + media_kit_video_plugin_register_with_registrar(media_kit_video_registrar); g_autoptr(FlPluginRegistrar) sqlcipher_flutter_libs_registrar = fl_plugin_registry_get_registrar_for_plugin(registry, "Sqlite3FlutterLibsPlugin"); sqlite3_flutter_libs_plugin_register_with_registrar(sqlcipher_flutter_libs_registrar); + g_autoptr(FlPluginRegistrar) url_launcher_linux_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "UrlLauncherPlugin"); + url_launcher_plugin_register_with_registrar(url_launcher_linux_registrar); + g_autoptr(FlPluginRegistrar) volume_controller_registrar = + fl_plugin_registry_get_registrar_for_plugin(registry, "VolumeControllerPlugin"); + volume_controller_plugin_register_with_registrar(volume_controller_registrar); } diff --git a/linux/flutter/generated_plugins.cmake b/linux/flutter/generated_plugins.cmake index 3c8cc63..e837b37 100644 --- a/linux/flutter/generated_plugins.cmake +++ b/linux/flutter/generated_plugins.cmake @@ -3,11 +3,16 @@ # list(APPEND FLUTTER_PLUGIN_LIST - dynamic_color + desktop_drop flutter_secure_storage_linux flutter_webrtc livekit_client + local_notifier + media_kit_libs_linux + media_kit_video sqlcipher_flutter_libs + url_launcher_linux + volume_controller ) list(APPEND FLUTTER_FFI_PLUGIN_LIST diff --git a/loader icon/pyramid-loader.json b/loader icon/pyramid-loader.json new file mode 100644 index 0000000..e56fd73 --- /dev/null +++ b/loader icon/pyramid-loader.json @@ -0,0 +1 @@ +{"v":"5.7.4","fr":60,"ip":0,"op":120,"w":200,"h":200,"nm":"PyramidLoader","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"face_0_slot_3","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[100],"h":1},{"t":2,"s":[100],"h":1},{"t":3,"s":[100],"h":1},{"t":4,"s":[100],"h":1},{"t":5,"s":[100],"h":1},{"t":6,"s":[100],"h":1},{"t":7,"s":[100],"h":1},{"t":8,"s":[100],"h":1},{"t":9,"s":[100],"h":1},{"t":10,"s":[100],"h":1},{"t":11,"s":[100],"h":1},{"t":12,"s":[100],"h":1},{"t":13,"s":[100],"h":1},{"t":14,"s":[100],"h":1},{"t":15,"s":[100],"h":1},{"t":16,"s":[100],"h":1},{"t":17,"s":[100],"h":1},{"t":18,"s":[100],"h":1},{"t":19,"s":[100],"h":1},{"t":20,"s":[100],"h":1},{"t":21,"s":[100],"h":1},{"t":22,"s":[100],"h":1},{"t":23,"s":[100],"h":1},{"t":24,"s":[100],"h":1},{"t":25,"s":[100],"h":1},{"t":26,"s":[100],"h":1},{"t":27,"s":[100],"h":1},{"t":28,"s":[100],"h":1},{"t":29,"s":[100],"h":1},{"t":30,"s":[100],"h":1},{"t":31,"s":[100],"h":1},{"t":32,"s":[100],"h":1},{"t":33,"s":[100],"h":1},{"t":34,"s":[100],"h":1},{"t":35,"s":[100],"h":1},{"t":36,"s":[100],"h":1},{"t":37,"s":[100],"h":1},{"t":38,"s":[100],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014843,171.41663917972903],[25.254606555010795,168.4823104778698]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331856,171.41663917972903],[27.051928158630545,165.11883425295738]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.280660659196656,171.41663917972903],[30.329202572241016,161.70386936171468]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513414,171.41663917972903],[35.23167595892863,158.32327808225233]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.545421763770435,171.41663917972903],[41.867430278900926,155.08151817465492]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112144,171.41663917972903],[50.290594742135035,152.10096254861588]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[60.48276971388455,149.51968659541475]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.021711443009764,171.41663917972903],[72.33361100630755,147.4873228087879]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530236,171.41663917972903],[85.62202576908322,146.15861054812373]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.76383848175135,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.15046474746714,166.49908237253814],[114.37797423091669,146.15861054812373],[114.37797423091669,146.15861054812373]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.035359501747664,161.95417685080264],[127.6663889936925,147.4873228087879],[127.6663889936925,147.4873228087879]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.97759368381941,157.9009504134384],[139.51723028611542,149.51968659541475],[139.51723028611542,149.51968659541475]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.524739673823944,154.41502126880033],[149.7094052578649,152.10096254861585],[149.7094052578649,152.10096254861585]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[52.23930132816764,151.53412935182934],[158.13256972109895,155.08151817465486],[158.13256972109895,155.08151817465486]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[61.71757321027329,149.26456770823847],[164.7683240410713,158.3232780822523],[164.7683240410713,158.3232780822523]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.60176086831838,147.5878230578733],[169.67079742775897,161.70386936171468],[169.67079742775897,161.70386936171468]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.58645024373618,146.4669291932127],[172.94807184136943,165.11883425295736],[172.94807184136943,165.11883425295736]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.42059682997896,145.85220900074034],[174.7453934449892,168.48231047786976],[174.7453934449892,168.48231047786976]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.9061668000921,145.6862229301544],[174.3461075040085,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[109.89444817484419,145.9078517026294],[167.00604580866076,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.28089606093508,146.4555207003181],[162.02428061713266,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.9992085169768,147.26962670455904],[158.59688923713986,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[133.01516676125698,148.29425928080326],[156.25574276290297,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.32062633606557,149.47832409788663],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[144.9279202573607,150.77617838683688],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.86483302362365,152.14788350454043],[153.29873006042072,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[154.1702249825266,153.55916933063904],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[157.89032775993167,154.98119240867067],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[161.07569026230578,156.39015609296857],[153.90410328496438,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[163.7787279457848,157.7668476672345],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[166.05181248302944,159.09613519733574],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.94583184319973,160.36645616899267],[156.46115967472622,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.5091497314232,161.56932089599852],[157.58326505555533,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.78689635032543,162.6988462564911],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[171.8205280053716,163.75132940997366],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.64760001130034,164.72486659520752],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.30170482167705,165.61901871326904],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.81253471130574,166.43452296328823],[164.04759992204185,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.20603531105112,167.17304813479808],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.50462260185213,167.836990104014],[166.61675437660261,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.72744150919286,168.42930348868117],[167.821185092542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.89064897156487,168.95336516806938],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.00770831106672,169.4128653744158],[169.99796493107303,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.08968496955248,169.81172223294573],[170.9492051502293,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.14553626674518,170.1540159102598],[171.7996075308126,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.18238987263604,170.44393888058158],[172.5457254570127,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.20580725120632,170.6857592030873],[173.18694334757177,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2200295079158,170.88379409754347],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.22820393443305,171.04239149313332],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23259015718264,171.16591759537795],[174.5136772126083,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2347452187699,171.25874886104174],[174.7787355115039,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23568720142907,171.32526708618758],[174.97042363235644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2360371788439,171.36985659529591],[175.0997505080749,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23613938850093,171.3969027679839],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2361595754449,171.41079135350373],[175.21906944484536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616148789233,171.41590820144467],[175.23402437178987,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"face_1_slot_3","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[100],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[100],"h":1},{"t":59,"s":[100],"h":1},{"t":60,"s":[100],"h":1},{"t":61,"s":[100],"h":1},{"t":62,"s":[100],"h":1},{"t":63,"s":[100],"h":1},{"t":64,"s":[100],"h":1},{"t":65,"s":[100],"h":1},{"t":66,"s":[100],"h":1},{"t":67,"s":[100],"h":1},{"t":68,"s":[100],"h":1},{"t":69,"s":[100],"h":1},{"t":70,"s":[100],"h":1},{"t":71,"s":[100],"h":1},{"t":72,"s":[100],"h":1},{"t":73,"s":[100],"h":1},{"t":74,"s":[100],"h":1},{"t":75,"s":[100],"h":1},{"t":76,"s":[100],"h":1},{"t":77,"s":[100],"h":1},{"t":78,"s":[100],"h":1},{"t":79,"s":[100],"h":1},{"t":80,"s":[100],"h":1},{"t":81,"s":[100],"h":1},{"t":82,"s":[100],"h":1},{"t":83,"s":[100],"h":1},{"t":84,"s":[100],"h":1},{"t":85,"s":[100],"h":1},{"t":86,"s":[100],"h":1},{"t":87,"s":[100],"h":1},{"t":88,"s":[100],"h":1},{"t":89,"s":[100],"h":1},{"t":90,"s":[100],"h":1},{"t":91,"s":[100],"h":1},{"t":92,"s":[100],"h":1},{"t":93,"s":[100],"h":1},{"t":94,"s":[100],"h":1},{"t":95,"s":[100],"h":1},{"t":96,"s":[100],"h":1},{"t":97,"s":[100],"h":1},{"t":98,"s":[100],"h":1},{"t":99,"s":[100],"h":1},{"t":100,"s":[100],"h":1},{"t":101,"s":[100],"h":1},{"t":102,"s":[100],"h":1},{"t":103,"s":[100],"h":1},{"t":104,"s":[100],"h":1},{"t":105,"s":[100],"h":1},{"t":106,"s":[100],"h":1},{"t":107,"s":[100],"h":1},{"t":108,"s":[100],"h":1},{"t":109,"s":[100],"h":1},{"t":110,"s":[100],"h":1},{"t":111,"s":[100],"h":1},{"t":112,"s":[100],"h":1},{"t":113,"s":[100],"h":1},{"t":114,"s":[100],"h":1},{"t":115,"s":[100],"h":1},{"t":116,"s":[100],"h":1},{"t":117,"s":[100],"h":1},{"t":118,"s":[100],"h":1},{"t":119,"s":[100],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.7659756282101,171.41663917972903],[24.763838512107654,171.4159082014447]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515457,171.41663917972903],[24.76384042455507,171.41079135350375]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[24.763860611499055,171.3969027679839]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192508,171.41663917972903],[24.7639628211561,171.36985659529594]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.02957636764353,171.41663917972903],[24.76431279857094,171.32526708618758]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496132,171.41663917972903],[24.765254781230098,171.25874886104174]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391742,171.41663917972903],[24.767409842817358,171.16591759537795]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087367,171.41663917972903],[24.771796065566974,171.04239149313335]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.27467983390227,171.41663917972903],[24.779970492084203,170.8837940975435]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.813056652428145,171.41663917972903],[24.794192748793662,170.68575920308734]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987264,171.41663917972903],[24.817610127363963,170.44393888058158]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187406,171.41663917972903],[24.854463733254804,170.1540159102598]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.050794849770682,171.41663917972903],[24.910315030447507,169.81172223294573]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926943,171.41663917972903],[24.992291688933264,169.41286537441582]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[25.109351028435142,168.95336516806938]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.17881490745795,171.41663917972903],[25.272558490807143,168.42930348868117]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339733,171.41663917972903],[25.495377398147852,167.83699010401403]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[25.793964688948876,167.17304813479808]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795812,171.41663917972903],[26.18746528869424,166.43452296328823]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312886,171.41663917972903],[26.698295178322923,165.61901871326907]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[27.352399988699673,164.72486659520754]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[28.179471994628386,163.75132940997366]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.20571106244855,171.41663917972903],[29.213103649674565,162.69884625649112]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444464,171.41663917972903],[30.49085026857678,161.56932089599854]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527375,171.41663917972903],[32.054168156800245,160.36645616899273]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009054,171.41663917972903],[33.948187516970535,159.09613519733577]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.4085587911411,171.41663917972903],[36.22127205421518,157.76684766723452]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.0958967150356,171.41663917972903],[38.92430973769417,156.39015609296857]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[42.10967224006833,154.9811924086707]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[45.82977501747337,153.55916933063907]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.701269939579305,171.41663917972903],[50.13516697637628,152.14788350454046]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[55.07207974263926,150.77617838683688]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042787,171.41663917972903],[60.67937366393438,149.47832409788663]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709705,171.41663917972903],[66.984833238743,148.29425928080326]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.40311076286019,171.41663917972903],[74.00079148302312,147.26962670455904]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.97571938286738,171.41663917972903],[81.71910393906488,146.4555207003181]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.99395419133931,171.41663917972903],[90.10555182515573,145.9078517026294]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.65389249599157,171.41663917972903],[99.09383319990782,145.6862229301544]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.254606555010795,168.4823104778698],[108.5794031700209,145.85220900074034],[108.5794031700209,145.85220900074034]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.051928158630545,165.11883425295738],[118.41354975626373,146.46692919321268],[118.41354975626373,146.46692919321268]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.329202572241016,161.70386936171468],[128.3982391316816,147.58782305787327],[128.3982391316816,147.58782305787327]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.23167595892863,158.32327808225233],[138.2824267897266,149.26456770823847],[138.2824267897266,149.26456770823847]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[41.867430278900926,155.08151817465492],[147.76069867183222,151.5341293518293],[147.76069867183222,151.5341293518293]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.290594742135035,152.10096254861588],[156.47526032617597,154.4150212688003],[156.47526032617597,154.4150212688003]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.48276971388455,149.51968659541475],[164.0224063161806,157.90095041343838],[164.0224063161806,157.90095041343838]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[72.33361100630755,147.4873228087879],[169.96464049825235,161.95417685080264],[169.96464049825235,161.95417685080264]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.62202576908322,146.15861054812373],[173.84953525253286,166.4990823725381],[173.84953525253286,166.4990823725381]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.37797423091669,146.15861054812373],[164.15776704046982,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[127.6663889936925,147.4873228087879],[157.9782885569902,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.51723028611542,149.51968659541475],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.7094052578649,152.10096254861585],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[158.13256972109895,155.08151817465486],[153.45457823622954,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.7683240410713,158.3232780822523],[154.92905150486584,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.67079742775897,161.70386936171468],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.94807184136943,165.11883425295736],[161.9568687706681,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.7453934449892,168.48231047786976],[167.93271906985146,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"face_2_slot_3","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[100],"h":1},{"t":50,"s":[100],"h":1},{"t":51,"s":[100],"h":1},{"t":52,"s":[100],"h":1},{"t":53,"s":[100],"h":1},{"t":54,"s":[100],"h":1},{"t":55,"s":[100],"h":1},{"t":56,"s":[100],"h":1},{"t":57,"s":[100],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838512107654,171.4159082014447],[100.00213723752422,145.68435644436695],[100.00213723752422,145.68435644436695]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76384042455507,171.41079135350375],[100.01709790004887,145.68435709846247],[100.01709790004887,145.68435709846247]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763860611499055,171.3969027679839],[100.05770540750385,145.68436400280396],[100.05770540750385,145.68436400280396]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.7639628211561,171.36985659529594],[100.1367831262165,145.68439896056552],[100.1367831262165,145.68439896056552]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76431279857094,171.32526708618758],[100.26715412914858,145.6845186598911],[100.26715412914858,145.6845186598911]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.765254781230098,171.25874886104174],[100.46164040852113,145.68484083693517],[100.46164040852113,145.68484083693517]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.767409842817358,171.16591759537795],[100.73306087154158,145.68557791140813],[100.73306087154158,145.68557791140813]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.771796065566974,171.04239149313335],[101.09422703281935,145.68707808794161],[101.09422703281935,145.68707808794161]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.779970492084203,170.8837940975435],[101.55793479589938,145.68987390647064],[101.55793479589938,145.68987390647064]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.794192748793662,170.68575920308734],[102.13695009169614,145.69473820474883],[102.13695009169614,145.69473820474883]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.817610127363963,170.44393888058158],[102.84398541468727,145.70274741992375],[102.84398541468727,145.70274741992375]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.854463733254804,170.1540159102598],[103.69166347102245,145.71535209549262],[103.69166347102245,145.71535209549262]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.910315030447507,169.81172223294573],[104.69246323090135,145.73445436416338],[104.69246323090135,145.73445436416338]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.992291688933264,169.41286537441582],[105.85864266890633,145.76249203264803],[105.85864266890633,145.76249203264803]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.109351028435142,168.95336516806938],[107.20213139409789,145.8025286847221],[107.20213139409789,145.8025286847221]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.272558490807143,168.42930348868117],[108.73438523824998,145.85834892439436],[108.73438523824998,145.85834892439436]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.495377398147852,167.83699010401403],[110.46619371861527,145.9345574790187],[110.46619371861527,145.9345574790187]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.793964688948876,167.17304813479808],[112.40743016966178,146.03668034701371],[112.40743016966178,146.03668034701371]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.18746528869424,166.43452296328823],[114.56673331575352,146.17126547853735],[114.56673331575352,146.17126547853735]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.698295178322923,165.61901871326907],[116.9511082303112,146.34597959060318],[116.9511082303112,146.34597959060318]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.352399988699673,164.72486659520754],[119.56543412751468,146.56969661159826],[119.56543412751468,146.56969661159826]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[28.179471994628386,163.75132940997366],[122.41186643342385,146.85257189760665],[122.41186643342385,146.85257189760665]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.213103649674565,162.69884625649112],[125.48912130867366,147.20609474441147],[125.48912130867366,147.20609474441147]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.49085026857678,161.56932089599854],[128.79163252777767,147.6431098261423],[128.79163252777767,147.6431098261423]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.054168156800245,160.36645616899273],[132.30857370939827,148.17779603433607],[132.30857370939827,148.17779603433607]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[33.948187516970535,159.09613519733577],[136.02274375594828,148.82558880736312],[136.02274375594828,148.82558880736312]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[36.22127205421518,157.76684766723452],[139.9093204855403,149.60302950658289],[139.9093204855403,149.60302950658289]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[38.92430973769417,156.39015609296857],[143.93449736804646,150.52752284250107],[143.93449736804646,150.52752284250107]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[42.10967224006833,154.9811924086707],[148.05403158786663,151.61698098210726],[148.05403158786663,151.61698098210726]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[45.82977501747337,153.55916933063907],[152.21174892054898,152.88933106722158],[152.21174892054898,152.88933106722158]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.13516697637628,152.14788350454046],[156.33807262878386,154.36186184207872],[156.33807262878386,154.36186184207872]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[55.07207974263926,150.77617838683688],[160.34867008765178,156.0503854539823],[160.34867008765178,156.0503854539823]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.67937366393438,149.47832409788663],[164.14334216845504,157.96819292461282],[164.14334216845504,157.96819292461282]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[66.984833238743,148.29425928080326],[167.60531609072166,160.12478711212304],[167.60531609072166,160.12478711212304]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.00079148302312,147.26962670455904],[170.60114132569498,162.52438615639866],[170.60114132569498,162.52438615639866]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.71910393906488,146.4555207003181],[172.98142804309384,165.16420448884634],[172.98142804309384,165.16420448884634]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[90.10555182515573,145.9078517026294],[174.58270506836902,168.0325385968404],[174.58270506836902,168.0325385968404]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.09383319990782,145.6862229301544],[175.2307042485341,171.10671188088455],[175.2307042485341,171.10671188088455]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.5794031700209,145.85220900074034],[167.93271906985157,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.41354975626373,146.46692919321268],[161.95686877066814,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.3982391316816,147.58782305787327],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[138.2824267897266,149.26456770823847],[154.92905150486587,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[147.76069867183222,151.5341293518293],[153.45457823622957,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.47526032617597,154.4150212688003],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.0224063161806,157.90095041343838],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.96464049825235,161.95417685080264],[157.97828855699024,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.84953525253286,166.4990823725381],[164.15776704046976,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.653892495991485,171.41663917972903],[24.76929575146589,171.10671188088457]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.993954191339256,171.41663917972903],[25.417294931630963,168.03253859684042]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.975719382867354,171.41663917972903],[27.01857195690613,165.16420448884637]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.403110762860145,171.41663917972903],[29.398858674304975,162.5243861563987]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709703,171.41663917972903],[32.394683909278314,160.12478711212307]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042786,171.41663917972903],[35.856657831544936,157.96819292461282]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[39.65132991234821,156.0503854539823]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.70126993957929,171.41663917972903],[43.661927371216095,154.36186184207872]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[47.78825107945101,152.88933106722158]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[51.94596841213336,151.61698098210726]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.095896715035614,171.41663917972903],[56.06550263195349,150.52752284250107]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.40855879114112,171.41663917972903],[60.09067951445965,149.6030295065829]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009055,171.41663917972903],[63.97725624405165,148.82558880736312]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527377,171.41663917972903],[67.69142629060164,148.1777960343361]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444467,171.41663917972903],[71.20836747222228,147.6431098261423]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.205711062448565,171.41663917972903],[74.5108786913263,147.20609474441147]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[77.58813356657613,146.85257189760665]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[80.43456587248531,146.56969661159826]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312914,171.41663917972903],[83.04889176968875,146.34597959060318]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795813,171.41663917972903],[85.43326668424646,146.17126547853735]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[87.59256983033822,146.03668034701371]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339737,171.41663917972903],[89.53380628138467,145.9345574790187]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.178814907457976,171.41663917972903],[91.26561476174996,145.85834892439436]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[92.79786860590211,145.8025286847221]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926972,171.41663917972903],[94.14135733109363,145.76249203264803]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.05079484977071,171.41663917972903],[95.30753676909862,145.73445436416338]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187392,171.41663917972903],[96.30833652897755,145.71535209549262]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987292,171.41663917972903],[97.1560145853127,145.70274741992375]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.81305665242823,171.41663917972903],[97.8630499083038,145.69473820474883]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.274679833902283,171.41663917972903],[98.44206520410059,145.68987390647064]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087395,171.41663917972903],[98.9057729671806,145.68707808794161]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391714,171.41663917972903],[99.26693912845845,145.68557791140813]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496118,171.41663917972903],[99.53835959147887,145.68484083693517]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.029576367643557,171.41663917972903],[99.7328458708514,145.6845186598911]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192511,171.41663917972903],[99.86321687378347,145.68439896056552]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[99.94229459249615,145.68436400280396]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515464,171.41663917972903],[99.98290209995109,145.6843570984625]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.765975628210114,171.41663917972903],[99.99786276247576,145.68435644436695]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751364,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"face_3_slot_3","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[100],"h":1},{"t":40,"s":[100],"h":1},{"t":41,"s":[100],"h":1},{"t":42,"s":[100],"h":1},{"t":43,"s":[100],"h":1},{"t":44,"s":[100],"h":1},{"t":45,"s":[100],"h":1},{"t":46,"s":[100],"h":1},{"t":47,"s":[100],"h":1},{"t":48,"s":[100],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.00213723752422,145.68435644436695],[175.2340243717899,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.01709790004887,145.68435709846247],[175.21906944484545,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.05770540750385,145.68436400280396],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.1367831262165,145.68439896056552],[175.09975050807492,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.26715412914858,145.6845186598911],[174.97042363235647,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.46164040852113,145.68484083693517],[174.77873551150387,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.73306087154158,145.68557791140813],[174.51367721260826,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.09422703281935,145.68707808794161],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.55793479589938,145.68987390647064],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.13695009169614,145.69473820474883],[173.18694334757186,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.84398541468727,145.70274741992375],[172.54572545701274,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[103.69166347102245,145.71535209549262],[171.79960753081258,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[104.69246323090135,145.73445436416338],[170.94920515022932,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[105.85864266890633,145.76249203264803],[169.99796493107306,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[107.20213139409789,145.8025286847221],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.73438523824998,145.85834892439436],[167.82118509254207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[110.46619371861527,145.9345574790187],[166.61675437660267,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[112.40743016966178,146.03668034701371],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.56673331575352,146.17126547853735],[164.04759992204188,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[116.9511082303112,146.34597959060318],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[119.56543412751468,146.56969661159826],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[122.41186643342385,146.85257189760665],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.48912130867366,147.20609474441147],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.79163252777767,147.6431098261423],[157.58326505555536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[132.30857370939827,148.17779603433607],[156.46115967472625,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[136.02274375594828,148.82558880736312],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.9093204855403,149.60302950658289],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[143.93449736804646,150.52752284250107],[153.9041032849644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[148.05403158786663,151.61698098210726],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[152.21174892054898,152.88933106722158],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.33807262878386,154.36186184207872],[153.2987300604207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[160.34867008765178,156.0503854539823],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.14334216845504,157.96819292461282],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.60531609072166,160.12478711212304],[156.25574276290294,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.60114132569498,162.52438615639866],[158.5968892371398,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.98142804309384,165.16420448884634],[162.0242806171326,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.58270506836902,168.0325385968404],[167.0060458086607,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2307042485341,171.10671188088455],[174.34610750400844,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530165,171.41663917972903],[26.15046474746714,166.49908237253814]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.02171144300978,171.41663917972903],[30.035359501747664,161.95417685080264]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[35.97759368381941,157.9009504134384]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112142,171.41663917972903],[43.524739673823944,154.41502126880033]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.54542176377046,171.41663917972903],[52.23930132816764,151.53412935182934]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513416,171.41663917972903],[61.71757321027329,149.26456770823847]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.28066065919667,171.41663917972903],[71.60176086831838,147.5878230578733]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331905,171.41663917972903],[81.58645024373618,146.4669291932127]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014854,171.41663917972903],[91.42059682997896,145.85220900074034]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76929575146589,171.10671188088457],[100.9061668000921,145.6862229301544],[100.9061668000921,145.6862229301544]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.417294931630963,168.03253859684042],[109.89444817484419,145.9078517026294],[109.89444817484419,145.9078517026294]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.01857195690613,165.16420448884637],[118.28089606093508,146.4555207003181],[118.28089606093508,146.4555207003181]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.398858674304975,162.5243861563987],[125.9992085169768,147.26962670455904],[125.9992085169768,147.26962670455904]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.394683909278314,160.12478711212307],[133.01516676125698,148.29425928080326],[133.01516676125698,148.29425928080326]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.856657831544936,157.96819292461282],[139.32062633606557,149.47832409788663],[139.32062633606557,149.47832409788663]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[39.65132991234821,156.0503854539823],[144.9279202573607,150.77617838683688],[144.9279202573607,150.77617838683688]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.661927371216095,154.36186184207872],[149.86483302362365,152.14788350454043],[149.86483302362365,152.14788350454043]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[47.78825107945101,152.88933106722158],[154.1702249825266,153.55916933063904],[154.1702249825266,153.55916933063904]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[51.94596841213336,151.61698098210726],[157.89032775993167,154.98119240867067],[157.89032775993167,154.98119240867067]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[56.06550263195349,150.52752284250107],[161.07569026230578,156.39015609296857],[161.07569026230578,156.39015609296857]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.09067951445965,149.6030295065829],[163.7787279457848,157.7668476672345],[163.7787279457848,157.7668476672345]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[63.97725624405165,148.82558880736312],[166.05181248302944,159.09613519733574],[166.05181248302944,159.09613519733574]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[67.69142629060164,148.1777960343361],[167.94583184319973,160.36645616899267],[167.94583184319973,160.36645616899267]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.20836747222228,147.6431098261423],[169.5091497314232,161.56932089599852],[169.5091497314232,161.56932089599852]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.5108786913263,147.20609474441147],[170.78689635032543,162.6988462564911],[170.78689635032543,162.6988462564911]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[77.58813356657613,146.85257189760665],[171.8205280053716,163.75132940997366],[171.8205280053716,163.75132940997366]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[80.43456587248531,146.56969661159826],[172.64760001130034,164.72486659520752],[172.64760001130034,164.72486659520752]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[83.04889176968875,146.34597959060318],[173.30170482167705,165.61901871326904],[173.30170482167705,165.61901871326904]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.43326668424646,146.17126547853735],[173.81253471130574,166.43452296328823],[173.81253471130574,166.43452296328823]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[87.59256983033822,146.03668034701371],[174.20603531105112,167.17304813479808],[174.20603531105112,167.17304813479808]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[89.53380628138467,145.9345574790187],[174.50462260185213,167.836990104014],[174.50462260185213,167.836990104014]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.26561476174996,145.85834892439436],[174.72744150919286,168.42930348868117],[174.72744150919286,168.42930348868117]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[92.79786860590211,145.8025286847221],[174.89064897156487,168.95336516806938],[174.89064897156487,168.95336516806938]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[94.14135733109363,145.76249203264803],[175.00770831106672,169.4128653744158],[175.00770831106672,169.4128653744158]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[95.30753676909862,145.73445436416338],[175.08968496955248,169.81172223294573],[175.08968496955248,169.81172223294573]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[96.30833652897755,145.71535209549262],[175.14553626674518,170.1540159102598],[175.14553626674518,170.1540159102598]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.1560145853127,145.70274741992375],[175.18238987263604,170.44393888058158],[175.18238987263604,170.44393888058158]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.8630499083038,145.69473820474883],[175.20580725120632,170.6857592030873],[175.20580725120632,170.6857592030873]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.44206520410059,145.68987390647064],[175.2200295079158,170.88379409754347],[175.2200295079158,170.88379409754347]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.9057729671806,145.68707808794161],[175.22820393443305,171.04239149313332],[175.22820393443305,171.04239149313332]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.26693912845845,145.68557791140813],[175.23259015718264,171.16591759537795],[175.23259015718264,171.16591759537795]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.53835959147887,145.68484083693517],[175.2347452187699,171.25874886104174],[175.2347452187699,171.25874886104174]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.7328458708514,145.6845186598911],[175.23568720142907,171.32526708618758],[175.23568720142907,171.32526708618758]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.86321687378347,145.68439896056552],[175.2360371788439,171.36985659529591],[175.2360371788439,171.36985659529591]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.94229459249615,145.68436400280396],[175.23613938850093,171.3969027679839],[175.23613938850093,171.3969027679839]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.98290209995109,145.6843570984625],[175.2361595754449,171.41079135350373],[175.2361595754449,171.41079135350373]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99786276247576,145.68435644436695],[175.23616148789233,171.41590820144467],[175.23616148789233,171.41590820144467]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":5,"ty":4,"nm":"face_0_slot_2","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[100],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[100],"h":1},{"t":40,"s":[100],"h":1},{"t":41,"s":[100],"h":1},{"t":42,"s":[100],"h":1},{"t":43,"s":[100],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[100],"h":1},{"t":67,"s":[100],"h":1},{"t":68,"s":[100],"h":1},{"t":69,"s":[100],"h":1},{"t":70,"s":[100],"h":1},{"t":71,"s":[100],"h":1},{"t":72,"s":[100],"h":1},{"t":73,"s":[100],"h":1},{"t":74,"s":[100],"h":1},{"t":75,"s":[100],"h":1},{"t":76,"s":[100],"h":1},{"t":77,"s":[100],"h":1},{"t":78,"s":[100],"h":1},{"t":79,"s":[100],"h":1},{"t":80,"s":[100],"h":1},{"t":81,"s":[100],"h":1},{"t":82,"s":[100],"h":1},{"t":83,"s":[100],"h":1},{"t":84,"s":[100],"h":1},{"t":85,"s":[100],"h":1},{"t":86,"s":[100],"h":1},{"t":87,"s":[100],"h":1},{"t":88,"s":[100],"h":1},{"t":89,"s":[100],"h":1},{"t":90,"s":[100],"h":1},{"t":91,"s":[100],"h":1},{"t":92,"s":[100],"h":1},{"t":93,"s":[100],"h":1},{"t":94,"s":[100],"h":1},{"t":95,"s":[100],"h":1},{"t":96,"s":[100],"h":1},{"t":97,"s":[100],"h":1},{"t":98,"s":[100],"h":1},{"t":99,"s":[100],"h":1},{"t":100,"s":[100],"h":1},{"t":101,"s":[100],"h":1},{"t":102,"s":[100],"h":1},{"t":103,"s":[100],"h":1},{"t":104,"s":[100],"h":1},{"t":105,"s":[100],"h":1},{"t":106,"s":[100],"h":1},{"t":107,"s":[100],"h":1},{"t":108,"s":[100],"h":1},{"t":109,"s":[100],"h":1},{"t":110,"s":[100],"h":1},{"t":111,"s":[100],"h":1},{"t":112,"s":[100],"h":1},{"t":113,"s":[100],"h":1},{"t":114,"s":[100],"h":1},{"t":115,"s":[100],"h":1},{"t":116,"s":[100],"h":1},{"t":117,"s":[100],"h":1},{"t":118,"s":[100],"h":1},{"t":119,"s":[100],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014843,171.41663917972903],[25.254606555010795,168.4823104778698]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331856,171.41663917972903],[27.051928158630545,165.11883425295738]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.280660659196656,171.41663917972903],[30.329202572241016,161.70386936171468]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513414,171.41663917972903],[35.23167595892863,158.32327808225233]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.545421763770435,171.41663917972903],[41.867430278900926,155.08151817465492]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112144,171.41663917972903],[50.290594742135035,152.10096254861588]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[60.48276971388455,149.51968659541475]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.021711443009764,171.41663917972903],[72.33361100630755,147.4873228087879]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530236,171.41663917972903],[85.62202576908322,146.15861054812373]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.76383848175135,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.15046474746714,166.49908237253814],[114.37797423091669,146.15861054812373],[114.37797423091669,146.15861054812373]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.035359501747664,161.95417685080264],[127.6663889936925,147.4873228087879],[127.6663889936925,147.4873228087879]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.97759368381941,157.9009504134384],[139.51723028611542,149.51968659541475],[139.51723028611542,149.51968659541475]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.524739673823944,154.41502126880033],[149.7094052578649,152.10096254861585],[149.7094052578649,152.10096254861585]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[52.23930132816764,151.53412935182934],[158.13256972109895,155.08151817465486],[158.13256972109895,155.08151817465486]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[61.71757321027329,149.26456770823847],[164.7683240410713,158.3232780822523],[164.7683240410713,158.3232780822523]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.60176086831838,147.5878230578733],[169.67079742775897,161.70386936171468],[169.67079742775897,161.70386936171468]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.58645024373618,146.4669291932127],[172.94807184136943,165.11883425295736],[172.94807184136943,165.11883425295736]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.42059682997896,145.85220900074034],[174.7453934449892,168.48231047786976],[174.7453934449892,168.48231047786976]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.9061668000921,145.6862229301544],[174.3461075040085,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[109.89444817484419,145.9078517026294],[167.00604580866076,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.28089606093508,146.4555207003181],[162.02428061713266,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.9992085169768,147.26962670455904],[158.59688923713986,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[133.01516676125698,148.29425928080326],[156.25574276290297,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.32062633606557,149.47832409788663],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[144.9279202573607,150.77617838683688],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.86483302362365,152.14788350454043],[153.29873006042072,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[154.1702249825266,153.55916933063904],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[157.89032775993167,154.98119240867067],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[161.07569026230578,156.39015609296857],[153.90410328496438,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[163.7787279457848,157.7668476672345],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[166.05181248302944,159.09613519733574],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.94583184319973,160.36645616899267],[156.46115967472622,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.5091497314232,161.56932089599852],[157.58326505555533,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.78689635032543,162.6988462564911],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[171.8205280053716,163.75132940997366],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.64760001130034,164.72486659520752],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.30170482167705,165.61901871326904],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.81253471130574,166.43452296328823],[164.04759992204185,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.20603531105112,167.17304813479808],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.50462260185213,167.836990104014],[166.61675437660261,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.72744150919286,168.42930348868117],[167.821185092542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.89064897156487,168.95336516806938],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.00770831106672,169.4128653744158],[169.99796493107303,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.08968496955248,169.81172223294573],[170.9492051502293,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.14553626674518,170.1540159102598],[171.7996075308126,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.18238987263604,170.44393888058158],[172.5457254570127,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.20580725120632,170.6857592030873],[173.18694334757177,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2200295079158,170.88379409754347],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.22820393443305,171.04239149313332],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23259015718264,171.16591759537795],[174.5136772126083,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2347452187699,171.25874886104174],[174.7787355115039,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23568720142907,171.32526708618758],[174.97042363235644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2360371788439,171.36985659529591],[175.0997505080749,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23613938850093,171.3969027679839],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2361595754449,171.41079135350373],[175.21906944484536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616148789233,171.41590820144467],[175.23402437178987,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":6,"ty":4,"nm":"face_1_slot_2","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[100],"h":1},{"t":2,"s":[100],"h":1},{"t":3,"s":[100],"h":1},{"t":4,"s":[100],"h":1},{"t":5,"s":[100],"h":1},{"t":6,"s":[100],"h":1},{"t":7,"s":[100],"h":1},{"t":8,"s":[100],"h":1},{"t":9,"s":[100],"h":1},{"t":10,"s":[100],"h":1},{"t":11,"s":[100],"h":1},{"t":12,"s":[100],"h":1},{"t":13,"s":[100],"h":1},{"t":14,"s":[100],"h":1},{"t":15,"s":[100],"h":1},{"t":16,"s":[100],"h":1},{"t":17,"s":[100],"h":1},{"t":18,"s":[100],"h":1},{"t":19,"s":[100],"h":1},{"t":20,"s":[100],"h":1},{"t":21,"s":[100],"h":1},{"t":22,"s":[100],"h":1},{"t":23,"s":[100],"h":1},{"t":24,"s":[100],"h":1},{"t":25,"s":[100],"h":1},{"t":26,"s":[100],"h":1},{"t":27,"s":[100],"h":1},{"t":28,"s":[100],"h":1},{"t":29,"s":[100],"h":1},{"t":30,"s":[100],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":54,"s":[100],"h":1},{"t":55,"s":[100],"h":1},{"t":56,"s":[100],"h":1},{"t":57,"s":[100],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.7659756282101,171.41663917972903],[24.763838512107654,171.4159082014447]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515457,171.41663917972903],[24.76384042455507,171.41079135350375]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[24.763860611499055,171.3969027679839]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192508,171.41663917972903],[24.7639628211561,171.36985659529594]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.02957636764353,171.41663917972903],[24.76431279857094,171.32526708618758]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496132,171.41663917972903],[24.765254781230098,171.25874886104174]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391742,171.41663917972903],[24.767409842817358,171.16591759537795]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087367,171.41663917972903],[24.771796065566974,171.04239149313335]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.27467983390227,171.41663917972903],[24.779970492084203,170.8837940975435]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.813056652428145,171.41663917972903],[24.794192748793662,170.68575920308734]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987264,171.41663917972903],[24.817610127363963,170.44393888058158]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187406,171.41663917972903],[24.854463733254804,170.1540159102598]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.050794849770682,171.41663917972903],[24.910315030447507,169.81172223294573]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926943,171.41663917972903],[24.992291688933264,169.41286537441582]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[25.109351028435142,168.95336516806938]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.17881490745795,171.41663917972903],[25.272558490807143,168.42930348868117]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339733,171.41663917972903],[25.495377398147852,167.83699010401403]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[25.793964688948876,167.17304813479808]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795812,171.41663917972903],[26.18746528869424,166.43452296328823]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312886,171.41663917972903],[26.698295178322923,165.61901871326907]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[27.352399988699673,164.72486659520754]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[28.179471994628386,163.75132940997366]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.20571106244855,171.41663917972903],[29.213103649674565,162.69884625649112]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444464,171.41663917972903],[30.49085026857678,161.56932089599854]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527375,171.41663917972903],[32.054168156800245,160.36645616899273]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009054,171.41663917972903],[33.948187516970535,159.09613519733577]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.4085587911411,171.41663917972903],[36.22127205421518,157.76684766723452]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.0958967150356,171.41663917972903],[38.92430973769417,156.39015609296857]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[42.10967224006833,154.9811924086707]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[45.82977501747337,153.55916933063907]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.701269939579305,171.41663917972903],[50.13516697637628,152.14788350454046]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[55.07207974263926,150.77617838683688]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042787,171.41663917972903],[60.67937366393438,149.47832409788663]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709705,171.41663917972903],[66.984833238743,148.29425928080326]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.40311076286019,171.41663917972903],[74.00079148302312,147.26962670455904]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.97571938286738,171.41663917972903],[81.71910393906488,146.4555207003181]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.99395419133931,171.41663917972903],[90.10555182515573,145.9078517026294]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.65389249599157,171.41663917972903],[99.09383319990782,145.6862229301544]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.254606555010795,168.4823104778698],[108.5794031700209,145.85220900074034],[108.5794031700209,145.85220900074034]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.051928158630545,165.11883425295738],[118.41354975626373,146.46692919321268],[118.41354975626373,146.46692919321268]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.329202572241016,161.70386936171468],[128.3982391316816,147.58782305787327],[128.3982391316816,147.58782305787327]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.23167595892863,158.32327808225233],[138.2824267897266,149.26456770823847],[138.2824267897266,149.26456770823847]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[41.867430278900926,155.08151817465492],[147.76069867183222,151.5341293518293],[147.76069867183222,151.5341293518293]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.290594742135035,152.10096254861588],[156.47526032617597,154.4150212688003],[156.47526032617597,154.4150212688003]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.48276971388455,149.51968659541475],[164.0224063161806,157.90095041343838],[164.0224063161806,157.90095041343838]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[72.33361100630755,147.4873228087879],[169.96464049825235,161.95417685080264],[169.96464049825235,161.95417685080264]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.62202576908322,146.15861054812373],[173.84953525253286,166.4990823725381],[173.84953525253286,166.4990823725381]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.37797423091669,146.15861054812373],[164.15776704046982,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[127.6663889936925,147.4873228087879],[157.9782885569902,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.51723028611542,149.51968659541475],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.7094052578649,152.10096254861585],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[158.13256972109895,155.08151817465486],[153.45457823622954,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.7683240410713,158.3232780822523],[154.92905150486584,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.67079742775897,161.70386936171468],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.94807184136943,165.11883425295736],[161.9568687706681,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.7453934449892,168.48231047786976],[167.93271906985146,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":7,"ty":4,"nm":"face_2_slot_2","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[100],"h":1},{"t":45,"s":[100],"h":1},{"t":46,"s":[100],"h":1},{"t":47,"s":[100],"h":1},{"t":48,"s":[100],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[100],"h":1},{"t":59,"s":[100],"h":1},{"t":60,"s":[100],"h":1},{"t":61,"s":[100],"h":1},{"t":62,"s":[100],"h":1},{"t":63,"s":[100],"h":1},{"t":64,"s":[100],"h":1},{"t":65,"s":[100],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838512107654,171.4159082014447],[100.00213723752422,145.68435644436695],[100.00213723752422,145.68435644436695]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76384042455507,171.41079135350375],[100.01709790004887,145.68435709846247],[100.01709790004887,145.68435709846247]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763860611499055,171.3969027679839],[100.05770540750385,145.68436400280396],[100.05770540750385,145.68436400280396]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.7639628211561,171.36985659529594],[100.1367831262165,145.68439896056552],[100.1367831262165,145.68439896056552]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76431279857094,171.32526708618758],[100.26715412914858,145.6845186598911],[100.26715412914858,145.6845186598911]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.765254781230098,171.25874886104174],[100.46164040852113,145.68484083693517],[100.46164040852113,145.68484083693517]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.767409842817358,171.16591759537795],[100.73306087154158,145.68557791140813],[100.73306087154158,145.68557791140813]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.771796065566974,171.04239149313335],[101.09422703281935,145.68707808794161],[101.09422703281935,145.68707808794161]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.779970492084203,170.8837940975435],[101.55793479589938,145.68987390647064],[101.55793479589938,145.68987390647064]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.794192748793662,170.68575920308734],[102.13695009169614,145.69473820474883],[102.13695009169614,145.69473820474883]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.817610127363963,170.44393888058158],[102.84398541468727,145.70274741992375],[102.84398541468727,145.70274741992375]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.854463733254804,170.1540159102598],[103.69166347102245,145.71535209549262],[103.69166347102245,145.71535209549262]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.910315030447507,169.81172223294573],[104.69246323090135,145.73445436416338],[104.69246323090135,145.73445436416338]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.992291688933264,169.41286537441582],[105.85864266890633,145.76249203264803],[105.85864266890633,145.76249203264803]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.109351028435142,168.95336516806938],[107.20213139409789,145.8025286847221],[107.20213139409789,145.8025286847221]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.272558490807143,168.42930348868117],[108.73438523824998,145.85834892439436],[108.73438523824998,145.85834892439436]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.495377398147852,167.83699010401403],[110.46619371861527,145.9345574790187],[110.46619371861527,145.9345574790187]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.793964688948876,167.17304813479808],[112.40743016966178,146.03668034701371],[112.40743016966178,146.03668034701371]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.18746528869424,166.43452296328823],[114.56673331575352,146.17126547853735],[114.56673331575352,146.17126547853735]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.698295178322923,165.61901871326907],[116.9511082303112,146.34597959060318],[116.9511082303112,146.34597959060318]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.352399988699673,164.72486659520754],[119.56543412751468,146.56969661159826],[119.56543412751468,146.56969661159826]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[28.179471994628386,163.75132940997366],[122.41186643342385,146.85257189760665],[122.41186643342385,146.85257189760665]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.213103649674565,162.69884625649112],[125.48912130867366,147.20609474441147],[125.48912130867366,147.20609474441147]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.49085026857678,161.56932089599854],[128.79163252777767,147.6431098261423],[128.79163252777767,147.6431098261423]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.054168156800245,160.36645616899273],[132.30857370939827,148.17779603433607],[132.30857370939827,148.17779603433607]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[33.948187516970535,159.09613519733577],[136.02274375594828,148.82558880736312],[136.02274375594828,148.82558880736312]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[36.22127205421518,157.76684766723452],[139.9093204855403,149.60302950658289],[139.9093204855403,149.60302950658289]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[38.92430973769417,156.39015609296857],[143.93449736804646,150.52752284250107],[143.93449736804646,150.52752284250107]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[42.10967224006833,154.9811924086707],[148.05403158786663,151.61698098210726],[148.05403158786663,151.61698098210726]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[45.82977501747337,153.55916933063907],[152.21174892054898,152.88933106722158],[152.21174892054898,152.88933106722158]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.13516697637628,152.14788350454046],[156.33807262878386,154.36186184207872],[156.33807262878386,154.36186184207872]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[55.07207974263926,150.77617838683688],[160.34867008765178,156.0503854539823],[160.34867008765178,156.0503854539823]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.67937366393438,149.47832409788663],[164.14334216845504,157.96819292461282],[164.14334216845504,157.96819292461282]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[66.984833238743,148.29425928080326],[167.60531609072166,160.12478711212304],[167.60531609072166,160.12478711212304]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.00079148302312,147.26962670455904],[170.60114132569498,162.52438615639866],[170.60114132569498,162.52438615639866]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.71910393906488,146.4555207003181],[172.98142804309384,165.16420448884634],[172.98142804309384,165.16420448884634]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[90.10555182515573,145.9078517026294],[174.58270506836902,168.0325385968404],[174.58270506836902,168.0325385968404]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.09383319990782,145.6862229301544],[175.2307042485341,171.10671188088455],[175.2307042485341,171.10671188088455]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.5794031700209,145.85220900074034],[167.93271906985157,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.41354975626373,146.46692919321268],[161.95686877066814,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.3982391316816,147.58782305787327],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[138.2824267897266,149.26456770823847],[154.92905150486587,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[147.76069867183222,151.5341293518293],[153.45457823622957,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.47526032617597,154.4150212688003],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.0224063161806,157.90095041343838],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.96464049825235,161.95417685080264],[157.97828855699024,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.84953525253286,166.4990823725381],[164.15776704046976,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.653892495991485,171.41663917972903],[24.76929575146589,171.10671188088457]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.993954191339256,171.41663917972903],[25.417294931630963,168.03253859684042]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.975719382867354,171.41663917972903],[27.01857195690613,165.16420448884637]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.403110762860145,171.41663917972903],[29.398858674304975,162.5243861563987]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709703,171.41663917972903],[32.394683909278314,160.12478711212307]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042786,171.41663917972903],[35.856657831544936,157.96819292461282]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[39.65132991234821,156.0503854539823]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.70126993957929,171.41663917972903],[43.661927371216095,154.36186184207872]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[47.78825107945101,152.88933106722158]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[51.94596841213336,151.61698098210726]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.095896715035614,171.41663917972903],[56.06550263195349,150.52752284250107]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.40855879114112,171.41663917972903],[60.09067951445965,149.6030295065829]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009055,171.41663917972903],[63.97725624405165,148.82558880736312]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527377,171.41663917972903],[67.69142629060164,148.1777960343361]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444467,171.41663917972903],[71.20836747222228,147.6431098261423]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.205711062448565,171.41663917972903],[74.5108786913263,147.20609474441147]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[77.58813356657613,146.85257189760665]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[80.43456587248531,146.56969661159826]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312914,171.41663917972903],[83.04889176968875,146.34597959060318]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795813,171.41663917972903],[85.43326668424646,146.17126547853735]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[87.59256983033822,146.03668034701371]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339737,171.41663917972903],[89.53380628138467,145.9345574790187]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.178814907457976,171.41663917972903],[91.26561476174996,145.85834892439436]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[92.79786860590211,145.8025286847221]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926972,171.41663917972903],[94.14135733109363,145.76249203264803]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.05079484977071,171.41663917972903],[95.30753676909862,145.73445436416338]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187392,171.41663917972903],[96.30833652897755,145.71535209549262]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987292,171.41663917972903],[97.1560145853127,145.70274741992375]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.81305665242823,171.41663917972903],[97.8630499083038,145.69473820474883]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.274679833902283,171.41663917972903],[98.44206520410059,145.68987390647064]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087395,171.41663917972903],[98.9057729671806,145.68707808794161]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391714,171.41663917972903],[99.26693912845845,145.68557791140813]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496118,171.41663917972903],[99.53835959147887,145.68484083693517]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.029576367643557,171.41663917972903],[99.7328458708514,145.6845186598911]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192511,171.41663917972903],[99.86321687378347,145.68439896056552]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[99.94229459249615,145.68436400280396]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515464,171.41663917972903],[99.98290209995109,145.6843570984625]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.765975628210114,171.41663917972903],[99.99786276247576,145.68435644436695]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751364,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":8,"ty":4,"nm":"face_3_slot_2","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[100],"h":1},{"t":32,"s":[100],"h":1},{"t":33,"s":[100],"h":1},{"t":34,"s":[100],"h":1},{"t":35,"s":[100],"h":1},{"t":36,"s":[100],"h":1},{"t":37,"s":[100],"h":1},{"t":38,"s":[100],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[100],"h":1},{"t":50,"s":[100],"h":1},{"t":51,"s":[100],"h":1},{"t":52,"s":[100],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.00213723752422,145.68435644436695],[175.2340243717899,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.01709790004887,145.68435709846247],[175.21906944484545,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.05770540750385,145.68436400280396],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.1367831262165,145.68439896056552],[175.09975050807492,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.26715412914858,145.6845186598911],[174.97042363235647,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.46164040852113,145.68484083693517],[174.77873551150387,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.73306087154158,145.68557791140813],[174.51367721260826,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.09422703281935,145.68707808794161],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.55793479589938,145.68987390647064],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.13695009169614,145.69473820474883],[173.18694334757186,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.84398541468727,145.70274741992375],[172.54572545701274,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[103.69166347102245,145.71535209549262],[171.79960753081258,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[104.69246323090135,145.73445436416338],[170.94920515022932,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[105.85864266890633,145.76249203264803],[169.99796493107306,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[107.20213139409789,145.8025286847221],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.73438523824998,145.85834892439436],[167.82118509254207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[110.46619371861527,145.9345574790187],[166.61675437660267,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[112.40743016966178,146.03668034701371],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.56673331575352,146.17126547853735],[164.04759992204188,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[116.9511082303112,146.34597959060318],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[119.56543412751468,146.56969661159826],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[122.41186643342385,146.85257189760665],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.48912130867366,147.20609474441147],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.79163252777767,147.6431098261423],[157.58326505555536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[132.30857370939827,148.17779603433607],[156.46115967472625,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[136.02274375594828,148.82558880736312],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.9093204855403,149.60302950658289],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[143.93449736804646,150.52752284250107],[153.9041032849644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[148.05403158786663,151.61698098210726],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[152.21174892054898,152.88933106722158],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.33807262878386,154.36186184207872],[153.2987300604207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[160.34867008765178,156.0503854539823],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.14334216845504,157.96819292461282],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.60531609072166,160.12478711212304],[156.25574276290294,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.60114132569498,162.52438615639866],[158.5968892371398,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.98142804309384,165.16420448884634],[162.0242806171326,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.58270506836902,168.0325385968404],[167.0060458086607,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2307042485341,171.10671188088455],[174.34610750400844,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530165,171.41663917972903],[26.15046474746714,166.49908237253814]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.02171144300978,171.41663917972903],[30.035359501747664,161.95417685080264]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[35.97759368381941,157.9009504134384]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112142,171.41663917972903],[43.524739673823944,154.41502126880033]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.54542176377046,171.41663917972903],[52.23930132816764,151.53412935182934]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513416,171.41663917972903],[61.71757321027329,149.26456770823847]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.28066065919667,171.41663917972903],[71.60176086831838,147.5878230578733]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331905,171.41663917972903],[81.58645024373618,146.4669291932127]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014854,171.41663917972903],[91.42059682997896,145.85220900074034]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76929575146589,171.10671188088457],[100.9061668000921,145.6862229301544],[100.9061668000921,145.6862229301544]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.417294931630963,168.03253859684042],[109.89444817484419,145.9078517026294],[109.89444817484419,145.9078517026294]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.01857195690613,165.16420448884637],[118.28089606093508,146.4555207003181],[118.28089606093508,146.4555207003181]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.398858674304975,162.5243861563987],[125.9992085169768,147.26962670455904],[125.9992085169768,147.26962670455904]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.394683909278314,160.12478711212307],[133.01516676125698,148.29425928080326],[133.01516676125698,148.29425928080326]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.856657831544936,157.96819292461282],[139.32062633606557,149.47832409788663],[139.32062633606557,149.47832409788663]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[39.65132991234821,156.0503854539823],[144.9279202573607,150.77617838683688],[144.9279202573607,150.77617838683688]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.661927371216095,154.36186184207872],[149.86483302362365,152.14788350454043],[149.86483302362365,152.14788350454043]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[47.78825107945101,152.88933106722158],[154.1702249825266,153.55916933063904],[154.1702249825266,153.55916933063904]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[51.94596841213336,151.61698098210726],[157.89032775993167,154.98119240867067],[157.89032775993167,154.98119240867067]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[56.06550263195349,150.52752284250107],[161.07569026230578,156.39015609296857],[161.07569026230578,156.39015609296857]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.09067951445965,149.6030295065829],[163.7787279457848,157.7668476672345],[163.7787279457848,157.7668476672345]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[63.97725624405165,148.82558880736312],[166.05181248302944,159.09613519733574],[166.05181248302944,159.09613519733574]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[67.69142629060164,148.1777960343361],[167.94583184319973,160.36645616899267],[167.94583184319973,160.36645616899267]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.20836747222228,147.6431098261423],[169.5091497314232,161.56932089599852],[169.5091497314232,161.56932089599852]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.5108786913263,147.20609474441147],[170.78689635032543,162.6988462564911],[170.78689635032543,162.6988462564911]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[77.58813356657613,146.85257189760665],[171.8205280053716,163.75132940997366],[171.8205280053716,163.75132940997366]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[80.43456587248531,146.56969661159826],[172.64760001130034,164.72486659520752],[172.64760001130034,164.72486659520752]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[83.04889176968875,146.34597959060318],[173.30170482167705,165.61901871326904],[173.30170482167705,165.61901871326904]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.43326668424646,146.17126547853735],[173.81253471130574,166.43452296328823],[173.81253471130574,166.43452296328823]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[87.59256983033822,146.03668034701371],[174.20603531105112,167.17304813479808],[174.20603531105112,167.17304813479808]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[89.53380628138467,145.9345574790187],[174.50462260185213,167.836990104014],[174.50462260185213,167.836990104014]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.26561476174996,145.85834892439436],[174.72744150919286,168.42930348868117],[174.72744150919286,168.42930348868117]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[92.79786860590211,145.8025286847221],[174.89064897156487,168.95336516806938],[174.89064897156487,168.95336516806938]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[94.14135733109363,145.76249203264803],[175.00770831106672,169.4128653744158],[175.00770831106672,169.4128653744158]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[95.30753676909862,145.73445436416338],[175.08968496955248,169.81172223294573],[175.08968496955248,169.81172223294573]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[96.30833652897755,145.71535209549262],[175.14553626674518,170.1540159102598],[175.14553626674518,170.1540159102598]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.1560145853127,145.70274741992375],[175.18238987263604,170.44393888058158],[175.18238987263604,170.44393888058158]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.8630499083038,145.69473820474883],[175.20580725120632,170.6857592030873],[175.20580725120632,170.6857592030873]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.44206520410059,145.68987390647064],[175.2200295079158,170.88379409754347],[175.2200295079158,170.88379409754347]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.9057729671806,145.68707808794161],[175.22820393443305,171.04239149313332],[175.22820393443305,171.04239149313332]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.26693912845845,145.68557791140813],[175.23259015718264,171.16591759537795],[175.23259015718264,171.16591759537795]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.53835959147887,145.68484083693517],[175.2347452187699,171.25874886104174],[175.2347452187699,171.25874886104174]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.7328458708514,145.6845186598911],[175.23568720142907,171.32526708618758],[175.23568720142907,171.32526708618758]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.86321687378347,145.68439896056552],[175.2360371788439,171.36985659529591],[175.2360371788439,171.36985659529591]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.94229459249615,145.68436400280396],[175.23613938850093,171.3969027679839],[175.23613938850093,171.3969027679839]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.98290209995109,145.6843570984625],[175.2361595754449,171.41079135350373],[175.2361595754449,171.41079135350373]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99786276247576,145.68435644436695],[175.23616148789233,171.41590820144467],[175.23616148789233,171.41590820144467]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":9,"ty":4,"nm":"face_0_slot_1","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[100],"h":1},{"t":45,"s":[100],"h":1},{"t":46,"s":[100],"h":1},{"t":47,"s":[100],"h":1},{"t":48,"s":[100],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[100],"h":1},{"t":59,"s":[100],"h":1},{"t":60,"s":[100],"h":1},{"t":61,"s":[100],"h":1},{"t":62,"s":[100],"h":1},{"t":63,"s":[100],"h":1},{"t":64,"s":[100],"h":1},{"t":65,"s":[100],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014843,171.41663917972903],[25.254606555010795,168.4823104778698]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331856,171.41663917972903],[27.051928158630545,165.11883425295738]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.280660659196656,171.41663917972903],[30.329202572241016,161.70386936171468]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513414,171.41663917972903],[35.23167595892863,158.32327808225233]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.545421763770435,171.41663917972903],[41.867430278900926,155.08151817465492]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112144,171.41663917972903],[50.290594742135035,152.10096254861588]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[60.48276971388455,149.51968659541475]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.021711443009764,171.41663917972903],[72.33361100630755,147.4873228087879]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530236,171.41663917972903],[85.62202576908322,146.15861054812373]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.76383848175135,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.15046474746714,166.49908237253814],[114.37797423091669,146.15861054812373],[114.37797423091669,146.15861054812373]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.035359501747664,161.95417685080264],[127.6663889936925,147.4873228087879],[127.6663889936925,147.4873228087879]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.97759368381941,157.9009504134384],[139.51723028611542,149.51968659541475],[139.51723028611542,149.51968659541475]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.524739673823944,154.41502126880033],[149.7094052578649,152.10096254861585],[149.7094052578649,152.10096254861585]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[52.23930132816764,151.53412935182934],[158.13256972109895,155.08151817465486],[158.13256972109895,155.08151817465486]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[61.71757321027329,149.26456770823847],[164.7683240410713,158.3232780822523],[164.7683240410713,158.3232780822523]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.60176086831838,147.5878230578733],[169.67079742775897,161.70386936171468],[169.67079742775897,161.70386936171468]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.58645024373618,146.4669291932127],[172.94807184136943,165.11883425295736],[172.94807184136943,165.11883425295736]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.42059682997896,145.85220900074034],[174.7453934449892,168.48231047786976],[174.7453934449892,168.48231047786976]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.9061668000921,145.6862229301544],[174.3461075040085,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[109.89444817484419,145.9078517026294],[167.00604580866076,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.28089606093508,146.4555207003181],[162.02428061713266,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.9992085169768,147.26962670455904],[158.59688923713986,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[133.01516676125698,148.29425928080326],[156.25574276290297,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.32062633606557,149.47832409788663],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[144.9279202573607,150.77617838683688],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.86483302362365,152.14788350454043],[153.29873006042072,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[154.1702249825266,153.55916933063904],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[157.89032775993167,154.98119240867067],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[161.07569026230578,156.39015609296857],[153.90410328496438,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[163.7787279457848,157.7668476672345],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[166.05181248302944,159.09613519733574],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.94583184319973,160.36645616899267],[156.46115967472622,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.5091497314232,161.56932089599852],[157.58326505555533,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.78689635032543,162.6988462564911],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[171.8205280053716,163.75132940997366],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.64760001130034,164.72486659520752],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.30170482167705,165.61901871326904],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.81253471130574,166.43452296328823],[164.04759992204185,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.20603531105112,167.17304813479808],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.50462260185213,167.836990104014],[166.61675437660261,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.72744150919286,168.42930348868117],[167.821185092542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.89064897156487,168.95336516806938],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.00770831106672,169.4128653744158],[169.99796493107303,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.08968496955248,169.81172223294573],[170.9492051502293,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.14553626674518,170.1540159102598],[171.7996075308126,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.18238987263604,170.44393888058158],[172.5457254570127,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.20580725120632,170.6857592030873],[173.18694334757177,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2200295079158,170.88379409754347],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.22820393443305,171.04239149313332],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23259015718264,171.16591759537795],[174.5136772126083,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2347452187699,171.25874886104174],[174.7787355115039,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23568720142907,171.32526708618758],[174.97042363235644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2360371788439,171.36985659529591],[175.0997505080749,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23613938850093,171.3969027679839],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2361595754449,171.41079135350373],[175.21906944484536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616148789233,171.41590820144467],[175.23402437178987,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":10,"ty":4,"nm":"face_1_slot_1","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[100],"h":1},{"t":32,"s":[100],"h":1},{"t":33,"s":[100],"h":1},{"t":34,"s":[100],"h":1},{"t":35,"s":[100],"h":1},{"t":36,"s":[100],"h":1},{"t":37,"s":[100],"h":1},{"t":38,"s":[100],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[100],"h":1},{"t":50,"s":[100],"h":1},{"t":51,"s":[100],"h":1},{"t":52,"s":[100],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.7659756282101,171.41663917972903],[24.763838512107654,171.4159082014447]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515457,171.41663917972903],[24.76384042455507,171.41079135350375]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[24.763860611499055,171.3969027679839]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192508,171.41663917972903],[24.7639628211561,171.36985659529594]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.02957636764353,171.41663917972903],[24.76431279857094,171.32526708618758]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496132,171.41663917972903],[24.765254781230098,171.25874886104174]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391742,171.41663917972903],[24.767409842817358,171.16591759537795]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087367,171.41663917972903],[24.771796065566974,171.04239149313335]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.27467983390227,171.41663917972903],[24.779970492084203,170.8837940975435]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.813056652428145,171.41663917972903],[24.794192748793662,170.68575920308734]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987264,171.41663917972903],[24.817610127363963,170.44393888058158]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187406,171.41663917972903],[24.854463733254804,170.1540159102598]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.050794849770682,171.41663917972903],[24.910315030447507,169.81172223294573]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926943,171.41663917972903],[24.992291688933264,169.41286537441582]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[25.109351028435142,168.95336516806938]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.17881490745795,171.41663917972903],[25.272558490807143,168.42930348868117]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339733,171.41663917972903],[25.495377398147852,167.83699010401403]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[25.793964688948876,167.17304813479808]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795812,171.41663917972903],[26.18746528869424,166.43452296328823]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312886,171.41663917972903],[26.698295178322923,165.61901871326907]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[27.352399988699673,164.72486659520754]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[28.179471994628386,163.75132940997366]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.20571106244855,171.41663917972903],[29.213103649674565,162.69884625649112]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444464,171.41663917972903],[30.49085026857678,161.56932089599854]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527375,171.41663917972903],[32.054168156800245,160.36645616899273]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009054,171.41663917972903],[33.948187516970535,159.09613519733577]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.4085587911411,171.41663917972903],[36.22127205421518,157.76684766723452]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.0958967150356,171.41663917972903],[38.92430973769417,156.39015609296857]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[42.10967224006833,154.9811924086707]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[45.82977501747337,153.55916933063907]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.701269939579305,171.41663917972903],[50.13516697637628,152.14788350454046]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[55.07207974263926,150.77617838683688]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042787,171.41663917972903],[60.67937366393438,149.47832409788663]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709705,171.41663917972903],[66.984833238743,148.29425928080326]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.40311076286019,171.41663917972903],[74.00079148302312,147.26962670455904]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.97571938286738,171.41663917972903],[81.71910393906488,146.4555207003181]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.99395419133931,171.41663917972903],[90.10555182515573,145.9078517026294]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.65389249599157,171.41663917972903],[99.09383319990782,145.6862229301544]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.254606555010795,168.4823104778698],[108.5794031700209,145.85220900074034],[108.5794031700209,145.85220900074034]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.051928158630545,165.11883425295738],[118.41354975626373,146.46692919321268],[118.41354975626373,146.46692919321268]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.329202572241016,161.70386936171468],[128.3982391316816,147.58782305787327],[128.3982391316816,147.58782305787327]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.23167595892863,158.32327808225233],[138.2824267897266,149.26456770823847],[138.2824267897266,149.26456770823847]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[41.867430278900926,155.08151817465492],[147.76069867183222,151.5341293518293],[147.76069867183222,151.5341293518293]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.290594742135035,152.10096254861588],[156.47526032617597,154.4150212688003],[156.47526032617597,154.4150212688003]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.48276971388455,149.51968659541475],[164.0224063161806,157.90095041343838],[164.0224063161806,157.90095041343838]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[72.33361100630755,147.4873228087879],[169.96464049825235,161.95417685080264],[169.96464049825235,161.95417685080264]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.62202576908322,146.15861054812373],[173.84953525253286,166.4990823725381],[173.84953525253286,166.4990823725381]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.37797423091669,146.15861054812373],[164.15776704046982,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[127.6663889936925,147.4873228087879],[157.9782885569902,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.51723028611542,149.51968659541475],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.7094052578649,152.10096254861585],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[158.13256972109895,155.08151817465486],[153.45457823622954,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.7683240410713,158.3232780822523],[154.92905150486584,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.67079742775897,161.70386936171468],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.94807184136943,165.11883425295736],[161.9568687706681,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.7453934449892,168.48231047786976],[167.93271906985146,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":11,"ty":4,"nm":"face_2_slot_1","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[100],"h":1},{"t":40,"s":[100],"h":1},{"t":41,"s":[100],"h":1},{"t":42,"s":[100],"h":1},{"t":43,"s":[100],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[100],"h":1},{"t":67,"s":[100],"h":1},{"t":68,"s":[100],"h":1},{"t":69,"s":[100],"h":1},{"t":70,"s":[100],"h":1},{"t":71,"s":[100],"h":1},{"t":72,"s":[100],"h":1},{"t":73,"s":[100],"h":1},{"t":74,"s":[100],"h":1},{"t":75,"s":[100],"h":1},{"t":76,"s":[100],"h":1},{"t":77,"s":[100],"h":1},{"t":78,"s":[100],"h":1},{"t":79,"s":[100],"h":1},{"t":80,"s":[100],"h":1},{"t":81,"s":[100],"h":1},{"t":82,"s":[100],"h":1},{"t":83,"s":[100],"h":1},{"t":84,"s":[100],"h":1},{"t":85,"s":[100],"h":1},{"t":86,"s":[100],"h":1},{"t":87,"s":[100],"h":1},{"t":88,"s":[100],"h":1},{"t":89,"s":[100],"h":1},{"t":90,"s":[100],"h":1},{"t":91,"s":[100],"h":1},{"t":92,"s":[100],"h":1},{"t":93,"s":[100],"h":1},{"t":94,"s":[100],"h":1},{"t":95,"s":[100],"h":1},{"t":96,"s":[100],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838512107654,171.4159082014447],[100.00213723752422,145.68435644436695],[100.00213723752422,145.68435644436695]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76384042455507,171.41079135350375],[100.01709790004887,145.68435709846247],[100.01709790004887,145.68435709846247]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763860611499055,171.3969027679839],[100.05770540750385,145.68436400280396],[100.05770540750385,145.68436400280396]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.7639628211561,171.36985659529594],[100.1367831262165,145.68439896056552],[100.1367831262165,145.68439896056552]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76431279857094,171.32526708618758],[100.26715412914858,145.6845186598911],[100.26715412914858,145.6845186598911]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.765254781230098,171.25874886104174],[100.46164040852113,145.68484083693517],[100.46164040852113,145.68484083693517]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.767409842817358,171.16591759537795],[100.73306087154158,145.68557791140813],[100.73306087154158,145.68557791140813]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.771796065566974,171.04239149313335],[101.09422703281935,145.68707808794161],[101.09422703281935,145.68707808794161]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.779970492084203,170.8837940975435],[101.55793479589938,145.68987390647064],[101.55793479589938,145.68987390647064]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.794192748793662,170.68575920308734],[102.13695009169614,145.69473820474883],[102.13695009169614,145.69473820474883]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.817610127363963,170.44393888058158],[102.84398541468727,145.70274741992375],[102.84398541468727,145.70274741992375]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.854463733254804,170.1540159102598],[103.69166347102245,145.71535209549262],[103.69166347102245,145.71535209549262]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.910315030447507,169.81172223294573],[104.69246323090135,145.73445436416338],[104.69246323090135,145.73445436416338]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.992291688933264,169.41286537441582],[105.85864266890633,145.76249203264803],[105.85864266890633,145.76249203264803]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.109351028435142,168.95336516806938],[107.20213139409789,145.8025286847221],[107.20213139409789,145.8025286847221]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.272558490807143,168.42930348868117],[108.73438523824998,145.85834892439436],[108.73438523824998,145.85834892439436]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.495377398147852,167.83699010401403],[110.46619371861527,145.9345574790187],[110.46619371861527,145.9345574790187]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.793964688948876,167.17304813479808],[112.40743016966178,146.03668034701371],[112.40743016966178,146.03668034701371]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.18746528869424,166.43452296328823],[114.56673331575352,146.17126547853735],[114.56673331575352,146.17126547853735]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.698295178322923,165.61901871326907],[116.9511082303112,146.34597959060318],[116.9511082303112,146.34597959060318]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.352399988699673,164.72486659520754],[119.56543412751468,146.56969661159826],[119.56543412751468,146.56969661159826]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[28.179471994628386,163.75132940997366],[122.41186643342385,146.85257189760665],[122.41186643342385,146.85257189760665]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.213103649674565,162.69884625649112],[125.48912130867366,147.20609474441147],[125.48912130867366,147.20609474441147]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.49085026857678,161.56932089599854],[128.79163252777767,147.6431098261423],[128.79163252777767,147.6431098261423]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.054168156800245,160.36645616899273],[132.30857370939827,148.17779603433607],[132.30857370939827,148.17779603433607]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[33.948187516970535,159.09613519733577],[136.02274375594828,148.82558880736312],[136.02274375594828,148.82558880736312]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[36.22127205421518,157.76684766723452],[139.9093204855403,149.60302950658289],[139.9093204855403,149.60302950658289]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[38.92430973769417,156.39015609296857],[143.93449736804646,150.52752284250107],[143.93449736804646,150.52752284250107]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[42.10967224006833,154.9811924086707],[148.05403158786663,151.61698098210726],[148.05403158786663,151.61698098210726]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[45.82977501747337,153.55916933063907],[152.21174892054898,152.88933106722158],[152.21174892054898,152.88933106722158]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.13516697637628,152.14788350454046],[156.33807262878386,154.36186184207872],[156.33807262878386,154.36186184207872]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[55.07207974263926,150.77617838683688],[160.34867008765178,156.0503854539823],[160.34867008765178,156.0503854539823]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.67937366393438,149.47832409788663],[164.14334216845504,157.96819292461282],[164.14334216845504,157.96819292461282]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[66.984833238743,148.29425928080326],[167.60531609072166,160.12478711212304],[167.60531609072166,160.12478711212304]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.00079148302312,147.26962670455904],[170.60114132569498,162.52438615639866],[170.60114132569498,162.52438615639866]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.71910393906488,146.4555207003181],[172.98142804309384,165.16420448884634],[172.98142804309384,165.16420448884634]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[90.10555182515573,145.9078517026294],[174.58270506836902,168.0325385968404],[174.58270506836902,168.0325385968404]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.09383319990782,145.6862229301544],[175.2307042485341,171.10671188088455],[175.2307042485341,171.10671188088455]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.5794031700209,145.85220900074034],[167.93271906985157,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.41354975626373,146.46692919321268],[161.95686877066814,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.3982391316816,147.58782305787327],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[138.2824267897266,149.26456770823847],[154.92905150486587,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[147.76069867183222,151.5341293518293],[153.45457823622957,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.47526032617597,154.4150212688003],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.0224063161806,157.90095041343838],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.96464049825235,161.95417685080264],[157.97828855699024,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.84953525253286,166.4990823725381],[164.15776704046976,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.653892495991485,171.41663917972903],[24.76929575146589,171.10671188088457]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.993954191339256,171.41663917972903],[25.417294931630963,168.03253859684042]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.975719382867354,171.41663917972903],[27.01857195690613,165.16420448884637]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.403110762860145,171.41663917972903],[29.398858674304975,162.5243861563987]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709703,171.41663917972903],[32.394683909278314,160.12478711212307]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042786,171.41663917972903],[35.856657831544936,157.96819292461282]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[39.65132991234821,156.0503854539823]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.70126993957929,171.41663917972903],[43.661927371216095,154.36186184207872]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[47.78825107945101,152.88933106722158]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[51.94596841213336,151.61698098210726]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.095896715035614,171.41663917972903],[56.06550263195349,150.52752284250107]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.40855879114112,171.41663917972903],[60.09067951445965,149.6030295065829]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009055,171.41663917972903],[63.97725624405165,148.82558880736312]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527377,171.41663917972903],[67.69142629060164,148.1777960343361]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444467,171.41663917972903],[71.20836747222228,147.6431098261423]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.205711062448565,171.41663917972903],[74.5108786913263,147.20609474441147]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[77.58813356657613,146.85257189760665]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[80.43456587248531,146.56969661159826]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312914,171.41663917972903],[83.04889176968875,146.34597959060318]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795813,171.41663917972903],[85.43326668424646,146.17126547853735]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[87.59256983033822,146.03668034701371]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339737,171.41663917972903],[89.53380628138467,145.9345574790187]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.178814907457976,171.41663917972903],[91.26561476174996,145.85834892439436]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[92.79786860590211,145.8025286847221]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926972,171.41663917972903],[94.14135733109363,145.76249203264803]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.05079484977071,171.41663917972903],[95.30753676909862,145.73445436416338]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187392,171.41663917972903],[96.30833652897755,145.71535209549262]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987292,171.41663917972903],[97.1560145853127,145.70274741992375]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.81305665242823,171.41663917972903],[97.8630499083038,145.69473820474883]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.274679833902283,171.41663917972903],[98.44206520410059,145.68987390647064]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087395,171.41663917972903],[98.9057729671806,145.68707808794161]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391714,171.41663917972903],[99.26693912845845,145.68557791140813]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496118,171.41663917972903],[99.53835959147887,145.68484083693517]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.029576367643557,171.41663917972903],[99.7328458708514,145.6845186598911]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192511,171.41663917972903],[99.86321687378347,145.68439896056552]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[99.94229459249615,145.68436400280396]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515464,171.41663917972903],[99.98290209995109,145.6843570984625]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.765975628210114,171.41663917972903],[99.99786276247576,145.68435644436695]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751364,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":12,"ty":4,"nm":"face_3_slot_1","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[100],"h":1},{"t":1,"s":[100],"h":1},{"t":2,"s":[100],"h":1},{"t":3,"s":[100],"h":1},{"t":4,"s":[100],"h":1},{"t":5,"s":[100],"h":1},{"t":6,"s":[100],"h":1},{"t":7,"s":[100],"h":1},{"t":8,"s":[100],"h":1},{"t":9,"s":[100],"h":1},{"t":10,"s":[100],"h":1},{"t":11,"s":[100],"h":1},{"t":12,"s":[100],"h":1},{"t":13,"s":[100],"h":1},{"t":14,"s":[100],"h":1},{"t":15,"s":[100],"h":1},{"t":16,"s":[100],"h":1},{"t":17,"s":[100],"h":1},{"t":18,"s":[100],"h":1},{"t":19,"s":[100],"h":1},{"t":20,"s":[100],"h":1},{"t":21,"s":[100],"h":1},{"t":22,"s":[100],"h":1},{"t":23,"s":[100],"h":1},{"t":24,"s":[100],"h":1},{"t":25,"s":[100],"h":1},{"t":26,"s":[100],"h":1},{"t":27,"s":[100],"h":1},{"t":28,"s":[100],"h":1},{"t":29,"s":[100],"h":1},{"t":30,"s":[100],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[100],"h":1},{"t":54,"s":[100],"h":1},{"t":55,"s":[100],"h":1},{"t":56,"s":[100],"h":1},{"t":57,"s":[100],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[100],"h":1},{"t":98,"s":[100],"h":1},{"t":99,"s":[100],"h":1},{"t":100,"s":[100],"h":1},{"t":101,"s":[100],"h":1},{"t":102,"s":[100],"h":1},{"t":103,"s":[100],"h":1},{"t":104,"s":[100],"h":1},{"t":105,"s":[100],"h":1},{"t":106,"s":[100],"h":1},{"t":107,"s":[100],"h":1},{"t":108,"s":[100],"h":1},{"t":109,"s":[100],"h":1},{"t":110,"s":[100],"h":1},{"t":111,"s":[100],"h":1},{"t":112,"s":[100],"h":1},{"t":113,"s":[100],"h":1},{"t":114,"s":[100],"h":1},{"t":115,"s":[100],"h":1},{"t":116,"s":[100],"h":1},{"t":117,"s":[100],"h":1},{"t":118,"s":[100],"h":1},{"t":119,"s":[100],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.00213723752422,145.68435644436695],[175.2340243717899,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.01709790004887,145.68435709846247],[175.21906944484545,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.05770540750385,145.68436400280396],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.1367831262165,145.68439896056552],[175.09975050807492,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.26715412914858,145.6845186598911],[174.97042363235647,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.46164040852113,145.68484083693517],[174.77873551150387,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.73306087154158,145.68557791140813],[174.51367721260826,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.09422703281935,145.68707808794161],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.55793479589938,145.68987390647064],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.13695009169614,145.69473820474883],[173.18694334757186,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.84398541468727,145.70274741992375],[172.54572545701274,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[103.69166347102245,145.71535209549262],[171.79960753081258,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[104.69246323090135,145.73445436416338],[170.94920515022932,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[105.85864266890633,145.76249203264803],[169.99796493107306,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[107.20213139409789,145.8025286847221],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.73438523824998,145.85834892439436],[167.82118509254207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[110.46619371861527,145.9345574790187],[166.61675437660267,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[112.40743016966178,146.03668034701371],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.56673331575352,146.17126547853735],[164.04759992204188,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[116.9511082303112,146.34597959060318],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[119.56543412751468,146.56969661159826],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[122.41186643342385,146.85257189760665],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.48912130867366,147.20609474441147],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.79163252777767,147.6431098261423],[157.58326505555536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[132.30857370939827,148.17779603433607],[156.46115967472625,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[136.02274375594828,148.82558880736312],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.9093204855403,149.60302950658289],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[143.93449736804646,150.52752284250107],[153.9041032849644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[148.05403158786663,151.61698098210726],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[152.21174892054898,152.88933106722158],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.33807262878386,154.36186184207872],[153.2987300604207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[160.34867008765178,156.0503854539823],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.14334216845504,157.96819292461282],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.60531609072166,160.12478711212304],[156.25574276290294,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.60114132569498,162.52438615639866],[158.5968892371398,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.98142804309384,165.16420448884634],[162.0242806171326,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.58270506836902,168.0325385968404],[167.0060458086607,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2307042485341,171.10671188088455],[174.34610750400844,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530165,171.41663917972903],[26.15046474746714,166.49908237253814]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.02171144300978,171.41663917972903],[30.035359501747664,161.95417685080264]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[35.97759368381941,157.9009504134384]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112142,171.41663917972903],[43.524739673823944,154.41502126880033]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.54542176377046,171.41663917972903],[52.23930132816764,151.53412935182934]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513416,171.41663917972903],[61.71757321027329,149.26456770823847]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.28066065919667,171.41663917972903],[71.60176086831838,147.5878230578733]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331905,171.41663917972903],[81.58645024373618,146.4669291932127]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014854,171.41663917972903],[91.42059682997896,145.85220900074034]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76929575146589,171.10671188088457],[100.9061668000921,145.6862229301544],[100.9061668000921,145.6862229301544]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.417294931630963,168.03253859684042],[109.89444817484419,145.9078517026294],[109.89444817484419,145.9078517026294]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.01857195690613,165.16420448884637],[118.28089606093508,146.4555207003181],[118.28089606093508,146.4555207003181]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.398858674304975,162.5243861563987],[125.9992085169768,147.26962670455904],[125.9992085169768,147.26962670455904]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.394683909278314,160.12478711212307],[133.01516676125698,148.29425928080326],[133.01516676125698,148.29425928080326]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.856657831544936,157.96819292461282],[139.32062633606557,149.47832409788663],[139.32062633606557,149.47832409788663]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[39.65132991234821,156.0503854539823],[144.9279202573607,150.77617838683688],[144.9279202573607,150.77617838683688]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.661927371216095,154.36186184207872],[149.86483302362365,152.14788350454043],[149.86483302362365,152.14788350454043]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[47.78825107945101,152.88933106722158],[154.1702249825266,153.55916933063904],[154.1702249825266,153.55916933063904]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[51.94596841213336,151.61698098210726],[157.89032775993167,154.98119240867067],[157.89032775993167,154.98119240867067]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[56.06550263195349,150.52752284250107],[161.07569026230578,156.39015609296857],[161.07569026230578,156.39015609296857]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.09067951445965,149.6030295065829],[163.7787279457848,157.7668476672345],[163.7787279457848,157.7668476672345]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[63.97725624405165,148.82558880736312],[166.05181248302944,159.09613519733574],[166.05181248302944,159.09613519733574]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[67.69142629060164,148.1777960343361],[167.94583184319973,160.36645616899267],[167.94583184319973,160.36645616899267]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.20836747222228,147.6431098261423],[169.5091497314232,161.56932089599852],[169.5091497314232,161.56932089599852]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.5108786913263,147.20609474441147],[170.78689635032543,162.6988462564911],[170.78689635032543,162.6988462564911]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[77.58813356657613,146.85257189760665],[171.8205280053716,163.75132940997366],[171.8205280053716,163.75132940997366]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[80.43456587248531,146.56969661159826],[172.64760001130034,164.72486659520752],[172.64760001130034,164.72486659520752]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[83.04889176968875,146.34597959060318],[173.30170482167705,165.61901871326904],[173.30170482167705,165.61901871326904]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.43326668424646,146.17126547853735],[173.81253471130574,166.43452296328823],[173.81253471130574,166.43452296328823]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[87.59256983033822,146.03668034701371],[174.20603531105112,167.17304813479808],[174.20603531105112,167.17304813479808]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[89.53380628138467,145.9345574790187],[174.50462260185213,167.836990104014],[174.50462260185213,167.836990104014]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.26561476174996,145.85834892439436],[174.72744150919286,168.42930348868117],[174.72744150919286,168.42930348868117]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[92.79786860590211,145.8025286847221],[174.89064897156487,168.95336516806938],[174.89064897156487,168.95336516806938]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[94.14135733109363,145.76249203264803],[175.00770831106672,169.4128653744158],[175.00770831106672,169.4128653744158]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[95.30753676909862,145.73445436416338],[175.08968496955248,169.81172223294573],[175.08968496955248,169.81172223294573]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[96.30833652897755,145.71535209549262],[175.14553626674518,170.1540159102598],[175.14553626674518,170.1540159102598]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.1560145853127,145.70274741992375],[175.18238987263604,170.44393888058158],[175.18238987263604,170.44393888058158]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.8630499083038,145.69473820474883],[175.20580725120632,170.6857592030873],[175.20580725120632,170.6857592030873]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.44206520410059,145.68987390647064],[175.2200295079158,170.88379409754347],[175.2200295079158,170.88379409754347]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.9057729671806,145.68707808794161],[175.22820393443305,171.04239149313332],[175.22820393443305,171.04239149313332]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.26693912845845,145.68557791140813],[175.23259015718264,171.16591759537795],[175.23259015718264,171.16591759537795]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.53835959147887,145.68484083693517],[175.2347452187699,171.25874886104174],[175.2347452187699,171.25874886104174]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.7328458708514,145.6845186598911],[175.23568720142907,171.32526708618758],[175.23568720142907,171.32526708618758]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.86321687378347,145.68439896056552],[175.2360371788439,171.36985659529591],[175.2360371788439,171.36985659529591]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.94229459249615,145.68436400280396],[175.23613938850093,171.3969027679839],[175.23613938850093,171.3969027679839]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.98290209995109,145.6843570984625],[175.2361595754449,171.41079135350373],[175.2361595754449,171.41079135350373]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99786276247576,145.68435644436695],[175.23616148789233,171.41590820144467],[175.23616148789233,171.41590820144467]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":13,"ty":4,"nm":"face_0_slot_0","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[100],"h":1},{"t":50,"s":[100],"h":1},{"t":51,"s":[100],"h":1},{"t":52,"s":[100],"h":1},{"t":53,"s":[100],"h":1},{"t":54,"s":[100],"h":1},{"t":55,"s":[100],"h":1},{"t":56,"s":[100],"h":1},{"t":57,"s":[100],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014843,171.41663917972903],[25.254606555010795,168.4823104778698]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331856,171.41663917972903],[27.051928158630545,165.11883425295738]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.280660659196656,171.41663917972903],[30.329202572241016,161.70386936171468]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513414,171.41663917972903],[35.23167595892863,158.32327808225233]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.545421763770435,171.41663917972903],[41.867430278900926,155.08151817465492]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112144,171.41663917972903],[50.290594742135035,152.10096254861588]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[60.48276971388455,149.51968659541475]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.021711443009764,171.41663917972903],[72.33361100630755,147.4873228087879]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530236,171.41663917972903],[85.62202576908322,146.15861054812373]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.76383848175135,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.15046474746714,166.49908237253814],[114.37797423091669,146.15861054812373],[114.37797423091669,146.15861054812373]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.035359501747664,161.95417685080264],[127.6663889936925,147.4873228087879],[127.6663889936925,147.4873228087879]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.97759368381941,157.9009504134384],[139.51723028611542,149.51968659541475],[139.51723028611542,149.51968659541475]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.524739673823944,154.41502126880033],[149.7094052578649,152.10096254861585],[149.7094052578649,152.10096254861585]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[52.23930132816764,151.53412935182934],[158.13256972109895,155.08151817465486],[158.13256972109895,155.08151817465486]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[61.71757321027329,149.26456770823847],[164.7683240410713,158.3232780822523],[164.7683240410713,158.3232780822523]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.60176086831838,147.5878230578733],[169.67079742775897,161.70386936171468],[169.67079742775897,161.70386936171468]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.58645024373618,146.4669291932127],[172.94807184136943,165.11883425295736],[172.94807184136943,165.11883425295736]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.42059682997896,145.85220900074034],[174.7453934449892,168.48231047786976],[174.7453934449892,168.48231047786976]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.9061668000921,145.6862229301544],[174.3461075040085,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[109.89444817484419,145.9078517026294],[167.00604580866076,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.28089606093508,146.4555207003181],[162.02428061713266,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.9992085169768,147.26962670455904],[158.59688923713986,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[133.01516676125698,148.29425928080326],[156.25574276290297,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.32062633606557,149.47832409788663],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[144.9279202573607,150.77617838683688],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.86483302362365,152.14788350454043],[153.29873006042072,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[154.1702249825266,153.55916933063904],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[157.89032775993167,154.98119240867067],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[161.07569026230578,156.39015609296857],[153.90410328496438,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[163.7787279457848,157.7668476672345],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[166.05181248302944,159.09613519733574],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.94583184319973,160.36645616899267],[156.46115967472622,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.5091497314232,161.56932089599852],[157.58326505555533,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.78689635032543,162.6988462564911],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[171.8205280053716,163.75132940997366],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.64760001130034,164.72486659520752],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.30170482167705,165.61901871326904],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.81253471130574,166.43452296328823],[164.04759992204185,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.20603531105112,167.17304813479808],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.50462260185213,167.836990104014],[166.61675437660261,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.72744150919286,168.42930348868117],[167.821185092542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.89064897156487,168.95336516806938],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.00770831106672,169.4128653744158],[169.99796493107303,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.08968496955248,169.81172223294573],[170.9492051502293,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.14553626674518,170.1540159102598],[171.7996075308126,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.18238987263604,170.44393888058158],[172.5457254570127,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.20580725120632,170.6857592030873],[173.18694334757177,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2200295079158,170.88379409754347],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.22820393443305,171.04239149313332],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23259015718264,171.16591759537795],[174.5136772126083,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2347452187699,171.25874886104174],[174.7787355115039,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23568720142907,171.32526708618758],[174.97042363235644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2360371788439,171.36985659529591],[175.0997505080749,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23613938850093,171.3969027679839],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2361595754449,171.41079135350373],[175.21906944484536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616148789233,171.41590820144467],[175.23402437178987,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":14,"ty":4,"nm":"face_1_slot_0","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[100],"h":1},{"t":40,"s":[100],"h":1},{"t":41,"s":[100],"h":1},{"t":42,"s":[100],"h":1},{"t":43,"s":[100],"h":1},{"t":44,"s":[100],"h":1},{"t":45,"s":[100],"h":1},{"t":46,"s":[100],"h":1},{"t":47,"s":[100],"h":1},{"t":48,"s":[100],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.7659756282101,171.41663917972903],[24.763838512107654,171.4159082014447]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515457,171.41663917972903],[24.76384042455507,171.41079135350375]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[24.763860611499055,171.3969027679839]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192508,171.41663917972903],[24.7639628211561,171.36985659529594]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.02957636764353,171.41663917972903],[24.76431279857094,171.32526708618758]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496132,171.41663917972903],[24.765254781230098,171.25874886104174]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391742,171.41663917972903],[24.767409842817358,171.16591759537795]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087367,171.41663917972903],[24.771796065566974,171.04239149313335]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.27467983390227,171.41663917972903],[24.779970492084203,170.8837940975435]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.813056652428145,171.41663917972903],[24.794192748793662,170.68575920308734]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987264,171.41663917972903],[24.817610127363963,170.44393888058158]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187406,171.41663917972903],[24.854463733254804,170.1540159102598]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.050794849770682,171.41663917972903],[24.910315030447507,169.81172223294573]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926943,171.41663917972903],[24.992291688933264,169.41286537441582]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[25.109351028435142,168.95336516806938]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.17881490745795,171.41663917972903],[25.272558490807143,168.42930348868117]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339733,171.41663917972903],[25.495377398147852,167.83699010401403]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[25.793964688948876,167.17304813479808]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795812,171.41663917972903],[26.18746528869424,166.43452296328823]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312886,171.41663917972903],[26.698295178322923,165.61901871326907]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[27.352399988699673,164.72486659520754]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[28.179471994628386,163.75132940997366]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.20571106244855,171.41663917972903],[29.213103649674565,162.69884625649112]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444464,171.41663917972903],[30.49085026857678,161.56932089599854]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527375,171.41663917972903],[32.054168156800245,160.36645616899273]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009054,171.41663917972903],[33.948187516970535,159.09613519733577]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.4085587911411,171.41663917972903],[36.22127205421518,157.76684766723452]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.0958967150356,171.41663917972903],[38.92430973769417,156.39015609296857]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[42.10967224006833,154.9811924086707]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[45.82977501747337,153.55916933063907]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.701269939579305,171.41663917972903],[50.13516697637628,152.14788350454046]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[55.07207974263926,150.77617838683688]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042787,171.41663917972903],[60.67937366393438,149.47832409788663]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709705,171.41663917972903],[66.984833238743,148.29425928080326]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.40311076286019,171.41663917972903],[74.00079148302312,147.26962670455904]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.97571938286738,171.41663917972903],[81.71910393906488,146.4555207003181]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.99395419133931,171.41663917972903],[90.10555182515573,145.9078517026294]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.65389249599157,171.41663917972903],[99.09383319990782,145.6862229301544]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.254606555010795,168.4823104778698],[108.5794031700209,145.85220900074034],[108.5794031700209,145.85220900074034]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.051928158630545,165.11883425295738],[118.41354975626373,146.46692919321268],[118.41354975626373,146.46692919321268]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.329202572241016,161.70386936171468],[128.3982391316816,147.58782305787327],[128.3982391316816,147.58782305787327]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.23167595892863,158.32327808225233],[138.2824267897266,149.26456770823847],[138.2824267897266,149.26456770823847]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[41.867430278900926,155.08151817465492],[147.76069867183222,151.5341293518293],[147.76069867183222,151.5341293518293]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.290594742135035,152.10096254861588],[156.47526032617597,154.4150212688003],[156.47526032617597,154.4150212688003]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.48276971388455,149.51968659541475],[164.0224063161806,157.90095041343838],[164.0224063161806,157.90095041343838]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[72.33361100630755,147.4873228087879],[169.96464049825235,161.95417685080264],[169.96464049825235,161.95417685080264]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.62202576908322,146.15861054812373],[173.84953525253286,166.4990823725381],[173.84953525253286,166.4990823725381]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.37797423091669,146.15861054812373],[164.15776704046982,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[127.6663889936925,147.4873228087879],[157.9782885569902,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.51723028611542,149.51968659541475],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[149.7094052578649,152.10096254861585],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[158.13256972109895,155.08151817465486],[153.45457823622954,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.7683240410713,158.3232780822523],[154.92905150486584,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.67079742775897,161.70386936171468],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.94807184136943,165.11883425295736],[161.9568687706681,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.7453934449892,168.48231047786976],[167.93271906985146,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751336,171.41663917972903],[24.763838481751336,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":15,"ty":4,"nm":"face_2_slot_0","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[100],"h":1},{"t":1,"s":[100],"h":1},{"t":2,"s":[100],"h":1},{"t":3,"s":[100],"h":1},{"t":4,"s":[100],"h":1},{"t":5,"s":[100],"h":1},{"t":6,"s":[100],"h":1},{"t":7,"s":[100],"h":1},{"t":8,"s":[100],"h":1},{"t":9,"s":[100],"h":1},{"t":10,"s":[100],"h":1},{"t":11,"s":[100],"h":1},{"t":12,"s":[100],"h":1},{"t":13,"s":[100],"h":1},{"t":14,"s":[100],"h":1},{"t":15,"s":[100],"h":1},{"t":16,"s":[100],"h":1},{"t":17,"s":[100],"h":1},{"t":18,"s":[100],"h":1},{"t":19,"s":[100],"h":1},{"t":20,"s":[100],"h":1},{"t":21,"s":[100],"h":1},{"t":22,"s":[100],"h":1},{"t":23,"s":[100],"h":1},{"t":24,"s":[100],"h":1},{"t":25,"s":[100],"h":1},{"t":26,"s":[100],"h":1},{"t":27,"s":[100],"h":1},{"t":28,"s":[100],"h":1},{"t":29,"s":[100],"h":1},{"t":30,"s":[100],"h":1},{"t":31,"s":[100],"h":1},{"t":32,"s":[100],"h":1},{"t":33,"s":[100],"h":1},{"t":34,"s":[100],"h":1},{"t":35,"s":[100],"h":1},{"t":36,"s":[100],"h":1},{"t":37,"s":[100],"h":1},{"t":38,"s":[100],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[0],"h":1},{"t":59,"s":[0],"h":1},{"t":60,"s":[0],"h":1},{"t":61,"s":[0],"h":1},{"t":62,"s":[0],"h":1},{"t":63,"s":[0],"h":1},{"t":64,"s":[0],"h":1},{"t":65,"s":[0],"h":1},{"t":66,"s":[0],"h":1},{"t":67,"s":[0],"h":1},{"t":68,"s":[0],"h":1},{"t":69,"s":[0],"h":1},{"t":70,"s":[0],"h":1},{"t":71,"s":[0],"h":1},{"t":72,"s":[0],"h":1},{"t":73,"s":[0],"h":1},{"t":74,"s":[0],"h":1},{"t":75,"s":[0],"h":1},{"t":76,"s":[0],"h":1},{"t":77,"s":[0],"h":1},{"t":78,"s":[0],"h":1},{"t":79,"s":[0],"h":1},{"t":80,"s":[0],"h":1},{"t":81,"s":[0],"h":1},{"t":82,"s":[0],"h":1},{"t":83,"s":[0],"h":1},{"t":84,"s":[0],"h":1},{"t":85,"s":[0],"h":1},{"t":86,"s":[0],"h":1},{"t":87,"s":[0],"h":1},{"t":88,"s":[0],"h":1},{"t":89,"s":[0],"h":1},{"t":90,"s":[0],"h":1},{"t":91,"s":[0],"h":1},{"t":92,"s":[0],"h":1},{"t":93,"s":[0],"h":1},{"t":94,"s":[0],"h":1},{"t":95,"s":[0],"h":1},{"t":96,"s":[0],"h":1},{"t":97,"s":[100],"h":1},{"t":98,"s":[100],"h":1},{"t":99,"s":[100],"h":1},{"t":100,"s":[100],"h":1},{"t":101,"s":[100],"h":1},{"t":102,"s":[100],"h":1},{"t":103,"s":[100],"h":1},{"t":104,"s":[100],"h":1},{"t":105,"s":[100],"h":1},{"t":106,"s":[100],"h":1},{"t":107,"s":[100],"h":1},{"t":108,"s":[100],"h":1},{"t":109,"s":[100],"h":1},{"t":110,"s":[100],"h":1},{"t":111,"s":[100],"h":1},{"t":112,"s":[100],"h":1},{"t":113,"s":[100],"h":1},{"t":114,"s":[100],"h":1},{"t":115,"s":[100],"h":1},{"t":116,"s":[100],"h":1},{"t":117,"s":[100],"h":1},{"t":118,"s":[100],"h":1},{"t":119,"s":[100],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838512107654,171.4159082014447],[100.00213723752422,145.68435644436695],[100.00213723752422,145.68435644436695]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76384042455507,171.41079135350375],[100.01709790004887,145.68435709846247],[100.01709790004887,145.68435709846247]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763860611499055,171.3969027679839],[100.05770540750385,145.68436400280396],[100.05770540750385,145.68436400280396]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.7639628211561,171.36985659529594],[100.1367831262165,145.68439896056552],[100.1367831262165,145.68439896056552]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76431279857094,171.32526708618758],[100.26715412914858,145.6845186598911],[100.26715412914858,145.6845186598911]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.765254781230098,171.25874886104174],[100.46164040852113,145.68484083693517],[100.46164040852113,145.68484083693517]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.767409842817358,171.16591759537795],[100.73306087154158,145.68557791140813],[100.73306087154158,145.68557791140813]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.771796065566974,171.04239149313335],[101.09422703281935,145.68707808794161],[101.09422703281935,145.68707808794161]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.779970492084203,170.8837940975435],[101.55793479589938,145.68987390647064],[101.55793479589938,145.68987390647064]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.794192748793662,170.68575920308734],[102.13695009169614,145.69473820474883],[102.13695009169614,145.69473820474883]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.817610127363963,170.44393888058158],[102.84398541468727,145.70274741992375],[102.84398541468727,145.70274741992375]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.854463733254804,170.1540159102598],[103.69166347102245,145.71535209549262],[103.69166347102245,145.71535209549262]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.910315030447507,169.81172223294573],[104.69246323090135,145.73445436416338],[104.69246323090135,145.73445436416338]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.992291688933264,169.41286537441582],[105.85864266890633,145.76249203264803],[105.85864266890633,145.76249203264803]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.109351028435142,168.95336516806938],[107.20213139409789,145.8025286847221],[107.20213139409789,145.8025286847221]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.272558490807143,168.42930348868117],[108.73438523824998,145.85834892439436],[108.73438523824998,145.85834892439436]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.495377398147852,167.83699010401403],[110.46619371861527,145.9345574790187],[110.46619371861527,145.9345574790187]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.793964688948876,167.17304813479808],[112.40743016966178,146.03668034701371],[112.40743016966178,146.03668034701371]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.18746528869424,166.43452296328823],[114.56673331575352,146.17126547853735],[114.56673331575352,146.17126547853735]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[26.698295178322923,165.61901871326907],[116.9511082303112,146.34597959060318],[116.9511082303112,146.34597959060318]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.352399988699673,164.72486659520754],[119.56543412751468,146.56969661159826],[119.56543412751468,146.56969661159826]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[28.179471994628386,163.75132940997366],[122.41186643342385,146.85257189760665],[122.41186643342385,146.85257189760665]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.213103649674565,162.69884625649112],[125.48912130867366,147.20609474441147],[125.48912130867366,147.20609474441147]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[30.49085026857678,161.56932089599854],[128.79163252777767,147.6431098261423],[128.79163252777767,147.6431098261423]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.054168156800245,160.36645616899273],[132.30857370939827,148.17779603433607],[132.30857370939827,148.17779603433607]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[33.948187516970535,159.09613519733577],[136.02274375594828,148.82558880736312],[136.02274375594828,148.82558880736312]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[36.22127205421518,157.76684766723452],[139.9093204855403,149.60302950658289],[139.9093204855403,149.60302950658289]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[38.92430973769417,156.39015609296857],[143.93449736804646,150.52752284250107],[143.93449736804646,150.52752284250107]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[42.10967224006833,154.9811924086707],[148.05403158786663,151.61698098210726],[148.05403158786663,151.61698098210726]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[45.82977501747337,153.55916933063907],[152.21174892054898,152.88933106722158],[152.21174892054898,152.88933106722158]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[50.13516697637628,152.14788350454046],[156.33807262878386,154.36186184207872],[156.33807262878386,154.36186184207872]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[55.07207974263926,150.77617838683688],[160.34867008765178,156.0503854539823],[160.34867008765178,156.0503854539823]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.67937366393438,149.47832409788663],[164.14334216845504,157.96819292461282],[164.14334216845504,157.96819292461282]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[66.984833238743,148.29425928080326],[167.60531609072166,160.12478711212304],[167.60531609072166,160.12478711212304]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.00079148302312,147.26962670455904],[170.60114132569498,162.52438615639866],[170.60114132569498,162.52438615639866]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[81.71910393906488,146.4555207003181],[172.98142804309384,165.16420448884634],[172.98142804309384,165.16420448884634]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[90.10555182515573,145.9078517026294],[174.58270506836902,168.0325385968404],[174.58270506836902,168.0325385968404]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.09383319990782,145.6862229301544],[175.2307042485341,171.10671188088455],[175.2307042485341,171.10671188088455]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.5794031700209,145.85220900074034],[167.93271906985157,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[118.41354975626373,146.46692919321268],[161.95686877066814,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.3982391316816,147.58782305787327],[157.71933934080334,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[138.2824267897266,149.26456770823847],[154.92905150486587,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[147.76069867183222,151.5341293518293],[153.45457823622957,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.47526032617597,154.4150212688003],[153.30788554887857,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.0224063161806,157.90095041343838],[154.6696915862507,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[169.96464049825235,161.95417685080264],[157.97828855699024,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[173.84953525253286,166.4990823725381],[164.15776704046976,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.653892495991485,171.41663917972903],[24.76929575146589,171.10671188088457]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.993954191339256,171.41663917972903],[25.417294931630963,168.03253859684042]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.975719382867354,171.41663917972903],[27.01857195690613,165.16420448884637]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.403110762860145,171.41663917972903],[29.398858674304975,162.5243861563987]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.74425723709703,171.41663917972903],[32.394683909278314,160.12478711212307]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.29032588042786,171.41663917972903],[35.856657831544936,157.96819292461282]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.23230120343495,171.41663917972903],[39.65132991234821,156.0503854539823]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.70126993957929,171.41663917972903],[43.661927371216095,154.36186184207872]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.79098542430458,171.41663917972903],[47.78825107945101,152.88933106722158]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.571199874666725,171.41663917972903],[51.94596841213336,151.61698098210726]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.095896715035614,171.41663917972903],[56.06550263195349,150.52752284250107]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.40855879114112,171.41663917972903],[60.09067951445965,149.6030295065829]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[44.54563205009055,171.41663917972903],[63.97725624405165,148.82558880736312]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[43.53884032527377,171.41663917972903],[67.69142629060164,148.1777960343361]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.41673494444467,171.41663917972903],[71.20836747222228,147.6431098261423]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[41.205711062448565,171.41663917972903],[74.5108786913263,147.20609474441147]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[39.930636022662924,171.41663917972903],[77.58813356657613,146.85257189760665]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.615185446789816,171.41663917972903],[80.43456587248531,146.56969661159826]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[37.281954893312914,171.41663917972903],[83.04889176968875,146.34597959060318]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.95240007795813,171.41663917972903],[85.43326668424646,146.17126547853735]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[34.64665143481096,171.41663917972903],[87.59256983033822,146.03668034701371]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[33.38324562339737,171.41663917972903],[89.53380628138467,145.9345574790187]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.178814907457976,171.41663917972903],[91.26561476174996,145.85834892439436]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[31.047773326877973,171.41663917972903],[92.79786860590211,145.8025286847221]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[30.002035068926972,171.41663917972903],[94.14135733109363,145.76249203264803]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[29.05079484977071,171.41663917972903],[95.30753676909862,145.73445436416338]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[28.200392469187392,171.41663917972903],[96.30833652897755,145.71535209549262]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[27.454274542987292,171.41663917972903],[97.1560145853127,145.70274741992375]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.81305665242823,171.41663917972903],[97.8630499083038,145.69473820474883]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[26.274679833902283,171.41663917972903],[98.44206520410059,145.68987390647064]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.834647452087395,171.41663917972903],[98.9057729671806,145.68707808794161]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.486322787391714,171.41663917972903],[99.26693912845845,145.68557791140813]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.221264488496118,171.41663917972903],[99.53835959147887,145.68484083693517]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[25.029576367643557,171.41663917972903],[99.7328458708514,145.6845186598911]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.90024949192511,171.41663917972903],[99.86321687378347,145.68439896056552]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.82147756784029,171.41663917972903],[99.94229459249615,145.68436400280396]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.78093055515464,171.41663917972903],[99.98290209995109,145.6843570984625]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.765975628210114,171.41663917972903],[99.99786276247576,145.68435644436695]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[24.763838481751364,171.41663917972903],[99.99999999999999,145.68435643398448]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.763838481751336,171.41663917972903],[100,145.68435643398448],[100,145.68435643398448]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0},{"ddd":0,"ind":16,"ty":4,"nm":"face_3_slot_0","sr":1,"ks":{"o":{"a":1,"k":[{"t":0,"s":[0],"h":1},{"t":1,"s":[0],"h":1},{"t":2,"s":[0],"h":1},{"t":3,"s":[0],"h":1},{"t":4,"s":[0],"h":1},{"t":5,"s":[0],"h":1},{"t":6,"s":[0],"h":1},{"t":7,"s":[0],"h":1},{"t":8,"s":[0],"h":1},{"t":9,"s":[0],"h":1},{"t":10,"s":[0],"h":1},{"t":11,"s":[0],"h":1},{"t":12,"s":[0],"h":1},{"t":13,"s":[0],"h":1},{"t":14,"s":[0],"h":1},{"t":15,"s":[0],"h":1},{"t":16,"s":[0],"h":1},{"t":17,"s":[0],"h":1},{"t":18,"s":[0],"h":1},{"t":19,"s":[0],"h":1},{"t":20,"s":[0],"h":1},{"t":21,"s":[0],"h":1},{"t":22,"s":[0],"h":1},{"t":23,"s":[0],"h":1},{"t":24,"s":[0],"h":1},{"t":25,"s":[0],"h":1},{"t":26,"s":[0],"h":1},{"t":27,"s":[0],"h":1},{"t":28,"s":[0],"h":1},{"t":29,"s":[0],"h":1},{"t":30,"s":[0],"h":1},{"t":31,"s":[0],"h":1},{"t":32,"s":[0],"h":1},{"t":33,"s":[0],"h":1},{"t":34,"s":[0],"h":1},{"t":35,"s":[0],"h":1},{"t":36,"s":[0],"h":1},{"t":37,"s":[0],"h":1},{"t":38,"s":[0],"h":1},{"t":39,"s":[0],"h":1},{"t":40,"s":[0],"h":1},{"t":41,"s":[0],"h":1},{"t":42,"s":[0],"h":1},{"t":43,"s":[0],"h":1},{"t":44,"s":[0],"h":1},{"t":45,"s":[0],"h":1},{"t":46,"s":[0],"h":1},{"t":47,"s":[0],"h":1},{"t":48,"s":[0],"h":1},{"t":49,"s":[0],"h":1},{"t":50,"s":[0],"h":1},{"t":51,"s":[0],"h":1},{"t":52,"s":[0],"h":1},{"t":53,"s":[0],"h":1},{"t":54,"s":[0],"h":1},{"t":55,"s":[0],"h":1},{"t":56,"s":[0],"h":1},{"t":57,"s":[0],"h":1},{"t":58,"s":[100],"h":1},{"t":59,"s":[100],"h":1},{"t":60,"s":[100],"h":1},{"t":61,"s":[100],"h":1},{"t":62,"s":[100],"h":1},{"t":63,"s":[100],"h":1},{"t":64,"s":[100],"h":1},{"t":65,"s":[100],"h":1},{"t":66,"s":[100],"h":1},{"t":67,"s":[100],"h":1},{"t":68,"s":[100],"h":1},{"t":69,"s":[100],"h":1},{"t":70,"s":[100],"h":1},{"t":71,"s":[100],"h":1},{"t":72,"s":[100],"h":1},{"t":73,"s":[100],"h":1},{"t":74,"s":[100],"h":1},{"t":75,"s":[100],"h":1},{"t":76,"s":[100],"h":1},{"t":77,"s":[100],"h":1},{"t":78,"s":[100],"h":1},{"t":79,"s":[100],"h":1},{"t":80,"s":[100],"h":1},{"t":81,"s":[100],"h":1},{"t":82,"s":[100],"h":1},{"t":83,"s":[100],"h":1},{"t":84,"s":[100],"h":1},{"t":85,"s":[100],"h":1},{"t":86,"s":[100],"h":1},{"t":87,"s":[100],"h":1},{"t":88,"s":[100],"h":1},{"t":89,"s":[100],"h":1},{"t":90,"s":[100],"h":1},{"t":91,"s":[100],"h":1},{"t":92,"s":[100],"h":1},{"t":93,"s":[100],"h":1},{"t":94,"s":[100],"h":1},{"t":95,"s":[100],"h":1},{"t":96,"s":[100],"h":1},{"t":97,"s":[0],"h":1},{"t":98,"s":[0],"h":1},{"t":99,"s":[0],"h":1},{"t":100,"s":[0],"h":1},{"t":101,"s":[0],"h":1},{"t":102,"s":[0],"h":1},{"t":103,"s":[0],"h":1},{"t":104,"s":[0],"h":1},{"t":105,"s":[0],"h":1},{"t":106,"s":[0],"h":1},{"t":107,"s":[0],"h":1},{"t":108,"s":[0],"h":1},{"t":109,"s":[0],"h":1},{"t":110,"s":[0],"h":1},{"t":111,"s":[0],"h":1},{"t":112,"s":[0],"h":1},{"t":113,"s":[0],"h":1},{"t":114,"s":[0],"h":1},{"t":115,"s":[0],"h":1},{"t":116,"s":[0],"h":1},{"t":117,"s":[0],"h":1},{"t":118,"s":[0],"h":1},{"t":119,"s":[0],"h":1}]},"r":{"a":0,"k":0},"p":{"a":0,"k":[0,0,0]},"a":{"a":0,"k":[0,0,0]},"s":{"a":0,"k":[100,100,100]}},"ao":0,"shapes":[{"ty":"gr","it":[{"ty":"sh","ks":{"a":1,"k":[{"t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":1,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.00213723752422,145.68435644436695],[175.2340243717899,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":2,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.01709790004887,145.68435709846247],[175.21906944484545,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":3,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.05770540750385,145.68436400280396],[175.1785224321597,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":4,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.1367831262165,145.68439896056552],[175.09975050807492,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":5,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.26715412914858,145.6845186598911],[174.97042363235647,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":6,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.46164040852113,145.68484083693517],[174.77873551150387,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":7,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100.73306087154158,145.68557791140813],[174.51367721260826,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":8,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.09422703281935,145.68707808794161],[174.16535254791262,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":9,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[101.55793479589938,145.68987390647064],[173.72532016609773,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":10,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.13695009169614,145.69473820474883],[173.18694334757186,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":11,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[102.84398541468727,145.70274741992375],[172.54572545701274,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":12,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[103.69166347102245,145.71535209549262],[171.79960753081258,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":13,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[104.69246323090135,145.73445436416338],[170.94920515022932,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":14,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[105.85864266890633,145.76249203264803],[169.99796493107306,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":15,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[107.20213139409789,145.8025286847221],[168.95222667312203,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":16,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[108.73438523824998,145.85834892439436],[167.82118509254207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":17,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[110.46619371861527,145.9345574790187],[166.61675437660267,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":18,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[112.40743016966178,146.03668034701371],[165.35334856518904,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":19,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[114.56673331575352,146.17126547853735],[164.04759992204188,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":20,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[116.9511082303112,146.34597959060318],[162.7180451066871,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":21,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[119.56543412751468,146.56969661159826],[161.3848145532102,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":22,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[122.41186643342385,146.85257189760665],[160.06936397733708,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":23,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[125.48912130867366,147.20609474441147],[158.79428893755144,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":24,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[128.79163252777767,147.6431098261423],[157.58326505555536,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":25,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[132.30857370939827,148.17779603433607],[156.46115967472625,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":26,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[136.02274375594828,148.82558880736312],[155.45436794990945,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":27,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[139.9093204855403,149.60302950658289],[154.5914412088589,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":28,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[143.93449736804646,150.52752284250107],[153.9041032849644,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":29,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[148.05403158786663,151.61698098210726],[153.42880012533328,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":30,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[152.21174892054898,152.88933106722158],[153.20901457569542,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":31,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[156.33807262878386,154.36186184207872],[153.2987300604207,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":32,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[160.34867008765178,156.0503854539823],[153.76769879656504,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":33,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[164.14334216845504,157.96819292461282],[154.70967411957213,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":34,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[167.60531609072166,160.12478711212304],[156.25574276290294,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":35,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[170.60114132569498,162.52438615639866],[158.5968892371398,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":36,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[172.98142804309384,165.16420448884634],[162.0242806171326,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":37,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[174.58270506836902,168.0325385968404],[167.0060458086607,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":38,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[175.2307042485341,171.10671188088455],[174.34610750400844,171.41663917972903],[100,28.583360820270954]],"c":true}],"h":1},{"t":39,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":40,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":41,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":42,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":43,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":44,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":45,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":46,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":47,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":48,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954],[100,28.583360820270954]],"c":true}],"h":1},{"t":49,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[35.842232959530165,171.41663917972903],[26.15046474746714,166.49908237253814]],"c":true}],"h":1},{"t":50,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.02171144300978,171.41663917972903],[30.035359501747664,161.95417685080264]],"c":true}],"h":1},{"t":51,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.330308413749286,171.41663917972903],[35.97759368381941,157.9009504134384]],"c":true}],"h":1},{"t":52,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.69211445112142,171.41663917972903],[43.524739673823944,154.41502126880033]],"c":true}],"h":1},{"t":53,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[46.54542176377046,171.41663917972903],[52.23930132816764,151.53412935182934]],"c":true}],"h":1},{"t":54,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[45.07094849513416,171.41663917972903],[61.71757321027329,149.26456770823847]],"c":true}],"h":1},{"t":55,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[42.28066065919667,171.41663917972903],[71.60176086831838,147.5878230578733]],"c":true}],"h":1},{"t":56,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[38.043131229331905,171.41663917972903],[81.58645024373618,146.4669291932127]],"c":true}],"h":1},{"t":57,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,28.583360820270954],[32.06728093014854,171.41663917972903],[91.42059682997896,145.85220900074034]],"c":true}],"h":1},{"t":58,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[24.76929575146589,171.10671188088457],[100.9061668000921,145.6862229301544],[100.9061668000921,145.6862229301544]],"c":true}],"h":1},{"t":59,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[25.417294931630963,168.03253859684042],[109.89444817484419,145.9078517026294],[109.89444817484419,145.9078517026294]],"c":true}],"h":1},{"t":60,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[27.01857195690613,165.16420448884637],[118.28089606093508,146.4555207003181],[118.28089606093508,146.4555207003181]],"c":true}],"h":1},{"t":61,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[29.398858674304975,162.5243861563987],[125.9992085169768,147.26962670455904],[125.9992085169768,147.26962670455904]],"c":true}],"h":1},{"t":62,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[32.394683909278314,160.12478711212307],[133.01516676125698,148.29425928080326],[133.01516676125698,148.29425928080326]],"c":true}],"h":1},{"t":63,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[35.856657831544936,157.96819292461282],[139.32062633606557,149.47832409788663],[139.32062633606557,149.47832409788663]],"c":true}],"h":1},{"t":64,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[39.65132991234821,156.0503854539823],[144.9279202573607,150.77617838683688],[144.9279202573607,150.77617838683688]],"c":true}],"h":1},{"t":65,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[43.661927371216095,154.36186184207872],[149.86483302362365,152.14788350454043],[149.86483302362365,152.14788350454043]],"c":true}],"h":1},{"t":66,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[47.78825107945101,152.88933106722158],[154.1702249825266,153.55916933063904],[154.1702249825266,153.55916933063904]],"c":true}],"h":1},{"t":67,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[51.94596841213336,151.61698098210726],[157.89032775993167,154.98119240867067],[157.89032775993167,154.98119240867067]],"c":true}],"h":1},{"t":68,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[56.06550263195349,150.52752284250107],[161.07569026230578,156.39015609296857],[161.07569026230578,156.39015609296857]],"c":true}],"h":1},{"t":69,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[60.09067951445965,149.6030295065829],[163.7787279457848,157.7668476672345],[163.7787279457848,157.7668476672345]],"c":true}],"h":1},{"t":70,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[63.97725624405165,148.82558880736312],[166.05181248302944,159.09613519733574],[166.05181248302944,159.09613519733574]],"c":true}],"h":1},{"t":71,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[67.69142629060164,148.1777960343361],[167.94583184319973,160.36645616899267],[167.94583184319973,160.36645616899267]],"c":true}],"h":1},{"t":72,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[71.20836747222228,147.6431098261423],[169.5091497314232,161.56932089599852],[169.5091497314232,161.56932089599852]],"c":true}],"h":1},{"t":73,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[74.5108786913263,147.20609474441147],[170.78689635032543,162.6988462564911],[170.78689635032543,162.6988462564911]],"c":true}],"h":1},{"t":74,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[77.58813356657613,146.85257189760665],[171.8205280053716,163.75132940997366],[171.8205280053716,163.75132940997366]],"c":true}],"h":1},{"t":75,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[80.43456587248531,146.56969661159826],[172.64760001130034,164.72486659520752],[172.64760001130034,164.72486659520752]],"c":true}],"h":1},{"t":76,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[83.04889176968875,146.34597959060318],[173.30170482167705,165.61901871326904],[173.30170482167705,165.61901871326904]],"c":true}],"h":1},{"t":77,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[85.43326668424646,146.17126547853735],[173.81253471130574,166.43452296328823],[173.81253471130574,166.43452296328823]],"c":true}],"h":1},{"t":78,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[87.59256983033822,146.03668034701371],[174.20603531105112,167.17304813479808],[174.20603531105112,167.17304813479808]],"c":true}],"h":1},{"t":79,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[89.53380628138467,145.9345574790187],[174.50462260185213,167.836990104014],[174.50462260185213,167.836990104014]],"c":true}],"h":1},{"t":80,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[91.26561476174996,145.85834892439436],[174.72744150919286,168.42930348868117],[174.72744150919286,168.42930348868117]],"c":true}],"h":1},{"t":81,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[92.79786860590211,145.8025286847221],[174.89064897156487,168.95336516806938],[174.89064897156487,168.95336516806938]],"c":true}],"h":1},{"t":82,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[94.14135733109363,145.76249203264803],[175.00770831106672,169.4128653744158],[175.00770831106672,169.4128653744158]],"c":true}],"h":1},{"t":83,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[95.30753676909862,145.73445436416338],[175.08968496955248,169.81172223294573],[175.08968496955248,169.81172223294573]],"c":true}],"h":1},{"t":84,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[96.30833652897755,145.71535209549262],[175.14553626674518,170.1540159102598],[175.14553626674518,170.1540159102598]],"c":true}],"h":1},{"t":85,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.1560145853127,145.70274741992375],[175.18238987263604,170.44393888058158],[175.18238987263604,170.44393888058158]],"c":true}],"h":1},{"t":86,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[97.8630499083038,145.69473820474883],[175.20580725120632,170.6857592030873],[175.20580725120632,170.6857592030873]],"c":true}],"h":1},{"t":87,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.44206520410059,145.68987390647064],[175.2200295079158,170.88379409754347],[175.2200295079158,170.88379409754347]],"c":true}],"h":1},{"t":88,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[98.9057729671806,145.68707808794161],[175.22820393443305,171.04239149313332],[175.22820393443305,171.04239149313332]],"c":true}],"h":1},{"t":89,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.26693912845845,145.68557791140813],[175.23259015718264,171.16591759537795],[175.23259015718264,171.16591759537795]],"c":true}],"h":1},{"t":90,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.53835959147887,145.68484083693517],[175.2347452187699,171.25874886104174],[175.2347452187699,171.25874886104174]],"c":true}],"h":1},{"t":91,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.7328458708514,145.6845186598911],[175.23568720142907,171.32526708618758],[175.23568720142907,171.32526708618758]],"c":true}],"h":1},{"t":92,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.86321687378347,145.68439896056552],[175.2360371788439,171.36985659529591],[175.2360371788439,171.36985659529591]],"c":true}],"h":1},{"t":93,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.94229459249615,145.68436400280396],[175.23613938850093,171.3969027679839],[175.23613938850093,171.3969027679839]],"c":true}],"h":1},{"t":94,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.98290209995109,145.6843570984625],[175.2361595754449,171.41079135350373],[175.2361595754449,171.41079135350373]],"c":true}],"h":1},{"t":95,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99786276247576,145.68435644436695],[175.23616148789233,171.41590820144467],[175.23616148789233,171.41590820144467]],"c":true}],"h":1},{"t":96,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[99.99999999999999,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":97,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":98,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":99,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":100,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":101,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":102,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":103,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":104,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":105,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":106,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":107,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":108,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":109,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":110,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":111,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":112,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":113,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":114,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":115,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":116,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":117,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":118,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1},{"t":119,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[100,28.583360820270954],[100,145.68435643398448],[175.23616151824865,171.41663917972903],[175.23616151824865,171.41663917972903]],"c":true}],"h":1}]}},{"ty":"fl","c":{"a":0,"k":[0.5294117647058824,0.3568627450980392,0.0784313725490196,1]},"o":{"a":0,"k":100},"r":1,"bm":0},{"ty":"st","c":{"a":0,"k":[0.9607843137254902,0.6470588235294118,0.1411764705882353,1]},"o":{"a":0,"k":100},"w":{"a":0,"k":2.9166666666666665},"lc":2,"lj":2,"ml":4,"bm":0},{"ty":"tr","p":{"a":0,"k":[0,0]},"a":{"a":0,"k":[0,0]},"s":{"a":0,"k":[100,100]},"r":{"a":0,"k":0},"o":{"a":0,"k":100},"sk":{"a":0,"k":0},"sa":{"a":0,"k":0}}],"nm":"face"}],"ip":0,"op":120,"st":0,"bm":0}]} \ No newline at end of file diff --git a/loader icon/pyramid-loader.svg b/loader icon/pyramid-loader.svg new file mode 100644 index 0000000..6246393 --- /dev/null +++ b/loader icon/pyramid-loader.svg @@ -0,0 +1,53 @@ + + + + + \ No newline at end of file diff --git a/macos/Flutter/GeneratedPluginRegistrant.swift b/macos/Flutter/GeneratedPluginRegistrant.swift index 4445597..03d6ff3 100644 --- a/macos/Flutter/GeneratedPluginRegistrant.swift +++ b/macos/Flutter/GeneratedPluginRegistrant.swift @@ -6,21 +6,47 @@ import FlutterMacOS import Foundation import connectivity_plus +import desktop_drop import device_info_plus -import dynamic_color +import file_picker +import firebase_core +import firebase_messaging +import flutter_local_notifications import flutter_secure_storage_darwin import flutter_webrtc import livekit_client +import local_notifier +import media_kit_libs_macos_video +import media_kit_video +import package_info_plus +import pdfx import shared_preferences_foundation +import sqflite_darwin import sqlcipher_flutter_libs +import url_launcher_macos +import volume_controller +import wakelock_plus func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) { ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin")) + DesktopDropPlugin.register(with: registry.registrar(forPlugin: "DesktopDropPlugin")) DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin")) - DynamicColorPlugin.register(with: registry.registrar(forPlugin: "DynamicColorPlugin")) + FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin")) + FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin")) + FLTFirebaseMessagingPlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseMessagingPlugin")) + FlutterLocalNotificationsPlugin.register(with: registry.registrar(forPlugin: "FlutterLocalNotificationsPlugin")) FlutterSecureStorageDarwinPlugin.register(with: registry.registrar(forPlugin: "FlutterSecureStorageDarwinPlugin")) FlutterWebRTCPlugin.register(with: registry.registrar(forPlugin: "FlutterWebRTCPlugin")) LiveKitPlugin.register(with: registry.registrar(forPlugin: "LiveKitPlugin")) + LocalNotifierPlugin.register(with: registry.registrar(forPlugin: "LocalNotifierPlugin")) + MediaKitLibsMacosVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitLibsMacosVideoPlugin")) + MediaKitVideoPlugin.register(with: registry.registrar(forPlugin: "MediaKitVideoPlugin")) + FPPPackageInfoPlusPlugin.register(with: registry.registrar(forPlugin: "FPPPackageInfoPlusPlugin")) + PdfxPlugin.register(with: registry.registrar(forPlugin: "PdfxPlugin")) SharedPreferencesPlugin.register(with: registry.registrar(forPlugin: "SharedPreferencesPlugin")) + SqflitePlugin.register(with: registry.registrar(forPlugin: "SqflitePlugin")) Sqlite3FlutterLibsPlugin.register(with: registry.registrar(forPlugin: "Sqlite3FlutterLibsPlugin")) + UrlLauncherPlugin.register(with: registry.registrar(forPlugin: "UrlLauncherPlugin")) + VolumeControllerPlugin.register(with: registry.registrar(forPlugin: "VolumeControllerPlugin")) + WakelockPlusMacosPlugin.register(with: registry.registrar(forPlugin: "WakelockPlusMacosPlugin")) } diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json index a2ec33f..96d3fee 100644 --- a/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/macos/Runner/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,68 +1,68 @@ { - "images" : [ - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_16.png", - "scale" : "1x" + "info": { + "version": 1, + "author": "xcode" }, - { - "size" : "16x16", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "2x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_32.png", - "scale" : "1x" - }, - { - "size" : "32x32", - "idiom" : "mac", - "filename" : "app_icon_64.png", - "scale" : "2x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_128.png", - "scale" : "1x" - }, - { - "size" : "128x128", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "2x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_256.png", - "scale" : "1x" - }, - { - "size" : "256x256", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "2x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_512.png", - "scale" : "1x" - }, - { - "size" : "512x512", - "idiom" : "mac", - "filename" : "app_icon_1024.png", - "scale" : "2x" - } - ], - "info" : { - "version" : 1, - "author" : "xcode" - } -} + "images": [ + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_16.png", + "scale": "1x" + }, + { + "size": "16x16", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "2x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_32.png", + "scale": "1x" + }, + { + "size": "32x32", + "idiom": "mac", + "filename": "app_icon_64.png", + "scale": "2x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_128.png", + "scale": "1x" + }, + { + "size": "128x128", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "2x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_256.png", + "scale": "1x" + }, + { + "size": "256x256", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "2x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_512.png", + "scale": "1x" + }, + { + "size": "512x512", + "idiom": "mac", + "filename": "app_icon_1024.png", + "scale": "2x" + } + ] +} \ No newline at end of file diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_1024.png index 82b6f9d9a33e198f5747104729e1fcef999772a5..ad5d7666fcefda96f55f912801fe4aae69c83ad6 100644 GIT binary patch literal 94762 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
+ + handleOpenProfile('mira', e)} + onOpenSettings={() => setShowSettings(true)} + call={call} + onLeaveCall={handleLeaveCall} + onToggleStreamCollapse={() => call && updateCall({ streamCollapsed: !call.streamCollapsed })} + onToggleMic={() => call && updateCall({ mic: !call.mic })} + onToggleDeaf={() => call && updateCall({ deaf: !call.deaf })} + onToggleScreen={() => call && updateCall({ streaming: !call.streaming, streamCollapsed: false })} + onToggleCam={() => call && updateCall({ cam: !call.cam })} + onJumpToCall={handleJumpToCall} + /> + {view === 'voice' ? ( + setRailCollapsed(v => !v)} + onOpenProfile={handleOpenProfile} + onToggleMic={() => call && updateCall({ mic: !call.mic })} + onToggleDeaf={() => call && updateCall({ deaf: !call.deaf })} + onToggleCam={() => call && updateCall({ cam: !call.cam })} + onToggleScreen={() => call && updateCall({ streaming: !call.streaming, streamCollapsed: false })} + /> + ) : ( + setMembersOpen(v => !v)} + membersOpen={membersOpen} + onOpenSearch={() => setShowSearch(true)} + onToggleRail={() => setRailCollapsed(v => !v)} + railCollapsed={railCollapsed} + onSend={handleSend} + onReact={handleReact} + /> + )} + {showMembers && } +
+ + { + if (v === 'voice') { + if (!call) startCall({ roomName: 'The Lounge', kind: 'voice', room: { id: 'lounge', name: 'The Lounge' } }); + setView('voice'); + } + else if (v === 'dm') { setActiveSpace('friends'); setActiveRoom('dm-juno'); setView('chat'); } + else if (v === 'chat') { setActiveSpace('atelier'); setActiveRoom('general'); setView('chat'); } + }} + onLogin={() => setLoggedIn(false)} + onSearch={() => setShowSearch(true)} + onSettings={() => setShowSettings(true)} + onProfile={(e) => handleOpenProfile('juno', e)} + onEmoji={(e) => handleOpenEmoji('composer', e)} + onTheme={() => setTheme(t => t === 'dark' ? 'light' : 'dark')} + theme={theme} + /> + + {showSettings && ( + setShowSettings(false)} + theme={theme} + onTheme={setTheme} + accentPresets={ACCENT_PRESETS} + accent={ACCENT_PRESETS[accentIdx].h} + onAccent={(p) => setAccentIdx(ACCENT_PRESETS.findIndex(a => a.name === p.name))} + density={density} + onDensity={setDensity} + motion={motion} + onMotion={setMotion} + radius={radius} + onRadius={setRadius} + /> + )} + {showSearch && setShowSearch(false)} onJump={() => setShowSearch(false)} />} + {profilePopover && ( + setProfilePopover(null)} + /> + )} + {emojiPickerAt && ( + setEmojiPickerAt(null)} + /> + )} + {messageActions && ( + setMessageActions(null)} + /> + )} + {toast && ( +
+ + {toast.msg} +
+ )} + + {tweaksMode && ( + { setTheme(v); pushEdits({ theme: v }); }} + accentIdx={accentIdx} setAccentIdx={(v) => { setAccentIdx(v); pushEdits({ accentIdx: v }); }} + density={density} setDensity={(v) => { setDensity(v); pushEdits({ density: v }); }} + motion={motion} setMotion={(v) => { setMotion(v); pushEdits({ motion: v }); }} + radius={radius} setRadius={(v) => { setRadius(v); pushEdits({ radius: v }); }} + /> + )} + + ); +}; + +const DemoSwitcher = ({ view, setView, onLogin, onSearch, onSettings, onProfile, onEmoji, onTheme, theme }) => { + return ( +
+ + + +
+ + + + + +
+ +
+ ); +}; + +const TweaksPanel = ({ theme, setTheme, accentIdx, setAccentIdx, density, setDensity, motion, setMotion, radius, setRadius }) => ( +
+
+
Tweaks
+ pyramid.sys +
+
+
+
Theme{theme}
+
+ + +
+
+
+
Accent{ACCENT_PRESETS[accentIdx].name}
+
+ {ACCENT_PRESETS.map((p, i) => ( +
setAccentIdx(i)} title={p.name} /> + ))} +
+
+
+
Density{density === 0.85 ? 'compact' : density === 1.2 ? 'cozy' : 'default'}
+
+ + + +
+
+
+
Corner radius{radius}px
+ setRadius(+e.target.value)} /> +
+
+
Motion{Math.round(motion*100)}%
+ setMotion(+e.target.value/100)} /> +
+
+
+); + +ReactDOM.createRoot(document.getElementById('root')).render(); diff --git a/mockup/Chat.jsx b/mockup/Chat.jsx new file mode 100644 index 0000000..9f18df9 --- /dev/null +++ b/mockup/Chat.jsx @@ -0,0 +1,273 @@ +/* Chat view — messages, composer, hover actions */ + +const renderText = (text, onMention) => { + if (!text) return null; + const parts = []; + const regex = /(@\w+|#[\w-]+|https?:\/\/\S+|`[^`]+`)/g; + let last = 0; + text.replace(regex, (m, _, idx) => { + if (idx > last) parts.push(text.slice(last, idx)); + if (m.startsWith('@')) parts.push( onMention?.(m)}>{m}); + else if (m.startsWith('#')) parts.push(
{m}); + else if (m.startsWith('http')) parts.push({m}); + else if (m.startsWith('`')) parts.push({m.slice(1, -1)}); + last = idx + m.length; + return m; + }); + if (last < text.length) parts.push(text.slice(last)); + return parts; +}; + +const Message = ({ msg, onOpenProfile, onReact, onOpenActions, onOpenEmoji }) => { + const hasAvatar = !msg.continuation; + return ( +
+
+ {hasAvatar ? ( +
onOpenProfile?.(msg.author, e)}> + {msg.avatar} +
+ ) : ( +
{msg.time}
+ )} +
+
+ {hasAvatar && ( +
+ onOpenProfile?.(msg.author, e)}>{msg.author} + {msg.time} +
+ )} + {msg.text &&
{renderText(msg.text)}
} + {msg.image && ( +
+ {msg.image} +
+ )} + {msg.reactions && msg.reactions.length > 0 && ( +
+ {msg.reactions.map((r, i) => ( + + ))} + +
+ )} +
+
+ + + + +
+
+ ); +}; + +const ChatHeader = ({ room, roomsData, onToggleMembers, membersOpen, onOpenSearch, onToggleRail, railCollapsed }) => { + const roomDef = findRoom(roomsData, room); + const isDM = roomDef?.type === 'dm'; + const title = roomDef?.name || room; + const topic = isDM + ? `direct message with ${roomDef.name}` + : 'hi-fi corner for paintings, zines, riso, and whatever else'; + + return ( +
+ +
+ {isDM ? ( +
+ {roomDef.avatar} + +
+ ) : ( + {roomIcon(roomDef?.type || 'text')} + )} + {title} +
+ {!isDM &&
{topic}
} + {isDM &&
} +
+ {isDM && ( + <> + + +
+ + )} + + + + +
+
+ ); +}; + +const findRoom = (roomsData, id) => { + if (!roomsData) return null; + for (const section of roomsData.sections) { + const r = section.rooms.find(r => r.id === id); + if (r) return r; + } + return null; +}; + +const Composer = ({ room, onSend, onOpenEmoji }) => { + const [text, setText] = React.useState(''); + const ref = React.useRef(null); + + const submit = () => { + if (text.trim()) { + onSend(text); + setText(''); + } + }; + + const handleKey = (e) => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + submit(); + } + }; + + const roomName = room?.name || room; + const placeholder = typeof roomName === 'string' && roomName.startsWith('dm-') + ? `Message…` + : `Message #${typeof roomName === 'string' ? roomName.replace('dm-', '') : 'room'}`; + + return ( +
+
+
+ +

KHiw$#n=YRhN_yf~hX#Nv5Yu=!8R7!<*E@70*R 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ⅅ8MglG&ER{i5lN315cO?EdHNLrg? zgxkP+ytd)OMWe7QvTf8yj4;V=?m172!BEt@6*TPUT4m3)yir}esnIodFGatGnsSfJ z**;;yw=1VCb2J|A7cBz-F5QFOQh2JDQFLarE>;4ZMzQ$s^)fOscIVv2-o{?ct3~Zv zy{0zU>3`+-PluS|ADraI9n~=3#Tvfx{pDr^5i$^-h5tL*CV@AeQFLxv4Y<$xI{9y< zZ}li*WIQ+XS!IK;?IVD0)C?pNBA(DMxqozMy1L#j+ba1Cd+2w&{^d-OEWSSHmNH>9 z%1Ldo(}5*>a8rjQF&@%Ka`-M|HM+m<^E#bJtVg&YM}uMb7UVJ|OVQI-zt-*BqQ zG&mq`Bn7EY;;+b%Obs9i{gC^%>kUz`{Qnc=ps7ra_UxEP$!?f&|5fHnU(rr?7?)D z$3m9e{&;Zu6yfa1ixTr;80IP7KLgkKCbgv1%f_weZK6b7tY+AS%fyjf6dR(wQa9TD zYG9`#!N4DqpMim|{uViKVf0B+Vmsr7p)Y+;*T~-2HFr!IOedrpiXXz+BDppd5BTf3 ztsg4U?0wR?9@~`iV*nwGmtYFGnq`X< zf?G%=o!t50?gk^qN#J(~!sxi=_yeg?Vio04*w<2iBT+NYX>V#CFuQGLsX^u8dPIkP zPraQK?ro`rqA4t7yUbGYk;pw6Z})Bv=!l-a5^R5Ra^TjoXI?=Qdup)rtyhwo<(c9_ zF>6P%-6Aqxb8gf?wY1z!4*hagIch)&A4treifFk=E9v@kRXyMm?V*~^LEu%Y%0u(| z52VvVF?P^D<|fG)_au(!iqo~1<5eF$Sc5?)*$4P3MAlSircZ|F+9T66-$)0VUD6>e zl2zlSl_QQ?>ULUA~H?QbWazYeh61%B!!u;c(cs`;J|l z=7?q+vo^T#kzddr>C;VZ5h*;De8^F2y{iA#9|(|5@zYh4^FZ-3r)xej=GghMN3K2Y z=(xE`TM%V8UHc4`6Cdhz4%i0OY^%DSguLUXQ?Y3LP+5x3jyN)-UDVhEC}AI5wImt; zHY|*=UW}^bS3va-@L$-fJz2P2LbCl)XybkY)p%2MjPJd-FzkdyWW~NBC@NlPJkz{v z+6k6#nif`E>>KCGaP34oY*c#nBFm#G8a0^px1S6mm6Cs+d}E8{J;DX=NEHb|{fZm0 z@Ors@ebTgbf^Jg&DzVS|h&Or)56$+;%&sh0)`&6VkS@QxQ=#6WxF5g+FWSr7Lp9uF zV#rc`yLe?f*u6oZoi3WpOkKFf^>lHb2GC6t!)dyGaQbK7&BNZ7oyP)hUX1Y(LdW-I z6LI2$i%+g!zsjT(5l}5ROLb)8`9kkldbklcq6tfLSrAyh#s(C1U2Sz9`h3#T9eX#Hryi1AU^!uv*&6I~qdM_B7-@`~8#O^jN&t7+S zTKI6;T$1@`Kky-;;$rU1*TdY;cUyg$JXalGc&3-Rh zJ&7kx=}~4lEx*%NUJA??g8eIeavDIDC7hTvojgRIT$=MlpU}ff0BTTTvjsZ0=wR)8 z?{xmc((XLburb0!&SA&fc%%46KU0e&QkA%_?9ZrZU%9Wt{*5DCUbqIBR%T#Ksp?)3 z%qL(XlnM!>F!=q@jE>x_P?EU=J!{G!BQq3k#mvFR%lJO2EU2M8egD?0r!2s*lL2Y} zdrmy`XvEarM&qTUz4c@>Zn}39Xi2h?n#)r3C4wosel_RUiL8$t;FSuga{9}-%FuOU z!R9L$Q!njtyY!^070-)|#E8My)w*~4k#hi%Y77)c5zfs6o(0zaj~nla0Vt&7bUqfD zrZmH~A50GOvk73qiyfXX6R9x3Qh)K=>#g^^D65<$5wbZjtrtWxfG4w1f<2CzsKj@e zvdsQ$$f6N=-%GJk~N7G(+-29R)Cbz8SIn_u|(VYVSAnlWZhPp8z6qm5=hvS$Y zULkbE?8HQ}vkwD!V*wW7BDBOGc|75qLVkyIWo~3<#nAT6?H_YSsvS+%l_X$}aUj7o z>A9&3f2i-`__#MiM#|ORNbK!HZ|N&jKNL<-pFkqAwuMJi=(jlv5zAN6EW`ex#;d^Z z<;gldpFcVD&mpfJ1d7><79BnCn~z8U*4qo0-{i@1$CCaw+<$T{29l1S2A|8n9ccx0!1Pyf;)aGWQ15lwEEyU35_Y zQS8y~9j9ZiByE-#BV7eknm>ba75<_d1^*% zB_xp#q`bpV1f9o6C(vbhN((A-K+f#~3EJtjWVhRm+g$1$f2scX!eZkfa%EIZd2ZVG z6sbBo@~`iwZQC4rH9w84rlHjd!|fHc9~12Il&?-FldyN50A`jzt~?_4`OWmc$qkgI zD_@7^L@cwg4WdL(sWrBYmkH;OjZGE^0*^iWZM3HBfYNw(hxh5>k@MH>AerLNqUg*Og9LiYmTgPw zX9IiqU)s?_obULF(#f~YeK#6P>;21x+cJ$KTL}|$xeG?i`zO;dAk0{Uj6GhT-p-=f zP2NJUcRJ{fZy=bbsN1Jk3q}(!&|Fkt_~GYdcBd7^JIt)Q!!7L8`3@so@|GM9b(D$+ zlD&69JhPnT>;xlr(W#x`JJvf*DPX(4^OQ%1{t@)Lkw5nc5zLVmRt|s+v zn(25v*1Z(c8RP@=3l_c6j{{=M$=*aO^ zPMUbbEKO7m2Q$4Xn>GIdwm#P_P4`or_w0+J+joK&qIP#uEiCo&RdOaP_7Z;PvfMh@ zsXUTn>ppdoEINmmq5T1BO&57*?QNLolW-8iz-jv7VAIgoV&o<<-vbD)--SD%FFOLd z>T$u+V>)4Dl6?A24xd1vgm}MovrQjf-@YH7cIk6tP^eq-xYFymnoSxcw}{lsbCP1g zE_sX|c_nq(+INR3iq+Oj^TwkjhbdOo}FmpPS2*#NGxNgl98|H0M*lu)Cu0TrA|*t=i`KIqoUl(Q7jN zb6!H-rO*!&_>-t)vG5jG>WR6z#O9O&IvA-4ho9g;as~hSnt!oF5 z6w(4pxz|WpO?HO<>sC_OB4MW)l`-E9DZJ$!=ytzO}fWXwnP>`8yWm5tYw`b1KDdg zp@oD;g===H+sj+^v6DCpEu7R?fh7>@pz>f74V5&#PvBN+95?28`mIdGR@f*L@j2%% z%;Rz5R>l#1U zYCS_5_)zUjgq#0SdO#)xEfYJ)JrHLXfe8^GK3F*CA(Y)jsSPJ{j&Ae!SeWN%Ev727 zxdd3Y0n^OBOtBSKdglEBL)i5=NdKfqK=1n~6LX`ja;#Tr!II$AAH{Z#sp%`rwNGT5 zvHT%(LJB+kD{5N}7c_Rk6}@tikIeq%@MqxX%$P!(238YD(H<_d;xxo*oMiv^1io>g zt5z&6`}cjci90q2r0hutQXr!UA~|4e*u=k81D(Cp7n{4LVCa+u0%-8Uha+sqI#Om~ z!&)KN(#Zone^~&@Ja{|l?X64Dxk)q>tLRv{=0|t$`Kdaj z#{AJr>{_BtpS|XEgTVJ4WMvBRk-(mk@ZYGdY1VwI z81;z(MBGV|2j*Cj%dvl8?b2{{B#e0B7&7wfv+>g`R2^Ai5C_WUx|CnTrHm+RFGXrt zs<~zBtk@?Niu%|o6IEL+y60Q>zJlv``ePCa07C%*O~lj?74|}&A0!uA)3V7ST8b_- z6CBP1;x+S@xTzgOY2#s%@=bhZ@i@BwmS)neQG&=9KUtRf^K=MvjC5JnqLqykCE_P0 zjf#V4SdH2#%2EuDb!>FLHK7j;nd6VLW|$3gJuegpEl3DZ`BpJU$<}}A(rW?<6OB@9 zKP9G3An?T5BztrLdlximA;{>Tr7GAeSU=^<*y;%RHj+7;v+tonyh(8d;Izn}2{oz& zW)fsZ9gHYpI?B|uekS3zHUue3mI zb7?0+&Zm>Kq(F>~%VYEn)0b32I3~O^?Wx-HI|Zu?1-OA2yfyJ;gWygLOeU;)vRm3u z5J4vDIQYztnEm=QauX2(WJO{yzI0HUFl+oO&isMf!Yh2pu@p}65)|0EdWRbg(@J6qo5_Els>#|_2a1p0&y&UP z8x#Z69q=d663NPPi>DHx3|QhJl5Ka$Cfqbvl*oRLYYXiH>g8*vriy!0XgmT~&jh3l z+!|~l=oCj<*PD>1EY*#+^a{rVk3T(66rJ^DxGt|~XTNnJf$vix1v1qdYu+d@Jn~bh z!7`a`y+IEcS#O*fSzA;I`e_T~XYzpW7alC%&?1nr);tSkNwO&J`JnX+7X1Q8fRh_d zx%)Xh_YjI3hwTCmGUeq_Z@H#ovkk_b(`osa$`aNmt`9A#t&<^jvuf z1E1DrW(%7PpAOQGwURz@luEW9-)L!`Jy*aC*4mcD?Si~mb=3Kn#M#1il9%`C0wkZ` zbpJ-qEPaOE5Y5iv_z%Wr{y4jh#U+o^KtP{pPCq-Qf&!=Uu)cEE(Iu9`uT#oHwHj+w z_R=kr7vmr~{^5sxXkj|WzNhAlXkW^oB4V)BZ{({~4ylOcM#O>DR)ZhD;RWwmf|(}y zDn)>%iwCE=*82>zP0db>I4jN#uxcYWod+<;#RtdMGPDpQW;riE;3cu``1toL|FaWa zK)MVA%ogXt3q55(Q&q+sjOG`?h=UJE9P;8i#gI*#f}@JbV(DuGEkee;La*9{p&Z?;~lE!&-kUFCtoDHY*MS zzj+S$L9+aTs(F^4ufZe6>SBg;m@>0&+kEZMFmD*~p~sx?rx=!>Ge;KYw<33y#*&77 zFZI`YE(Iz?+tH;Fq;y=MaSqT{Ayh*HFv0(z{_?Q+7@nE%p?S8%X6c!+y;!0NLXwJV8Co_}R3*7>n+oMsQpv8}8ZS-P@(Rg|gmxZHzf=nMOUAAY}AZGfWVzZjE@4$=7xkIrs8BE%606aVU%kxz_04ipig51k& z(>c9rJL2q%xvU%Zj#GR9C9)HLCR;#zQBB@x;e_9$ayn(JmSg_*0G?+wOF?&iu@}S{ zt$;TPf*Lj$3=d<}Q3o!Hq@3~lFxoiCyeEt}o3fihIn{x2s1)e2@3##&GYDq~YO|!q zUs0P-zy)+ohl-VQ`bhvUpC{-d$lkpML_M%Kl6@#_@A}w{jWCDsPa#cSbWA#C4Sf|*C*&Z{ zz?hOU7Cc`?>H$WGqITA2P~fYudnQHxB8^;0ZFKC;19F#~n_2P@{cE{Czq-#K5L_8| zc3aOEwq4%zL5>YU_mc9fc-p~{fBTWUkxTiZvxt9FOqC{s#TBp(#dWc+{Ee{dZ#B!g zHnaOJ8;KO1G;QU2ciodE+#Z$Wuz*Hc6NRO!AUMi|gov=>=cwcZeL&`>Jfn!35hV1J z;B2@0!bIR853w%T*m6)gQ?DPnQ)o6EtKaN3L;o?*q<83d&lG&U=A|6hcT?f0)4h6{ zGIZ0|!}-?*n{zr}-}cC}qWxEN%g60+{my)o^57{QEn(tSrmD7o)|r0+HVpQPopFu; z0<S}pW8W2vXzSxEqGD+qePj^x?R$e2LO&*ewsLo{+_Z)Wl|Z1K47j zsKoNRlX)h2z^ls_>IZ0!2X5t&irUs%RAO$Dr>0o$-D+$!Kb9puSgpoWza1jnX6(eG zTg-U z6|kf1atI!_>#@|=d01Ro@Rg)BD?mY3XBsG7U9%lmq>4;Gf&2k3_oyEOdEN&X6Hl5K zCz^hyt67G;IE&@w1n~%ji_{sob_ssP#Ke|qd!Xx?J&+|2K=^`WfwZ-zt|sklFouxC zXZeDgluD2a?Zd3e{MtE$gQfAY9eO@KLX;@8N`(?1-m`?AWp!a8bA%UN>QTntIcJX zvbY+C-GD&F?>E?jo$xhyKa@ps9$Dnwq>&)GB=W~2V3m)k;GNR$JoPRk%#f3#hgVdZ zhW3?cSQ*((Fog26jiEeNvum-6ID-fbfJ?q1ZU#)dgnJ^FCm`+sdP?g;d4VD$3XKx{ zs|Y4ePJp|93fpu)RL+#lIN9Ormd;<_5|oN!k5CENnpO>{60X;DN>vgHCX$QZYtgrj z*1{bEA1LKi8#U%oa!4W-4G+458~`5O4S1&tuyv>%H9DjLip7cC~RRS@HvdJ<|c z$TxEL=)r)XTfTgVxaG!gtZhLL`$#=gz1X=j|I@n~eHDUCW39r=o_ml@B z0cDx$5;3OA2l)&41kiKY^z7sO_U%1=)Ka4gV(P#(<^ z_zhThw=}tRG|2|1m4EP|p{Swfq#eNzDdi&QcVWwP+7920UQB*DpO0(tZHvLVMIGJl zdZ5;2J%a!N1lzxFwAkq05DPUg2*6SxcLRsSNI6dLiK0&JRuYAqwL}Z!YVJ$?mdnDF z82)J_t=jbY&le6Hq$Qs}@AOZGpB1}$Ah#i;&SzD1QQNwi6&1ddUf7UG0*@kX?E zDCbHypPZ9+H~KnDwBeOXZ-W-Y80wpoGB*A) z_;26Z`#s0tKrf~QBi2rl2=>;CS1w)rcD3-sB!8NI*1iQo59PJ>OLnqeV4iK7`RBi^ zFW{*6;nlD&cSunmU3v4JKj|K4xeN(q>H%;SsY8yDdw5BJ75q8>Ov)&D5OPZ`XiRHl z;)mAA0Woy6f!xCK(9H2rq?qzp83liZAIpBPl-dQ&$2=&H?Im~%g;vnIw1I+8q|kr! z36&^9}CMmR(U2rf|j12oG=vb%Ypsq8u9Kq}U*ANX*)9uK}fAi8;V_7Z;0_4*iydDxN-? zv?qJ=T*{MzL~-xUv{_Kh_q9#F{8gPV!yPUUS8pEq*=}2-#1d=sC_|U-rX~F0 zBLawgCWy#?#ax{~DAnDvh^`}wyUO`ioMK~jgh%L7^}#h?beSyvQ_g>+`2`}`-1h7# zg*?qJdm=53hwN8~B=^|LPmYtOVrQ(W{sNm4uofq=4P@dUA%$onWbw_m-KWia&n9iv zi)!9#OJ#^}eg8tE{wSb9(c0D^PS1 z9EBS5*ypSiVRS_G0v?$hyoZOS7hFWlp4qbYkf9Y&{%OzhsIdHskLptn96@k6@^K@U zszd8POehITDK+AyW#JKpnWY;ju#MC$JjB1Y*~(E6N%{p#kO+bVxG3X<34n3fW=k{A zCZt|KP%x^GQ9%mU)KE0{LA=vaZvRQbxSlK~eAkwWo2Z<{j5eS5NVTMe`m%re8%~7K zZLtU&b~YDN%~uA9wPf>x2=PI=MA6_oVe>Ek$s5&&Z=8vvF5EODP4Av(b|dlNgF1O8 zy83W0WRdzjz2iNA~t1piEqlyU&`$yZtqR`6X_PmuP>W+D|8iH;FQ zN{JuU#Tz9mV=4R_IewROL1|mK^`lLat#LcIBfggzM(iO$pQT*-c_ z94^LUWw#5B9~sp2W1p`c)Y(xfR<{O^9n4E6vDDw{#-R4UMBKo{>Hqlqn*a9rl_>+0 zS5MwJC~nCC`1X%VCyWFsiDX;bfAJQAUkU#105f_s5U-8rqO}n8fA1{b>Fr6Q|Ea(V z5B11Lo^ooWF?`^{-U#?iatokWI-e$632frzY?Yzzx(xJc@LFM4A~-eg!u|tl{)8Nx ztZLXsSC*68g%9TFu(f&J9nmc^9hgyy#uUOMJFCaifSaDcyQ&6=8e9=t zIFEAQ{EK{|73{($!a4=!wj4ABcQrUQp#+gGM?wEUp(w@+Fzi{!lt}|3`PM%&d-seeR zB$}BrFGD3R10CE>Hsb>;PrP}pd` zaY4}6+Wu(`#uAV+E5SV7VIT7ES#b(U0%%DgN1}USJH>)mm;CHPv>}B18&0F~Kj@1= z&^Jyo+z-E)GRT4U*7$8wJO1OibWg0Jw>C$%Ge|=YwV@Y1(4fR>cV#6aGtRoF@I`*w_V4;)V231NzNqb6g@jdpjmjv*<2j02yU$F8ZS$fTvCC`%|Yn#x< zXUnP&b!GLpOY-TY3d?<-Hhxom_LM9`JC9LEX2{t1P-Nj%nG+0Vq)vQwvO^}coPH-> zAo8w#s>Je^Yy*#PlK=XDxpVS~pFe-j#jN-(As&LRewOf(kN-aKF(H+s*{*!0xrlZw zchJu@XAvQWX7DI1E8?F}Wc8m46eT+C<0eXVB+Z^(g=Kl@FG-cn@u$suj)1V2(KNg_ zh29ws6&6(q~+sOAoHY^o86A<#n*?Pg2)cK$+y;cY$hJLq4)4V84=j+3ShSr##Tk5kgmxB zkW+8A1GtceEx~^Ebhwm36U?oA)h)!mt=eg0QE$D1QsLNZ_T3NH?=B&0j~#298!6iv zhc0|-{46*3`Rx&nKSXnf1&w-Rs>#PGAGuY@cBTU-j|Fxbn3z49S#6KBaP^Lx*AOXxIibr z!1ysMi(&kr!1wwQB5w`BDH2~>T4bI`T1}A2RM0zd7ikC&kuBRsB`Z2@J!Udm{AmSN zrr0k6_qCZL**=)xRW`MFu(OY=OT;3G8eF~ z2mmkXZ9X(sjuKmq+_<=LSjphB$~R1o^Yb=rO!j!(4ErIox^x55o{pXSE9X$!76^*$ zoKhlAX6y%n^U=C~@!vIlEgXQGD@>oOU=_(aXF-Sjas*$AKESfRzxQ8#3yOj|y0OCU z>6Z-0%LCcjla&7I+CXm&caKp@@jQ!5M`(_{CL=@4#JJ}cHeZw>^b6fpv269LSV?gV5Q{kk?4;;y9RIsy5vk%DIRiL(9xe1aA@4!VX zDh2}xgUd5X?6nji%&7-%QuyKSYA-Z{PwJijUQ}In+EJl|x@dF1P<5bPa5W3&&?^h$ zZCo8LepKo0a(Fsln*cHL;D(gu9MMkoiM0*n31u)jHqX5x^F95tnI&^}^yKx3YwEm@ zo8?EZ710ykx@19{=yz5IXb8w4yjdveWb{IVL6Z(Cs>!a_0X^1E27o!4e&b43+J*u2Gb(59k2uK0goLwhO{ujLS ziI9LA9`&x~Y$6JNX!aEXR``}LUI}Gr#=<^wBHmg%v<)zRWDVtq)kT$-P7iU1R)2XZ zi~bYhV@EZ`@prgK(cs{>2jn$pxg$<|KjJ7%26Km>%KcXh^bU@y@V_Lf@=j1x%R4{v zOcQn{I}!2W<~08FOVnoV>zOTH=+>v9!jFo|q)ucqIe!N4{U5_G`>>*sVD{8I~4FqyU8imZ**-Gy`~Xd z4w35GMf%7^i65HdX{Iz|f2Kg193#KhPIeR)-=eYx3Z!%RM=JjwLrdk^B#6rg!ym2w zPbFqYyO4>W_Z6PonAwiu7?!h=x%sR-T+_*xZOGh2wWhWr%}%2^$$ zQvACIB~pi=m|`hXIMvoq`TOCx=J_D2>pi6$NPy3&8#vy|oX)=kM0Z}$BR$r0G}MzOk-OqG+VmZtOZoj6x4(tLh|5h) zBv64Y{DPHsy&_H(5_l(&Y}FhVvr9m_*_Q~Zy-}V9+VmGnvndEjYW4qt4K~N&Y&6g| zfpz*V=A#^mVmuOAz)(KVI<%v5NY0%Goy!{9&o41upsPWk(yFuRP|A4q6NMnX%V~MT zi_Rb-Bno2kI+j0Cw`@ydy{e%ARS#Z%b6I%_yfo_ZKXr4BLVoHzBKJ^ZG z-2>2IzU)55@9C|?_P$ew^-7zEiAKG1XAi{!3h%1m#9s%^pGy6S9wKFYY4<$djeoJP z{GI}Vd%idY$4_fh(7NXm7#;cC!DS&-{tGr!Qze{^%bUx2jgG@-kMta^q-EwrKB}d8 z{%FT>rFk_bzW<{lc%eYlrsiYTZXGgzD1&lmRyp+c1O=0=zAX=KV62bx-a~JP{cPF4 zU$-XT#(9&T>l@bMu3nSr{)%-5lV+0t&bxip4DVJ~vlL$J2P6X~ zd{FS8vm{Lhrieul*7&(AgPuXhjpGila%6_?-+k#b)cdk#M1jB*nE>G6NGOr+Ek{`= z9b%S1`$`=g0CC$>0$Db;l_szReLYVmce*(()9%Zz1`*fNXhI*oRlerWHarD(v^W^c zuc1Vuw6Gbp7ZsoRH>QGt#&lv;5G~Ovt$%7VFd*-rN2>UjbOWBFGNGO`bru7CFB4tn zL`^?69Lj_g_TA&`9`dSI8s|)K|QM0 zybvV7!>xDY|6c6y;Q}qs`){1+WQu_5Dgd8Qe|q}}bxjH+joQQtqs1IVZn6{e7T{ia zF|=^xa%eWO%(x<7j*QZbcU_;aVaVP!arexOLOtoSNt*hvsRL%}%)jPetSich(`b-^ zMZ$PM9%s@%*jPVz0Z^W*cK_>G4f}+eEVX`HOaHg#!B`<4v;x}zDLMR*M27`kNfp!! zOfdt(>k-g>7jf^{Se@3$8<+;R*cYtw+wD_Z8Pl~!JDCUEPq{Ea*!J9`%ihyNJZ30i zmfve}S5<$Uso}_?SuI$ks|{-ddGLu9WR9`^9)Kdi@Vs;x#SY-xp}wHPU0|vEA7234 z@BN1z7OF=OOQtPF$4twn3!HTVlUVD_)ubMM7PEPoiC6lQgL2q9PK4~e8v-OuH%lie z?NgBLkIdPMG$QBq(>r^AOHB`|*1#*!2Z? zuU8H|FD`OBRu^(R?Z-Vhr0j;FLpS~a34KREnd}B=EYHS*>Hm+f%tgJt!4J8Q`qn^4 z9F=tO#JRJ}tzA`vx$nZ)O%wC?Uiv0+_nz}5Lj4ki*&=K&*#U`=rv z`Q@Q{+IhAj@6lrNK2B=8Yln!O2%zomfRehFT~;!O@(@Xy|1Jlw*uOB-M$#6K^)QBm z_7%#QVUDPwnW{iOV-grMQQU|3{=BQMh}c5(yMGdoQf*)k9-B zMQ(^GdJh+y)>qJprknS!%WxqM>HlHOP#7UVdy>%PW$!l72J`n-p7j(DBKoGxXWh(Y z>BFDZl|7knU_jg_SSbvFk8)39%2)Hu5W0}HKlh>EaqvFoXI&56Yy)3) zQkE4X^P0QnPn?iUUVHJZXzPp`s5uv?pG{K9IgGoHvcmlBxubi|iF7n{)mhenIcxGs zgr0OpQy#Y#u=5lOyiECfE_Sn?Fj1LyoRKcbTgX{p<T*v!CGkPc)pcA2D=4Ekp0Gb*wpy7S88C%Ywsbr?MI(3UdsCM?XJ1X%*hNjB)XqZ*W(qDdtSb z<3XN74ARXL3=c^bfW~F%NM^5*Zx92>Wq`&M625p~j$8mYwLbk%Kf)jbn#<2z$%vP5 zy#b>-tF-S2_AB4;R^K&^-1LJrUmi@9rB^FLF)-k&YHK8P+k@RCJ1qSTZ@=kHxA3l$ zmK_ZG)l6(nmCR1a8|;QF-B5e_ELnjJ1$m-;4UXX?WytF_wz7#&AjwZYTMVieLbq@R z3t-q|G4^BB#EpNu4uyfDebB+-uu_$9>y-dzB30Y9F=R zrW-Heqnj*InPTWHgR9v^R7~hokldh&h8=HDhMW(EFfim1*{)5Lc1-+eBVkK-2!u=N zuZKABgJs3I--NbjE;>Undg6uK`^U>AQ6V zhc!RhYgvrmeGNsftr+(C<_MtuV$`5RZTf#5r=DR?gWG->#})#=(td%C3`oO+2B7im zUqY}&a_QNTn?s+?=mNXiREN%x_=(H)L|DtYPY>SR3pQfBOel7G_jR_{!9`dSj8Up-`JgcB;=Oor)U=_EVjF3C5{Sqh8cq=~bRjoBpoc$kJCgtTyZGSpQ4= zYi$6b$-dGmuTDF&@amhV?cU05g(AZV&v2$4m&j_~GZk;&keSO(@LRESRZ&p`dV*6w z2$em~p*8yM6j;SYorw`M5K2mluJq7P5Yn$VtZj8DEs2Zk=O@4T&Q}>~f31Z{uk}`E z{Dp{KObh1kk~~MfLUod72{Pk6G@T$_0_N??lOrdR=Z;VV#m0l)&@hz{Z?)@sgImi-&i1@95g53rON83v!yVPDHRU*Mzc4yZ(-Fr z{8{WXmIJf7jeswk$;6s~Qac6QyM3W&`}m#gRt=rr95A+Ad&wSAgvXZ|F))rBJVJ5W1CsjN`QaOzct2ocq#0!v zmj#075)C!3oS>&N;aHS@<+c>RHL)8j^p)k(8#7$LEx!1g_1^02!4_qA=;uhKW=+ix zGX%+vBMiRiF^^jm{mdO(?GdWJ#unO#_F^7mhT8)s(z_WlwFyJ#Xh)k5+RG2f;LC*K**1dr`#}~6A=0B=I&V;%zDA1)d@G!X#Rng)7G*2k8Kg447r0ox> z5NK`d(H-afBwo9feDOUi>;BbPsu!2|=@g=3j*PY}@YrOb+SX6?#Yb2xaaK!?>SX1J z_!VsB`2n1=wwSftkydm!39|-1?c%Epx?TO<(#GO~I&{f4+)XwRk<7RQ1~5>QcKH|D z?!}j1ueO0Lk;FZ{k4FA_(S`Ot0w~tl&m0duID*f6RY#bkw||o;kZ# zISYNTb|{~|X$m$Q-Jv#uxyw)eM0gIv`V#wOAp&Vv@>X4_tSZ&L#juM@$S9 zx_X_tLh<_^-F;LAQ09s@sPb%PMTrcw*HUV0P=RYSlM&AXEOI&&R&YCm_S<7DRBx^L zA^R^iwW+LMk(r*$Pq-fKU5X@=mQ=`ErO30H@@&qqnI7zJcrbSh+H<V ze&7Uli0xj@WrW#&-9%*FP~kPYF_YYM_hs5~|ExMynQ%qvq`leRB6W0yhC@pCb8>_P zlf=F~WMv_u*-DV=UaVu#2rlzK{q8D95VwZrfV?gj@rSNWXFvktUq)V5+YrlxwX302ae(;aG4e>L-M@3J+-f3IT{b9l!kg*2M zC1+ND9}6m^()LE87Mt+^Q|)!y#suc&v26C=0W88%a{?)E8Yvo@kM&KNMaOst#|-_CbUTm}WS@-c>nRb;&z^ zYr)+IE$1=jov(CZ%3uR+`~NI>1&Gs6W(jaamjcN$a`2!*nO}l|b%?)Q%%UWzw>A`C zR@px(P*7j$TK?jbv*%x)e^|jcLsv}aF(Z0=7(%Oa7+1wY>{B>d+i&ZA$}k(qgZPZY z;VkW~8eWnU&HPIAbco?&tc2O1$6=7n{u|^Y*nXoac{o1W-6aXfy~KlNbJfLoq~6;+ zDYmnv--Fhqrl+UV#k@_(1=gWNtqhyVKN=9CZ-{Ohi>e=~bm4IKbhM%%W zW8oXE!rGpV7Wt(_^4nndH1_imheaWzDi|I})9ZVZ9>pN+P%dVc5wG`Ze*4`@rjn1^ z`ln(;vPBHQUb}y8S>=8q__r7g+=z$>!pReVB0@XKchAvyGjLQs-u>+w%`frV4FeIG zj=7n~hGrwx*&5aHy(7X$bDZ7YhcP%(*>G^lAYMK;qG~V8Jz@b7oNg;IA1z$9@TbzW z;@I51@Ekef#qbxnG$Y8Z%bm~ibZ=4#%yKr%#b)CDrfKN`ujIY?tA4h9)i~dZ4E;ZM znvb$n2)zn$Wx&zlW%mJZDh28ox$@%`w3i7YFepXUChw}$UXKI=-TM51`M#FH=tdr*mQ!c=aB1296Lu>iTTKZWss0f z5~ihdImPN$aTle_AdbYC^31}_^EK|9R&l#%3hbx;8vJ+Gp^tm{9JDILu*1PW!rh^Dn9p<)h#Sl4kKM%nm<+!ESSk* zC;lLNT$fgr-!+{aBsSx$41b}yy6o>r3F#1&iv3cfY2N<+`0qJ+>=&Qxs}JOEkD?^l-F5i`t5+zNuvJf z3Fh4$mNqiFXL-aq4U4K@Ae$fq-TDT`rvrx;gqx96w^*@s=mcthCaIyPe(w)6kI{EqV10tcShHU9eeAPs)s?6#vrq}>y3FeTJu$Udha+z zs7}rmA@yR(L&>35sNjQqrw}o^)UitMU!5g6nnG)(tgst!^`FKJEzI1(d@j_w@;^hr zgYxlIRYjho4U$bhczfq&YySCqCE(5_d>l(4tk1v9!V7PB%Vx{QO=G2NC@c1%3rEzw zN<6i?h;CJX>h)kn49Sr)g#Em6km6ESP`1qc5C3ZHizN>r>V-fSS=X1nT{+Thh@kC! z(H=PlqDt7V6gOYezXUK-dretz!1?IUD6&eL2b!4=9h+HUO&DYZKMM>|YhlEEg?q?S z^XT4$2Fd|zT=x3U#L1|F;-#`to-Y6hiYkWdO=rRC)meY72pIfl`3zEGDU8($iWR^K zI$nq80aSJII<;#W5Pj>^_T&013BJ*O89Uoq z5>;Paa^E}xar^r=!pexg&OTM8wluk4R~Ru=)Hgk`Y#i_$jk{jc8hx}?(dW*X!l4vs z6_%$s#duJJFmaFc-5#>v6Yea=I~)s_pXGS>Tkz?s+WS}>Qp<9MappMLXpkXpSM~SmH6u)`Z5>o02kJs;w@KhdiZ3}29y*xr|6tMo zBHzGic+b+dTd!xOJ;p{Rguh^corJ;K?R6daayQKm+0rf7|AXg0qs!R9eS7t4{G=fs z1$=?kK1Ih=gEkI>@jgXDWHZt*C7FUEWs|u^pE3Z``^K|1KEC^sbN*4nQUfRc_AyE0 zn)?RrGjgPkzfE~_s!rDB!fDsV+*|kEX4+DyS#8%!cshn;s8svwBXSsDGX2ZRa0={* z=`p1F{zD17*Rk>Uk_cw3t5j=9-d6$}MoM~z{v{t^M!g75-+o8_XkP@CZWUQ2z!^26 zCNOu~hgrrK)y>bgqb{`Q_1^zrG4;cGarP!nb4E~(ZKWc`LVeEq;IewVneLp^ZU2+% z95PgN*M5v7Q;ZlGvM#`&u2NdHm%&gZ{bZM5wBCp&?HeZhwU87wyT_z!n4z+1?=RvXZ^72d*%+R1s1$KbAFtR|= zw;MEq=O7pMIKpFwKH6$OOszJAf<_Z<1)36cB>D>|Z6$gJL~jH`n3MMou$#Si%rDAu z4pSkJspG|^CJ86vg6kkfXsA_`8@8iOryOe!Qhn8SV6}mPlof3=WJRVqAr_b;e->`Z zMR(p|K|$L0^6;u~USxg#B6-ZNc%E1dv*^P=|2k*^NOBni#G%9Y?##{=)8KZwh85OL zSBG9|gb|hdmY^gn(ziY&O5#@I?W)W;361Yb^VQNpz0A7&^(7HRAsUvw#)fvhocvja zLxV65J0_$>&cVRctJFsn^qLos^tG`+B0_gQ{NeOwKt-!C^gGFufdtPT*Vi>l#X1|V z2XxsAcixN)Ekq=a##_^=k_^BFH5_zpvPDRP>u6+3$}i&b zy0@FdzAHw?i9OqnlTts_w5D@Nd#eM)KKEuN#m{|AJyscxa}(eA?z4&4yvXo{OBS65 z-?gW;<+;+ntM}U_yTmHm6*2zj0Imj<&ZgE9Wj|gfsXhrVH-c0p$7HXnR8bxDYOi z=_r3FA~u`L&2;Vir8}P3)k|@c?sK1U@&iWo{HEXcoy>6wQSuJ+b4l%aTBuigs&k@Y<2c=S3Ef?p zH>ki4yDuXdo_eu>X1{E$g(Q-u#zVXN^&%70guoizo7x(kQ0OZ}H$O9UB}(FaX8Ct1 zFpx~}EbHf2r6V;x=@8GH$C2|6*?K~?LrtMYd^bw*WYXhA z_))@RMH;nZedW3+qfWbv<|_#BYOxX^rhbN+!za)|!|8K*LRs(R$O*2SDM{g9k7e{u zN4VIdi}e#0&h?sBxu$>Yy%)j(k1V2fuhp8r!}gfF@b;F?U`6}YnnMh1&sSU&lR^?# zu!61+lGsuFEfDraX3+$QZibCbKzc{75G^T7@WZSQ)j5898G1AOXB*H*TSd`f<`IK# zm1%&t?i|2Z-a&r!pJehzg@!awNp)R)aa?q_SqGrxE5u+T#f?K2;GAHV?O&>!W@Q*k)7=g2vDW+7K zbyY9i{|nOF*SbMYoRQSAbSH2y$bE5(@d6xKxcF#@TE~X#3o=;`0sc!RupdRmQsML? z&>SCwS{FOpSr+@6Uuz3m`hj}(^g`Jz|6?({!%WVJn$H|ugxW+x-GEA?J&U^ugj3Nb z;65~)W<}iH2PJ@st8LtLfSOLXYgj=9<;?ih7rq$bXW9J#!B8!Wu6#U`A$wlcoC*&` z_9Js~7%m79#+edeT&P`@_Ng@e&5J+pqpx%31tAF71)pcz~-yJ>P5yX(nuM4;bUHDa8E(~~l{j~JeCGkX>nHJDpgSf&bTHEf)qw8{Q~CBPEVen|MW2P3vmf`8X9-g|>>ddp zcgfjbl~(?3Wa*NzQH>4nsM$3}Ul>pX1xC0oF3TZXe7=V!9!n?WgvH|R zpbruczmB%z=zkZ>=1R|gXwGThLELqD5KCUhtiRGT*JwKIvzbzV%ZU!e!VcNHSSX3> zObH|oohc8nvQZ2}q??C}@>!fe3gH+HF@4(qWqi>;ag~md#D;cl8&gQb^?2a@5cikT z=7r78@&5gV3Ggc9f=<<8v~yz`NcEGvbX1V_`IL(&+Z>LB zM~$ok2qXzod@1$TEl*U~H$V5g$er{Uj^($sWb7Nr{gsIbE(`$LRGECTOraXiU%=uq z0zvpi1S%)RxTjzoVcR4#10)fs()4Mtsa@e?9j)Bk!LsYyXIZga2q7d%`vQE!V@<1Y zmkpH3LeXJNO9f7l>F84g;huc=4nk(UnU}RLZmYk2TtB#lv34K(?8~gyx-mN%g=U44 zOPdr_!j-;IEbe|l9-buuKEy^Q9MLjSKG$S6dz)!U_32{1)N}L)3+COmlg=nY1@od$ zJ<0z-B%sisAR1yh>z-RfQQb6M4i-d#vxvb~f69M{JLPZv1JSCh1$gQ*LxOF-tH9!k zbQ0ZW)S7)qCSF|=2`q_A3}OHBNBueZwTTz^ar~gz#2KA74&&D)KHt~m4F_nK<^*7_ z!!pN@xiGkq%>1N(rNxw$zu-=1t*IpAy$ z4~dD0w%9;E?(greVWZ3(o9ux`elM>Rek#0 zO=#-(4p5B+wFzlEU7^k{3EdL6sIp|K*>xrriI`}E8ze|z-$YpN`^_teL_7P`%e>IN z7tNiH619P+0Q1hBR|W#POOta)1|LkIRtgz zMJ9VOxXN#o)mlXS=u%`Q>~PBuKEmOWsIuQRp{y%!ty{fEyL0gV)$LQeL#pqX3L@SR zJ2Gb^E9+KVd?;joVOXlGie3?z6>(>u(i!(qGz(W( ze~^xj&IRF<98ypEis{Y_FoHn%C0bW(XeF#Lj=2WUEBqKNPPFppEH?_a3}-h906X}C zSYKcZFU`Om5YlWhh@ogzCn3NvuM~F9jOX|xe-X*!YL+#ceh_tJoHXz`aTnvSrOAZ| zOtdGz?QdT!oAJr3(XL2G(p%2X4{xEohU&vd_zQ(U%ihHOlKPWnb$&YYhx48?|R++>`5?sxvM?!;ru|9 zZ#nwuTK^S%ce<+ggdJBE&fRrXN7O!{nu`%q`M{2Ef_+IRad2cf01P9pST9AOK>y75c!9}~)Et^6$`&Nm{wzWcm4c0j9DF!xJTpGrMp3esI4D_iiDe`sswXSu{dQZE_`^A11 z?Z@Hw=65mVu^%X`>;$mciK}XiZ{xw7I_!t)S00^JuxdCXhIRO~S*lPS(S^je`DH4E zxbKNs8RL`N?gCQ@YSOU=>0FE#Ku#DRO7JA&fu-X8b;3!^#{=7`WsDXUxfUsE(FKSQ z&=N`A7IwLq%+vt(F;z+T=uZNl=@K4|E%p{p^o5(BGjsE|WOR`%8+XgGW8xJTFJc4L zVY#L`OdnSM{HyS$fX1)3_JuNNH1aDsDqi>CzCT5=kY5zV<~29bX)c^I8R5n&ymHkx zj(QC4t#mDK;2xi8O%V;C{HqDQeM64=b4@sa*N_K0a&ro4+8LY6cFHz< ze|!g}zF|tDrP=`+U7KwKl20gdW1%!iN>1=uxA|NZJ2peruBOj?RBPb~8G;s6xIi6- z?_odhafsxoxiBf zwZZ)c*)FLc0#wE~bXw0TPBYl+h9hs|DYr_B4LR_YL@S1hQs=p zNEh%_fUvWZCbJtaF#kP5=(O#{8|g&Kmz1&8{@Lufw^DhtvKx955~aqxi2C=)Z-!Kd z+m-u+#^U4(HYn6a1w652kO0bYBt&goyx(n?MR^kI+{Q?0Y{G~W2) z0dS3fuJ?SU(6ZDp=kUley%PK}K_;YQyK|U|?7t9SHiyIfpT4a_kUVIhH4PSaj@3mo z`z}|mHhx1Pq?@(3vTBb5HTXuFAzFZEt0D-fw_kd=XvwIUh3VXTm{wbDA~cESd5cI1 zd>6=&AvG3yu+)`9oxmfrDQ(1fzv(_0l?bp{a364dXLRRBI8kBv!KsL;brY)#E3`o{ z3TlWUsS0{Voci?6MejccG9x_KiqN>So*1{25r6BSl9jUyR}1TgXBLL7Pr6Wv~Nu47;fbiU7TbL}>qmtl36YSZ() zVf@nqW(As~#`@bIC+AxSw!O5Pocf&rYaCFm?Jd?XR)p#@{!|5^Ws@wd855)mI^8y{ zws+VvGXW6%xoj@JkGb=~%oJ~7m6+uhOv?bH+jJJ~eFgp+}~*^C+3>R-MY!IZQoabCh( zN(T+z@Oyc^C)WqQESmh{d!!T8zS(!wX=R#hEKxMXy(eg zZ+Cwm1a%?;RH$h2_ws|nRjn8ZY!>3gn+6Ep4xT|AeFox7!rac2Lw?jsz}JqPE?5JG zok0}q1P;cuzs%Yrze|&d$oTr<`Lx{fbq2OV=!3v-ODq(n?|WxuhtmwJBIoW^^FB+D z-?Ok9HBKc5@)L(W&vmI{prL?4^OE9TR)bELS=<>*w%&aKjzi*@;5#P3moG@dm{Eke zhE#Is;&=o|{2GWai}7LYEI+gmc^Kj4K7w7n)+9godg?yB2?xs}pF1<*!Sv?D~Uvbkgs9xx9s#6zBv9l@ox>d#H6eqw^KZO;Vg}h!q zI33^$4}yF*q+q{DsJsa(SsV!YQ#zi^IF9MQV6i{SiN4dWWCi%YQ+hNc1r!^+<(YnB zG62-D`M3w3Q2;@X{S`n`{QO>migDpz0FK`->sYDOESs6u>-~<}_XN_6><2g7U#XC{ z$#Ig;n{_yEMnlvx-lP*;ts#DHV0r8j518>~33?Ak#jocW>uk>6V||p7{4rov#RS9c zdPD6r`qF1om9r!zS4Jk1>7fn#GCnmD=JIt1Na`X)=*LP7R!3XATgk`;&U*P<(0d z9p<0T&eYqQ9jot39FxpfuPSPYlfQ$s-*;+c1KL+cHIVcG5`H~^Ryu1Hk7%Nf$TCwR!SzG31@NHpm`mcp8v!wyWM49TjTxASJ-8JP*MTHLC}hF==PUOh8kaaXeGFGd<|e29vSDaS ztPeu&zv0^wN}Hahi`$pcDs~FVt2F;K!q}q*Y@{7i#stWfU`u2La4aerBKhV`^zG~j zJWvtZpcHIP7x*tfLSQcng6D(`HVp4=LWp_0Xt=2wEHjK)!DSz_Z?5J@>awRyk?azj zU-kdSs~cp))*pfJ_q7u`IsCq8F|OShB~D56S(Mwwlt?{yURE7#eI&WcpVq(@9Fd~g zeUiD!a4w51Nj(YzLnau+O3MDub|?loF0=<#jLztAM>PruE7yNDD0L}y=Ayuc?^?Ni zf~%GK=iEhn2}xKp7GonJx!JpDmDsco$|$XtRdUDwbM9$9s7x9-of2nKNj~?b@UOKz z9{`=Irz^ba-c&1vSQxSh;I2`cKc8-4)aCy%#bam;3_8vSJ-jw`_}lyukEC~z00EbC zI*dU3F21A)dSZr{qA5QF+{a%D`h#?8o%M?)*hWxuqnQD(TpcmfNq&UN$BmB)0!r8) zxno@Q?$_D&*4(rW6b+?-Y^5|*P`DHmJ%pI<6*yP)o}2^?>d7P#bd2j=vvx2mfLW@R zQLD`%buR*}nzNYNf%68w-D$7%v|=bXg1mYrdZy~}(@RRZ-U+Gx=nmCjVxr5Ag# zLw3R29-MHJl|`mRxj#sv@EfyR#-q>BE-XFEENbV$#dWM?!VjU8~kKZsd@G=HPrI{HiqN&j<92*-3$^M*;n@rG*i! zvi#?j;lc5w>@+r!6*CVUrN9as=S3?(ZBT979$5R#ZpPm?2VjIyQcEFp9orGR>f;G? zK<~FiYY6ow-&}|v7k?+03TC++so$)2~rN``u z>N%j$AbNQLX_!evzG8abf=15260vIXdz7K^a$YS)iw{@x5<|Rr#ii|ov=LJ{eu>dZYe_ip$ZuzvRu1dpjQK1BvP zH~m#t=2_wy>9+YkdNF-z` zQ*#7=^r%R*pIi2AI`>n9>(QJVE1k8?Ilav<)NUjW^O$}^yZZ{_Uwn!4Fq1`aslX;Y zj`XDIm`E1sz|wShA=?a@ZGKDSMU#Z3$E!1nZ)g^Eg3ZDoSN6@RXrGVCHvMIauS7d> zuJltXf9)LdTWdF!n%-iA9b#2$W#i??K)zYho^((ZqluvhAr@{H{diy0%@-~VW zKYC|2Ma)2^=skdLT@ZVqJfiCDqS@~qIGexL(BKy6Aw9ch0hoHN&E+m3*uka9+AIh3gTWdSe~W({-&^oFw`!j7$DcsF$7`pO?kRMK<9h=SV?cmyJIe`$4|zoI(6u9#qY9zM?#zNe^!Dl2>Z^dH`>`wSY# ztU;V*+g0R0DH6EnJA$U{QL&T~&s{`smeC2I-5mzv=v$l@iF;yN0hMibU=CG^e>J;+9k`Si9PzLaj$>}QKI6lWmO_o+_( zmhxA*0|-Na`+*J1qEMIXZf9rb#;pcOw>EDeDjb!|GumQ2!1ac;YqU|X;F@l1_lemzTN0J|U zFJF(kO21aHg)*KfuKT=BA{VDkOvlx(b{f|A9D69_BHUm#S$F>~`Mt@GesjLp3;reY zP~q>6Tt;`XkjqV?i7lqPbWGh`y<7dq<}pDHl-dDA4QG6`QDq)+vq_&HfW!}P6Cp4d zt>Qnli5ri*I1ILEOGD~3Y!@2^Jmcy1xDXmKolC?at}_6;neEfca0rLHT}NLpoUYh` zDbCtfZnYN&>}m-(F{5d1=)bBuZ?OcP`GmsQV@kn%JMJUIep`Avon#8=ATpEo-@hg& z12f-)R=HCD%pUjvbWa|P!}u)=wInpZG*LHKrZDMeC>Qils^IyY)x;kDRs4c3!DDOG zAptSsf#1X>kSli|Qka@S)6O4un-2aKL?bcV;$*>KSxHovjrfZ^-+c#>;(42yj71K| zzRyFiLrwv$rPcNA{mtv=o(*JDA0kS93>OE0D{KMJzLk$cc_5dCLWnJcFJd6_>BpE< z?aW9;^!;arQcIjloW&YL+~MkNO&a>N=pmhg>{SM<@`a&VeUA`ay*P@R$_+WS2%r?_ zs&Z%c`>ie+%!I=Lz>$9$7a`-`hoc&*dl60^whsaQ;~9~@JYn1Oc_bmgVVyAzUOYgZ z#j{`#D_YZ)(wa5;qzR#zo4a|-ANJjBB90r4Iun3*BkMxw_Ti>SjhktsmR|BPCLt>9 zZ_3eQjweI*-8+HNt)$9^s|+10w@sU!PY{`#BnF!ULS=#{k0Zr5`yOS?p8PfWbKT`6 z@T+PeRJ4`fj5t8bMs)0>o9|C>mBTlfQ*nFG#Rri-Q7}E}+eaz`LmO!`Y_pHkoAruu z`&!5VNnA3IG$}Pz)V&pt&AF!$E{J-;or3vWv3&Sl&9KzG+ae73Zf}=aP*SCI1{?0T z9SAC)W(?DSKOkcmW$(K5Bl?c@(5#>J#j@eq#ctX~$TIjkl>Wrfv%Ey+bl1Z-v?NxJ zwZ9!ae-MsHPUx&_W22?9$mCE%&~lzVG?hDXM%~gXGk+Q!Jf0BspkMWxy;^!n<6JIrSYjv z6F%~$8)0^qbUho9Sdf97b_n({$;|XH9-RHrohHuPcro@03KEPFejN&q?&nJFoIQY; zSI#uL6>2^^yOR!51OLO65xGas55dPG;3=uQ35ZYW04#+~byXQf^7Vq`G z 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 Pe7HEdAEg|=c=LY&YVNkY diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_128.png index 13b35eba55c6dabc3aac36f33d859266c18fa0d0..cb662678bafcdd9dc3eedb4df6fbe4ac608f2824 100644 GIT binary patch literal 4750 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 JnJg;ge*j{{-LwDz literal 5680 zcmaiYXH?Tqu=Xz`p-L#B_gI#0we$cm_HcmYFP$?wjD#BaCN4mzC5#`>w9y6=ThxrYZc0WPXprg zYjB`UsV}0=eUtY$(P6YW}npdd;%9pi?zS3k-nqCob zSX_AQEf|=wYT3r?f!*Yt)ar^;l3Sro{z(7deUBPd2~(SzZ-s@0r&~Km2S?8r##9-< z)2UOSVaHqq6}%sA9Ww;V2LG=PnNAh6mA2iWOuV7T_lRDR z&N8-eN=U)-T|;wo^Wv=34wtV0g}sAAe}`Ph@~!|<;z7*K8(qkX0}o=!(+N*UWrkEja*$_H6mhK1u{P!AC39} z|3+Z(mAOq#XRYS)TLoHv<)d%$$I@+x+2)V{@o~~J-!YUI-Q9%!Ldi4Op&Lw&B>jj* zwAgC#Y>gbIqv!d|J5f!$dbCXoq(l3GR(S>(rtZ~Z*agXMMKN!@mWT_vmCbSd3dUUm z4M&+gz?@^#RRGal%G3dDvj7C5QTb@9+!MG+>0dcjtZEB45c+qx*c?)d<%htn1o!#1 zpIGonh>P1LHu3s)fGFF-qS}AXjW|M*2Xjkh7(~r(lN=o#mBD9?jt74=Rz85I4Nfx_ z7Z)q?!};>IUjMNM6ee2Thq7))a>My?iWFxQ&}WvsFP5LP+iGz+QiYek+K1`bZiTV- zHHYng?ct@Uw5!gquJ(tEv1wTrRR7cemI>aSzLI^$PxW`wL_zt@RSfZ1M3c2sbebM* ze0=;sy^!90gL~YKISz*x;*^~hcCoO&CRD)zjT(A2b_uRue=QXFe5|!cf0z1m!iwv5GUnLw9Dr*Ux z)3Lc!J@Ei;&&yxGpf2kn@2wJ2?t6~obUg;?tBiD#uo$SkFIasu+^~h33W~`r82rSa ztyE;ehFjC2hjpJ-e__EH&z?!~>UBb=&%DS>NT)1O3Isn-!SElBV2!~m6v0$vx^a<@ISutdTk1@?;i z<8w#b-%|a#?e5(n@7>M|v<<0Kpg?BiHYMRe!3Z{wYc2hN{2`6(;q`9BtXIhVq6t~KMH~J0~XtUuT06hL8c1BYZWhN zk4F2I;|za*R{ToHH2L?MfRAm5(i1Ijw;f+0&J}pZ=A0;A4M`|10ZskA!a4VibFKn^ zdVH4OlsFV{R}vFlD~aA4xxSCTTMW@Gws4bFWI@xume%smAnuJ0b91QIF?ZV!%VSRJ zO7FmG!swKO{xuH{DYZ^##gGrXsUwYfD0dxXX3>QmD&`mSi;k)YvEQX?UyfIjQeIm! z0ME3gmQ`qRZ;{qYOWt}$-mW*>D~SPZKOgP)T-Sg%d;cw^#$>3A9I(%#vsTRQe%moT zU`geRJ16l>FV^HKX1GG7fR9AT((jaVb~E|0(c-WYQscVl(z?W!rJp`etF$dBXP|EG z=WXbcZ8mI)WBN>3<@%4eD597FD5nlZajwh8(c$lum>yP)F}=(D5g1-WVZRc)(!E3} z-6jy(x$OZOwE=~{EQS(Tp`yV2&t;KBpG*XWX!yG+>tc4aoxbXi7u@O*8WWFOxUjcq z^uV_|*818$+@_{|d~VOP{NcNi+FpJ9)aA2So<7sB%j`$Prje&auIiTBb{oD7q~3g0 z>QNIwcz(V-y{Ona?L&=JaV5`o71nIsWUMA~HOdCs10H+Irew#Kr(2cn>orG2J!jvP zqcVX0OiF}c<)+5&p}a>_Uuv)L_j}nqnJ5a?RPBNi8k$R~zpZ33AA4=xJ@Z($s3pG9 zkURJY5ZI=cZGRt_;`hs$kE@B0FrRx(6K{`i1^*TY;Vn?|IAv9|NrN*KnJqO|8$e1& zb?OgMV&q5|w7PNlHLHF) zB+AK#?EtCgCvwvZ6*u|TDhJcCO+%I^@Td8CR}+nz;OZ*4Dn?mSi97m*CXXc=};!P`B?}X`F-B5v-%ACa8fo0W++j&ztmqK z;&A)cT4ob9&MxpQU41agyMU8jFq~RzXOAsy>}hBQdFVL%aTn~M>5t9go2j$i9=(rZ zADmVj;Qntcr3NIPPTggpUxL_z#5~C!Gk2Rk^3jSiDqsbpOXf^f&|h^jT4|l2ehPat zb$<*B+x^qO8Po2+DAmrQ$Zqc`1%?gp*mDk>ERf6I|42^tjR6>}4`F_Mo^N(~Spjcg z_uY$}zui*PuDJjrpP0Pd+x^5ds3TG#f?57dFL{auS_W8|G*o}gcnsKYjS6*t8VI<) zcjqTzW(Hk*t-Qhq`Xe+x%}sxXRerScbPGv8hlJ;CnU-!Nl=# zR=iTFf9`EItr9iAlAGi}i&~nJ-&+)Y| zMZigh{LXe)uR+4D_Yb+1?I93mHQ5{pId2Fq%DBr7`?ipi;CT!Q&|EO3gH~7g?8>~l zT@%*5BbetH)~%TrAF1!-!=)`FIS{^EVA4WlXYtEy^|@y@yr!C~gX+cp2;|O4x1_Ol z4fPOE^nj(}KPQasY#U{m)}TZt1C5O}vz`A|1J!-D)bR%^+=J-yJsQXDzFiqb+PT0! zIaDWWU(AfOKlSBMS};3xBN*1F2j1-_=%o($ETm8@oR_NvtMDVIv_k zlnNBiHU&h8425{MCa=`vb2YP5KM7**!{1O>5Khzu+5OVGY;V=Vl+24fOE;tMfujoF z0M``}MNnTg3f%Uy6hZi$#g%PUA_-W>uVCYpE*1j>U8cYP6m(>KAVCmbsDf39Lqv0^ zt}V6FWjOU@AbruB7MH2XqtnwiXS2scgjVMH&aF~AIduh#^aT1>*V>-st8%=Kk*{bL zzbQcK(l2~)*A8gvfX=RPsNnjfkRZ@3DZ*ff5rmx{@iYJV+a@&++}ZW+za2fU>&(4y`6wgMpQGG5Ah(9oGcJ^P(H< zvYn5JE$2B`Z7F6ihy>_49!6}(-)oZ(zryIXt=*a$bpIw^k?>RJ2 zQYr>-D#T`2ZWDU$pM89Cl+C<;J!EzHwn(NNnWpYFqDDZ_*FZ{9KQRcSrl5T>dj+eA zi|okW;6)6LR5zebZJtZ%6Gx8^=2d9>_670!8Qm$wd+?zc4RAfV!ZZ$jV0qrv(D`db zm_T*KGCh3CJGb(*X6nXzh!h9@BZ-NO8py|wG8Qv^N*g?kouH4%QkPU~Vizh-D3<@% zGomx%q42B7B}?MVdv1DFb!axQ73AUxqr!yTyFlp%Z1IAgG49usqaEbI_RnbweR;Xs zpJq7GKL_iqi8Md?f>cR?^0CA+Uk(#mTlGdZbuC*$PrdB$+EGiW**=$A3X&^lM^K2s zzwc3LtEs5|ho z2>U(-GL`}eNgL-nv3h7E<*<>C%O^=mmmX0`jQb6$mP7jUKaY4je&dCG{x$`0=_s$+ zSpgn!8f~ya&U@c%{HyrmiW2&Wzc#Sw@+14sCpTWReYpF9EQ|7vF*g|sqG3hx67g}9 zwUj5QP2Q-(KxovRtL|-62_QsHLD4Mu&qS|iDp%!rs(~ah8FcrGb?Uv^Qub5ZT_kn%I^U2rxo1DDpmN@8uejxik`DK2~IDi1d?%~pR7i#KTS zA78XRx<(RYO0_uKnw~vBKi9zX8VnjZEi?vD?YAw}y+)wIjIVg&5(=%rjx3xQ_vGCy z*&$A+bT#9%ZjI;0w(k$|*x{I1c!ECMus|TEA#QE%#&LxfGvijl7Ih!B2 z6((F_gwkV;+oSKrtr&pX&fKo3s3`TG@ye+k3Ov)<#J|p8?vKh@<$YE@YIU1~@7{f+ zydTna#zv?)6&s=1gqH<-piG>E6XW8ZI7&b@-+Yk0Oan_CW!~Q2R{QvMm8_W1IV8<+ zQTyy=(Wf*qcQubRK)$B;QF}Y>V6d_NM#=-ydM?%EPo$Q+jkf}*UrzR?Nsf?~pzIj$ z<$wN;7c!WDZ(G_7N@YgZ``l;_eAd3+;omNjlpfn;0(B7L)^;;1SsI6Le+c^ULe;O@ zl+Z@OOAr4$a;=I~R0w4jO`*PKBp?3K+uJ+Tu8^%i<_~bU!p%so z^sjol^slR`W@jiqn!M~eClIIl+`A5%lGT{z^mRbpv}~AyO%R*jmG_Wrng{B9TwIuS z0!@fsM~!57K1l0%{yy(#no}roy#r!?0wm~HT!vLDfEBs9x#`9yCKgufm0MjVRfZ=f z4*ZRc2Lgr(P+j2zQE_JzYmP0*;trl7{*N341Cq}%^M^VC3gKG-hY zmPT>ECyrhIoFhnMB^qpdbiuI}pk{qPbK^}0?Rf7^{98+95zNq6!RuV_zAe&nDk0;f zez~oXlE5%ve^TmBEt*x_X#fs(-En$jXr-R4sb$b~`nS=iOy|OVrph(U&cVS!IhmZ~ zKIRA9X%Wp1J=vTvHZ~SDe_JXOe9*fa zgEPf;gD^|qE=dl>Qkx3(80#SE7oxXQ(n4qQ#by{uppSKoDbaq`U+fRqk0BwI>IXV3 zD#K%ASkzd7u>@|pA=)Z>rQr@dLH}*r7r0ng zxa^eME+l*s7{5TNu!+bD{Pp@2)v%g6^>yj{XP&mShhg9GszNu4ITW=XCIUp2Xro&1 zg_D=J3r)6hp$8+94?D$Yn2@Kp-3LDsci)<-H!wCeQt$e9Jk)K86hvV^*Nj-Ea*o;G zsuhRw$H{$o>8qByz1V!(yV{p_0X?Kmy%g#1oSmlHsw;FQ%j9S#}ha zm0Nx09@jmOtP8Q+onN^BAgd8QI^(y!n;-APUpo5WVdmp8!`yKTlF>cqn>ag`4;o>i zl!M0G-(S*fm6VjYy}J}0nX7nJ$h`|b&KuW4d&W5IhbR;-)*9Y0(Jj|@j`$xoPQ=Cl diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_16.png index 0a3f5fa40fb3d1e0710331a48de5d256da3f275d..531dede67abda0a47f3bf480dc06439494a3c200 100644 GIT binary patch delta 837 zcmV-L1G@Z(1ltCXBYy#bX+uL$b5ch_AW20-HZeIiHZ3wPF#rH4k#&*3OF~f;$3JRe zWMNQ)LxY4hWtf4~(qNPY)nEo$E&BWw_~Y@O5z!j71_e<|zlQn?Y7Lr$peTZ9j>e*v zlGk}ED3RxK?)lvBz2|W6xnPZCm7Lz>gIvC-g+oF2LUhq>e}AJ17Y=OLVv4TL%uPgS zXkQOl%y{QDYc)RiuQ?J)T>(pr@Tj6{Md3-|>9wM2@~&`~l8GgR&xQLnxuEd9smCk) zYI3^5KPGFD@EBM-gx%>nj@Pl0(Q?A_ay+^0s#3j=`I5F|etu43k9apaVL}9PGsQS# z1Q=vQ<^W#&41dUq2Kl~n{wxK_Rb*CKM`MLF8H)6ax+>L^5>uilWn@`5`~SDEdTPjD zsooZZ<`={G=mq-@l(r4y``9o_Ct!Pqt9&iLa0J7jqHotU&mlNB;o`cc#rNQH3tUfX zOpBEzo47TVg7-6Mk3#1yv@TV8R^8|H5h5G%RX4DI0DpaQ-nsk>07hrGjDM$Q0004% zNkl3w#80n^wO&hhcy)FB4a; zC%+3+G3&jTzrSuc^=0q>{|q1fO}S-NB-ucI|C-|=pfYp!$Ez|F`@!-0XUrt_p`0EBtu5RU91|2yzm0)uowO|V#$*Mph?fm(#&!HHw=-{UdZ{V0Ut P00000NkvXXu0mjf0S}%Y delta 495 zcmcc3*1Hb>FZqno^zN^3(+@_@XjP1uC>hJC?a{y* zD{|!jx7m$}htAgXd~cj3+ZrK}6l!2{cx$4>2i}b0%U|nx*4NknNi1N>>I*rxRx*XF zjWIp$e|p7N*%gv6a^xe`+J2V*GqU;lt>1BWf2ShLW$77g5go>ce}0@lm7sd+gu(Y? z@okUe{~JYoFgC6@om9@LBk=#Q%~7_H=W1tk diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_256.png index bdb57226d5f2bd20f11934f4903f16459cf52379..b36354881c65bb756380f85fda19220a32007d0a 100644 GIT binary patch literal 11306 zcmc(_^+S~36E=L)NF(^6J0zr}yQHN-MHWOrMapIA21x~^1?eso1VMJCyHiS7It6KP zX`aLP{Ttrr`Du6IoVn+oGjq)~Gv}Rwo(3rqJrM*!q*|H}j35XLe8qwY@xccSQSuV} z2!5@qYT#<5p~9-ArYa#KEg>OrUr+>sc;emTn{-qRsk;>IpW8k+2vH3Q6@QT$JT_{T zgg0)5Zzgbdapz=tKZ|mNz8W9TP^T&UjM$zuEhLBMt=)&typIW!-h4dq>xi9G^lrmC zd>3UEW1E~Yw-N$tED2Lp#;CZBI0fe4q9JpfvVLDa*suG*&h8oclYXytaR+e)OojAq zEekB2sJ)Urd$mQa#XmK9_6Ozgl!SL&p+jNk;;5XxhSDzn3wy-RRz+@y_&wSuvZ1qo zWIjw*CX66j4-j&wzhy=Zv8M??Yy$%HtYf_-WuB|xx`=j2+2GRJK3Ib+FG#xIqkDf8^^JCK>hoxJ{fLsC;lNb#TOj0*m_uCK0lOL zeLMe-rac>lkIJb1<46?iEsk59xhU*gw=A?Y?aCvARwH;BqDejeA{g(wN|v|pGd<=q z6)ER5)jNpLGTP#tiq_Tort^IHK!G?;SdsG^^8<4>Y-U2^PwmK+yLej-B`I0DyT4ua zF!lbsvn;L(rWHGxpR%&D&e#0T-7ueajFk+N1`)jl#5p{@D+X8wNo4uhIXq12cuIyc z(L_OcZnSqGwLijq(EHKnCJ=RDTM5LY9bx!?f1%97`1CCeRoC&shKTFqg1)?m_;-TH zMCsFRLuYEvjYf}-M+^G$9ToW?ro!$4CkW1Q@q{qo`n$4jMxm!nFJ@+N?e3dAlg4_fZ&UU|LtKK{MU|LH!j2_&QPk-PYx zZ%+kEx2L1&Tlc_h$i8-su9`7-B$1Lv_vp$?2-)pqg#B&q?=B{R4FbADKuclzv}~fW z3sMQ)rz_k7pMAU;-WNTj0G2UW>HK##&&&pC#KwlNg}g8gwA<1tes~-F3+#DD5QI0> zOp{u$HMj0gpdR&@ypun$Qn$l|JBX+`!_}(VD{33t&hVT?cU>KK?(<0SVH8m_V`5>? zTLw%Q+`1u zrehm$w(#nObQ1N21S+oVh~JmpyqYwpPU8BpZ;v7(J!Wg}$3KkXkPyOk$g2KeM1ZgA zKAQ=&7RN5Bhyw|^bk2`$AbD9UKgi;qH>}+KE`|zx?QI%?yG97aaOfn`9QpPLiEMk{ zay&Xge~&_=C21@CY^kC?Kcoc<^1BCwp4f1aeHER9^uB*cBi2v^Qkc}7%c{x(k$7s4 zZ;ZugxUz;05IRLgx?H7lL&x4{c6M{7kB*yWLznoBZx)CEb62YO9&n;^6PuRdRK_kP_&;lphyJx>!Je#LQRO(sl8Bs^jvzFtH1un~w_d^aC<L@!IIiYqwd8~jlj2{C~W>%Vw?a47S- z+YvZV8#sx&dR=?uo7rR1h1`~@D{R7c+$o!ed%7M10u=#=xXx;yDEJ^z?RbXss-Xdu zlN}Y?2$q^`2kf|g-27Zr{+G=_*Co$FM@g`#*Us(=3(EKpK7;zuVjxU$2MUcneZ9kj zI3xh?`TIa3=~h0ra0oT3lFA?5MSCC9N{+GrMovah6i&|TBK1N{Y*+B}*|UshC*B+V z@##nhDu}M@a{8DzaFe+4bK7&JJzV3{uOB@+redfUxIvPBS~X`uf*{#=HbDw}@)C}r zip!Z${0QvO56ldt1HR%i@E-;{atYWo_2XiB+wKa(_l#X2^aD~?risH*&6>%rC4zc4jtOGOY$+)F=uL&0k! z{+ghnZ#u$yfh^2eIX*`=mUq_P1{XN6c%lc{GYWfh3s=XR96Tp`J#w*yJAmY;Kr;Jt zx5`AH1^+RLWCGJZV{gR3hqZbdlsg^^AVM0e{hPkCM=VJY_oQAr@eMXBdL#r|Hl?5~R@Riv#sj~rtv-?f z!9s1cvK9vL+_LqgvX6xW7glY>BQQCZvqS_p#;M?siw@@&`h2FSp7i*)x(QSiH!|$k z{dEsVz#@Q%k1^Fj@CzkAIptiJ%vpZ{0hox2tdFvqE9;UbKDl_sv&rB#$bJ7jQAowq=;M*+s5xwHESd%M8ERgBe z^42-~K{&f43(&zg{)OQWfNQ*Y-2-~E4UgJ|nK3eg$@q~MJQHD0L5{e= z{4=4y^V@393IL#=iDGgcarhvrqV9nxEGr>bTJl=)Q2V1{!XUBRO5Ws2ixF~B!{1g* z0k{-@*^Cti*2B6JbZa^9O7Ae5Q^H=~nqwWhe}d0AF{7j_%6uTU_fHpyHhgqU&fZ(( zhy_F!bPseuaQ%XGefPhH`&dbF)!t00WnWbV14=^TWOr9ahDiW0Ab>f5UtGLR&q+l5 z+W)ICn(mW9VbC@0MLy~sFihdDU~0+QzIetiNuFeSnW=q@Rw#nSz{y+0sHk9QyNrGvaE0kRA?gv@)<1?zvPG)BQpk@*fbP~V9>Z62R)ui1C! zFM^kAmpw~NgNep)L>03&~0M@k>p}6SeRhR0U1d4^)3#p+{`^kuZ zShxSH_ZM>lAd+0zv+gz;_f-SWilKXy^A9EgqvkQEwe5P#5q6UCM2L0FbGXP%DU93r zeD8A zZwB3(M^F1L3>*uNhgTFW{jz<4<3q2vx|@vlUKKqN_xn>DAw80U$q>~p6b66q(#(Sy zU3;<#f=H3p@X?D9uu%js!%3Xxs863fc=FdQyOKMvr7_G=D&2j}o!ZCf3d&CH%%}>g z+p?Ph&LBXQW601lzz}iwbRFS+5$K|^ANZ|2QmU;smnQuXjUYO*rzf~dseR09fsTK5 zK=Y4FBP`7VI2vR0V`jGA&yLu9khx}jx;eD48vK-=eR{5PUiDNfK1gIWr+2lO)SCk~ zmsDH1bB6slvN@lg2`LVAqy&f){Skv-L=`(7yO>5e=BZ~}P`h7pV5lyHI)$;|-O-`o z7yFn3sP_PH1`6YstAM9ZvA;*7@gSP}ovrTuhU)!z%S!EtIarelVY!F%p}N%<8jeEQ z16jZ_0o}VPE<^=(l;443jTBVcZ#mSsZ^`@fbJ-tncXP!DfWGl%1;~)|9Q|@DQLSOi;#_hs%!F4E-nKy+v!Rk`E8;2eJH^ zc4VDZH0N|2v)F`M=6?tg9TO}kE8aqfjAGvj(ghGD3t839ME}W2jQoo7S4s5LJPoyX z@+0vjGGW1ebwq9Lnme!K?9%pDpV*s60KDLXDlzHr^EzqLS2iRKPD37!XQ_G$B$7oe zGTBtLuhEJ{fk84JXD$9wZ_p^r9!{(O|F;VOr(bN071i_}?5}K&>xI8bOfPDN;`NG1 z_&xWj({pM4+yTb7xgS)r8KTe^W*`x&G8#Y4!~UiP3`_~3qdb;Nzq?Sxj=fxynSs+k zj24Eovk9E)s&R(fduTmCo|7kgcG=lE3w%Da>G#$qHi0DG0d~?MuODMq?Apml#p%X= zNkBnCW`%p#WJ_}1hMgc-vv2io^7T)4$-t+N+y~GRx8D&pbA$Tk17^Mjc}}_&%n!_rXDMs{-+3T6|feMn6=rxOHEV?F5Ok;wEmUO`Bh3R!xT*d8Rup5*>7^?l_ z${KIG{tQ|DGqU*b4odAI)FI3ac@TDhdn9{`4bt(+L$h&xB1|su7%AoVXxK{{lv_HR zXV%-zjW$go0+-h)gytks%_2=?Kuqcf<#I*UP5y1$cp$ViH1WFn#XtEmKhb2E%X|tp-^izK)dEQ`qP`M%En;vb+%Fgl+847Fe zSr#sQsacUfUunKo*PqGCylU{XJ!E#4YubE~FwCWAOMIE=*N zY>>|VAr-_PIx=57Bhd!9`x^>O!A+d7dTiQny;YysX#VR!l^#1}e)or}rE*Dya+$xX zphB|#UzdwadrJd;Viv8*U9LC1qbm%Xc+~*baFBNb=2#4gb@0_lXF6`%7&wgvzp@)c zi8y)x$&grG8T~@pWZq^SpUw}Srt$7RF9?2yobG|I5L{$hpr#G=vPInoQ&_uQQXjlW zGVO(x6w%fo*-Xc?!w@%mGBehVwPP+-HPpa!ByM3?!gRBFUT4ScnX0(-WIFj=z@{8g z=^9>Z$%I@j9Y$PJbAZ-fJ=Y*mgD3FXQ~FknkyR{CgyH%5(7@_#@tD#QsJgg& zKoIhJVe1qYyXenKOSR4xYPlg@^wRM+IfZ@taB0cf5@eHlZM| zK29^<#ASS}`6C?XSP)9MSZ+s{2Fv2g~I+t=(^T-*&A~-NxxXp&52Z(x>y$ zsQvvJN}580k~VpC?D^?}8nhOO-=n82uP4&HYCrK53#78>G+v%QUxUkj!k7_}V2WRa} zQ0fhSY8pdI@?nNlu;0WMN8G_2sPB;ufb$o{>A93Z4-i(>b{tpboMc+%igPrG(?Yod zCtjgVT6cLpMr7QxGA6y`zM+V^@G;JV3brs2mdhP=+^dF8JixRfo4@WI{z^Ca6%IQ# z$U4c0@gltKX3wvn9<^mK?_Y@o2ipe#twICsS`2o9pD`0PM;@o-+%(DS z#T}W?M^6+dukdVXjpU#jrcDRJTaPrUgHCmk^W5r6Gw5BBENzfA|K{P?bW|jkK)7)J zi~30?=XO(qCFP>EDU9q<$+U>cd03nrfnQAOTKEc9weIeBb;6)$3TWKLa@X=GvN3l& zJQE0;8igA8nZ!`iV=eO!N&l#f39GPpaP}Uja$J2zsvn&B%B8F}n*qg3DbGok zkS-`r2hSSyhEetW!?QI@^D|4K&Nsxe>K?Uy)s#{%(0V5#=z06kgN$?jOsYD?@Hj)G z0pcA--tgy{dmo@xA#psYa6OH2;ObWty50jEuq(U8I@k|#)+0zNL~2EGWi+72VjVjS zDN*mH>qiRMVk2I!Y|h+W$hN@bR|J(R?1MqKu)9#e?~(%+s^Z~Yu1Qd&cNDIgl9DKu zKory{>CYg{T+*E!%zL;#{)>>qFEx%YlXuBN4`-N^4>wq~t-%mhA885J{Ql6R8w^#( z{jz-E^GnCF80LvEHNZo0^B3ds6!dNEovcVG302z+F0qYvQRFXH5?ZvE*AgJOD*VK^ zJF)rH@D%>G(;}konfhCW0BSYQx(c?oBKt1}ib@ZG!w*$ZqCoC~6Rx*eMDgo<=_AWB)V`!nTI`B^ z_%M-OBDT*_wBpO=uIRc4(H$tl-ULlDl=kUugrmyVka`{b@ZwVyz*Z%uM(&>-GD46kEhU?UG3US4oaxn*G$(6_ zGuOdYP%k7f_N6#mUHwT4D1FU0gfnS^ivR6a_W90JjtF+nmwr%WWj;y$C*bvZzj7E2 z<;s;leR@EMe9CM<%5Omvb!&Y#bfGK43fKfwOu>RRIYfJ?w*xthSC zW#HRa5^hO)#1PSGa`?{0&@ctdy0ebBRX+ujX=h9)W%Z{Tn%#V~FCXdS0O!u^A{csW zSc*y5TeCIf*ObGmn)8*h+4yz3rX~<!hX?jFT@eDKjp1Q;#3HGLrtYad*rmH@urH1&uK|z{rbdu${s=A~*SJrZ@ zn^};BtZlUuMknjPyDD9bETjX+79^BA1rTz&Ng2`PQYZc(`g6>$C4xlaZ|}^oNwPWU zUY9&%!^scjG@0onArJ4x3--LW`L}p~>OznY@%_o8VD${ME=%YOs=SDHxj?BJU96_CjR5>vtXWn6H{0WQ3;pooo zlzK+kFJsJVvGkDO^<1Glo-7xrivRXD)}^+MwzZ1mAd8eY!f1P$@K)Az#B1DQrW~}} zk;6f~OfuOsWZqKfZk%NDE0(1q>TzlBevhUUSbAa4_21t2Dw&i}ZR?PKa6~pjMA<86 zU*WYKQ6#~KUYu;9@gos&?{tDsuAjNuTDw#+6aTJ)yJ?=yM7(#28(qG9MT7GG4ayi& z_H0zXC^jI$dPn;S-77HNemYsxzD}~cMtM|3KXTK^Ow49TuC>(hc}Qp{3$7H(i;~M# z{g;+uK08;OSVflfGHH$TI^{j1EBk=`r1DO`O4B1$`p7MN*05q(OJ~lZEiOG5`%BXw z#|eFr>JTxiqr$%0=l{$m`aekml>x#(0R`1#m2oAS=OtAchATxkjq@1fKiJ4EEcn(r z-5Z)?0~d9MGN)2{IZi^8ZMA{3wq#Sjioj?-{phAM{Jg&b0{uWAkp9$8iqFZ-HgXfAGv1rz9~3c5l@~4b zYGtyB9?=?qHu|H|#j}j>#`s1j(}mP)G;WGM^K3hqhr^wG;NKyLDFvY6CuA||`3@eS zAL$Ku0#vX#y<}I)mI!*^5a_H&w1>!Wk6Ve$z0l@#3WDZ=_YOM!%*vI6M!Frmml6W+$oAbyfPwO~{Nd z?lZ!VI2`xRl(uueQK)CfecrvOvt6^ze<8DJVH@zLL_!R~YGIjTLnvpo>u($8`(2$xjdc+j zxZsT#V>D86oUFjk)lrn?twcDZIezIZlQDBS{&B=P=bNxH-O?@B%=C=Oc2Xy!xBpQ& zDC0>iR!L;P8U&p^7=WVmbgYFi=R_Z+g6VHgPV5~x2CtFRSzE|fLE+;ZBhVv``oY{R zQ&wu@Gj@3>&9Pq3*%W={;{4vlsyC?Nj$Smx(#x?aF$(X~(6zjjG!pc2NrdTrG4wi=g(V=IX>KCTyN$p?@X?ydw_qPR|Z~= zyRgux#&Db>9AOi~l1jk$G9$Y;#Mi2ntv*H!XL{^!Q1rVQq4CZn7o(b2(YZPUxBpx` z*?nK9Uw%RA*lyR9QlRGiv9By34Yl)7L=xc5nj_?uKSM%iL|CfNY7!FhZ?Q@<(^slO z0z>gLfXB%(hP;&_D0f~ViTPSRNrS>zf%i>Dc%Az9A&_q^A05*~9=`g3q6AZ@dc4_K zTQ3p$&D`lOee(VpzcJs#R0D!c6JvzsJ6pzol217YrD>qQ+FJ88gQRqP$=sc~>m)|K z+0#YpMArW?kjs@+*HSd@_V1pzCSp9`5r|9)LzNzRSkV^Y#{hetaH9dG1uujIMA}+eNVN1hwic? zdSpiI8D7vXc5@8`|2PwvbzV3Au7yL7BldJrLMqzdPYm853eCISA?!+f%%1fzUoo-Fog%Ae z3Cs%pPp-rJo62&1kg9N7e?1f({*o3xUV5p-n8N&@AgP|tD(OSie+Dw;607AS1+&5S zXG{-%E=SLG4f=equJ;Kv8^^qQeGs5b;_MnYuWC)P>|(ehze)G@C%|5muEn^oO8UTj;9M?C2d(1%4*Bb>?F$l< z?FStTTsvoND;;5%iZG zbXia-Cj{8fVJFJwN;VBnIcRt}$;sl1I(Z3V!EMO3X0M1rK7uNQptmdldKb*(B0a<9 z(7xcIPr^(PbT{kQ#x=h!i%rRxC!c?Hi_FEk@@7Ufop!(o7+`vX(RQM6NdFhW4J&p0 zES4l}W?$B49}=lBy~&l}uN5jPI*{%Yutik9f=e~&iu-){Xl+&b%kDSwR0u05(*mPG zsSDZdr-#=|_D03Yy*0Q(qZU*`vokulI$jz}htrw}Ye0fyboHF2=`L|NP zXSVF#j=mZJ$9pyRh(Vr!179~=+4!X_)vwR9^P+mVjVtQR^h2yK)z~hs32)(<{?f?{ zSr#vFaLImk2jzX!VBc=mmvrwh0D7Y)#>Fyb)aiuRU!JdjWt(KAWoz~h%{$_(b!++j zM>_v{(N*wYTLiQDrHoh^R$L_-@F3NPQU+tLt0j z(5k6^9kCoc&QhC+_%5v2AcX%Tu%B!Mxa?mrp5qWfPG5>!@6mLN=8!O@UdOLYxb}rE z9`5z4Ii8|GrokLLOTuEukL5!6!Vmbm*lFfA$yI{4h|jyKGAE6N zrmDbr>%Ee@_%W|2HbtT5=I`&Vq#l4Umv0(+rFbi{2G1hKG1*8wj;l)u5{g9R5eSh?`P2JjxV--<$0Dv z^|k`1nI`V>Fh$x{)9)cQdhN`2Po5O4ubt{|&mSIu4u7COj$+pjQ7UY!kboQBvE?eh zR>)wt8<9qk)D;wlGbwW=-59kiq_nwSp)O=~cNzu;$`3$Yv8R4J?Rm$VWR1!mJq8mU zCFeKgzw}(Kmw%-_n~JPlt4mz|;xdJaR$u~z&$GPeIaJ>a?c$axVB4h@9D&Yi#qO zu^SMc^ja)5SS+SbXEO^z{v&u>hz%oZ;%4rT1wX z>3rBCjg~t%FeM{H%<L9z@d;vvR2F^VRX1x(KW4IIefKARVyXQ3WrclOdGKf&5Ng^OPZr3p?^a7TPP2CV%=-)j#${5# zW4J)?%7H$+xRg2w4C}ysrF6W<3NK5@40HoUs8Vh2R-RPTU;1%G1~chO{pPA0z5#$7 z2R=XZl0T)p$otcVD=#O-!U^>YAx3nqSJc)>SY%e9QkSQfxcsZ5SVkYm3@wRsdl2qH7UXZ+}FjvO{>o`OAjtRg37`XtT><0kP+e950p#THTrx$KfR zHzVUhSL)k{!=2-dZl%G#R&S6cDIPfcK1A**i zFbCV>zWlk@j@PXBZ)BINu=caanPT;Bn1j`a`%y`zP9YHrj@OQd6AhhzqgsyDoaf|d zE6|EP2t63+hfL`ureHT~z{IlX8}2^_YBO=-YvfUYQc%-brVf><90fkCnVMdg{C z`);xzU=g+3^Ty{GSW02fDY*T?pU5}Vj%T$#*LHr_0$=SD?oG=EUC<}&f@MJc0u12) j-&|_^|K&dAg(69IDlhkUA69S&7}8SHdr+=o_4fY&Sk|0- literal 14142 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 XsS#}nO%AeS00000NkvXXu0mjfP@->3 delta 1046 zcmV+x1nK*;3aSW@BYyw^b5ch_0Itp)=>Px#L}ge>W=%~1DgXcg2mk?xX#fNO00031 z000^Q000001E2u_0{{R30RRC20H6W@1ONa40RR91AfN*P1ONa40RR91AOHXW0IY^$ z^8f$?lu1NER9Fe^SItioK@|V(ZWmgLZT;XwPgVuWM>O%^|9_yEkU-*%n;uO3NYv;R zJsM3!u3ork^kPCHQDcY%MS{_&iC_RFh!ijwR8UDjc73ngDc$LATNA4nUU=-z%zN|u z&3kWVw!nt`=Ljfn_@-$dq_Gat2x)*+Cl$hevad;ftU?m>@}2Y@>0Q!$ilStXQ{D^JNiP(3%faD)Q3SZ!2dUuhq{A-2n<(cT z_B;jW0Do!kDoB8HKC)=w=3E?1Bqj9RMJs3U5am3Uv`@+{jgqO^f}Lx_Jp~CoP3N4A zMZr~4&d)T`R?`(M{W5WWJV^z~2B|-oih@h^D#DuzGbl(P5>()u*YGo*Och=oRr~3P z1wOlKqI)udc$|)(bacG5>~p(y>?{JD7nQf_*?*wALP1xfhU#(^&2+pTulG>3E13Ca z;>uVYpJROXS>h+~6JZY;HY+(-rLd8owiwZQ&R3`7Y50Xg?NJrl=fL6*6Q`cXFhk%~ zbl!)`6!6L!eBZW$Ynq_DAcG;NARS1VC$QCLagDB+=p2nWsJPlG{G`1taUr|3y$YDeNX#{=)#1Zk{;tz8` QaR2}S07*qoM6N<$g8nt#4FCWD diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_512.png index 326c0e72c9d820600887813b3b98d0dd69c5d4e8..bb83aecf77dc6dc6c42109b2e7e69de635bfbbe2 100644 GIT binary patch literal 38190 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 Mn^<3~xQdMZADJk~RR910 literal 36406 zcmeGE=RaKU_dbB`8KZ_EB%(x35TbX25d=Z>h)%Q!Av#fJM3Csc_g zC2I6x%$)80`Tkz#KRA!h1FzY`?0es3t!rKDT5EjPe6B=BLPr7s0GW!if;Ip^!AmGW zL;$`Vdre+|FA!I4r6)keFvAx3M#1`}ijBHDzy)3t0gwjl|qC2YB`SSxFKHr(oY#H$)x{L$LL zBdLKTlsOrmb>T0wd=&6l3+_Te>1!j0OU8%b%N342^opKmT)gni(wV($s(>V-fUv@0p8!f`=>PxC|9=nu ze{ToBBj8b<{PLfXV$h8YPgA~E!_sF9bl;QOF{o6t&JdsX?}rW!_&d`#wlB6T_h;Xf zl{4Tz5>qjF4kZgjO7ZiLPRz_~U@k5%?=30+nxEh9?s78gZ07YHB`FV`4%hlQlMJe@J`+e(qzy+h(9yY^ckv_* zb_E6o4p)ZaWfraIoB2)U7_@l(J0O%jm+Or>8}zSSTkM$ASG^w3F|I? z$+eHt7T~04(_WfKh27zqS$6* zzyy-ZyqvSIZ0!kkSvHknm_P*{5TKLQs8S6M=ONuKAUJWtpxbL#2(_huvY(v~Y%%#~ zYgsq$JbLLprKkV)32`liIT$KKEqs$iYxjFlHiRNvBhxbDg*3@Qefw4UM$>i${R5uB zhvTgmqQsKA{vrKN;TSJU2$f9q=y{$oH{<)woSeV>fkIz6D8@KB zf4M%v%f5U2?<8B(xn}xV+gWP?t&oiapJhJbfa;agtz-YM7=hrSuxl8lAc3GgFna#7 zNjX7;`d?oD`#AK+fQ=ZXqfIZFEk{ApzjJF0=yO~Yj{7oQfXl+6v!wNnoqwEvrs81a zGC?yXeSD2NV!ejp{LdZGEtd1TJ)3g{P6j#2jLR`cpo;YX}~_gU&Gd<+~SUJVh+$7S%`zLy^QqndN<_9 zrLwnXrLvW+ew9zX2)5qw7)zIYawgMrh`{_|(nx%u-ur1B7YcLp&WFa24gAuw~& zKJD3~^`Vp_SR$WGGBaMnttT)#fCc^+P$@UHIyBu+TRJWbcw4`CYL@SVGh!X&y%!x~ zaO*m-bTadEcEL6V6*{>irB8qT5Tqd54TC4`h`PVcd^AM6^Qf=GS->x%N70SY-u?qr>o2*OV7LQ=j)pQGv%4~z zz?X;qv*l$QSNjOuQZ>&WZs2^@G^Qas`T8iM{b19dS>DaXX~=jd4B2u`P;B}JjRBi# z_a@&Z5ev1-VphmKlZEZZd2-Lsw!+1S60YwW6@>+NQ=E5PZ+OUEXjgUaXL-E0fo(E* zsjQ{s>n33o#VZm0e%H{`KJi@2ghl8g>a~`?mFjw+$zlt|VJhSU@Y%0TWs>cnD&61fW4e0vFSaXZa4-c}U{4QR8U z;GV3^@(?Dk5uc@RT|+5C8-24->1snH6-?(nwXSnPcLn#X_}y3XS)MI_?zQ$ZAuyg+ z-pjqsw}|hg{$~f0FzmmbZzFC0He_*Vx|_uLc!Ffeb8#+@m#Z^AYcWcZF(^Os8&Z4g zG)y{$_pgrv#=_rV^D|Y<_b@ICleUv>c<0HzJDOsgJb#Rd-Vt@+EBDPyq7dUM9O{Yp zuGUrO?ma2wpuJuwl1M=*+tb|qx7Doj?!F-3Z>Dq_ihFP=d@_JO;vF{iu-6MWYn#=2 zRX6W=`Q`q-+q@Db|6_a1#8B|#%hskH82lS|9`im0UOJn?N#S;Y0$%xZw3*jR(1h5s z?-7D1tnIafviko>q6$UyqVDq1o@cwyCb*})l~x<@s$5D6N=-Uo1yc49p)xMzxwnuZ zHt!(hu-Ek;Fv4MyNTgbW%rPF*dB=;@r3YnrlFV{#-*gKS_qA(G-~TAlZ@Ti~Yxw;k za1EYyX_Up|`rpbZ0&Iv#$;eC|c0r4XGaQ-1mw@M_4p3vKIIpKs49a8Ns#ni)G314Z z8$Ei?AhiT5dQGWUYdCS|IC7r z=-8ol>V?u!n%F*J^^PZ(ONT&$Ph;r6X;pj|03HlDY6r~0g~X#zuzVU%a&!fs_f|m?qYvg^Z{y?9Qh7Rn?T*F%7lUtA6U&={HzhYEzA`knx1VH> z{tqv?p@I(&ObD5L4|YJV$QM>Nh-X3cx{I&!$FoPC_2iIEJfPk-$;4wz>adRu@n`_y z_R6aN|MDHdK;+IJmyw(hMoDCFCQ(6?hCAG5&7p{y->0Uckv# zvooVuu04$+pqof777ftk<#42@KQ((5DPcSMQyzGOJ{e9H$a9<2Qi_oHjl{#=FUL9d z+~0^2`tcvmp0hENwfHR`Ce|<1S@p;MNGInXCtHnrDPXCKmMTZQ{HVm_cZ>@?Wa6}O zHsJc7wE)mc@1OR2DWY%ZIPK1J2p6XDO$ar`$RXkbW}=@rFZ(t85AS>>U0!yt9f49^ zA9@pc0P#k;>+o5bJfx0t)Lq#v4`OcQn~av__dZ-RYOYu}F#pdsl31C^+Qgro}$q~5A<*c|kypzd} ziYGZ~?}5o`S5lw^B{O@laad9M_DuJle- z*9C7o=CJh#QL=V^sFlJ0c?BaB#4bV^T(DS6&Ne&DBM_3E$S^S13qC$7_Z?GYXTpR@wqr70wu$7+qvf-SEUa5mdHvFbu^7ew!Z1a^ zo}xKOuT*gtGws-a{Tx}{#(>G~Y_h&5P@Q8&p!{*s37^QX_Ibx<6XU*AtDOIvk|^{~ zPlS}&DM5$Ffyu-T&0|KS;Wnaqw{9DB&B3}vcO14wn;)O_e@2*9B&0I_ zZz{}CMxx`hv-XouY>^$Y@J(_INeM>lIQI@I>dBAqq1)}?Xmx(qRuX^i4IV%=MF306 z9g)i*79pP%_7Ex?m6ag-4Tlm=Z;?DQDyC-NpUIb#_^~V_tsL<~5<&;Gf2N+p?(msn zzUD~g>OoW@O}y0@Z;RN)wjam`CipmT&O7a|YljZqU=U86 zedayEdY)2F#BJ6xvmW8K&ffdS*0!%N<%RB!2~PAT4AD*$W7yzHbX#Eja9%3aD+Ah2 zf#T;XJW-GMxpE=d4Y>}jE=#U`IqgSoWcuvgaWQ9j1CKzG zDkoMDDT)B;Byl3R2PtC`ip=yGybfzmVNEx{xi_1|Cbqj>=FxQc{g`xj6fIfy`D8fA z##!-H_e6o0>6Su&$H2kQTujtbtyNFeKc}2=|4IfLTnye#@$Au7Kv4)dnA;-fz@D_8 z)>irG$)dkBY~zX zC!ZXLy*L3xr6cb70QqfN#Q>lFIc<>}>la4@3%7#>a1$PU&O^&VszpxLC%*!m-cO{B z-Y}rQr4$84(hvy#R69H{H zJ*O#uJh)TF6fbXy;fZkk%X=CjsTK}o5N1a`d7kgYYZLPxsHx%9*_XN8VWXEkVJZ%A z1A+5(B;0^{T4aPYr8%i@i32h)_)|q?9vws)r+=5u)1YNftF5mknwfd*%jXA2TeP}Z zQ!m?xJ3?9LpPM?_A3$hQ1QxNbR&}^m z!F999s?p^ak#C4NM_x2p9FoXWJ$>r?lJ)2bG)sX{gExgLA2s5RwHV!h6!C~d_H||J z>9{E{mEv{Z1z~65Vix@dqM4ZqiU|!)eWX$mwS5mLSufxbpBqqS!jShq1bmwCR6 z4uBri7ezMeS6ycaXPVu(i2up$L; zjpMtB`k~WaNrdgM_R=e#SN?Oa*u%nQy01?()h4A(jyfeNfx;5o+kX?maO4#1A^L}0 zYNyIh@QVXIFiS0*tE}2SWTrWNP3pH}1Vz1;E{@JbbgDFM-_Mky^7gH}LEhl~Ve5PexgbIyZ(IN%PqcaV@*_`ZFb=`EjspSz%5m2E34BVT)d=LGyHVz@-e%9Ova*{5@RD;7=Ebkc2GP%pIP^P7KzKapnh`UpH?@h z$RBpD*{b?vhohOKf-JG3?A|AX|2pQ?(>dwIbWhZ38GbTm4AImRNdv_&<99ySX;kJ| zo|5YgbHZC#HYgjBZrvGAT4NZYbp}qkVSa;C-LGsR26Co+i_HM&{awuO9l)Ml{G8zD zs$M8R`r+>PT#Rg!J(K6T4xHq7+tscU(}N$HY;Yz*cUObX7J7h0#u)S7b~t^Oj}TBF zuzsugnst;F#^1jm>22*AC$heublWtaQyM6RuaquFd8V#hJ60Z3j7@bAs&?dD#*>H0SJaDwp%U~27>zdtn+ z|8sZzklZy$%S|+^ie&P6++>zbrq&?+{Yy11Y>@_ce@vU4ZulS@6yziG6;iu3Iu`M= zf3rcWG<+3F`K|*(`0mE<$89F@jSq;j=W#E>(R}2drCB7D*0-|D;S;(;TwzIJkGs|q z2qH{m_zZ+el`b;Bv-#bQ>}*VPYC|7`rgBFf2oivXS^>v<&HHTypvd4|-zn|=h=TG{ z05TH2+{T%EnADO>3i|CB zCu60#qk`}GW{n4l-E$VrqgZGbI zbQW690KgZt4U3F^5@bdO1!xu~p@7Y~*_FfWg2CdvED5P5#w#V46LH`<&V0{t&Ml~4 zHNi7lIa+#i+^Z6EnxO7KJQw)wD)4~&S-Ki8)3=jpqxmx6c&zU&<&h%*c$I(5{1HZT zc9WE}ijcWJiVa^Q^xC|WX0habl89qycOyeViIbi(LFsEY_8a|+X^+%Qv+W4vzj>`y zpuRnjc-eHNkvXvI_f{=*FX=OKQzT?bck#2*qoKTHmDe>CDb&3AngA1O)1b}QJ1Tun z_<@yVEM>qG7664Pa@dzL@;DEh`#?yM+M|_fQS<7yv|i*pw)|Z8)9IR+QB7N3v3K(wv4OY*TXnH&X0nQB}?|h2XQeGL^q~N7N zDFa@x0E(UyN7k9g%IFq7Sf+EAfE#K%%#`)!90_)Dmy3Bll&e1vHQyPA87TaF(xbqMpDntVp?;8*$87STop$!EAnGhZ?>mqPJ(X zFsr336p3P{PpZCGn&^LP(JjnBbl_3P3Kcq+m}xVFMVr1zdCPJMDIV_ki#c=vvTwbU z*gKtfic&{<5ozL6Vfpx>o2Tts?3fkhWnJD&^$&+Mh5WGGyO7fG@6WDE`tEe(8<;+q z@Ld~g08XDzF8xtmpIj`#q^(Ty{Hq>t*v`pedHnuj(0%L(%sjkwp%s}wMd!a<*L~9T z9MM@s)Km~ogxlqEhIw5(lc46gCPsSosUFsgGDr8H{mj%OzJz{N#;bQ;KkV+ZWA1(9 zu0PXzyh+C<4OBYQ0v3z~Lr;=C@qmt8===Ov2lJ1=DeLfq*#jgT{YQCuwz?j{&3o_6 zsqp2Z_q-YWJg?C6=!Or|b@(zxTlg$ng2eUQzuC<+o)k<6^9ju_Z*#x+oioZ5T8Z_L zz9^A1h2eFS0O5muq8;LuDKwOv4A9pxmOjgb6L*i!-(0`Ie^d5Fsgspon%X|7 zC{RRXEmYn!5zP9XjG*{pLa)!2;PJB2<-tH@R7+E1cRo=Wz_5Ko8h8bB$QU%t9#vol zAoq?C$~~AsYC|AQQ)>>7BJ@{Cal)ZpqE=gjT+Juf!RD-;U0mbV1ED5PbvFD6M=qj1 zZ{QERT5@(&LQ~1X9xSf&@%r|3`S#ZCE=sWD`D4YQZ`MR`G&s>lN{y2+HqCfvgcw3E z-}Kp(dfGG?V|97kAHQX+OcKCZS`Q%}HD6u*e$~Ki&Vx53&FC!x94xJd4F2l^qQeFO z?&JdmgrdVjroKNJx64C!H&Vncr^w zzR#XI}Dn&o8jB~_YlVM^+#0W(G1LZH5K^|uYT@KSR z^Y5>^*Bc45E1({~EJB(t@4n9gb-eT#s@@7)J^^<_VV`Pm!h7av8XH6^5zO zOcQBhTGr;|MbRsgxCW69w{bl4EW#A~);L?d4*y#j8Ne=Z@fmJP0k4{_cQ~KA|Y#_#BuUiYx8y*za3_6Y}c=GSe7(2|KAfhdzud!Zq&}j)=o4 z7R|&&oX7~e@~HmyOOsCCwy`AR+deNjZ3bf6ijI_*tKP*_5JP3;0d;L_p(c>W1b%sG zJ*$wcO$ng^aW0E(5ldckV9unU7}OB7s?Wx(761?1^&8tA5y0_(ieV>(x-e@}1`lWC z-YH~G$D>#ud!SxK2_Iw{K%92=+{4yb-_XC>ji&j7)1ofp(OGa4jjF;Hd*`6YQL+Jf zffg+6CPc8F@EDPN{Kn96yip;?g@)qgkPo^nVKFqY?8!=h$G$V=<>%5J&iVjwR!7H0 z$@QL|_Q81I;Bnq8-5JyNRv$Y>`sWl{qhq>u+X|)@cMlsG!{*lu?*H`Tp|!uv z9oEPU1jUEj@ueBr}%Y)7Luyi)REaJV>eQ{+uy4uh0ep0){t;OU8D*RZ& zE-Z-&=BrWQLAD^A&qut&4{ZfhqK1ZQB0fACP)=zgx(0(o-`U62EzTkBkG@mXqbjXm z>w`HNeQM?Is&4xq@BB(K;wv5nI6EXas)XXAkUuf}5uSrZLYxRCQPefn-1^#OCd4aO zzF=dQ*CREEyWf@n6h7(uXLNgJIwGp#Xrsj6S<^bzQ7N0B0N{XlT;`=m9Olg<>KL}9 zlp>EKTx-h|%d1Ncqa=wnQEuE;sIO-f#%Bs?g4}&xS?$9MG?n$isHky0caj za8W+B^ERK#&h?(x)7LLpOqApV5F>sqB`sntV%SV>Q1;ax67qs+WcssfFeF3Xk=e4^ zjR2^(%K1oBq%0%Rf!y&WT;lu2Co(rHi|r1_uW)n{<7fGc-c=ft7Z0Q}r4W$o$@tQF#i?jDBwZ8h+=SC}3?anUp3mtRVv9l#H?-UD;HjTF zQ*>|}e=6gDrgI9p%c&4iMUkQa4zziS$bO&i#DI$Wu$7dz7-}XLk%!US^XUIFf2obO zFCTjVEtkvYSKWB;<0C;_B{HHs~ax_48^Cml*mjfBC5*7^HJZiLDir(3k&BerVIZF8zF;0q80eX8c zPN4tc+Dc5DqEAq$Y3B3R&XPZ=AQfFMXv#!RQnGecJONe0H;+!f^h5x0wS<+%;D}MpUbTNUBA}S2n&U59-_5HKr{L^jPsV8B^%NaH|tUr)mq=qCBv_- ziZ1xUp(ZzxUYTCF@C}To;u60?RIfTGS?#JnB8S8@j`TKPkAa)$My+6ziGaBcA@){d z91)%+v2_ba7gNecdj^8*I4#<11l!{XKl6s0zkXfJPxhP+@b+5ev{a>p*W-3*25c&} zmCf{g9mPWVQ$?Sp*4V|lT@~>RR)9iNdN^7KT@>*MU3&v^3e?=NTbG9!h6C|9zO097 zN{Qs6YwR-5$)~ z`b~qs`a1Dbx8P>%V=1XGjBptMf%P~sl1qbHVm1HYpY|-Z^Dar8^HqjIw}xaeRlsYa zJ_@Apy-??`gxPmb`m`0`z`#G7*_C}qiSZe~l2z65tE~IwMw$1|-u&t|z-8SxliH00 zlh1#kuqB56s+E&PWQ7Nz17?c}pN+A@-c^xLqh(j;mS|?>(Pf7(?qd z5q@jkc^nA&!K-}-1P=Ry0yyze0W!+h^iW}7jzC1{?|rEFFWbE^Yu7Y}t?jmP-D$f+ zmqFT7nTl0HL|4jwGm7w@a>9 zKD)V~+g~ysmei$OT5}%$&LK8?ib|8aY|>W3;P+0B;=oD=?1rg+PxKcP(d;OEzq1CKA&y#boc51P^ZJPPS)z5 zAZ)dd2$glGQXFj$`XBBJyl2y-aoBA8121JC9&~|_nY>nkmW>TLi%mWdn-^Jks-Jv| zSR*wij;A3Fcy8KsDjQ15?Z9oOj|Qw2;jgJiq>dxG(2I2RE- z$As!#zSFIskebqU2bnoM^N<4VWD2#>!;saPSsY8OaCCQqkCMdje$C?Sp%V}f2~tG5 z0whMYk6tcaABwu*x)ak@n4sMElGPX1_lmv@bgdI2jPdD|2-<~Jf`L`@>Lj7{<-uLQ zE3S_#3e10q-ra=vaDQ42QUY^@edh>tnTtpBiiDVUk5+Po@%RmuTntOlE29I4MeJI?;`7;{3e4Qst#i-RH6s;>e(Sc+ubF2_gwf5Qi%P!aa89fx6^{~A*&B4Q zKTF|Kx^NkiWx=RDhe<{PWXMQ;2)=SC=yZC&mh?T&CvFVz?5cW~ritRjG2?I0Av_cI z)=s!@MXpXbarYm>Kj0wOxl=eFMgSMc?62U#2gM^li@wKPK9^;;0_h7B>F>0>I3P`{ zr^ygPYp~WVm?Qbp6O3*O2)(`y)x>%ZXtztz zMAcwKDr=TCMY!S-MJ8|2MJCVNUBI0BkJV6?(!~W!_dC{TS=eh}t#X+2D>Kp&)ZN~q zvg!ogxUXu^y(P*;Q+y_rDoGeSCYxkaGPldDDx)k;ocJvvGO#1YKoQLHUf2h_pjm&1 zqh&!_KFH03FcJvSdfgUYMp=5EpigZ*8}7N_W%Ms^WSQ4hH`9>3061OEcxmf~TcYn5_oHtscWn zo5!ayj<_fZ)vHu3!A!7M;4y1QIr8YGy$P2qDD_4+T8^=^dB6uNsz|D>p~4pF3Nrb6 zcpRK*($<~JUqOya#M1=#IhOZ zG)W+rJS-x(6EoVz)P zsSo>JtnChdj9^);su%SkFG~_7JPM zEDz3gk2T7Y%x>1tWyia|op(ilEzvAujW?Xwlw>J6d7yEi8E zv30riR|a_MM%ZZX&n!qm0{2agq(s?x9E@=*tyT$nND+{Djpm7Rsy!+c$j+wqMwTOF zZL8BQ|I`<^bGW)5apO{lh(Asqen?_U`$_n0-Ob~Yd%^89oEe%9yGumQ_8Be+l2k+n zCxT%s?bMpv|AdWP7M1LQwLm|x+igA~;+iK-*+tClF&ueX_V}>=4gvZ01xpubQWXD_ zi?Un>&3=$fu)dgk-Z;0Ll}HK5_YM->l^Czrd0^cJ))(DwL2g3aZuza7ga9^|mT_70 z))}A}r1#-(9cxtn<9jGRwOB4hb9kK@YCgjfOM-90I$8@l=H^`K$cyhe2mTM|FY9vW znH~h)I<_aa#V1xmhk?Ng@$Jw-s%a!$BI4Us+Df+?J&gKAF-M`v}j`OWKP3>6`X`tEmhe#y*(Xm$_^Ybbs=%;L7h zp7q^C*qM}Krqsinq|WolR99>_!GL#Z71Hhz|IwQQv<>Ds09B?Je(lhI1(FInO8mc} zl$RyKCUmfku+Cd^8s0|t+e}5g7M{ZPJQH=UB3(~U&(w#Bz#@DTDHy>_UaS~AtN>4O zJ-I#U@R($fgupHebcpuEBX`SZ>kN!rW$#9>s{^3`86ZRQRtYTY)hiFm_9wU3c`SC8 z-5M%g)h}3Pt|wyj#F%}pGC@VL`9&>9P+_UbudCkS%y2w&*o})hBplrB*@Z?gel5q+ z%|*59(sR9GMk3xME}wd%&k?7~J)OL`rK#4d-haC7uaU8-L@?$K6(r<0e<;y83rK&` z3Q!1rD9WkcB8WBQ|WT|$u^lkr0UL4WH4EQTJyk@5gzHb18cOte4w zS`fLv8q;PvAZyY;*Go3Qw1~5#gP0D0ERla6M6#{; zr1l?bR}Nh+OC7)4bfAs(0ZD(axaw6j9v`^jh5>*Eo&$dAnt?c|Y*ckEORIiJXfGcM zEo`bmIq6rJm`XhkXR-^3d8^RTK2;nmVetHfUNugJG(4XLOu>HJA;0EWb~?&|0abr6 zxqVp@p=b3MN^|~?djPe!=eex(u!x>RYFAj|*T$cTi*Sd3Bme7Pri1tkK9N`KtRmXf zZYNBNtik97ct1R^vamQBfo9ZUR@k*LhIg8OR9d_{iv#t)LQV91^5}K5u{eyxwOFoU zHMVq$C>tfa@uNDW^_>EmO~WYQd(@!nKmAvSSIb&hPO|}g-3985t?|R&WZXvxS}Kt2i^eRe>WHb_;-K5cM4=@AN1>E&1c$k!w4O*oscx(f=<1K6l#8Exi)U(ZiZ zdr#YTP6?m1e1dOKysUjQ^>-MR={OuD00g6+(a^cvcmn#A_%Fh3Of%(qP5nvjS1=(> z|Ld8{u%(J}%2SY~+$4pjy{()5HN2MYUjg1X9umxOMFFPdM+IwOVEs4Z(olynvT%G) zt9|#VR}%O2@f6=+6uvbZv{3U)l;C{tuc zZ{K$rut=eS%3_~fQv^@$HV6#9)K9>|0qD$EV2$G^XUNBLM|5-ZmFF!KV)$4l^KVj@ zZ4fI}Knv*K%zPqK77}B-h_V{66VrmoZP2>@^euu8Rc}#qwRwt5uEBWcJJE5*5rT2t zA4Jpx`QQ~1Sh_n_a9x%Il!t1&B~J6p54zxAJx`REov${jeuL8h8x-z=?qwMAmPK5i z_*ES)BW(NZluu#Bmn1-NUKQip_X&_WzJy~J`WYxEJQ&Gu7DD< z&F9urE;}8S{x4{yB zaq~1Zrz%8)<`prSQv$eu5@1RY2WLu=waPTrn`WK%;G5(jt^FeM;gOdvXQjYhax~_> z{bS_`;t#$RYMu-;_Dd&o+LD<5Afg6v{NK?0d8dD5ohAN?QoocETBj?y{MB)jQ%UQ}#t3j&iL!qr@#6JEajR3@^k5wgLfI9S9dT2^f`2wd z%I#Q*@Ctk@w=(u)@QC}yBvUP&fFRR-uYKJ){Wp3&$s(o~W7OzgsUIPx0|ph2L1(r*_Pa@T@mcH^JxBjh09#fgo|W#gG7}|)k&uD1iZxb0 z@|Y)W79SKj9sS&EhmTD;uI#)FE6VwQ*YAr&foK$RI5H8_ripb$^=;U%gWbrrk4!5P zXDcyscEZoSH~n6VJu8$^6LE6)>+=o#Q-~*jmob^@191+Ot1w454e3)WMliLtY6~^w zW|n#R@~{5K#P+(w+XC%(+UcOrk|yzkEes=!qW%imu6>zjdb!B#`efaliKtN}_c!Jp zfyZa`n+Nx8;*AquvMT2;c8fnYszdDA*0(R`bsof1W<#O{v%O!1IO4WZe=>XBu_D%d zOwWDaEtX%@B>4V%f1+dKqcXT>m2!|&?}(GK8e&R=&w?V`*Vj)sCetWp9lr@@{xe6a zE)JL&;p}OnOO}Nw?vFyoccXT*z*?r}E8{uPtd;4<(hmX;d$rqJhEF}I+kD+m(ke;J z7Cm$W*CSdcD=RYEBhedg>tuT{PHqwCdDP*NkHv4rvQTXkzEn*Mb0oJz&+WfWIOS4@ zzpPJ|e%a-PIwOaOC7uQcHQ-q(SE(e@fj+7oC@34wzaBNaP;cw&gm{Z8yYX?V(lIv5 zKbg*zo1m5aGA4^lwJ|bAU=j3*d8S{vp!~fLFcK8s6%Ng55_qW_d*3R%e=34aDZPfD z&Le39j|ahp6E7B0*9OVdeMNrTErFatiE+=Z!XZ^tv0y%zZKXRTBuPyP&C{5(H?t)S zKV24_-TKpOmCPzU&by8R1Q5HY^@IDoeDA9MbgizgQ*F1Er~HVmvSU>vx}pZVQ&tr| zOtZl8vfY2#L<)gZ=ba&wG~EI*Vd?}lRMCf+!b5CDz$8~be-HKMo5omk$w7p4`Mym*IR8WiTz4^kKcUo^8Hkcsu14u z`Pkg`#-Y^A%CqJ0O@UF|caAulf68@(zhqp~YjzInh7qSN7Ov%Aj(Qz%{3zW|xubJ- ztNE_u_MO7Q_585r;xD?e=Er}@U1G@BKW5v$UM((eByhH2p!^g9W}99OD8VV@7d{#H zv)Eam+^K(5>-Ot~U!R$Um3prQmM)7DyK=iM%vy>BRX4#aH7*oCMmz07YB(EL!^%F7?CA#>zXqiYDhS;e?LYPTf(bte6B ztrfvDXYG*T;ExK-w?Knt{jNv)>KMk*sM^ngZ-WiUN;=0Ev^GIDMs=AyLg2V@3R z7ugNc45;4!RPxvzoT}3NCMeK$7j#q3r_xV(@t@OPRyoKBzHJ#IepkDsm$EJRxL)A* zf{_GQYttu^OXr$jHQn}zs$Eh|s|Z!r?Yi+bS-bi+PE*lH zo|6ztu6$r_?|B~S#m>imI!kQP9`6X426uHRri!wGcK;J;`%sFM(D#*Le~W*t2uH`Q z(HEO9-c_`mhA@4QhbW+tgtt9Pzx=_*3Kh~TB$SKmU4yx-Ay&)n%PZPKg#rD4H{%Ke zdMY@rf5EAFfqtrf?Vmk&N(_d-<=bvfOdPrYwY*;5%j@O6@O#Qj7LJTk-x3LN+dEKy+X z>~U8j3Ql`exr1jR>+S4nEy+4c2f{-Q!3_9)yY758tLGg7k^=nt<6h$YE$ltA+13S<}uOg#XHe6 zZHKdNsAnMQ_RIuB;mdoZ%RWpandzLR-BnjN2j@lkBbBd+?i ze*!5mC}!Qj(Q!rTu`KrRRqp22c=hF6<^v&iCDB`n7mHl;vdclcer%;{;=kA(PwdGG zdX#BWoC!leBC4);^J^tPkPbIe<)~nYb6R3u{HvC!NOQa?DC^Q`|_@ zcz;rk`a!4rSLAS>_=b@g?Yab4%=J3Cc7pRv8?_rHMl_aK*HSPU%0pG2Fyhef_biA!aW|-(( z*RIdG&Lmk(=(nk28Q1k1Oa$8Oa-phG%Mc6dT3>JIylcMMIc{&FsBYBD^n@#~>C?HG z*1&FpYVvXOU@~r2(BUa+KZv;tZ15#RewooEM0LFb>guQN;Z0EBFMFMZ=-m$a3;gVD z)2EBD4+*=6ZF?+)P`z@DOT;azK0Q4p4>NfwDR#Pd;no|{q_qB!zk1O8QojE;>zhPu z1Q=1z^0MYHo1*``H3ex|bW-Zy==5J4fE2;g6sq6YcXMYK5i|S^9(OSw#v!3^!EB<% zZF~J~CleS`V-peStyf*I%1^R88D;+8{{qN6-t!@gTARDg^w2`uSzFZbPQ!)q^oC}m zPo8VOQxq2BaIN`pAVFGu8!{p3}(+iZ`f4ck2ygVpEZMQW38nLpj3NQx+&sAkb8`}P3- zc>N*k6AG?r}bfO6_vccTuKX+*- z7W4Q#2``P0jIHYs)F>uG#AM#I6W2)!Nu2nD5{CRV_PmkDS2ditmbd#pggqEgAo%5oC?|CP zGa0CV)wA*ko!xC7pZYkqo{10CN_e00FX5SjWkI3?@XG}}bze!(&+k2$C-C`6temSk z_YyYpB^wh3woo`B zrMSTd4T?(X-jh`FeO76C(3xsOm9s2BP_b%ospg^!#*2*o9N;tf4(X9$qc_d(()yz5 zDk@1}u_Xd+86vy5RBs?LQCuYKCGPS;E4uFOi@V%1JTK&|eRf~lp$AV#;*#O}iRI2=i3rFL8{ zA^ptDZ0l6k-mq=hUJ0x$Y@J>UNfz~I5l63H(`~*v;qX`Z{zwsQQD-!wp0D&hyB8&Z z7$R07gIKGJ^%AvQ{4KM0edM39iFRx=P^6`!<1(s0t|JbB2tXs_B_IH9#ajH0C=-n+ z`nz`fKMBKLlf?2AC+|83M+0rqR%uhNGD;uKA6jOjp7YDe^4%0fRB<^bcjlS2KF~F; zu09wh1x0&4pG&76M;x8$u`b134t=dEPBn6PV|X29<#T4F1mxGF*HOgiWU8tN@cguI z_F@o+XL7FJztR63wC|j4x_DANzcX94r7Iz-O2x$({&qd*mdLG=-Rv)uZ}UlMR+F&q zU}=lkfb0p1>1Ho){o$@}mSKIV;h*$AND7~Dl)QzpFBlSM99Kx+F7GsVK5xcR? z_4Q(Z%cgk8ST}U;;=!LwyZVu^S$>B-Waeik%wzcKTIqeX=0FP(TGQ=nxi=dsS5BYF zl@?}NT!Y!Iyos^@v7XWXA{_bV~1lxz7gC?xuXxy0_?GaN!AhRRM5>)^t%&ODd;@HN5L{MD3 zc>i2keQZVm#?NrDwbfd}_<*5^U&w0zv~n-y8=GGN-!=_`FU^cM8oVCWRFxw?BM^YD zi=Vxz4q|jwPTg+?q7_XI)-S@gQkh>w0ZUB}a{^ z_i;`Y(~fvpI!vmW*A^|P7(6+@C4UeL2WATf{P1?H5rk`5{TL zcf!CgP6Mi{MvjZS)rfo7JLDZK7M7ANd$3`{j9baD*7{#Zu-33fOYUzjvtKzR2)_T1I1s7fe&z|=)QkX;=`zX8!Byw-veM#yr;|wjO^II>!B*B z0+w%;0(=*G3V@88t!}~zx)&do(uF=073Yeh*fEhZb3Vn>t!m(9p~Y_FdV3IgR)9eT z)~e9xpI%2deTWyHlXA(7srrfc_`7ACm!R>SoIgkuF8 z!wkOhrixFy9y@)GdxAntd!!7@=L_tFD2T5OdSUO)I%yj02le`qeQ=yKq$g^h)NG;# za(0J@#VBi^5YI|QI=rq{KlxwGabZJ0dKmfWDROkcM}lUN$@DV`K7fU?8CP2H23QPi zG?YF*=Vn=kTK*#Y_{AQN&oLju|0#E=fx%YVh>S{puu&K$b;BN*jIo@VYhqPiJPzzM>#kxoy0vW9i;ne2_BIG0zyRFp<3M(iY(%*M_>q0ulV2K}Tg zkG{EWKS{i%4DUuHi%DVKy%e+Q!~Uf`>>F6NgD{{I8~nO4!VgOvtFOc7(O)X`|7n*f zxBa4CJ-v9fUUH+`7sPVvpM_C*udZ@OTGTzx56QM5y~OlrZc&w9=)B?nmd@keRn+^= zvm~4sa5987LFDnU{(N|N zJAR8H@}p1fC+H(yTI4n#%~TbImMpuqYn9cQ<0QQ%=PzZItLkC*ef9WJUvfITKWh#D zc#__8`4am9%#NslIUw+<82#SR8AYG|woLfBg#!-&dqq}@P>|I0%lbdy0lSMmNe+}o zj0zZuFr6Wb?Y{Qy-S=|r`bdrDmhnmvkRnkdn`YCleU>Q$=je}LGhh>_QAj6aa_0Oc z%Swsmui;IRx7bN*=AAS@5yW&Y2hy;3&|HAiA8}!HT6!Z!RVn~MZg`RmI6&%#tBZDx zfD+y@Z~NWlk*4l13vmt3AK2wP!fQlnBbECL>?p)F?T)<`w&QN>cP_V>r7UTcsTaaP zTOb$f!P@zf$6>890NVKbIkG8rE?9!Y97sMSZjfF?A zYR8lp`LMoz~O?iaZN;gcX;LC-%Ia*R%A&SLx!YIf29?P+=XAAojK8!^OU*@?R&DK!#G_lsn!#;S375uZ&B0HH1|BO0R90$U>qs zSvHv>H~mAgNCcjo-e+;RjY6B9NCbQrZ|BHjTkehaU<9CSkdd>Vl*ifA2LNOP&R2Qdy3k3-TQ+ zbq=#vI43x`s=%~cGyN&y4Y!FxhwgDe@i6uv8^BLL&3z*SO=D0aLjih?gY4-9uWp5or)H+v~w6n5X#F-I52z=Z_p4JB(;M| zeaVFhuR2|3UD2MzVc~^nSoD2(dD#uL_1PdnIxeA{V5n`#3xf1Zx@4lw(DsQ&H$h zw#%3O<1173hjg2_nhKi!d1ej=h7y`hVjCNB6|HTnx>SWuCE-kgTnfT+YGX4_Lun({ zDv2`>d3vrS)tTf7ps_vvh!Cx^e1BFuWnEAh0(7fkNk|-3oU|iRWdsC6U)?Raft~HN z;^$U}vZK5O8|LV$>6X5T(uYkblv{zwPxnQBh(BQ5tA~J!vGiAMYP^_ki~pkIxDfOZ zUJDwq%O~WueeV6%uN<54&u*c&E4y431cklBNrb06zGOOy4XNT~JS-q(s6@)F@ovbe ze`fial(O4(-su%6@@1+V0MsdLLMyE8;)nou(7}czU(5ASaZYDT(kUZ0L(&g$nF^n9 z9-Pi`ZZLX&)^*M6As4_2Mmc9S7OT)F8KkL2NJ)KJcnCuWU=Wy402A&45#Q9Id~BBH z0cY*xlv!uXzKrXLH!xQu(OtJvEj|0-DmRj1vjFz{c*I4$Pe(+_V|^b~S!0xm{8lq= zZv)@NlcyL3Xdz+*|L137F7y6L-2VsrKw=q^S>F6i%<{Fr8zk06$Ay-(!L$fY@7mcng!2}L0t zgi|KxfB63Xtk_Q8#ZPipQ@!zgjdpEIbK_?q17Hoi4Eiyun$hrc>T(7pOLVLQE=lgGwA+A308p& z7@=09(|$>eLy5gLe{*|3b(M;1n;C^~v?o88jYib48eR4$QGsBFzd}3QuwO^_XE(=B zq+hMi0UFC|dB{LCwch7;zYT=NK})O%sgi0k#yV;My@24^B1+CuZmYOh0^b)5Ba_)) zC%i#_Iev&nsu%I|1N5=MVc#PrlunKAs&hY|3s5;@}`>sB>}gzxuB zB=2vrRyB3uiyW(hkDUNe1@&(b`;>ZvGgw|@s{zVC#_`HXIN_^J@Etb zA7A+F?ot37T{<-vTy8h&b3e+WKHE1oh;pUQrN4yRRrx?mT_9jRa2i4l1fUnLW^Cbl z!I1>VzyFe?VELWWhM?@?t-YPZkD-Qjo@bC2(o#ZtZmr{KZsdFWItV`rs$gp{724@C zL8K5}E0+DHcWcL^{BGei4>@J-3%a#$y6;I}=upc};-NDv-z#kPX26ylOpH)Ov1uU{ zkLj6oiH6l_s+B~_z;|Jc2oi?naS7#3H63~~lWj4rUnd=fCnKdkik<@R&kch9q##G{ z4u!%=rlM~Yp3jk*t8}1B`Sv6<%Z^}~1e@aq zg|JQ`QO2pSjAm-g*?IrNc$^~sIrNBo2$m|Sxanr?Mfs>2@Auu49 zGXlsS<9XS1&8h(dD*Hl&5HBDG!^pJ*lkau_Ur+7`7z;rcs$hT4we?3bT=7Fe<>{5( z2m2(c+hUz2BTHM8dCe*Z3XX&Av;b~a=$6EF>&^E8%nyxO@m_n!q&XD^A{SRjRZQ0L~qDeC=j&0$j6=LNIz@`ni^>ch|sv}^6 zlm>?28yPl@WmDPR?Y-A9X{U9Dv_IsbXJnzKCjkRksLOg#42uG2mE_acbTQ4)J|1V>%U@K(FP3AYhL0U zdeOCPN1qLv!|#c=p!_+%VNV(GHt`RuLRV^vz<5tt-r)yOK**kUWPspVAf|}ZL{LS= z@k(@@!P&W!>wwe`x{+GrFSWhHov7hu?{KuuT%kl#WO@*WX$i_@retlhQBj++SVNCx z5$78LxP>Z=^aJ)D280r_jj=zFfMJFXCIe^B{~V@d1rl_F(qo&AB4bC-vYL>x2jSKX zpuTG-6kgp3e^T&+dtV*i6a~)v@n?n*MffN59y}<0djUX zt27R+SE#hp8bzc#;rk$jw3r4)Q@eI$*`_)=Pvge8@8|8>H3X)<9YX6cXa=ii#Le;(qKm@%0-7$>2ShnYc`j#zJ7gu_FE^?uAkL|H)UIH#gPu^40!6^J=^ zr`}iwa^!4tzW~vOMZAaKF>*8A{^8m$i(VK)>?=#l`xrVe>wseSvM_aF zATNkY>kM_P3?1kE`uIq#mvr-wuTgUH0N<&JhF=(E9%^NS*HLm!4GZ4_XI zL=R5tlG5Mk_1rPfg)sk^llFuKPMPBhuU|L5q#yP_mzxp1o&pAzi-X31sgFpIHn@($ z_>=`AB5(8tP6p2zS5VEvH5J$M` z_much3>S7t3Yo`Yx!>83-hW9LYzDKP?mKdkD#QAK8*M((sx{eBQdrR<^3ZhFP81+& zBnJMUefQyNBji~$5d88Wfw1Lv59aJN9t2!pABLg;ewJ#LXL-10;QcJl+Y4Mtngb)k6JZlCf)3uD_u)J3sYyN;NN5hNbg$%W!i-GK%e&!Us)2IExWSss$YG(hm3kJ-h%yD z>8q^n$+4I(_y_mbT{du4P%h1j3oSpjhY97{+IZ`aA4ug!vNJ6*p?<2H(2w+GD3j$I z1TUXGyNzdf>_yB3grP~FZUs<2Quw;eEi*7s(-MiIkQ%@J^+WGdQvYSUN+TRiD-xto zJ=OUU+kxGYc!HCLNbCvR4lGTp~#L;DFzGd-#gJe*xf(P3hDQz|y)?b9mwU3WUVnpcqXM<@w%r-k*Wr^gzAv)8T^sqA=Ye z!7qy&exJmAcAt~CwS#@yNmjr8*T*!A6w4~E*ibaLRs0CFo(;R3=ODhDt6zWNodmo0 zXx&bT$6&+5c>a|WJ)F4G-^GjY0H#*tY=UNyYr_q5fsrcjk(c^~e*7Lf`!Jd`)p412 zn|^*hV= zFI4UbwA%X@smDd$cQOiMC%jfitTxTb+#`9`G=2rJDfK!E=5ra|So>lc{X1$~w28i+ z4p&cTGwZ#5VueiXS9O8#;RR$yg7tL9!^)Sz&pZYIzlSh}0}V{LxL$Cu%B4U5_}k}- zm~|CsD<076x@<>m=6w6N?WaThIBP`!u{-;WF)xc=2otx*lwf|5+MkdJePjh(B z9SH+%cHGCMAXNxB{_3^otDWdsV7Ob6n{0 z+&!(;iaHOX__5z_$Qk{%xYV%Ig@7iokGBwR`3642ZP#H#v9QGbWl8<|MS*=@qO@Uj z6+SZ_v9`1paUe5tFN~v(b#J3a_Lx0+;r9giZIx-A5TxdbG>xi#AZ5_z1V}B^n)sxT zz49}eK7EWb6wR!6-qQOrHQHkUvshvq%=G2d&@(#XM*Am1;WbnJ{X_!a{ZkphD$^TQ z=Iskb&}=lBm(RHiwJoGg`*NiQ6#RB$T#LF+>#ef;Jne&MxKPX!#r`&TVEFsp2jnNx>dClzpcPy&G&13a_<0qaR3i+k212~hoQ z8nMk{JP-t04I{GW5gUBqcJW-jSMrlw}>p)ptx?WKuCUV77taMiV zHok9V=6yv+Uts@fMY&A}amC=!Yj}eL@=e%XJ#%?agkt1jWF+10{(E9mHLDa>Ll7Vj zG=3cp%ljIB-6pC}6&`xJ*6WCP|IlglLWJ^?yviI8Ve)?V_i4%n;olzny62_`-|IGi z^=}p_O>Z8M;c4|RExu70E7ePW(HWVS&E$+LL6xSQgB`QfMQJ|4pCTFowA39p5P-|$ zUtM_H2HnP8_RoS~Vwk(FhbG zH41licj%=0a;Ln2STFBvU}Ne&O&%8bYKj!h1FA#sNM`232fX|U3QPp#3C?mN2;hE9 z;)!@5ixSPl<89^7gwhHc2YAX1KJK$#*3`KOMIQ253q7-*RJ5k)zp9GBO|Ga~X*^}US5oN@aG&waHV%vi~r{t^`ptTxb zL}q1W8S7*>7oWwvgV4uFLZ(@k`R*=LO_|Gu`prs~!WQXj-NLIa^2(7IHg>BG^N zc|i{-^=&Cek9dkJFQys|sjG9i>LLz|;yCv{^1i%c*h>8zF91kLvS9HBQi~ZU!JL`B zK8N+U0fr1*6??Ium)AF!6tc1eGhXIYL6IRT7rmKp7+>?%5Pa6zC5)KY$ycF0ZJ`G5nEQDG100U-jLkH8^UE4g6wq?sg%pP=-$&G#bcN`^?w3a6 z((s$6eRKcSEIslW-kk5Qi|5Mg-(xdLF}PxxVh$PuO}#aR6pW1kV4Af!Bqh*btXNNZ z>-4(IUl+L4dw+3LcpGut=qB45O+W)Q5?*zZ2A6rJcg`qkSvWA!j^r2mqKuCm6`Py? z@^T#Ux04HemPGd!Hs7NkZdVn1}8_j`o?)*OKZGS!`ff)gF zG?v-lj$wWNWCcw2Mg2o18D~1?3_b0XzdiKBNkYSDpcv@&kp0POmweJE2ZkIQ3B!a! zIgIoE+Xv?;34kyo^QYjZk+tEqZvq^#QG(OzX4~X+KtsoQoddTWUR(yo8R+ObEF1j<-syWOb>)JQ&Zbdu(sctU%Mt zW&YR0{ttY2TTXYZ?~WNU&cES1Z2q(7SrWDh``!J(JM+Nk$!hu&Y;(7E`ZNKTe0w+% zJc?Qnw2B+%UR}0;cB0Rufa(7-3FF}?629@LgTiEC&2uyL6NxexOp?AKT^aAx3gi(W zao>r>MPw0eQ3>IV02uLsC@>yK_epX6GRg4{NEL2wPPF9=*L2RV3yyK8DhuEK>rmmV z`&Q~#c`lgR&93TdOCja|ewOXmPNRh7!&dMT(1ett#iDr8HZW~VqWW@7fe9B6;7S+? zbC`d4@MEau&mKlOPKd>*10q0c{~^baw6!a*w^sY#0Xim{oOsiXiDOhbG&kl3c$$n1 zMRrD83&QucDSEcV*7LIp8VTA@F<%qe+_c`L;6on(>SjAU^}5c9!BCffT>$VQhe=)z z8(=Ej{5>jhmjB3{xDfj2R@VmHQ!CqjlO4KnuOmvHy3K#po$yp_V;p_MKjh1`(rzj6 zHW956k1yvntz{_g?Xbs`avK(IjlTnsu%htO;D7 z?J#x^EzuvVn&NA=!MEj7cwe5A-Z$Zk2LBZH$~%E* zf`((xH0?`}hs|HA%mtwfOEsZJxxrennkTYcwP#FKO5%Lpc^JXhSpV|ZH$Wr;`}`_( zIP==gd3LYyVtwD|*ZJGi{7~x8{=^bGVqu0RJ`n_BZH9+}kz%-4ZRsImi@rx%=ZEKs zcPnUXo6hbJV>fH;@1|bAHIe0ijYI*&kdT|HkDS$9No9 zCHo=*HWb~U+Dtzxr+Esao}6@|;Pf+E$ay0$kQp#s{wlw+7aIKbMdf`OqhoG*;Tco0 zjrP}VQG#Y2cJuqoJg&5({)S(BA}q9T1lGeWRyu=Je|)I!6a+aj!IP^1({)ZYe&x6w zt3a)Dq^TB+A7CdB0-}#z2Ur$W&h3YVw8==!xONy$uQmDWh-@15iEOt!q2m&?ZLA|w z8loSb(0}7y6Xu0?M5Uf4>VZGluB`wMf2oh;m)ghxVda>3m}4%V)r^0nVQ5V6f3>*) z0&VN!N0~GC^P}vj$`EDMZEmVV;N&RISY2C;$0;2(<{Lt&PKzqRByQdiEHGAbwtbS zPj`Da5%U6k1oEtVzI}QNw;!hT6F+~|@=c@$C4NtO@=xgP?|5MyZAyuCzcvq4rdAv@C06%gZ`9%I);R6UGiGJobfux+<0DLS&|MSG4UH z_~o{^^9>ixMg~mY!-@Fai{xaE4^;qy9iZN15Gbn5ZqHWf>Jc5Rv6(#n8`1NcCsdmG zab*dSXVPaE?)wCalD;$ivF%@nB#7D`@YG04p6ed9m}4iJW|pfVMLE<-c{=-8$e?cH zUdU#mCj4gb zZKA^b9p*9S(}8@tw~1RNPHr7tQr;P+-)D8|sq=*o)G%RGqt> zzP5yf`pVxb)I51D_G~Xp^GNK zVI6sAX)a9s)e{8N3?35YA6aQTXuyszK3ah~CemzA&CII#8F&F#KN41~8I^&_%}6MCNb{W87qAF`zj_Y^szhb> z3p3}KbOxotY|(lD=;)`fYE_*{S}x;f^SW#)SU&5X#o|-R|trpa|L5PS5aa0 zTHw8%SDSVtU4?vyrhnq+^@dgFS)|(y{~(4j%3UEiO-rBM9%`)8(dh33pMLiuurNY# z#10AsQ7%*0Cu_DSAU}P;X(JwA64~Q_^R%d_zSm^6Aux?Pn70PM>9EvLeOX z&w9c)pGmcL22;MO3C_B>=NC0RJpMp8?#ZUf=GWRvy z6RHq3B}=MGVg?9@iKFBpsvnkVh3{Vpp=`CcD=u~@ql{my|6?3ssi3mCOPnjI&E}VC zc@X+Yl>;;DNo0W0`0th!X{?luDhOC{E8N=?!w}K1{V=)+1={m(f`Oc|N=07>}3;z{-(A zm{JL=j?Sro5iecmE2-pWlRf(r%|HEQ7kgwQ9+kt=NBhtQI7OwcZ#3%$Uf%^r2nhjY zoQ08MfC%_X{O9~WcirMZMhn#z^ux4Erx-tf-6bHD)9eH&^L>^jvAd^9A^DCDs?0;k zkm7LE*KjP6`2d17MrQaaLqd_Rka}J$csvUec#hw78<=s(hyR>065~YCVCA9+#Q+; za(*L0IEw!r5P|@-;x33L$Lv9 zcuN8YG&g{<(SeJG18~(b!5yywSqQiLAX0;---;}mF5&b4lg|T?LwKREa{9YX_-zL@ZE?Zqi@HxK^2KO1>0LATu{te=T zprmHtY)bDVfxI1S}KBE7V zznP7KQ8HekWU#W6mw`dr-boV}pMQR==&5=Q5T=_q091jfc;R*jX#&=MQ%~@E@9^?`$v48ks<>(fI(F6L(5ppKy|$HWng*bKOb(4|cMUB&z$#ob#XV z5-mg)gmFIybZf=znm3ZPyUO^GJfxt0kmHjaTZ|sthsxXw&}Y)fOUSg=JhRSR^UjZ- zhqqb}Wsyw4zdnj6@#BAJa#-PdI4_dgafFXh85DsEQ_cT+5)XpZq$fZlBA_9UsE9r6 zEFec5?uqN@QhJ^IzwZrwl-5J`CmVPv{(YDTqEqWR^dI;5hXc~cxP%B3v&~s0`Ct89 z@S`i~a^c%V^N81dDT*ItFS*&IN;@O$EgzX0e7x&}TD=!zS}hTpezBLS>mdX(5< z)8DEI(-o_D)c-UX@dA1MuJ*yc>Hf4|`*B2S_O>w*-tbUwtiu`;W(Ud{HTty@(&x(T(F&;M zJ=?H>6`B7nf-90e8V`WSVp|0oEKB-P2M{}4ZDawzvM&a!y>`Y#jCsD%T_l``@ah(I2nJs~Q|%uSKu@k!m~*8B*IoA{*TgtF<(5sHCGG;n@NE%~Xt(G$^&<87u;}Na zx-8cq0g`uA(&RBFo=-4Y1GUZ<``Zw{xL4jfHkZw~%~wvtGueszcXt)_QwH8g!; z%s&3kSa~R$dO$-%L-)c@_hi7&>{6L_M>OZFkUQu;{sL_bUMStNrt{{&O(Wn~*zPOk zB>dnfszb29NSTf2pqIs68k|p-UrSrxgLHqi?3N-UFa!LHy9n1)=s>`yS+J{MEzS@ zNlfGtpma7kG&LR3JE@wB%rFA*h~~KitlO=IP)ZjN6dQLM6qsry zHkB#cyNh#n`)}bCrN1My*;k)^@>e4gJ`LJK?2)Pwp?4Tl4)4FA0(tvY+#1jOUM)xw zlMz4x-f@g^+yKUN`?Vu)|AwujArnM~Pa@y*Q9S8eS(u{-S%(Z5=R~pRl5ZGDjdqH% zC8rW&{##wOpU_oTIG4WXMk4&%2t1;lWcW5&!yxmOT*!hBcKyTqEcNoO+R2;Q?Yj+W z1-Y4?59fijz4(MIDwGe4-baYf08UCs;r|YefD-Md2ST;=cxwpgW=tR76-dQVAhn^= zG9Wk5lQk%jIR@KNU!UMp6@BfU;r+;y4VQ)D2!Il9HX%yW-9nOzV+m$YKzVaO`B8S7t z$!S2Mz`xw>V(RjE`0>bQp<0y&h~Y=M#jpy!#=dE>`=e_AjSZq6u!Dy1xJf~-7|0F! zPR9|n`e_7D2DIV2H(CESQ}hA>U>n|6`%z?YKEA~)BOVY%y=jPV zT=44R!L?J)736X#csn|lfBJ)o8ixaZclguWgrGO<`TN2FMfO}7;5}d+BlK0yTSH3* z4!=;5rOh85&2|x=46hkNaz?)U8&=bcfh=N_#8BNpZ2v$aVBo;sk^*X`v;4-LU;D>! zM*h12MxXIQy)SfAqE4;jY)wgnppazZkdNNVVF;(PLf^qK$FgY9+VFyBKE7UC|f z`R|?&egV11K3s$rJ6!GvoeW=jV*!-e(wA;x(2=d0E_e_%0x--0o8#~m^H1%AH5Z^B zn!TNPn927*bvaf0pt}zhK0o^V@WlGwwKo(*nQ|Q~4_;>~-8y20`HP>@UJa)3nEnGG z5Hwhs|FcmFG16ZVNb5hL`2Gc1{zWIMM{_OiKewV!hCi}U!VuE?s9wU-QbZ!)+Y^tS zGzp5OSi5iq6hmEr$w}&9DFgoB+i*`q`8TBi^MVS{SKEb8Aw%@K7@XCo(De2A`6%mf&a2#~y1N)+kJLD$1HCP!22)(U}xo2|j?WRzt(11j8Z_*v;P$R+Ug*Gy3VxV4K; zGGUGabnW*`Z}~`ydXL-l9e=GC$pY#z|63vy>E*m=$=j}iWP{sRTh0%H54`t>2xYH% zsk+M&u&pNgMCM@3e)Xc?jBWX-TIR_cQ1Z!RW7!B zBjZX=+^3}?SE)B+$EP+0oi1Fp5blDT?*}nsP>filqXH{ms zxU<$hetC`u)Wi+x|EKL-`y^#aQX+sDYIa{M;V%LqLrOk~lR>u0Q!+pyQSU4zY`?E^ z|5@)C)w6G_=i5YYC5SE_u(7hDNYr}uKT|@DSqF%S++lTIbIk^$a>{~0IH8KNFEy%+ zW#$&!ynpgNJh>6uR~?2c)ZMW+h0OKu231(7L_vETPaR+(P)Zy%0~yGm>E9?@@x!Jy z3PYgS}Q@b}x}E#F27@F+j}0=&Ql4gES&f8acMrPAVlVs9$97`FR))R5wI zc&}KFI1UIewh>3PkhnB7u zS3AT8_*|nexznG|Z*DU0c!K@jsI4J)5#DyNi#|e#`l1Vv1`1)*NVcy0LZ``aL0n8B zecupJ(rhq3u8bW0NIRhKYq$v1li+jp*4hfAd&wxYDE8vn1TQ7S@bTM|I2Ob z8vMOIxA7&_j{AKmD+O@EyXT`|dElt0pED^@IV0m)RPBUs*5jW60>>w1!@_G3aBKzG z_f(KfAPBk}-jQtR*Sroq!*3rbQ_m27e+YdzQjUb<_*k8vc_C)y!@cj5E>NxUhPu&g z@Z2<~esU`)ih+4opWe+K7sbN9n*9@n>#@n3*o z?xoROgDuvhq>jJ;Ve{6i<3roQNfgo5^4Q4(|GNExO2Dr7GjgA2zWuKp_K)K0R(6lv z!l$!zW-+T6mb3gQaAFviTQi{|*t%>{(mhTdy+y;Re4qT@kccy#{b z&zWy~kLO@>*WPj2k#H)|7L&gAJ37DmHQAme#@m;(Y8Nu^`D5vf8sZFW#+lA2!HK=( zJ)#hO6JD*`o~&c*&46d}g=Qj@SsoB5ikC z^1V8E+&<-OzuS_C`p5<<(A6fB`LXT(!kV^0_~hL6PpW4={l%|#xgdh?5EIk~lu8{D z2hiyhv3Yxij_#$Wu>P@7SYsl`-~3;}Ktx{34_NL^Kwin&=?!HDv3elQDbcU*qyYpN z(#yw~f1vFGK-t%CC-qa-4FYHbA^h>bag-I&*qaxwn?Qv|idE$<>1H|Gr6JtUu(he2$eg!N z@HTF@dG1)*y;4fxe)4_ZkpaBHH9hXp9p4|gLrRQyuevRd@gSS}JhRnWqrvm|U@>qM z=yl7RQROTKwQtzP3!zUF)_6Ld#NGA6v~2{J9Dd`h6{%+XsU#qGLh%`fB1Hc?wfayK zN`H4BpDp)npVQuu$DVW1qsBS&AJ2eP%6Qw>;k{)Z$8%HL=Q4(a$Ng2_vHw&vA!1L+9zc8vaX2GtqJ{L-;gvF0IR$em zMQ8@{Qp3+3Quk)TJ$?I<8KmwzD*7#(q<@Mc`dchngW}cRG14(Z6K7{T|LhFXwhqUQ;BET;cYqPcAcMgt6M$V9$(?jHo@Sud$an$U&5F zZ1QNh^ztt)E*d#Ij;<43oSKKnd+WNr$_r}+s_O_x6DZSB10*5Q{ourqq>mTl| zx4y^(cy+9;t@R=*j>3_dmm_m)$k$#937V(sllby&5)Xex^UD-|m|q<(jEd#@DV(of zAd7sSdmS*zUDqJ9|K%O2J2OfdUiK{{b{PCy)pi<;hp~7v1CQj&4-10 zgO<3dqhYH1#-Fa}Q{pjql5>>P6gZH21zLfxZ4$SK4T@7b!|`nWF9b*84Bq8&Eht;9 z*P72x&NUCZ7*@B$`FtE=hz5b}S`|c6Ey+j@D1ZibjJaRlR;{cxAWv z?Nqa>QqV*H-*zzaPvpLMHt~nl(x6?vrPpR?zn7~wow?oj*1TKmx4j71>$hvtC$DLD zUrz0^tiP0792U&dxJxNv@r}Elsjn^aSLUu=9#mD{&9n8|ayIL$!H3s>%KEvbchBFW z%cd?VU83mGF#Dar9*s~w&AnmQRQIOvR+uWsuZ?+|a=TzApXO@q^(r%8=}iv#wCnFq z=K9}JbqU@k99Q%j-}NNk+qLCP)jXfmOO|)@?mHcnynd6({mJisP1_}u7k)|eYHXWK z63eQ)E$ufFi!3CWUY2gw%e>omCv}qEX66aH-k&35f9`Q@Us|NPetVqe8=dX*VxJdn ze`q7b=Dn(UA(2sf&g)cOmQFhNJ#<-aMELJZbA#@to>25@kbW<)&!X01 z%NMJt>1ST)tyX)h@?`DxhbgCHr>S4wv}WC&Nw-!{+Z7$2D}74QAcXTvip=M0%Tp_N zor=k`)t|ra^ySr-+(|R9mB(E=`MX#y(wSw)$!iymzB;^c*>%&^*7HxTnRga=soSZT zdDl+9s;r!v8hk6POtzBaig4pRp7eWF(<8gufvNHPu6xs-=e{;mnHzJyGKE+8L0j}; z@%8-e^UCL5HhMiR>sD3Rve&yVZ#{Q1*CO8c+qSr^Z#CN;)(X5>tGG5yUw3<+CfhaL z%bP;hZ?jvgJU67BWyiy74_)6r)_nSxttxn0`0?HE^5(uydHVgP+HE$V?Lv)Leti43 zWA|;f-RqX``95>)^P-fw!Vi{3KNsII-*5f){gdxqd%gVdB1sOBNe=nEW%;i~g_P8J w!5uhoe-Jcg1nPN%MiEAtgE$;km@@t6ukO)1^!cY^83Pb_y85}Sb4q9e0FIsP9{>OV diff --git a/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png b/macos/Runner/Assets.xcassets/AppIcon.appiconset/app_icon_64.png index 2f1632cfddf3d9dade342351e627a0a75609fb46..f5dcc1681ae81dfefecb343643cd4873680ed455 100644 GIT binary patch delta 2470 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 diff --git a/mockup/App.jsx b/mockup/App.jsx new file mode 100644 index 0000000..9731dc1 --- /dev/null +++ b/mockup/App.jsx @@ -0,0 +1,478 @@ +/* Pyramid · main app */ + +const ACCENT_PRESETS = [ + { name: 'amber', h: 42, s: 95, l: 58 }, + { name: 'coral', h: 12, s: 85, l: 62 }, + { name: 'mint', h: 160, s: 65, l: 50 }, + { name: 'violet', h: 268, s: 78, l: 66 }, + { name: 'cobalt', h: 220, s: 85, l: 62 }, + { name: 'lime', h: 80, s: 70, l: 55 }, +]; + +const TWEAK_DEFAULTS = /*EDITMODE-BEGIN*/{ + "accentIdx": 0, + "theme": "dark", + "density": 1, + "motion": 1, + "radius": 12, + "view": "chat" +}/*EDITMODE-END*/; + +const loadTweak = (k, d) => { + try { const v = localStorage.getItem('pyr_' + k); return v === null ? d : JSON.parse(v); } catch { return d; } +}; +const saveTweak = (k, v) => { try { localStorage.setItem('pyr_' + k, JSON.stringify(v)); } catch {} }; + +const DEFAULT_CALL_PARTICIPANTS = [ + { name: 'juno', avatar: 'J', color: '#06b6d4', speaking: true, muted: false, cam: false }, + { name: 'sachi', avatar: 'S', color: '#a855f7', speaking: false, muted: false, cam: false }, + { name: 'mira (you)', avatar: 'M', color: '#ff6b9d', speaking: false, muted: false, cam: false, self: true }, + { name: 'ren', avatar: 'R', color: '#10b981', speaking: false, muted: true, cam: false }, +]; + +const App = () => { + const [theme, setTheme] = React.useState(() => loadTweak('theme', TWEAK_DEFAULTS.theme)); + const [accentIdx, setAccentIdx] = React.useState(() => loadTweak('accentIdx', TWEAK_DEFAULTS.accentIdx)); + const [density, setDensity] = React.useState(() => loadTweak('density', TWEAK_DEFAULTS.density)); + const [motion, setMotion] = React.useState(() => loadTweak('motion', TWEAK_DEFAULTS.motion)); + const [radius, setRadius] = React.useState(() => loadTweak('radius', TWEAK_DEFAULTS.radius)); + + const [loggedIn, setLoggedIn] = React.useState(() => loadTweak('loggedIn', true)); + const [view, setView] = React.useState(() => { + // never land on voice without an active call + const v = loadTweak('view', 'chat'); + return v === 'voice' ? 'chat' : v; + }); + const [activeSpace, setActiveSpace] = React.useState(() => loadTweak('space', 'atelier')); + const [activeRoom, setActiveRoom] = React.useState(() => loadTweak('room', 'general')); + const [railCollapsed, setRailCollapsed] = React.useState(false); + const [membersOpen, setMembersOpen] = React.useState(true); + const [tweaksMode, setTweaksMode] = React.useState(false); + + const [showSettings, setShowSettings] = React.useState(false); + const [showSearch, setShowSearch] = React.useState(false); + const [profilePopover, setProfilePopover] = React.useState(null); + const [emojiPickerAt, setEmojiPickerAt] = React.useState(null); + const [messageActions, setMessageActions] = React.useState(null); + const [toast, setToast] = React.useState(null); + + const [messagesState, setMessagesState] = React.useState(() => window.PYRAMID_DATA.messagesByRoom); + + /* call state — persists across navigation */ + const [call, setCall] = React.useState(null); + const [callReturnRoom, setCallReturnRoom] = React.useState(null); + + React.useEffect(() => { saveTweak('theme', theme); }, [theme]); + React.useEffect(() => { saveTweak('accentIdx', accentIdx); }, [accentIdx]); + React.useEffect(() => { saveTweak('density', density); }, [density]); + React.useEffect(() => { saveTweak('motion', motion); }, [motion]); + React.useEffect(() => { saveTweak('radius', radius); }, [radius]); + React.useEffect(() => { saveTweak('view', view); }, [view]); + React.useEffect(() => { saveTweak('space', activeSpace); }, [activeSpace]); + React.useEffect(() => { saveTweak('room', activeRoom); }, [activeRoom]); + React.useEffect(() => { saveTweak('loggedIn', loggedIn); }, [loggedIn]); + + React.useEffect(() => { + const a = ACCENT_PRESETS[accentIdx]; + const r = document.documentElement; + r.setAttribute('data-theme', theme); + r.style.setProperty('--accent-h', a.h); + r.style.setProperty('--accent-s', a.s + '%'); + r.style.setProperty('--accent-l', a.l + '%'); + r.style.setProperty('--density', density); + r.style.setProperty('--motion', motion); + r.style.setProperty('--r-base', radius + 'px'); + }, [theme, accentIdx, density, motion, radius]); + + React.useEffect(() => { + const handler = (e) => { + if (e.data?.type === '__activate_edit_mode') setTweaksMode(true); + if (e.data?.type === '__deactivate_edit_mode') setTweaksMode(false); + }; + window.addEventListener('message', handler); + window.parent?.postMessage({ type: '__edit_mode_available' }, '*'); + return () => window.removeEventListener('message', handler); + }, []); + + const pushEdits = (edits) => { + try { window.parent?.postMessage({ type: '__edit_mode_set_keys', edits }, '*'); } catch {} + }; + + React.useEffect(() => { + const h = (e) => { + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'k') { e.preventDefault(); setShowSearch(true); } + if ((e.metaKey || e.ctrlKey) && e.key.toLowerCase() === 'b') { e.preventDefault(); setRailCollapsed(v => !v); } + if ((e.metaKey || e.ctrlKey) && e.shiftKey && e.key.toLowerCase() === 'u') { e.preventDefault(); setMembersOpen(v => !v); } + if (e.key === 'Escape') { + setShowSearch(false); setShowSettings(false); + setProfilePopover(null); setEmojiPickerAt(null); setMessageActions(null); + } + }; + window.addEventListener('keydown', h); + return () => window.removeEventListener('keydown', h); + }, []); + + const showToast = (msg, icon = 'check') => { + setToast({ msg, icon }); + setTimeout(() => setToast(null), 2400); + }; + + const handleSelectSpace = (spaceId) => { + setActiveSpace(spaceId); + setView('chat'); + const data = window.PYRAMID_DATA.rooms[spaceId]; + if (data) { + const firstActive = data.sections.flatMap(s => s.rooms).find(r => r.active) || data.sections[0].rooms[0]; + setActiveRoom(firstActive.id); + } + }; + + const handleSelectRoom = (roomId) => { + setActiveRoom(roomId); + const data = window.PYRAMID_DATA.rooms[activeSpace]; + const roomDef = data?.sections.flatMap(s => s.rooms).find(r => r.id === roomId); + if (roomDef?.type === 'voice') { + // joining a voice room starts a call for that room + startCall({ roomName: roomDef.name, kind: 'voice', room: roomDef }); + setView('voice'); + } else { + setView('chat'); + } + }; + + const startCall = ({ roomName, kind, room }) => { + setCall({ + active: true, + roomName, + kind, + participants: DEFAULT_CALL_PARTICIPANTS, + mic: true, cam: kind === 'video', deaf: false, + streaming: false, streamCollapsed: false, + streamer: 'mira (you)', + roomId: room?.id || null, + }); + setCallReturnRoom({ space: activeSpace, room: activeRoom }); + }; + + /* called from DM header */ + React.useEffect(() => { + window.__startDMCall = (roomDef, kind) => { + startCall({ roomName: roomDef?.name || 'DM', kind, room: roomDef }); + setView('voice'); + }; + return () => { window.__startDMCall = null; }; + }, [activeSpace, activeRoom]); + + const handleLeaveCall = () => { + setCall(null); + if (view === 'voice') { + if (callReturnRoom) { + setActiveSpace(callReturnRoom.space); + setActiveRoom(callReturnRoom.room); + } + setView('chat'); + } + setCallReturnRoom(null); + showToast('left the call', 'phoneOff'); + }; + + const updateCall = (patch) => setCall(c => c ? { ...c, ...patch } : c); + + const handleJumpToCall = () => { + setView('voice'); + }; + + const handleSend = (text) => { + const newMsg = { + id: 'm' + Date.now(), + author: 'mira', + avatar: 'M', + color: '#ff6b9d', + time: new Date().toLocaleTimeString([], { hour: 'numeric', minute: '2-digit' }), + text, + }; + setMessagesState(prev => ({ + ...prev, + [activeRoom]: [...(prev[activeRoom] || []), newMsg], + })); + }; + + const handleReact = (msgId, emoji) => { + setMessagesState(prev => { + const list = [...(prev[activeRoom] || [])]; + const idx = list.findIndex(m => m.id === msgId); + if (idx < 0) return prev; + const msg = { ...list[idx] }; + const reactions = [...(msg.reactions || [])]; + const existing = reactions.findIndex(r => r.emoji === emoji); + if (existing >= 0) { + const r = { ...reactions[existing] }; + if (r.mine) { r.mine = false; r.count--; } else { r.mine = true; r.count++; } + if (r.count <= 0) reactions.splice(existing, 1); + else reactions[existing] = r; + } else { + reactions.push({ emoji, count: 1, mine: true }); + } + msg.reactions = reactions; + list[idx] = msg; + return { ...prev, [activeRoom]: list }; + }); + }; + + const handleOpenProfile = (name, e) => { + const rect = e?.currentTarget?.getBoundingClientRect(); + const profiles = { + juno: { name: 'juno', handle: '@juno:pyramid.chat', avatar: 'J', color: '#06b6d4', status: 'online', about: 'risograph, zines, tea. teaches at the atelier on tuesdays.', roles: [{ name: 'founder', color: '#f59e0b' }, { name: 'print-nerd', color: '#06b6d4' }] }, + sachi: { name: 'sachi', handle: '@sachi:pyramid.chat', avatar: 'S', color: '#a855f7', status: 'online', about: 'illustration, collage, usually reading', roles: [{ name: 'mod', color: '#a855f7' }] }, + ren: { name: 'ren', handle: '@ren:pyramid.chat', avatar: 'R', color: '#10b981', status: 'busy', about: 'graphic design studio of one', roles: [] }, + kai: { name: 'kai', handle: '@kai:pyramid.chat', avatar: 'K', color: '#f43f5e', status: 'away', about: '3d + motion. fancy renders upon request.', roles: [] }, + ezra: { name: 'ezra', handle: '@ezra:pyramid.chat', avatar: 'E', color: '#3b82f6', status: 'online', about: 'keeps the lights on. dev-lab lurker.', roles: [{ name: 'dev', color: '#3b82f6' }] }, + mira: { name: 'mira', handle: '@mira:pyramid.chat', avatar: 'M', color: '#ff6b9d', status: 'online', about: 'painter · printmaker · pastry enthusiast', roles: [{ name: 'founder', color: '#f59e0b' }] }, + }; + setProfilePopover({ anchor: rect, profile: profiles[name] || profiles.juno }); + }; + + const handleOpenEmoji = (target, e) => { + const rect = e?.currentTarget?.getBoundingClientRect(); + setEmojiPickerAt({ target, rect }); + }; + + const handlePickEmoji = (emoji) => { + if (emojiPickerAt?.target === 'composer') { + showToast(`${emoji} added`, 'check'); + } else if (emojiPickerAt?.target) { + handleReact(emojiPickerAt.target, emoji); + } + }; + + const handleOpenActions = (msgId, e) => { + const rect = e?.currentTarget?.getBoundingClientRect(); + setMessageActions({ msgId, rect }); + }; + + const handleMsgAction = (action) => { + const labels = { + reply: 'replying…', thread: 'thread opened', edit: 'editing message', + pin: 'pinned to room', bookmark: 'saved for later', + copy: 'copied', link: 'message link copied', delete: 'message deleted', + }; + showToast(labels[action] || action); + }; + + if (!loggedIn) { + return setLoggedIn(true)} />; + } + + const spaces = window.PYRAMID_DATA.spaces; + const roomsData = window.PYRAMID_DATA.rooms[activeSpace] || window.PYRAMID_DATA.rooms.atelier; + const messages = messagesState[activeRoom] || []; + const members = window.PYRAMID_DATA.membersByRoom[activeRoom] || window.PYRAMID_DATA.membersByRoom.general; + + const showMembers = membersOpen && view !== 'voice'; + + const appClasses = [ + 'app', + railCollapsed && 'rail-collapsed', + showMembers && 'right-open', + ].filter(Boolean).join(' '); + + return ( + <> +